AI 144185: Integrate cdma into the main code base.

Automated import of CL 144185
diff --git a/Android.mk b/Android.mk
index 1246c73..14d387a 100644
--- a/Android.mk
+++ b/Android.mk
@@ -119,8 +119,8 @@
 	telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl \
 	telephony/java/com/android/internal/telephony/ITelephony.aidl \
 	telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl \
-	telephony/java/com/android/internal/telephony/gsm/ISimPhoneBook.aidl \
-	telephony/java/com/android/internal/telephony/gsm/ISms.aidl \
+	telephony/java/com/android/internal/telephony/IIccPhoneBook.aidl \
+	telephony/java/com/android/internal/telephony/ISms.aidl \
 	wifi/java/android/net/wifi/IWifiManager.aidl \
 	telephony/java/com/android/internal/telephony/IExtendedNetworkService.aidl
 
@@ -432,3 +432,5 @@
 ifeq (,$(ONE_SHOT_MAKEFILE))
 include $(call first-makefiles-under,$(LOCAL_PATH))
 endif
+
+
diff --git a/api/current.xml b/api/current.xml
index da3ea64..66128c5 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -10252,6 +10252,28 @@
  visibility="public"
 >
 </field>
+<field name="stat_sys_vp_phone_call"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17302061"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="stat_sys_vp_phone_call_on_hold"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17302062"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="stat_sys_warning"
  type="int"
  transient="false"
@@ -95471,7 +95493,7 @@
  abstract="false"
  static="false"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <method name="divideMessage"
@@ -95480,8 +95502,8 @@
  native="false"
  synchronized="false"
  static="false"
- final="false"
- deprecated="not deprecated"
+ final="true"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="text" type="java.lang.String">
@@ -95493,8 +95515,8 @@
  native="false"
  synchronized="false"
  static="true"
- final="false"
- deprecated="not deprecated"
+ final="true"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -95504,8 +95526,8 @@
  native="false"
  synchronized="false"
  static="false"
- final="false"
- deprecated="not deprecated"
+ final="true"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="destinationAddress" type="java.lang.String">
@@ -95527,8 +95549,8 @@
  native="false"
  synchronized="false"
  static="false"
- final="false"
- deprecated="not deprecated"
+ final="true"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="destinationAddress" type="java.lang.String">
@@ -95548,8 +95570,8 @@
  native="false"
  synchronized="false"
  static="false"
- final="false"
- deprecated="not deprecated"
+ final="true"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="destinationAddress" type="java.lang.String">
@@ -95570,7 +95592,7 @@
  value="1"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -95581,7 +95603,7 @@
  value="4"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -95592,7 +95614,7 @@
  value="3"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -95603,7 +95625,7 @@
  value="2"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -95614,7 +95636,7 @@
  value="0"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -95625,7 +95647,7 @@
  value="1"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -95636,7 +95658,7 @@
  value="5"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -95647,7 +95669,7 @@
  value="3"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -95658,7 +95680,7 @@
  value="7"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -95668,14 +95690,14 @@
  abstract="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <constructor name="SmsMessage"
  type="android.telephony.gsm.SmsMessage"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </constructor>
@@ -95686,7 +95708,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="messageBody" type="java.lang.CharSequence">
@@ -95701,7 +95723,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="messageBody" type="java.lang.String">
@@ -95716,7 +95738,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="pdu" type="byte[]">
@@ -95729,7 +95751,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -95740,7 +95762,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -95751,7 +95773,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -95762,7 +95784,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -95773,7 +95795,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -95784,7 +95806,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -95795,7 +95817,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -95806,7 +95828,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -95817,7 +95839,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -95828,7 +95850,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -95839,7 +95861,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -95850,7 +95872,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -95861,7 +95883,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -95872,7 +95894,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -95883,7 +95905,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="scAddress" type="java.lang.String">
@@ -95902,7 +95924,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="scAddress" type="java.lang.String">
@@ -95923,7 +95945,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="pdu" type="java.lang.String">
@@ -95936,7 +95958,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -95947,7 +95969,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -95958,7 +95980,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -95969,7 +95991,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -95980,7 +96002,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -95991,7 +96013,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -96002,7 +96024,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -96013,7 +96035,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -96024,7 +96046,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -96035,7 +96057,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -96046,7 +96068,7 @@
  value="3"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -96057,7 +96079,7 @@
  value="1"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -96068,7 +96090,7 @@
  value="2"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -96079,7 +96101,7 @@
  value="0"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -96090,7 +96112,7 @@
  value="140"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -96101,7 +96123,7 @@
  value="160"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -96112,7 +96134,7 @@
  value="153"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -96122,7 +96144,7 @@
  abstract="false"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <method name="valueOf"
@@ -96155,14 +96177,14 @@
  abstract="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <constructor name="SmsMessage.SubmitPdu"
  type="android.telephony.gsm.SmsMessage.SubmitPdu"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </constructor>
@@ -96173,7 +96195,7 @@
  value="null"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -96184,7 +96206,7 @@
  value="null"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index 1d939e1..ed7c056 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -117,28 +117,28 @@
                     mMobileDataState = state;
 
                     switch (state) {
-                        case DISCONNECTED:
-                            setDetailedState(DetailedState.DISCONNECTED, reason, apnName);
-                            if (mInterfaceName != null) {
-                                NetworkUtils.resetConnections(mInterfaceName);
-                            }
-                            mInterfaceName = null;
-                            mDefaultGatewayAddr = 0;
-                            break;
-                        case CONNECTING:
-                            setDetailedState(DetailedState.CONNECTING, reason, apnName);
-                            break;
-                        case SUSPENDED:
-                            setDetailedState(DetailedState.SUSPENDED, reason, apnName);
-                            break;
-                        case CONNECTED:
-                            mInterfaceName = intent.getStringExtra(Phone.DATA_IFACE_NAME_KEY);
-                            if (mInterfaceName == null) {
-                                Log.d(TAG, "CONNECTED event did not supply interface name.");
-                            }
-                            setupDnsProperties();
-                            setDetailedState(DetailedState.CONNECTED, reason, apnName);
-                            break;
+                    case DISCONNECTED:
+                        setDetailedState(DetailedState.DISCONNECTED, reason, apnName);
+                        if (mInterfaceName != null) {
+                            NetworkUtils.resetConnections(mInterfaceName);
+                        }
+                        mInterfaceName = null;
+                        mDefaultGatewayAddr = 0;
+                        break;
+                    case CONNECTING:
+                        setDetailedState(DetailedState.CONNECTING, reason, apnName);
+                        break;
+                    case SUSPENDED:
+                        setDetailedState(DetailedState.SUSPENDED, reason, apnName);
+                        break;
+                    case CONNECTED:
+                        mInterfaceName = intent.getStringExtra(Phone.DATA_IFACE_NAME_KEY);
+                        if (mInterfaceName == null) {
+                            Log.d(TAG, "CONNECTED event did not supply interface name.");
+                        }
+                        setupDnsProperties();
+                        setDetailedState(DetailedState.CONNECTED, reason, apnName);
+                        break;
                     }
                 }
             } else if (intent.getAction().equals(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED)) {
@@ -199,7 +199,7 @@
      */
     public boolean isAvailable() {
         getPhoneService(false);
-        
+
         /*
          * If the phone process has crashed in the past, we'll get a
          * RemoteException and need to re-reference the service.
@@ -214,7 +214,7 @@
                 if (retry == 0) getPhoneService(true);
             }
         }
-        
+
         return false;
     }
 
@@ -241,18 +241,28 @@
      * for this network.
      */
     public String getTcpBufferSizesPropName() {
-      String networkTypeStr = "unknown";
+        String networkTypeStr = "unknown";
         TelephonyManager tm = new TelephonyManager(mContext);
+        //TODO We have to edit the parameter for getNetworkType regarding CDMA
         switch(tm.getNetworkType()) {
-          case TelephonyManager.NETWORK_TYPE_GPRS:
+        case TelephonyManager.NETWORK_TYPE_GPRS:
             networkTypeStr = "gprs";
             break;
-          case TelephonyManager.NETWORK_TYPE_EDGE:
+        case TelephonyManager.NETWORK_TYPE_EDGE:
             networkTypeStr = "edge";
             break;
-          case TelephonyManager.NETWORK_TYPE_UMTS:
+        case TelephonyManager.NETWORK_TYPE_UMTS:
             networkTypeStr = "umts";
             break;
+        case TelephonyManager.NETWORK_TYPE_CDMA:
+            networkTypeStr = "cdma";
+            break;
+        case TelephonyManager.NETWORK_TYPE_EVDO_0:
+            networkTypeStr = "evdo";
+            break;
+        case TelephonyManager.NETWORK_TYPE_EVDO_A:
+            networkTypeStr = "evdo";
+            break;
         }
         return "net.tcp.buffersize." + networkTypeStr;
     }
@@ -281,7 +291,7 @@
                 if (retry == 0) getPhoneService(true);
             }
         }
-        
+
         Log.w(TAG, "Failed to tear down mobile data connectivity");
         return false;
     }
@@ -330,7 +340,7 @@
                     "Ignoring mobile radio request because could not acquire PhoneService");
                 break;
             }
-            
+
             try {
                 return mPhoneService.setRadio(turnOn);
             } catch (RemoteException e) {
diff --git a/core/java/android/provider/Checkin.java b/core/java/android/provider/Checkin.java
index a87f5fa..3c23db0 100644
--- a/core/java/android/provider/Checkin.java
+++ b/core/java/android/provider/Checkin.java
@@ -132,6 +132,7 @@
             BROWSER_SNAP_CENTER,
             BROWSER_TEXT_SIZE_CHANGE,
             BROWSER_ZOOM_OVERVIEW,
+
             CRASHES_REPORTED,
             CRASHES_TRUNCATED,
             ELAPSED_REALTIME_SEC,
@@ -181,6 +182,9 @@
             MARKET_REASON_PARSE_MANIFEST_EMPTY,
             MARKET_REASON_UNKNOWN,
             MARKET_STALE_INSTALL_ATTEMPT,
+            PHONE_CDMA_REGISTERED,
+            PHONE_CDMA_DATA_ATTEMPTED,
+            PHONE_CDMA_DATA_CONNECTED,
         }
     }
 
@@ -347,3 +351,6 @@
         }
     }
 }
+
+
+
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 4c9471c..c563dd6 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2049,6 +2049,70 @@
          * @hide pending API council
          */
         public static final String BACKGROUND_DATA = "background_data";
+
+        /**
+         * The CDMA roaming mode 0 = Home Networks, CDMA default
+         *                       1 = Roaming on Affiliated networks
+         *                       2 = Roaming on any networks
+         * @hide
+         */
+        public static final String CDMA_ROAMING_MODE = "roaming_settings";
+
+        /**
+         * The CDMA subscription mode 0 = RUIM/SIM (default)
+         *                                1 = NV
+         * @hide
+         */
+        public static final String CDMA_SUBSCRIPTION_MODE = "subscription_mode";
+
+        /**
+         * represents current active phone class
+         * 1 = GSM-Phone, 0 = CDMA-Phone
+         * @hide
+         */
+        public static final String CURRENT_ACTIVE_PHONE = "current_active_phone";
+
+        /**
+         * The preferred network mode 7 = Global, CDMA default
+         *                            4 = CDMA only
+         *                            3 = GSM/UMTS only
+         * @hide
+         */
+        public static final String PREFERRED_NETWORK_MODE =
+                "preferred_network_mode";
+
+        /**
+         * CDMA Cell Broadcast SMS
+         *                            0 = CDMA Cell Broadcast SMS disabled
+         *                            1 = CDMA Cell Broadcast SMS enabled
+         * @hide
+         */
+        public static final String CDMA_CELL_BROADCAST_SMS =
+                "cdma_cell_broadcast_sms";
+
+        /**
+         * The cdma subscription 0 = Subscription from RUIM, when available
+         *                       1 = Subscription from NV
+         * @hide
+         */
+        public static final String PREFERRED_CDMA_SUBSCRIPTION =
+                "preferred_cdma_subscription";
+
+        /**
+         * Whether the enhanced voice privacy mode is enabled.
+         * 0 = normal voice privacy
+         * 1 = enhanced voice privacy
+         * @hide
+         */
+        public static final String ENHANCED_VOICE_PRIVACY_ENABLED = "enhanced_voice_privacy_enabled";
+
+        /**
+         * Whether the TTY mode mode is enabled.
+         * 0 = disabled
+         * 1 = enabled
+         * @hide
+         */
+        public static final String TTY_MODE_ENABLED = "tty_mode_enabled";
     }
     
     /**
@@ -3127,13 +3191,13 @@
             throw new RuntimeException("this should never happen");
         }
 
-        String imei = TelephonyManager.getDefault().getDeviceId();
-        if (TextUtils.isEmpty(imei)) {
+        String deviceId = TelephonyManager.getDefault().getDeviceId();
+        if (TextUtils.isEmpty(deviceId)) {
             return "";
         }
 
-        byte[] hashedImei = digest.digest(imei.getBytes());
-        String id = new String(Base64.encodeBase64(hashedImei), 0, 12);
+        byte[] hashedDeviceId = digest.digest(deviceId.getBytes());
+        String id = new String(Base64.encodeBase64(hashedDeviceId), 0, 12);
         id = id.replaceAll("/", "_");
         sJidResource = JID_RESOURCE_PREFIX + id;
         return sJidResource;
@@ -3152,3 +3216,4 @@
         return "android-" + Long.toHexString(androidId);
     }
 }
+
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 61ab228..a4145c4 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -26,7 +26,7 @@
 import android.content.Intent;
 import android.database.Cursor;
 import android.net.Uri;
-import android.telephony.gsm.SmsMessage;
+import android.telephony.SmsMessage;
 import android.text.TextUtils;
 import android.text.util.Regex;
 import android.util.Config;
@@ -47,6 +47,10 @@
     private static final boolean DEBUG = false;
     private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV;
 
+    // Constructor
+    public Telephony() {
+    }
+
     /**
      * Base columns for tables that contain text based SMSs.
      */
@@ -1601,3 +1605,5 @@
 }
 
 
+
+
diff --git a/core/java/android/webkit/gears/AndroidRadioDataProvider.java b/core/java/android/webkit/gears/AndroidRadioDataProvider.java
index c920d45..2d431a8 100644
--- a/core/java/android/webkit/gears/AndroidRadioDataProvider.java
+++ b/core/java/android/webkit/gears/AndroidRadioDataProvider.java
@@ -46,6 +46,9 @@
   private static final int RADIO_TYPE_UNKNOWN = 0;
   private static final int RADIO_TYPE_GSM = 1;
   private static final int RADIO_TYPE_WCDMA = 2;
+  private static final int RADIO_TYPE_CDMA = 3;
+  private static final int RADIO_TYPE_EVDO = 4;
+  private static final int RADIO_TYPE_1xRTT = 5;
 
   /** Simple container for radio data */
   public static final class RadioData {
@@ -102,12 +105,21 @@
       }
 
       // Finally get the radio type.
+      //TODO We have to edit the parameter for getNetworkType regarding CDMA
       int type = telephonyManager.getNetworkType();
       if (type == TelephonyManager.NETWORK_TYPE_UMTS) {
         radioData.radioType = RADIO_TYPE_WCDMA;
       } else if (type == TelephonyManager.NETWORK_TYPE_GPRS
                  || type == TelephonyManager.NETWORK_TYPE_EDGE) {
         radioData.radioType = RADIO_TYPE_GSM;
+      } else if (type == TelephonyManager.NETWORK_TYPE_CDMA) {
+          radioData.radioType = RADIO_TYPE_CDMA;
+      } else if (type == TelephonyManager.NETWORK_TYPE_EVDO_0) {
+          radioData.radioType = RADIO_TYPE_EVDO;
+      } else if (type == TelephonyManager.NETWORK_TYPE_EVDO_A) {
+          radioData.radioType = RADIO_TYPE_EVDO;
+      } else if (type == TelephonyManager.NETWORK_TYPE_1xRTT) {
+          radioData.radioType = RADIO_TYPE_1xRTT;
       }
 
       // Print out what we got.
diff --git a/core/res/res/drawable/stat_sys_data_connected_1xrtt.png b/core/res/res/drawable/stat_sys_data_connected_1xrtt.png
new file mode 100644
index 0000000..c2fbbdf
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_data_connected_1xrtt.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_data_connected_evdo.png b/core/res/res/drawable/stat_sys_data_connected_evdo.png
new file mode 100644
index 0000000..db9f282
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_data_connected_evdo.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_data_in_1xrtt.png b/core/res/res/drawable/stat_sys_data_in_1xrtt.png
new file mode 100644
index 0000000..a421a8a
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_data_in_1xrtt.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_data_in_evdo.png b/core/res/res/drawable/stat_sys_data_in_evdo.png
new file mode 100644
index 0000000..54f55ba
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_data_in_evdo.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_data_inandout_1xrtt.png b/core/res/res/drawable/stat_sys_data_inandout_1xrtt.png
new file mode 100644
index 0000000..1a94cdf
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_data_inandout_1xrtt.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_data_inandout_evdo.png b/core/res/res/drawable/stat_sys_data_inandout_evdo.png
new file mode 100644
index 0000000..7aa6f00
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_data_inandout_evdo.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_data_out_1xrtt.png b/core/res/res/drawable/stat_sys_data_out_1xrtt.png
new file mode 100644
index 0000000..74fd351
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_data_out_1xrtt.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_data_out_evdo.png b/core/res/res/drawable/stat_sys_data_out_evdo.png
new file mode 100644
index 0000000..21e19a7
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_data_out_evdo.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_r_signal_0_cdma.png b/core/res/res/drawable/stat_sys_r_signal_0_cdma.png
new file mode 100644
index 0000000..f615681
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_r_signal_0_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_r_signal_1_cdma.png b/core/res/res/drawable/stat_sys_r_signal_1_cdma.png
new file mode 100644
index 0000000..c3962a2
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_r_signal_1_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_r_signal_2_cdma.png b/core/res/res/drawable/stat_sys_r_signal_2_cdma.png
new file mode 100644
index 0000000..68bfe94
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_r_signal_2_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_r_signal_3_cdma.png b/core/res/res/drawable/stat_sys_r_signal_3_cdma.png
new file mode 100644
index 0000000..4ccd416
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_r_signal_3_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_r_signal_4_cdma.png b/core/res/res/drawable/stat_sys_r_signal_4_cdma.png
new file mode 100644
index 0000000..0b25570
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_r_signal_4_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_ra_signal_0_cdma.png b/core/res/res/drawable/stat_sys_ra_signal_0_cdma.png
new file mode 100644
index 0000000..9a38733
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_ra_signal_0_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_ra_signal_1_cdma.png b/core/res/res/drawable/stat_sys_ra_signal_1_cdma.png
new file mode 100644
index 0000000..c70e283
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_ra_signal_1_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_ra_signal_2_cdma.png b/core/res/res/drawable/stat_sys_ra_signal_2_cdma.png
new file mode 100644
index 0000000..a09564c
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_ra_signal_2_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_ra_signal_3_cdma.png b/core/res/res/drawable/stat_sys_ra_signal_3_cdma.png
new file mode 100644
index 0000000..2637dec
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_ra_signal_3_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_ra_signal_4_cdma.png b/core/res/res/drawable/stat_sys_ra_signal_4_cdma.png
new file mode 100644
index 0000000..aba13e7
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_ra_signal_4_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_0_cdma.png b/core/res/res/drawable/stat_sys_signal_0_cdma.png
new file mode 100644
index 0000000..0ef7d53
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_0_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_1_cdma.png b/core/res/res/drawable/stat_sys_signal_1_cdma.png
new file mode 100644
index 0000000..f4839d4
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_1_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_2_cdma.png b/core/res/res/drawable/stat_sys_signal_2_cdma.png
new file mode 100644
index 0000000..e25a99c
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_2_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_3_cdma.png b/core/res/res/drawable/stat_sys_signal_3_cdma.png
new file mode 100644
index 0000000..d828d99
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_3_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_signal_4_cdma.png b/core/res/res/drawable/stat_sys_signal_4_cdma.png
new file mode 100644
index 0000000..53a31ea
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_signal_4_cdma.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_tty_mode.png b/core/res/res/drawable/stat_sys_tty_mode.png
new file mode 100644
index 0000000..ed157a8
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_tty_mode.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_vp_phone_call.png b/core/res/res/drawable/stat_sys_vp_phone_call.png
new file mode 100644
index 0000000..aa03b4f5
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_vp_phone_call.png
Binary files differ
diff --git a/core/res/res/drawable/stat_sys_vp_phone_call_on_hold.png b/core/res/res/drawable/stat_sys_vp_phone_call_on_hold.png
new file mode 100644
index 0000000..5f45440
--- /dev/null
+++ b/core/res/res/drawable/stat_sys_vp_phone_call_on_hold.png
Binary files differ
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 06e752a..d84778e 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1099,4 +1099,12 @@
    <public type="anim" name="anticipate_overshoot_interpolator" id="0x010a0009" />
    <public type="anim" name="bounce_interpolator" id="0x010a000a" />
 
+  <public type="drawable" name="stat_sys_vp_phone_call" id="0x0108022d" />
+  <public type="drawable" name="stat_sys_vp_phone_call_on_hold" id="0x0108022e" />
+
 </resources>
+
+
+
+
+
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index e0bc9d2..4cd0168 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -97,6 +97,12 @@
     <string name="PwdMmi">Password change</string>
     <!-- Displayed as the title for a success/failure report changing the SIM PIN. -->
     <string name="PinMmi">PIN change</string>
+    <string name="CnipMmi">Calling number present</string>
+    <string name="CnirMmi">Calling number restricted</string>
+    <string name="ThreeWCMmi">Three way calling</string>
+    <string name="RuacMmi">Rejection of undesired annoying calls</string>
+    <string name="CndMmi">Calling number delivery</string>
+    <string name="DndMmi">Do not disturb</string>
 
     <!-- Displayed to confirm to the user that caller ID will be restricted on the next call as usual. -->
     <string name="CLIRDefaultOnNextCallOn">Caller ID defaults to restricted. Next call: Restricted</string>
@@ -2290,6 +2296,7 @@
     <!-- Shown in the tutorial for tap twice for zoom control. -->
     <string name="tutorial_double_tap_to_zoom_message_short">Tap twice for zoom control</string>
 
+
     <!-- Shown in gadget hosts (e.g. the home screen) when there was an error inflating
     the gadget. -->
     <string name="gadget_host_error_inflating">Error inflating widget</string>
@@ -2316,6 +2323,7 @@
          ContactsProvider and GoogleContactsProvider -->
     <skip />
 
+
     <!-- This string appears (on two lines) when you type a number into contacts search, to let you dial the phone number you typed.  The first line will be in bigger type than the second. -->
     <string name="dial_number_using">Dial number\nusing <xliff:g id="number" example="555">%s</xliff:g></string>
 
@@ -2326,3 +2334,8 @@
     <string-array translatable="false" name="carrier_locales">
     </string-array>    
 </resources>
+
+
+
+
+
diff --git a/location/java/com/android/internal/location/CellState.java b/location/java/com/android/internal/location/CellState.java
index eb6535e..ad89f85 100644
--- a/location/java/com/android/internal/location/CellState.java
+++ b/location/java/com/android/internal/location/CellState.java
@@ -60,9 +60,11 @@
     }
 
     public CellState(TelephonyManager telephonyManager, CellLocation location, int signalStrength) {
-        GsmCellLocation loc = (GsmCellLocation)location;
-        mLac = loc.getLac(); // example: 6032
-        mCid = loc.getCid(); // example: 31792
+        if (location instanceof GsmCellLocation) {
+            GsmCellLocation loc = (GsmCellLocation)location;
+            mLac = loc.getLac(); // example: 6032
+            mCid = loc.getCid(); // example: 31792
+        }
         mTime = System.currentTimeMillis();
 
         // Get radio type
@@ -72,6 +74,11 @@
             mRadioType = RADIO_TYPE_GPRS;
         } else if (radioType == TelephonyManager.NETWORK_TYPE_UMTS) {
             mRadioType = RADIO_TYPE_WCDMA;
+        } else if (radioType == TelephonyManager.NETWORK_TYPE_CDMA ||
+                radioType == TelephonyManager.NETWORK_TYPE_EVDO_0 ||
+                radioType == TelephonyManager.NETWORK_TYPE_EVDO_A ||
+                radioType == TelephonyManager.NETWORK_TYPE_1xRTT) {
+            mRadioType = RADIO_TYPE_CDMA;
         }
 
         // Get neighboring cells
@@ -290,3 +297,4 @@
         }
     }
 }
+
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index d39934b..b9d567c 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -38,6 +38,7 @@
 import android.util.Log;
 import android.util.Xml;
 import com.android.internal.util.XmlUtils;
+import com.android.internal.telephony.RILConstants;
 
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.LockPatternView;
@@ -175,7 +176,8 @@
                 // Shortcuts, applications, folders
                 db.execSQL("UPDATE favorites SET spanX=1, spanY=1 WHERE itemType<=0");
                 // Photo frames, clocks
-                db.execSQL("UPDATE favorites SET spanX=2, spanY=2 WHERE itemType=1000 or itemType=1002");
+                db.execSQL(
+                    "UPDATE favorites SET spanX=2, spanY=2 WHERE itemType=1000 or itemType=1002");
                 // Search boxes
                 db.execSQL("UPDATE favorites SET spanX=4, spanY=1 WHERE itemType=1001");
                 db.setTransactionSuccessful();
@@ -582,6 +584,8 @@
                 + " VALUES(?,?);");
         
         Resources r = mContext.getResources();
+        loadSetting(stmt, Settings.Secure.CURRENT_ACTIVE_PHONE,
+                RILConstants.CDMA_PHONE);
         loadBooleanSetting(stmt, Settings.System.DIM_SCREEN,
                 R.bool.def_dim_screen);
         loadSetting(stmt, Settings.System.STAY_ON_WHILE_PLUGGED_IN, 
@@ -655,6 +659,18 @@
             loadSetting(stmt, Settings.Secure.WIFI_WATCHDOG_WATCH_LIST, wifiWatchList);
         }
 
+        // Set the preferred network mode to 0 = Global, CDMA default
+        loadSetting(stmt, Settings.Secure.PREFERRED_NETWORK_MODE, 
+                RILConstants.PREFERRED_NETWORK_MODE);
+
+        // Enable or disable Cell Broadcast SMS
+        loadSetting(stmt, Settings.Secure.CDMA_CELL_BROADCAST_SMS,
+                RILConstants.CDMA_CELL_BROADCAST_SMS_DISABLED);
+
+        // Set the preferred cdma subscription to 0 = Subscription from RUIM, when available
+        loadSetting(stmt, Settings.Secure.PREFERRED_CDMA_SUBSCRIPTION, 
+                RILConstants.PREFERRED_CDMA_SUBSCRIPTION);
+
         // Don't do this.  The SystemServer will initialize ADB_ENABLED from a
         // persistent system property instead.
         //loadSetting(stmt, Settings.Secure.ADB_ENABLED, 0);
@@ -691,3 +707,4 @@
                 Float.toString(mContext.getResources().getFraction(resid, base, base)));
     }
 }
+
diff --git a/preloaded-classes b/preloaded-classes
index e3197b41..7d719e9 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -300,8 +300,8 @@
 android.telephony.PhoneStateListener
 android.telephony.ServiceState
 android.telephony.TelephonyManager
-android.telephony.gsm.SmsManager
-android.telephony.gsm.SmsMessage
+android.telephony.SmsManager
+android.telephony.SmsMessage
 android.text.AutoText
 android.text.BoringLayout
 android.text.BoringLayout$Metrics
@@ -453,17 +453,22 @@
 android.view.inputmethod.BaseInputConnection
 android.view.inputmethod.CompletionInfo
 android.view.inputmethod.CompletionInfo$1
+
 android.view.inputmethod.EditorInfo
 android.view.inputmethod.EditorInfo$1
+
 android.view.inputmethod.ExtractedText
 android.view.inputmethod.ExtractedText$1
+
 android.view.inputmethod.ExtractedTextRequest
 android.view.inputmethod.ExtractedTextRequest$1
+
 android.view.inputmethod.InputBinding
 android.view.inputmethod.InputBinding$1
 android.view.inputmethod.InputConnection
 android.view.inputmethod.InputMethod
 android.view.inputmethod.InputMethod$SessionCallback
+
 android.view.inputmethod.InputMethodInfo
 android.view.inputmethod.InputMethodInfo$1
 android.view.inputmethod.InputMethodManager
@@ -471,6 +476,7 @@
 android.view.inputmethod.InputMethodManager$2
 android.view.inputmethod.InputMethodManager$ControlledInputConnectionWrapper
 android.view.inputmethod.InputMethodManager$H
+
 android.view.inputmethod.InputMethodSession
 android.view.inputmethod.InputMethodSession$EventCallback
 android.webkit.BrowserFrame
@@ -629,50 +635,59 @@
 com.android.internal.telephony.Phone$SuppService
 com.android.internal.telephony.PhoneBase
 com.android.internal.telephony.PhoneStateIntentReceiver
-com.android.internal.telephony.SimCard$State
-com.android.internal.telephony.gsm.BaseCommands
-com.android.internal.telephony.gsm.CallForwardInfo
-com.android.internal.telephony.gsm.CommandsInterface
-com.android.internal.telephony.gsm.DriverCall
-com.android.internal.telephony.gsm.DriverCall$State
-com.android.internal.telephony.gsm.GSMConnection
+com.android.internal.telephony.IccCard$State
+com.android.internal.telephony.BaseCommands
+com.android.internal.telephony.CallForwardInfo
+com.android.internal.telephony.CommandsInterface
+com.android.internal.telephony.DriverCall
+com.android.internal.telephony.DriverCall$State
+com.android.internal.telephony.gsm.GsmConnection
 com.android.internal.telephony.gsm.GSMPhone
-com.android.internal.telephony.gsm.GsmAlphabet
+com.android.internal.telephony.GsmAlphabet
 com.android.internal.telephony.gsm.GsmMmiCode
-com.android.internal.telephony.gsm.GsmSimCard
-com.android.internal.telephony.gsm.ISms$Stub
-com.android.internal.telephony.gsm.PdpConnection$PdpFailCause
-com.android.internal.telephony.gsm.RIL
-com.android.internal.telephony.gsm.ServiceStateTracker
+com.android.internal.telephony.gsm.SimCard
+com.android.internal.telephony.ISms$Stub
+com.android.internal.telephony.RIL
+com.android.internal.telephony.ServiceStateTracker
+
 com.android.internal.telephony.gsm.stk.ComprehensionTlvTag
 com.android.internal.telephony.gsm.stk.ResultCode
 com.android.internal.util.FastXmlSerializer
 com.android.internal.view.IInputConnectionWrapper
 com.android.internal.view.IInputConnectionWrapper$MyHandler
 com.android.internal.view.IInputConnectionWrapper$SomeArgs
+
 com.android.internal.view.IInputContext
 com.android.internal.view.IInputContext$Stub
 com.android.internal.view.IInputContext$Stub$Proxy
+
 com.android.internal.view.IInputContextCallback
 com.android.internal.view.IInputContextCallback$Stub
 com.android.internal.view.IInputContextCallback$Stub$Proxy
+
 com.android.internal.view.IInputMethod
 com.android.internal.view.IInputMethod$Stub
 com.android.internal.view.IInputMethod$Stub$Proxy
+
 com.android.internal.view.IInputMethodCallback
 com.android.internal.view.IInputMethodCallback$Stub
 com.android.internal.view.IInputMethodCallback$Stub$Proxy
+
 com.android.internal.view.IInputMethodClient
 com.android.internal.view.IInputMethodClient$Stub
 com.android.internal.view.IInputMethodClient$Stub$Proxy
+
 com.android.internal.view.IInputMethodManager
 com.android.internal.view.IInputMethodManager$Stub
 com.android.internal.view.IInputMethodManager$Stub$Proxy
+
 com.android.internal.view.IInputMethodSession
 com.android.internal.view.IInputMethodSession$Stub
 com.android.internal.view.IInputMethodSession$Stub$Proxy
+
 com.android.internal.view.InputBindResult
 com.android.internal.view.InputBindResult$1
+
 com.android.internal.view.InputConnectionWrapper
 com.android.internal.view.InputConnectionWrapper$InputContextCallback
 com.android.internal.view.menu.ExpandedMenuView
@@ -1165,3 +1180,4 @@
 org.xmlpull.v1.XmlPullParserFactory
 org.xmlpull.v1.sax2.Driver
 sun.misc.Unsafe
+
diff --git a/services/java/com/android/server/status/StatusBarPolicy.java b/services/java/com/android/server/status/StatusBarPolicy.java
index 713cd13..0b161d6 100644
--- a/services/java/com/android/server/status/StatusBarPolicy.java
+++ b/services/java/com/android/server/status/StatusBarPolicy.java
@@ -16,13 +16,6 @@
 
 package com.android.server.status;
 
-import com.android.internal.R;
-import com.android.internal.app.IBatteryStats;
-import com.android.internal.location.GpsLocationProvider;
-import com.android.internal.telephony.SimCard;
-import com.android.internal.telephony.TelephonyIntents;
-import com.android.server.am.BatteryStatsService;
-
 import android.app.AlertDialog;
 import android.bluetooth.BluetoothA2dp;
 import android.bluetooth.BluetoothDevice;
@@ -59,6 +52,14 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import com.android.internal.R;
+import com.android.internal.app.IBatteryStats;
+import com.android.internal.location.GpsLocationProvider;
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.cdma.TtyIntent;
+import com.android.server.am.BatteryStatsService;
+
 import java.util.Calendar;
 import java.util.TimeZone;
 
@@ -110,7 +111,10 @@
     // phone
     private TelephonyManager mPhone;
     private IBinder mPhoneIcon;
+
+    //***** Signal strength icons
     private IconData mPhoneData;
+    //GSM/UMTS
     private static final int[] sSignalImages = new int[] {
             com.android.internal.R.drawable.stat_sys_signal_0,
             com.android.internal.R.drawable.stat_sys_signal_1,
@@ -125,7 +129,32 @@
             com.android.internal.R.drawable.stat_sys_r_signal_3,
             com.android.internal.R.drawable.stat_sys_r_signal_4
         };
+    //CDMA
+    private static final int[] sSignalImages_cdma = new int[] {
+        com.android.internal.R.drawable.stat_sys_signal_0_cdma,
+        com.android.internal.R.drawable.stat_sys_signal_1_cdma,
+        com.android.internal.R.drawable.stat_sys_signal_2_cdma,
+        com.android.internal.R.drawable.stat_sys_signal_3_cdma,
+        com.android.internal.R.drawable.stat_sys_signal_4_cdma
+    };
+    private static final int[] sSignalImages_r_cdma = new int[] {
+        com.android.internal.R.drawable.stat_sys_r_signal_0_cdma,
+        com.android.internal.R.drawable.stat_sys_r_signal_1_cdma,
+        com.android.internal.R.drawable.stat_sys_r_signal_2_cdma,
+        com.android.internal.R.drawable.stat_sys_r_signal_3_cdma,
+        com.android.internal.R.drawable.stat_sys_r_signal_4_cdma
+    };
+    private static final int[] sSignalImages_ra_cdma = new int[] {
+        com.android.internal.R.drawable.stat_sys_ra_signal_0_cdma,
+        com.android.internal.R.drawable.stat_sys_ra_signal_1_cdma,
+        com.android.internal.R.drawable.stat_sys_ra_signal_2_cdma,
+        com.android.internal.R.drawable.stat_sys_ra_signal_3_cdma,
+        com.android.internal.R.drawable.stat_sys_ra_signal_4_cdma
+    };
+
+    //***** Data connection icons
     private int[] mDataIconList = sDataNetType_g;
+    //GSM/UMTS
     private static final int[] sDataNetType_g = new int[] {
             com.android.internal.R.drawable.stat_sys_data_connected_g,
             com.android.internal.R.drawable.stat_sys_data_in_g,
@@ -144,12 +173,25 @@
             com.android.internal.R.drawable.stat_sys_data_out_e,
             com.android.internal.R.drawable.stat_sys_data_inandout_e,
         };
+    //CDMA
+    private static final int[] sDataNetType_evdo = new int[] {
+        com.android.internal.R.drawable.stat_sys_data_connected_evdo,
+        com.android.internal.R.drawable.stat_sys_data_in_evdo,
+        com.android.internal.R.drawable.stat_sys_data_out_evdo,
+        com.android.internal.R.drawable.stat_sys_data_inandout_evdo,
+    };
+    private static final int[] sDataNetType_1xrtt = new int[] {
+        com.android.internal.R.drawable.stat_sys_data_connected_1xrtt,
+        com.android.internal.R.drawable.stat_sys_data_in_1xrtt,
+        com.android.internal.R.drawable.stat_sys_data_out_1xrtt,
+        com.android.internal.R.drawable.stat_sys_data_inandout_1xrtt,
+    };
+
     // Assume it's all good unless we hear otherwise.  We don't always seem
     // to get broadcasts that it *is* there.
-    SimCard.State mSimState = SimCard.State.READY;
+    IccCard.State mSimState = IccCard.State.READY;
     int mPhoneState = TelephonyManager.CALL_STATE_IDLE;
     int mDataState = TelephonyManager.DATA_DISCONNECTED;
-    int mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
     int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
     ServiceState mServiceState;
     int mSignalAsu = -1;
@@ -163,7 +205,7 @@
     private IBinder mVolumeIcon;
     private IconData mVolumeData;
     private boolean mVolumeVisible;
-    
+
     // bluetooth device status
     private IBinder mBluetoothIcon;
     private IconData mBluetoothData;
@@ -202,6 +244,11 @@
     private IBinder mSyncActiveIcon;
     private IBinder mSyncFailingIcon;
 
+    // TTY mode
+    // Icon lit when TTY mode is enabled
+    private IBinder mTTYModeIcon;
+    private IconData mTTYModeEnableIconData;
+
     private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -250,6 +297,9 @@
             else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
                 updateSimState(intent);
             }
+            else if (action.equals(TtyIntent.TTY_ENABLED_CHANGE_ACTION)) {
+                updateTTY(intent);
+            }
         }
     };
 
@@ -294,7 +344,13 @@
         mWifiIcon = service.addIcon(mWifiData, null);
         service.setIconVisibility(mWifiIcon, false);
         // wifi will get updated by the sticky intents
-        
+
+        // TTY status
+        mTTYModeEnableIconData = IconData.makeIcon("tty",
+                null, com.android.internal.R.drawable.stat_sys_tty_mode, 0, 0);
+        mTTYModeIcon = service.addIcon(mTTYModeEnableIconData, null);
+        service.setIconVisibility(mTTYModeIcon, false);
+
         // bluetooth status
         mBluetoothData = IconData.makeIcon("bluetooth",
                 null, com.android.internal.R.drawable.stat_sys_data_bluetooth, 0, 0);
@@ -362,6 +418,7 @@
         filter.addAction(GpsLocationProvider.GPS_ENABLED_CHANGE_ACTION);
         filter.addAction(GpsLocationProvider.GPS_FIX_CHANGE_ACTION);
         filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+        filter.addAction(TtyIntent.TTY_ENABLED_CHANGE_ACTION);
         mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
     }
 
@@ -506,7 +563,7 @@
                 com.android.internal.R.styleable.Theme);
         lp.dimAmount = a.getFloat(android.R.styleable.Theme_backgroundDimAmount, 0.5f);
         a.recycle();
-        
+
         lp.setTitle("Battery");
 
         TextView levelTextView = (TextView)v.findViewById(com.android.internal.R.id.level_percent);
@@ -642,26 +699,26 @@
     
 
     private final void updateSimState(Intent intent) {
-        String stateExtra = intent.getStringExtra(SimCard.INTENT_KEY_SIM_STATE);
-        if (SimCard.INTENT_VALUE_SIM_ABSENT.equals(stateExtra)) {
-            mSimState = SimCard.State.ABSENT;
+        String stateExtra = intent.getStringExtra(IccCard.INTENT_KEY_ICC_STATE);
+        if (IccCard.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
+            mSimState = IccCard.State.ABSENT;
         }
-        else if (SimCard.INTENT_VALUE_SIM_READY.equals(stateExtra)) {
-            mSimState = SimCard.State.READY;
+        else if (IccCard.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
+            mSimState = IccCard.State.READY;
         }
-        else if (SimCard.INTENT_VALUE_SIM_LOCKED.equals(stateExtra)) {
-            final String lockedReason = intent.getStringExtra(SimCard.INTENT_KEY_LOCKED_REASON);
-            if (SimCard.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
-                mSimState = SimCard.State.PIN_REQUIRED;
+        else if (IccCard.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
+            final String lockedReason = intent.getStringExtra(IccCard.INTENT_KEY_LOCKED_REASON);
+            if (IccCard.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
+                mSimState = IccCard.State.PIN_REQUIRED;
             } 
-            else if (SimCard.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
-                mSimState = SimCard.State.PUK_REQUIRED;
+            else if (IccCard.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
+                mSimState = IccCard.State.PUK_REQUIRED;
             }
             else {
-                mSimState = SimCard.State.NETWORK_LOCKED;
+                mSimState = IccCard.State.NETWORK_LOCKED;
             }
         } else {
-            mSimState = SimCard.State.UNKNOWN;
+            mSimState = IccCard.State.UNKNOWN;
         }
         updateDataIcon();
     }
@@ -707,28 +764,54 @@
         else asu = 1;
 
         int[] iconList;
-        if (mPhone.isNetworkRoaming()) {
+        if (mPhone.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
+            switch(ss.getExtendedCdmaRoaming()) {
+            case ServiceState.REGISTRATION_STATE_ROAMING:
+                iconList = this.sSignalImages_r_cdma;
+                break;
+            case ServiceState.REGISTRATION_STATE_ROAMING_AFFILIATE:
+                iconList = this.sSignalImages_ra_cdma;
+                break;
+            default:
+                iconList = this.sSignalImages_cdma;
+            break;
+            }
+        } else if (mPhone.isNetworkRoaming()) {
             iconList = sSignalImages_r;
         } else {
             iconList = sSignalImages;
         }
-        
+
         mPhoneData.iconId = iconList[asu];
         mService.updateIcon(mPhoneIcon, mPhoneData, null);
     }
 
     private final void updateDataNetType() {
-        mDataNetType = mPhone.getNetworkType();
-        switch (mDataNetType) {
-            case TelephonyManager.NETWORK_TYPE_EDGE:
-                mDataIconList = sDataNetType_e;
-                break;
-            case TelephonyManager.NETWORK_TYPE_UMTS:
-                mDataIconList = sDataNetType_3g;
-                break;
-            default:
-                mDataIconList = sDataNetType_g;
-                break;
+        int net = mPhone.getNetworkType();
+        ServiceState ss = this.mServiceState;
+
+        switch (net) {
+
+        case TelephonyManager.NETWORK_TYPE_EDGE:
+            mDataIconList = sDataNetType_e;
+            break;
+        case TelephonyManager.NETWORK_TYPE_UMTS:
+            mDataIconList = sDataNetType_3g;
+            break;
+        case TelephonyManager.NETWORK_TYPE_CDMA:
+            // display 1xRTT for IS95A/B
+            mDataIconList = this.sDataNetType_1xrtt;
+            break;
+        case TelephonyManager.NETWORK_TYPE_1xRTT:
+            mDataIconList = this.sDataNetType_1xrtt;
+            break;
+        case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through
+        case TelephonyManager.NETWORK_TYPE_EVDO_A:
+            mDataIconList = sDataNetType_evdo;
+            break;
+        default:
+            mDataIconList = sDataNetType_g;
+        break;
         }
     }
 
@@ -736,9 +819,9 @@
         int iconId;
         boolean visible = true;
 
-        if (mSimState == SimCard.State.READY || mSimState == SimCard.State.UNKNOWN) {
+        if (mSimState == IccCard.State.READY || mSimState == IccCard.State.UNKNOWN) {
             int data = mDataState;
-            
+
             int[] list = mDataIconList;
 
             ServiceState ss = mServiceState;
@@ -775,7 +858,7 @@
         }
         long ident = Binder.clearCallingIdentity();
         try {
-            mBatteryStats.notePhoneDataConnectionState(mDataNetType, visible);
+            mBatteryStats.notePhoneDataConnectionState(mPhone.getNetworkType(), visible);
         } catch (RemoteException e) {
         } finally {
             Binder.restoreCallingIdentity(ident);
@@ -865,10 +948,10 @@
                 } else {
                     iconId = sWifiSignalImages[mLastWifiSignalLevel];
                 }
-                
+
                 // Show the icon since wi-fi is connected
                 mService.setIconVisibility(mWifiIcon, true);
-                
+
             } else {
                 mLastWifiSignalLevel = -1;
                 mIsWifiConnected = false;
@@ -914,6 +997,24 @@
         }
     }
 
+    private final void updateTTY(Intent intent) {       
+        final String action = intent.getAction();
+        final boolean enabled = intent.getBooleanExtra(TtyIntent.TTY_ENABLED, false);
+
+        Log.i(TAG, "updateTTY: enabled: " + enabled);
+
+        if (enabled) {
+            // TTY is on
+            Log.i(TAG, "updateTTY: set TTY on");
+            mService.updateIcon(mTTYModeIcon, mTTYModeEnableIconData, null);
+            mService.setIconVisibility(mTTYModeIcon, true);          
+        } else {
+            // TTY is off
+            Log.i(TAG, "updateTTY: set TTY off");
+            mService.setIconVisibility(mTTYModeIcon, false);           
+        }
+    }
+
     private class StatusBarHandler extends Handler {
         @Override
         public void handleMessage(Message msg) {
@@ -927,3 +1028,6 @@
         }
     }
 }
+
+
+
diff --git a/telephony/java/android/telephony/CellLocation.java b/telephony/java/android/telephony/CellLocation.java
index 464085f..dd98608 100644
--- a/telephony/java/android/telephony/CellLocation.java
+++ b/telephony/java/android/telephony/CellLocation.java
@@ -19,8 +19,14 @@
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.SystemProperties;
+import android.provider.Settings;
+
+
+import android.telephony.cdma.CdmaCellLocation;
 import android.telephony.gsm.GsmCellLocation;
 import com.android.internal.telephony.ITelephony;
+import com.android.internal.telephony.RILConstants;
 
 /**
  * Abstract class that represents the location of the device.  Currently the only
@@ -56,7 +62,17 @@
      * @hide
      */
     public static CellLocation newFromBundle(Bundle bundle) {
-        return new GsmCellLocation(bundle);
+        // TODO: My need to be use: Settings.Secure.getInt(mContext, Settings.Secure.CURRENT_ACTIVE_PHONE, 0))
+        //       instead of SystemProperties???
+
+        // NOTE here TelephonyManager.getDefault().getPhoneType() cannot be used since at startup
+        //      ITelephony have not been created
+        if (RILConstants.CDMA_PHONE ==
+                SystemProperties.getInt(Settings.Secure.CURRENT_ACTIVE_PHONE, 0)) {
+            return new CdmaCellLocation(bundle);
+        } else {
+            return new GsmCellLocation(bundle);
+        }
     }
 
     /**
@@ -66,8 +82,20 @@
 
     /**
      * Return a new CellLocation object representing an unknown location.
+     *
      */
     public static CellLocation getEmpty() {
-        return new GsmCellLocation();
+        // TODO: My need to be use: Settings.Secure.getInt(mContext, Settings.Secure.CURRENT_ACTIVE_PHONE, 0))
+        //       instead of SystemProperties???
+
+        // NOTE here TelephonyManager.getDefault().getPhoneType() cannot be used since at startup
+        //      ITelephony have not been created
+        if (RILConstants.CDMA_PHONE ==
+                SystemProperties.getInt(Settings.Secure.CURRENT_ACTIVE_PHONE, 0)) {
+            return new CdmaCellLocation();
+        } else {
+            return new GsmCellLocation();
+        }
     }
+
 }
diff --git a/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java b/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
index 0bc6c04..8a47339 100644
--- a/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
+++ b/telephony/java/android/telephony/PhoneNumberFormattingTextWatcher.java
@@ -25,7 +25,7 @@
 
 /**
  * Watches a {@link TextView} and if a phone number is entered will format it using
- * {@link PhoneNumberUtils#formatNumber(Editable, int)}. The formatting is based on 
+ * {@link PhoneNumberUtils#formatNumber(Editable, int)}. The formatting is based on
  * the current system locale when this object is created and future locale changes
  * may not take effect on this instance.
  */
@@ -35,7 +35,7 @@
     static private Locale sCachedLocale;
     private boolean mFormatting;
     private boolean mDeletingHyphen;
-    private int mHyphenStart;    
+    private int mHyphenStart;
     private boolean mDeletingBackward;
 
     public PhoneNumberFormattingTextWatcher() {
@@ -60,7 +60,7 @@
                     text.delete(mHyphenStart, mHyphenStart + 1);
                 }
             }
-            
+
             PhoneNumberUtils.formatNumber(text, sFormatType);
 
             mFormatting = false;
@@ -73,8 +73,8 @@
             // Make sure user is deleting one char, without a selection
             final int selStart = Selection.getSelectionStart(s);
             final int selEnd = Selection.getSelectionEnd(s);
-            if (s.length() > 1 // Can delete another character 
-                    && count == 1 // Deleting only one character 
+            if (s.length() > 1 // Can delete another character
+                    && count == 1 // Deleting only one character
                     && after == 0 // Deleting
                     && s.charAt(start) == '-' // a hyphen
                     && selStart == selEnd) { // no selection
@@ -89,7 +89,7 @@
             } else {
                 mDeletingHyphen = false;
             }
-        }        
+        }
     }
 
     public void onTextChanged(CharSequence s, int start, int before, int count) {
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index 8a8a675e7..df6860b 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -11,18 +11,18 @@
 
 /**
  * A listener class for monitoring changes in specific telephony states
- * on the device, including service state, signal strength, message 
+ * on the device, including service state, signal strength, message
  * waiting indicator (voicemail), and others.
  * <p>
- * Override the methods for the state that you wish to receive updates for, and 
+ * Override the methods for the state that you wish to receive updates for, and
  * pass your PhoneStateListener object, along with bitwise-or of the LISTEN_
  * flags to {@link TelephonyManager#listen TelephonyManager.listen()}.
  * <p>
  * Note that access to some telephony information is
- * permission-protected. Your application won't receive updates for protected 
- * information unless it has the appropriate permissions declared in 
+ * permission-protected. Your application won't receive updates for protected
+ * information unless it has the appropriate permissions declared in
  * its manifest file. Where permissions apply, they are noted in the
- * appropriate LISTEN_ flags. 
+ * appropriate LISTEN_ flags.
  */
 public class PhoneStateListener {
 
@@ -67,17 +67,17 @@
     public static final int LISTEN_CALL_FORWARDING_INDICATOR                = 0x00000008;
 
     /**
-     * Listen for changes to the device's cell location. Note that 
+     * Listen for changes to the device's cell location. Note that
      * this will result in frequent callbacks to the listener.
      * {@more}
      * Requires Permission: {@link android.Manifest.permission#ACCESS_COARSE_LOCATION
      * ACCESS_COARSE_LOCATION}
      * <p>
-     * If you need regular location updates but want more control over 
-     * the update interval or location precision, you can set up a listener 
-     * through the {@link android.location.LocationManager location manager} 
-     * instead. 
-     * 
+     * If you need regular location updates but want more control over
+     * the update interval or location precision, you can set up a listener
+     * through the {@link android.location.LocationManager location manager}
+     * instead.
+     *
      * @see #onCellLocationChanged
      */
     public static final int LISTEN_CELL_LOCATION                            = 0x00000010;
@@ -100,7 +100,7 @@
      * Listen for changes to the direction of data traffic on the data
      * connection (cellular).
      *
-     * Example: The status bar uses this to display the appropriate  
+     * Example: The status bar uses this to display the appropriate
      * data-traffic icon.
      *
      * @see #onDataActivity
@@ -111,7 +111,7 @@
     }
 
     /**
-     * Callback invoked when device service state changes. 
+     * Callback invoked when device service state changes.
      *
      * @see ServiceState#STATE_EMERGENCY_ONLY
      * @see ServiceState#STATE_IN_SERVICE
@@ -135,28 +135,28 @@
     }
 
     /**
-     * Callback invoked when the message-waiting indicator changes. 
+     * Callback invoked when the message-waiting indicator changes.
      */
     public void onMessageWaitingIndicatorChanged(boolean mwi) {
         // default implementation empty
     }
 
     /**
-     * Callback invoked when the call-forwarding indicator changes. 
+     * Callback invoked when the call-forwarding indicator changes.
      */
     public void onCallForwardingIndicatorChanged(boolean cfi) {
         // default implementation empty
     }
 
     /**
-     * Callback invoked when device cell location changes. 
+     * Callback invoked when device cell location changes.
      */
     public void onCellLocationChanged(CellLocation location) {
         // default implementation empty
     }
 
     /**
-     * Callback invoked when device call state changes. 
+     * Callback invoked when device call state changes.
      *
      * @see TelephonyManager#CALL_STATE_IDLE
      * @see TelephonyManager#CALL_STATE_RINGING
@@ -167,7 +167,7 @@
     }
 
     /**
-     * Callback invoked when connection state changes. 
+     * Callback invoked when connection state changes.
      *
      * @see TelephonyManager#DATA_DISCONNECTED
      * @see TelephonyManager#DATA_CONNECTING
@@ -179,7 +179,7 @@
     }
 
     /**
-     * Callback invoked when data activity state changes. 
+     * Callback invoked when data activity state changes.
      *
      * @see TelephonyManager#DATA_ACTIVITY_NONE
      * @see TelephonyManager#DATA_ACTIVITY_IN
diff --git a/telephony/java/android/telephony/ServiceState.aidl b/telephony/java/android/telephony/ServiceState.aidl
index b1cf379..8522889 100644
--- a/telephony/java/android/telephony/ServiceState.aidl
+++ b/telephony/java/android/telephony/ServiceState.aidl
@@ -2,16 +2,16 @@
 **
 ** Copyright 2007, 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 
+** 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 
+**     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 
+** 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.
 */
 
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 2c58051..4de0954 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -19,7 +19,7 @@
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
-import com.android.internal.telephony.Phone;
+import android.util.Log;
 
 /**
  * Contains phone state and service related information.
@@ -35,6 +35,8 @@
  */
 public class ServiceState implements Parcelable {
 
+    static final String LOG_TAG = "PHONE";
+
     /**
      * Normal operation condition, the phone is registered
      * with an operator either in home network or in roaming.
@@ -59,13 +61,61 @@
      */
     public static final int STATE_POWER_OFF = 3;
 
+
+    /**
+     * Available radio technologies for GSM, UMTS and CDMA.
+     */
+    /** @hide */
+    public static final int RADIO_TECHNOLOGY_UNKNOWN = 0;
+    /** @hide */
+    public static final int RADIO_TECHNOLOGY_GPRS = 1;
+    /** @hide */
+    public static final int RADIO_TECHNOLOGY_EDGE = 2;
+    /** @hide */
+    public static final int RADIO_TECHNOLOGY_UMTS = 3;
+    /** @hide */
+    public static final int RADIO_TECHNOLOGY_IS95A = 4;
+    /** @hide */
+    public static final int RADIO_TECHNOLOGY_IS95B = 5;
+    /** @hide */
+    public static final int RADIO_TECHNOLOGY_1xRTT = 6;
+    /** @hide */
+    public static final int RADIO_TECHNOLOGY_EVDO_0 = 7;
+    /** @hide */
+    public static final int RADIO_TECHNOLOGY_EVDO_A = 8;
+
+    /**
+     * Available registration states for GSM, UMTS and CDMA.
+     */
+    /** @hide */
+    public static final int REGISTRATION_STATE_NOT_REGISTERED_AND_NOT_SEARCHING = 0;
+    /** @hide */
+    public static final int REGISTRATION_STATE_HOME_NETWORK = 1;
+    /** @hide */
+    public static final int REGISTRATION_STATE_NOT_REGISTERED_AND_SEARCHING = 2;
+    /** @hide */
+    public static final int REGISTRATION_STATE_REGISTRATION_DENIED = 3;
+    /** @hide */
+    public static final int REGISTRATION_STATE_UNKNOWN = 4;
+    /** @hide */
+    public static final int REGISTRATION_STATE_ROAMING = 5;
+    /** @hide */
+    public static final int REGISTRATION_STATE_ROAMING_AFFILIATE = 6;
+
     private int mState = STATE_OUT_OF_SERVICE;
     private boolean mRoaming;
+    private int mExtendedCdmaRoaming;
     private String mOperatorAlphaLong;
     private String mOperatorAlphaShort;
     private String mOperatorNumeric;
     private boolean mIsManualNetworkSelection;
 
+    //***** CDMA
+    private int mRadioTechnology;
+    private boolean mCssIndicator;
+    private int mNetworkId;
+    private int mSystemId;
+
     /**
      * Create a new ServiceState from a intent notifier Bundle
      *
@@ -105,6 +155,11 @@
         mOperatorAlphaShort = s.mOperatorAlphaShort;
         mOperatorNumeric = s.mOperatorNumeric;
         mIsManualNetworkSelection = s.mIsManualNetworkSelection;
+        mRadioTechnology = s.mRadioTechnology;
+        mCssIndicator = s.mCssIndicator;
+        mNetworkId = s.mNetworkId;
+        mSystemId = s.mSystemId;
+        mExtendedCdmaRoaming = s.mExtendedCdmaRoaming;
     }
 
     /**
@@ -117,6 +172,11 @@
         mOperatorAlphaShort = in.readString();
         mOperatorNumeric = in.readString();
         mIsManualNetworkSelection = in.readInt() != 0;
+        mRadioTechnology = in.readInt();
+        mCssIndicator = (in.readInt() != 0);
+        mNetworkId = in.readInt();
+        mSystemId = in.readInt();
+        mExtendedCdmaRoaming = in.readInt();
     }
 
     public void writeToParcel(Parcel out, int flags) {
@@ -126,6 +186,11 @@
         out.writeString(mOperatorAlphaShort);
         out.writeString(mOperatorNumeric);
         out.writeInt(mIsManualNetworkSelection ? 1 : 0);
+        out.writeInt(mRadioTechnology);
+        out.writeInt(mCssIndicator ? 1 : 0);
+        out.writeInt(mNetworkId);
+        out.writeInt(mSystemId);
+        out.writeInt(mExtendedCdmaRoaming);
     }
 
     public int describeContents() {
@@ -166,6 +231,11 @@
         return mRoaming;
     }
 
+    /** @hide */
+    public int getExtendedCdmaRoaming(){
+        return this.mExtendedCdmaRoaming;
+    }
+
     /**
      * Get current registered operator name in long alphanumeric format
      *
@@ -213,18 +283,19 @@
 
     @Override
     public int hashCode() {
-        return (mState * 0x1234)
+        return ((mState * 0x1234)
                 + (mRoaming ? 1 : 0)
                 + (mIsManualNetworkSelection ? 1 : 0)
                 + ((null == mOperatorAlphaLong) ? 0 : mOperatorAlphaLong.hashCode())
                 + ((null == mOperatorAlphaShort) ? 0 : mOperatorAlphaShort.hashCode())
-                + ((null == mOperatorNumeric) ? 0 : mOperatorNumeric.hashCode());
+                + ((null == mOperatorNumeric) ? 0 : mOperatorNumeric.hashCode())
+                + (mExtendedCdmaRoaming));
     }
 
     @Override
     public boolean equals (Object o) {
         ServiceState s;
-        
+
         try {
             s = (ServiceState) o;
         } catch (ClassCastException ex) {
@@ -235,21 +306,66 @@
             return false;
         }
 
-        return mState == s.mState
+        return (mState == s.mState
                 && mRoaming == s.mRoaming
                 && mIsManualNetworkSelection == s.mIsManualNetworkSelection
                 && equalsHandlesNulls(mOperatorAlphaLong, s.mOperatorAlphaLong)
                 && equalsHandlesNulls(mOperatorAlphaShort, s.mOperatorAlphaShort)
-                && equalsHandlesNulls(mOperatorNumeric, s.mOperatorNumeric);
+                && equalsHandlesNulls(mOperatorNumeric, s.mOperatorNumeric)
+                && equalsHandlesNulls(mRadioTechnology, s.mRadioTechnology)
+                && equalsHandlesNulls(mCssIndicator, s.mCssIndicator)
+                && equalsHandlesNulls(mNetworkId, s.mNetworkId)
+                && equalsHandlesNulls(mSystemId, s.mSystemId)
+                && equalsHandlesNulls(mExtendedCdmaRoaming, s.mExtendedCdmaRoaming));
     }
 
     @Override
     public String toString() {
-        return mState + " " + (mRoaming ? "roaming" : "home")
+        String radioTechnology = new String("Error in radioTechnology");
+
+        switch(this.mRadioTechnology) {
+        case 0:
+            radioTechnology = "Unknown";
+            break;
+        case 1:
+            radioTechnology = "GPRS";
+            break;
+        case 2:
+            radioTechnology = "EDGE";
+            break;
+        case 3:
+            radioTechnology = "UMTS";
+            break;
+        case 4:
+            radioTechnology = "IS95A";
+            break;
+        case 5:
+            radioTechnology = "IS95B";
+            break;
+        case 6:
+            radioTechnology = "1xRTT";
+            break;
+        case 7:
+            radioTechnology = "EvDo rev. 0";
+            break;
+        case 8:
+            radioTechnology = "EvDo rev. A";
+            break;
+        default:
+            Log.w(LOG_TAG, "mRadioTechnology variable out of range.");
+        break;
+        }
+
+        return (mState + " " + (mRoaming ? "roaming" : "home")
                 + " " + mOperatorAlphaLong
                 + " " + mOperatorAlphaShort
                 + " " + mOperatorNumeric
-                + " " + (mIsManualNetworkSelection ? "(manual)" : "");
+                + " " + (mIsManualNetworkSelection ? "(manual)" : "")
+                + " " + radioTechnology
+                + " " + (mCssIndicator ? "CSS supported" : "CSS not supported")
+                + "NetworkId: " + mNetworkId
+                + "SystemId: " + mSystemId
+                + "ExtendedCdmaRoaming: " + mExtendedCdmaRoaming);
     }
 
     public void setStateOutOfService() {
@@ -259,6 +375,11 @@
         mOperatorAlphaShort = null;
         mOperatorNumeric = null;
         mIsManualNetworkSelection = false;
+        mRadioTechnology = 0;
+        mCssIndicator = false;
+        mNetworkId = -1;
+        mSystemId = -1;
+        mExtendedCdmaRoaming = -1;
     }
 
     public void setStateOff() {
@@ -268,6 +389,11 @@
         mOperatorAlphaShort = null;
         mOperatorNumeric = null;
         mIsManualNetworkSelection = false;
+        mRadioTechnology = 0;
+        mCssIndicator = false;
+        mNetworkId = -1;
+        mSystemId = -1;
+        mExtendedCdmaRoaming = -1;
     }
 
     public void setState(int state) {
@@ -278,6 +404,11 @@
         mRoaming = roaming;
     }
 
+    /** @hide */
+    public void setExtendedCdmaRoaming (int roaming) {
+        this.mExtendedCdmaRoaming = roaming;
+    }
+
     public void setOperatorName(String longName, String shortName, String numeric) {
         mOperatorAlphaLong = longName;
         mOperatorAlphaShort = shortName;
@@ -287,7 +418,7 @@
     public void setIsManualSelection(boolean isManual) {
         mIsManualNetworkSelection = isManual;
     }
-    
+
     /**
      * Test whether two objects hold the same data values or both are null
      *
@@ -312,6 +443,11 @@
         mOperatorAlphaShort = m.getString("operator-alpha-short");
         mOperatorNumeric = m.getString("operator-numeric");
         mIsManualNetworkSelection = m.getBoolean("manual");
+        mRadioTechnology = m.getInt("radioTechnology");
+        mCssIndicator = m.getBoolean("cssIndicator");
+        mNetworkId = m.getInt("networkId");
+        mSystemId = m.getInt("systemId");
+        mExtendedCdmaRoaming = m.getInt("extendedCdmaRoaming");
     }
 
     /**
@@ -327,5 +463,47 @@
         m.putString("operator-alpha-short", mOperatorAlphaShort);
         m.putString("operator-numeric", mOperatorNumeric);
         m.putBoolean("manual", Boolean.valueOf(mIsManualNetworkSelection));
+        m.putInt("radioTechnology", mRadioTechnology);
+        m.putBoolean("cssIndicator", mCssIndicator);
+        m.putInt("networkId", mNetworkId);
+        m.putInt("systemId", mSystemId);
+        m.putInt("extendedCdmaRoaming", mExtendedCdmaRoaming);
+    }
+
+    //***** CDMA
+    /** @hide */
+    public void setRadioTechnology(int state) {
+        this.mRadioTechnology = state;
+    }
+
+    /** @hide */
+    public void setCssIndicator(int css) {
+        this.mCssIndicator = (css != 0);
+    }
+
+    /** @hide */
+    public void setSystemAndNetworkId(int systemId, int networkId) {
+        this.mSystemId = systemId;
+        this.mNetworkId = networkId;
+    }
+
+    /** @hide */
+    public int getRadioTechnology() {
+        return this.mRadioTechnology;
+    }
+
+    /** @hide */
+    public int getCssIndicator() {
+        return this.mCssIndicator ? 1 : 0;
+    }
+
+    /** @hide */
+    public int getNetworkId() {
+        return this.mNetworkId;
+    }
+
+    /** @hide */
+    public int getSystemId() {
+        return this.mSystemId;
     }
 }
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
new file mode 100644
index 0000000..9395d66
--- /dev/null
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -0,0 +1,441 @@
+/*
+ * Copyright (C) 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.
+ * 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 android.telephony;
+
+import android.app.PendingIntent;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.text.TextUtils;
+
+import com.android.internal.telephony.EncodeException;
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.ISms;
+import com.android.internal.telephony.IccConstants;
+import com.android.internal.telephony.SmsRawData;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static android.telephony.SmsMessage.ENCODING_7BIT;
+import static android.telephony.SmsMessage.ENCODING_8BIT;
+import static android.telephony.SmsMessage.ENCODING_16BIT;
+import static android.telephony.SmsMessage.ENCODING_UNKNOWN;
+import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES;
+import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES_WITH_HEADER;
+import static android.telephony.SmsMessage.MAX_USER_DATA_SEPTETS;
+import static android.telephony.SmsMessage.MAX_USER_DATA_SEPTETS_WITH_HEADER;
+
+/**
+ * Manages SMS operations such as sending data, text, and pdu SMS messages.
+ * Get this object by calling the static method SmsManager.getDefault().
+ * @hide
+ */
+public final class SmsManager {
+    private static SmsManager sInstance;
+
+    /**
+     * Send a text based SMS.
+     *
+     * @param destinationAddress the address to send the message to
+     * @param scAddress is the service center address or null to use
+     *  the current default SMSC
+     * @param text the body of the message to send
+     * @param sentIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is sucessfully sent, or failed.
+     *  The result code will be <code>Activity.RESULT_OK<code> for success,
+     *  or one of these errors:
+     *  <code>RESULT_ERROR_GENERIC_FAILURE</code>
+     *  <code>RESULT_ERROR_RADIO_OFF</code>
+     *  <code>RESULT_ERROR_NULL_PDU</code>.
+     *  The per-application based SMS control checks sentIntent. If sentIntent
+     *  is NULL the caller will be checked against all unknown applications,
+     *  which cause smaller number of SMS to be sent in checking period.
+     * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is delivered to the recipient.  The
+     *  raw pdu of the status report is in the extended data ("pdu").
+     *
+     * @throws IllegalArgumentException if destinationAddress or text are empty
+     */
+    public void sendTextMessage(
+            String destinationAddress, String scAddress, String text,
+            PendingIntent sentIntent, PendingIntent deliveryIntent) {
+        if (TextUtils.isEmpty(destinationAddress)) {
+            throw new IllegalArgumentException("Invalid destinationAddress");
+        }
+
+        if (TextUtils.isEmpty(text)) {
+            throw new IllegalArgumentException("Invalid message body");
+        }
+
+        SmsMessage.SubmitPdu pdus = SmsMessage.getSubmitPdu(
+                scAddress, destinationAddress, text, (deliveryIntent != null));
+        sendRawPdu(pdus.encodedScAddress, pdus.encodedMessage, sentIntent, deliveryIntent);
+    }
+
+    /**
+     * Divide a text message into several messages, none bigger than
+     * the maximum SMS message size.
+     *
+     * @param text the original message.  Must not be null.
+     * @return an <code>ArrayList</code> of strings that, in order,
+     *   comprise the original message
+     */
+    public ArrayList<String> divideMessage(String text) {
+        int size = text.length();
+        int[] params = SmsMessage.calculateLength(text, false);
+            /* SmsMessage.calculateLength returns an int[4] with:
+             *   int[0] being the number of SMS's required,
+             *   int[1] the number of code units used,
+             *   int[2] is the number of code units remaining until the next message.
+             *   int[3] is the encoding type that should be used for the message.
+             */
+        int messageCount = params[0];
+        int encodingType = params[3];
+        ArrayList<String> result = new ArrayList<String>(messageCount);
+
+        int start = 0;
+        int limit;
+
+        if (messageCount > 1) {
+            limit = (encodingType == ENCODING_7BIT)?
+                MAX_USER_DATA_SEPTETS_WITH_HEADER: MAX_USER_DATA_BYTES_WITH_HEADER;
+        } else {
+            limit = (encodingType == ENCODING_7BIT)?
+                MAX_USER_DATA_SEPTETS: MAX_USER_DATA_BYTES;
+        }
+
+        try {
+            while (start < size) {
+                int end = GsmAlphabet.findLimitIndex(text, start, limit, encodingType);
+                result.add(text.substring(start, end));
+                start = end;
+            }
+        }
+        catch (EncodeException e) {
+            // ignore it.
+        }
+        return result;
+    }
+
+    /**
+     * Send a multi-part text based SMS.  The callee should have already
+     * divided the message into correctly sized parts by calling
+     * <code>divideMessage</code>.
+     *
+     * @param destinationAddress the address to send the message to
+     * @param scAddress is the service center address or null to use
+     *   the current default SMSC
+     * @param parts an <code>ArrayList</code> of strings that, in order,
+     *   comprise the original message
+     * @param sentIntents if not null, an <code>ArrayList</code> of
+     *   <code>PendingIntent</code>s (one for each message part) that is
+     *   broadcast when the corresponding message part has been sent.
+     *   The result code will be <code>Activity.RESULT_OK<code> for success,
+     *   or one of these errors:
+     *   <code>RESULT_ERROR_GENERIC_FAILURE</code>
+     *   <code>RESULT_ERROR_RADIO_OFF</code>
+     *   <code>RESULT_ERROR_NULL_PDU</code>.
+     *   The per-application based SMS control checks sentIntent. If sentIntent
+     *   is NULL the caller will be checked against all unknown applicaitons,
+     *   which cause smaller number of SMS to be sent in checking period.
+     * @param deliveryIntents if not null, an <code>ArrayList</code> of
+     *   <code>PendingIntent</code>s (one for each message part) that is
+     *   broadcast when the corresponding message part has been delivered
+     *   to the recipient.  The raw pdu of the status report is in the
+     *   extended data ("pdu").
+     *
+     * @throws IllegalArgumentException if destinationAddress or data are empty
+     */
+    public void sendMultipartTextMessage(
+            String destinationAddress, String scAddress, ArrayList<String> parts,
+            ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) {
+        if (TextUtils.isEmpty(destinationAddress)) {
+            throw new IllegalArgumentException("Invalid destinationAddress");
+        }
+        if (parts == null || parts.size() < 1) {
+            throw new IllegalArgumentException("Invalid message body");
+        }
+
+        if (parts.size() > 1) {
+            try {
+                ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
+                if (iccISms != null) {
+                    iccISms.sendMultipartText(destinationAddress, scAddress, parts,
+                            sentIntents, deliveryIntents);
+                }
+            } catch (RemoteException ex) {
+                // ignore it
+            }
+        } else {
+            PendingIntent sentIntent = null;
+            PendingIntent deliveryIntent = null;
+            if (sentIntents != null && sentIntents.size() > 0) {
+                sentIntent = sentIntents.get(0);
+            }
+            if (deliveryIntents != null && deliveryIntents.size() > 0) {
+                deliveryIntent = deliveryIntents.get(0);
+            }
+            sendTextMessage(destinationAddress, scAddress, parts.get(0),
+                    sentIntent, deliveryIntent);
+        }
+    }
+
+    /**
+     * Send a data based SMS to a specific application port.
+     *
+     * @param destinationAddress the address to send the message to
+     * @param scAddress is the service center address or null to use
+     *  the current default SMSC
+     * @param destinationPort the port to deliver the message to
+     * @param data the body of the message to send
+     * @param sentIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is sucessfully sent, or failed.
+     *  The result code will be <code>Activity.RESULT_OK<code> for success,
+     *  or one of these errors:
+     *  <code>RESULT_ERROR_GENERIC_FAILURE</code>
+     *  <code>RESULT_ERROR_RADIO_OFF</code>
+     *  <code>RESULT_ERROR_NULL_PDU</code>.
+     *  The per-application based SMS control checks sentIntent. If sentIntent
+     *  is NULL the caller will be checked against all unknown applicaitons,
+     *  which cause smaller number of SMS to be sent in checking period.
+     * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is delivered to the recipient.  The
+     *  raw pdu of the status report is in the extended data ("pdu").
+     *
+     * @throws IllegalArgumentException if destinationAddress or data are empty
+     */
+    public void sendDataMessage(
+            String destinationAddress, String scAddress, short destinationPort,
+            byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
+        if (TextUtils.isEmpty(destinationAddress)) {
+            throw new IllegalArgumentException("Invalid destinationAddress");
+        }
+
+        if (data == null || data.length == 0) {
+            throw new IllegalArgumentException("Invalid message data");
+        }
+
+        SmsMessage.SubmitPdu pdus = SmsMessage.getSubmitPdu(
+                scAddress, destinationAddress,
+                destinationPort, data, (deliveryIntent != null));
+        sendRawPdu(pdus.encodedScAddress, pdus.encodedMessage, sentIntent, deliveryIntent);
+    }
+
+    /**
+     * Send a raw SMS PDU.
+     *
+     * @param smsc the SMSC to send the message through, or NULL for the
+     *  default SMSC
+     * @param pdu the raw PDU to send
+     * @param sentIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is successfully sent, or failed.
+     *  The result code will be <code>Activity.RESULT_OK<code> for success,
+     *  or one of these errors:
+     *  <code>RESULT_ERROR_GENERIC_FAILURE</code>
+     *  <code>RESULT_ERROR_RADIO_OFF</code>
+     *  <code>RESULT_ERROR_NULL_PDU</code>.
+     *  The per-application based SMS control checks sentIntent. If sentIntent
+     *  is NULL the caller will be checked against all unknown applications,
+     *  which cause smaller number of SMS to be sent in checking period.
+     * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
+     *  broadcast when the message is delivered to the recipient.  The
+     *  raw pdu of the status report is in the extended data ("pdu").
+     *
+     * @hide
+     */
+    private void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent,
+            PendingIntent deliveryIntent) {
+        try {
+            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
+            if (iccISms != null) {
+                iccISms.sendRawPdu(smsc, pdu, sentIntent, deliveryIntent);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+    }
+
+    /**
+     * Get the default instance of the SmsManager
+     *
+     * @return the default instance of the SmsManager
+     */
+    public static SmsManager getDefault() {
+        if (sInstance == null) {
+            sInstance = new SmsManager();
+        }
+        return sInstance;
+    }
+
+    private SmsManager() {
+        //nothing
+    }
+
+    /**
+     * Copy a raw SMS PDU to the ICC.
+     *
+     * @param smsc the SMSC for this message, or NULL for the default SMSC
+     * @param pdu the raw PDU to store
+     * @param status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD,
+     *               STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT)
+     * @return true for success
+     *
+     * {@hide}
+     */
+    public boolean copyMessageToIcc(byte[] smsc, byte[] pdu, int status) {
+        boolean success = false;
+
+        try {
+            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
+            if (iccISms != null) {
+                success = iccISms.copyMessageToIccEf(status, pdu, smsc);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+
+        return success;
+    }
+
+    /**
+     * Delete the specified message from the ICC.
+     *
+     * @param messageIndex is the record index of the message on ICC
+     * @return true for success
+     *
+     * {@hide}
+     */
+    public boolean
+    deleteMessageFromIcc(int messageIndex) {
+        boolean success = false;
+        byte[] pdu = new byte[IccConstants.SMS_RECORD_LENGTH-1];
+        Arrays.fill(pdu, (byte)0xff);
+
+        try {
+            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
+            if (iccISms != null) {
+                success = iccISms.updateMessageOnIccEf(messageIndex, STATUS_ON_ICC_FREE, pdu);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+
+        return success;
+    }
+
+    /**
+     * Update the specified message on the ICC.
+     *
+     * @param messageIndex record index of message to update
+     * @param newStatus new message status (STATUS_ON_ICC_READ,
+     *                  STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT,
+     *                  STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE)
+     * @param pdu the raw PDU to store
+     * @return true for success
+     *
+     * {@hide}
+     */
+    public boolean updateMessageOnIcc(int messageIndex, int newStatus, byte[] pdu) {
+        boolean success = false;
+
+        try {
+            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
+            if (iccISms != null) {
+                success = iccISms.updateMessageOnIccEf(messageIndex, newStatus, pdu);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+
+        return success;
+    }
+
+    /**
+     * Retrieves all messages currently stored on ICC.
+     *
+     * @return <code>ArrayList</code> of <code>SmsMessage</code> objects
+     *
+     * {@hide}
+     */
+    public ArrayList<SmsMessage> getAllMessagesFromIcc() {
+        List<SmsRawData> records = null;
+
+        try {
+            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
+            if (iccISms != null) {
+                records = iccISms.getAllMessagesFromIccEf();
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+
+        return createMessageListFromRawRecords(records);
+   }
+
+    /**
+     * Create a list of <code>SmsMessage</code>s from a list of RawSmsData
+     * records returned by <code>getAllMessagesFromIcc()</code>
+     *
+     * @param records SMS EF records, returned by
+     *   <code>getAllMessagesFromIcc</code>
+     * @return <code>ArrayList</code> of <code>SmsMessage</code> objects.
+     */
+    private ArrayList<SmsMessage> createMessageListFromRawRecords(List records) {
+        ArrayList<SmsMessage> messages = new ArrayList<SmsMessage>();
+        if (records != null) {
+            int count = records.size();
+            for (int i = 0; i < count; i++) {
+                SmsRawData data = (SmsRawData)records.get(i);
+                // List contains all records, including "free" records (null)
+                if (data != null) {
+                    SmsMessage sms = SmsMessage.createFromEfRecord(i+1, data.getBytes());
+                    messages.add(sms);
+                }
+            }
+        }
+        return messages;
+    }
+
+    // see SmsMessage.getStatusOnIcc
+
+    /** Free space (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
+    static public final int STATUS_ON_ICC_FREE      = 0;
+
+    /** Received and read (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
+    static public final int STATUS_ON_ICC_READ      = 1;
+
+    /** Received and unread (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
+    static public final int STATUS_ON_ICC_UNREAD    = 3;
+
+    /** Stored and sent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
+    static public final int STATUS_ON_ICC_SENT      = 5;
+
+    /** Stored and unsent (TS 51.011 10.5.3 / 3GPP2 C.S0023 3.4.27). */
+    static public final int STATUS_ON_ICC_UNSENT    = 7;
+
+    // SMS send failure result codes
+
+    /** Generic failure cause */
+    static public final int RESULT_ERROR_GENERIC_FAILURE    = 1;
+    /** Failed because radio was explicitly turned off */
+    static public final int RESULT_ERROR_RADIO_OFF          = 2;
+    /** Failed because no pdu provided */
+    static public final int RESULT_ERROR_NULL_PDU           = 3;
+    /** Failed because service is currently unavailable */
+    static public final int RESULT_ERROR_NO_SERVICE         = 4;
+}
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
new file mode 100644
index 0000000..3b7f4b5
--- /dev/null
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -0,0 +1,628 @@
+/*
+ * Copyright (C) 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.
+ * 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 android.telephony;
+
+import android.os.Parcel;
+
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.EncodeException;
+import com.android.internal.telephony.SmsMessageBase;
+import com.android.internal.telephony.SmsMessageBase.SubmitPduBase;
+
+import static android.telephony.TelephonyManager.PHONE_TYPE_CDMA;
+
+
+/**
+ * A Short Message Service message.
+ * @hide
+ */
+public class SmsMessage {
+    private static final boolean LOCAL_DEBUG = true;
+    private static final String LOG_TAG = "SMS";
+
+    /**
+     * SMS Class enumeration.
+     * See TS 23.038.
+     *
+     */
+    public enum MessageClass{
+        UNKNOWN, CLASS_0, CLASS_1, CLASS_2, CLASS_3;
+    }
+
+    /** Unknown encoding scheme (see TS 23.038) */
+    public static final int ENCODING_UNKNOWN = 0;
+    /** 7-bit encoding scheme (see TS 23.038) */
+    public static final int ENCODING_7BIT = 1;
+    /** 8-bit encoding scheme (see TS 23.038) */
+    public static final int ENCODING_8BIT = 2;
+    /** 16-bit encoding scheme (see TS 23.038) */
+    public static final int ENCODING_16BIT = 3;
+
+    /** The maximum number of payload bytes per message */
+    public static final int MAX_USER_DATA_BYTES = 140;
+
+    /**
+     * The maximum number of payload bytes per message if a user data header
+     * is present.  This assumes the header only contains the
+     * CONCATENATED_8_BIT_REFERENCE element.
+     *
+     * @hide pending API Council approval to extend the public API
+     */
+    public static final int MAX_USER_DATA_BYTES_WITH_HEADER = 134;
+
+    /** The maximum number of payload septets per message */
+    public static final int MAX_USER_DATA_SEPTETS = 160;
+
+    /**
+     * The maximum number of payload septets per message if a user data header
+     * is present.  This assumes the header only contains the
+     * CONCATENATED_8_BIT_REFERENCE element.
+     */
+    public static final int MAX_USER_DATA_SEPTETS_WITH_HEADER = 153;
+
+    /** Contains actual SmsMessage. Only public for debugging and for framework layer.
+    * {@hide}
+    */
+    public SmsMessageBase mWrappedSmsMessage;
+
+    public static class SubmitPdu extends SubmitPduBase {
+
+        //Constructor
+        public SubmitPdu() {
+        }
+
+        /* {@hide} */
+        protected SubmitPdu(SubmitPduBase spb) {
+            this.encodedMessage = spb.encodedMessage;
+            this.encodedScAddress = spb.encodedScAddress;
+        }
+
+    }
+
+    // Constructor
+    public SmsMessage() {
+        this(getSmsFacility());
+    }
+
+    private SmsMessage(SmsMessageBase smb) {
+        mWrappedSmsMessage = smb;
+    }
+
+    /**
+     * Create an SmsMessage from a raw PDU.
+     */
+    public static SmsMessage createFromPdu(byte[] pdu) {
+        SmsMessageBase wrappedMessage;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.createFromPdu(pdu);
+        } else {
+            wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.createFromPdu(pdu);
+        }
+
+        return new SmsMessage(wrappedMessage);
+    }
+
+    /**
+     * TS 27.005 3.4.1 lines[0] and lines[1] are the two lines read from the
+     * +CMT unsolicited response (PDU mode, of course)
+     *  +CMT: [&lt;alpha>],<length><CR><LF><pdu>
+     *
+     * Only public for debugging and for RIL
+     *
+     * {@hide}
+     */
+    public static SmsMessage newFromCMT(String[] lines){
+        SmsMessageBase wrappedMessage;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.newFromCMT(lines);
+        } else {
+            wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.newFromCMT(lines);
+        }
+
+        return new SmsMessage(wrappedMessage);
+    }
+
+    /** @hide */
+    protected static SmsMessage newFromCMTI(String line) {
+        SmsMessageBase wrappedMessage;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.newFromCMTI(line);
+        } else {
+            wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.newFromCMTI(line);
+        }
+
+        return new SmsMessage(wrappedMessage);
+    }
+
+    /** @hide */
+    public static SmsMessage newFromCDS(String line) {
+        SmsMessageBase wrappedMessage;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.newFromCDS(line);
+        } else {
+            wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.newFromCDS(line);
+        }
+
+        return new SmsMessage(wrappedMessage);
+    }
+
+    /** @hide */
+    public static SmsMessage newFromParcel(Parcel p) {
+        SmsMessageBase wrappedMessage;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.newFromParcel(p);
+        } else {
+            wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.newFromParcel(p);
+        }
+
+        return new SmsMessage(wrappedMessage);
+    }
+
+    /**
+     * Create an SmsMessage from an SMS EF record.
+     *
+     * @param index Index of SMS record. This should be index in ArrayList
+     *              returned by SmsManager.getAllMessagesFromSim + 1.
+     * @param data Record data.
+     * @return An SmsMessage representing the record.
+     *
+     * @hide
+     */
+    public static SmsMessage createFromEfRecord(int index, byte[] data) {
+        SmsMessageBase wrappedMessage;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.createFromEfRecord(
+                    index, data);
+        } else {
+            wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.createFromEfRecord(
+                    index, data);
+        }
+
+        return new SmsMessage(wrappedMessage);
+    }
+
+    /**
+     * Get the TP-Layer-Length for the given SMS-SUBMIT PDU Basically, the
+     * length in bytes (not hex chars) less the SMSC header
+     */
+    public static int getTPLayerLengthForPDU(String pdu) {
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            return com.android.internal.telephony.cdma.SmsMessage.getTPLayerLengthForPDU(pdu);
+        } else {
+            return com.android.internal.telephony.gsm.SmsMessage.getTPLayerLengthForPDU(pdu);
+        }
+    }
+
+    /**
+     * Calculates the number of SMS's required to encode the message body and
+     * the number of characters remaining until the next message, given the
+     * current encoding.
+     *
+     * @param messageBody the message to encode
+     * @param use7bitOnly if true, characters that are not part of the GSM
+     *         alphabet are counted as a single space char.  If false, a
+     *         messageBody containing non-GSM alphabet characters is calculated
+     *         for 16-bit encoding.
+     * @return an int[4] with int[0] being the number of SMS's required, int[1]
+     *         the number of code units used, and int[2] is the number of code
+     *         units remaining until the next message. int[3] is the encoding
+     *         type that should be used for the message.
+     */
+    public static int[] calculateLength(CharSequence messageBody, boolean use7bitOnly) {
+        int ret[] = new int[4];
+
+        try {
+            // Try GSM alphabet
+            int septets = GsmAlphabet.countGsmSeptets(messageBody, !use7bitOnly);
+            ret[1] = septets;
+            if (septets > MAX_USER_DATA_SEPTETS) {
+                ret[0] = (septets / MAX_USER_DATA_SEPTETS_WITH_HEADER) + 1;
+                ret[2] = MAX_USER_DATA_SEPTETS_WITH_HEADER
+                            - (septets % MAX_USER_DATA_SEPTETS_WITH_HEADER);
+            } else {
+                ret[0] = 1;
+                ret[2] = MAX_USER_DATA_SEPTETS - septets;
+            }
+            ret[3] = ENCODING_7BIT;
+        } catch (EncodeException ex) {
+            // fall back to UCS-2
+            int octets = messageBody.length() * 2;
+            ret[1] = messageBody.length();
+            if (octets > MAX_USER_DATA_BYTES) {
+                // 6 is the size of the user data header
+                ret[0] = (octets / MAX_USER_DATA_BYTES_WITH_HEADER) + 1;
+                ret[2] = (MAX_USER_DATA_BYTES_WITH_HEADER
+                            - (octets % MAX_USER_DATA_BYTES_WITH_HEADER))/2;
+            } else {
+                ret[0] = 1;
+                ret[2] = (MAX_USER_DATA_BYTES - octets)/2;
+            }
+            ret[3] = ENCODING_16BIT;
+        }
+
+        return ret;
+    }
+
+    /**
+     * Calculates the number of SMS's required to encode the message body and
+     * the number of characters remaining until the next message, given the
+     * current encoding.
+     *
+     * @param messageBody the message to encode
+     * @param use7bitOnly if true, characters that are not part of the GSM
+     *         alphabet are counted as a single space char.  If false, a
+     *         messageBody containing non-GSM alphabet characters is calculated
+     *         for 16-bit encoding.
+     * @return an int[4] with int[0] being the number of SMS's required, int[1]
+     *         the number of code units used, and int[2] is the number of code
+     *         units remaining until the next message. int[3] is the encoding
+     *         type that should be used for the message.
+     */
+    public static int[] calculateLength(String messageBody, boolean use7bitOnly) {
+        return calculateLength((CharSequence)messageBody, use7bitOnly);
+    }
+
+    /**
+     * Get an SMS-SUBMIT PDU for a destination address and a message
+     *
+     * @param scAddress Service Centre address.  Null means use default.
+     * @return a <code>SubmitPdu</code> containing the encoded SC
+     *         address, if applicable, and the encoded message.
+     *         Returns null on encode error.
+     * @hide
+     */
+    public static SubmitPdu getSubmitPdu(String scAddress,
+            String destinationAddress, String message,
+            boolean statusReportRequested, byte[] header) {
+        SubmitPduBase spb;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress,
+                    destinationAddress, message, statusReportRequested, header);
+        } else {
+            spb = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(scAddress,
+                    destinationAddress, message, statusReportRequested, header);
+        }
+
+        return new SubmitPdu(spb);
+    }
+
+    /**
+     * Get an SMS-SUBMIT PDU for a destination address and a message
+     *
+     * @param scAddress Service Centre address.  Null means use default.
+     * @return a <code>SubmitPdu</code> containing the encoded SC
+     *         address, if applicable, and the encoded message.
+     *         Returns null on encode error.
+     */
+    public static SubmitPdu getSubmitPdu(String scAddress,
+            String destinationAddress, String message, boolean statusReportRequested) {
+        SubmitPduBase spb;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress,
+                    destinationAddress, message, statusReportRequested);
+        } else {
+            spb = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(scAddress,
+                    destinationAddress, message, statusReportRequested);
+        }
+
+        return new SubmitPdu(spb);
+    }
+
+    /**
+     * Get an SMS-SUBMIT PDU for a data message to a destination address &amp; port
+     *
+     * @param scAddress Service Centre address. null == use default
+     * @param destinationAddress the address of the destination for the message
+     * @param destinationPort the port to deliver the message to at the
+     *        destination
+     * @param data the dat for the message
+     * @return a <code>SubmitPdu</code> containing the encoded SC
+     *         address, if applicable, and the encoded message.
+     *         Returns null on encode error.
+     */
+    public static SubmitPdu getSubmitPdu(String scAddress,
+            String destinationAddress, short destinationPort, byte[] data,
+            boolean statusReportRequested) {
+        SubmitPduBase spb;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress,
+                    destinationAddress, destinationPort, data, statusReportRequested);
+        } else {
+            spb = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(scAddress,
+                    destinationAddress, destinationPort, data, statusReportRequested);
+        }
+
+        return new SubmitPdu(spb);
+    }
+
+    /**
+     * Returns the address of the SMS service center that relayed this message
+     * or null if there is none.
+     */
+    public String getServiceCenterAddress() {
+        return mWrappedSmsMessage.getServiceCenterAddress();
+    }
+
+    /**
+     * Returns the originating address (sender) of this SMS message in String
+     * form or null if unavailable
+     */
+    public String getOriginatingAddress() {
+        return mWrappedSmsMessage.getOriginatingAddress();
+    }
+
+    /**
+     * Returns the originating address, or email from address if this message
+     * was from an email gateway. Returns null if originating address
+     * unavailable.
+     */
+    public String getDisplayOriginatingAddress() {
+        return mWrappedSmsMessage.getDisplayOriginatingAddress();
+    }
+
+    /**
+     * Returns the message body as a String, if it exists and is text based.
+     * @return message body is there is one, otherwise null
+     */
+    public String getMessageBody() {
+        return mWrappedSmsMessage.getMessageBody();
+    }
+
+    /**
+     * Returns the class of this message.
+     */
+    public MessageClass getMessageClass() {
+        return mWrappedSmsMessage.getMessageClass();
+    }
+
+    /**
+     * Returns the message body, or email message body if this message was from
+     * an email gateway. Returns null if message body unavailable.
+     */
+    public String getDisplayMessageBody() {
+        return mWrappedSmsMessage.getDisplayMessageBody();
+    }
+
+    /**
+     * Unofficial convention of a subject line enclosed in parens empty string
+     * if not present
+     */
+    public String getPseudoSubject() {
+        return mWrappedSmsMessage.getPseudoSubject();
+    }
+
+    /**
+     * Returns the service centre timestamp in currentTimeMillis() format
+     */
+    public long getTimestampMillis() {
+        return mWrappedSmsMessage.getTimestampMillis();
+    }
+
+    /**
+     * Returns true if message is an email.
+     *
+     * @return true if this message came through an email gateway and email
+     *         sender / subject / parsed body are available
+     */
+    public boolean isEmail() {
+        return mWrappedSmsMessage.isEmail();
+    }
+
+     /**
+     * @return if isEmail() is true, body of the email sent through the gateway.
+     *         null otherwise
+     */
+    public String getEmailBody() {
+        return mWrappedSmsMessage.getEmailBody();
+    }
+
+    /**
+     * @return if isEmail() is true, email from address of email sent through
+     *         the gateway. null otherwise
+     */
+    public String getEmailFrom() {
+        return mWrappedSmsMessage.getEmailFrom();
+    }
+
+    /**
+     * Get protocol identifier.
+     */
+    public int getProtocolIdentifier() {
+        return mWrappedSmsMessage.getProtocolIdentifier();
+    }
+
+    /**
+     * See TS 23.040 9.2.3.9 returns true if this is a "replace short message"
+     * SMS
+     */
+    public boolean isReplace() {
+        return mWrappedSmsMessage.isReplace();
+    }
+
+    /**
+     * Returns true for CPHS MWI toggle message.
+     *
+     * @return true if this is a CPHS MWI toggle message See CPHS 4.2 section
+     *         B.4.2
+     */
+    public boolean isCphsMwiMessage() {
+        return mWrappedSmsMessage.isCphsMwiMessage();
+    }
+
+    /**
+     * returns true if this message is a CPHS voicemail / message waiting
+     * indicator (MWI) clear message
+     */
+    public boolean isMWIClearMessage() {
+        return mWrappedSmsMessage.isMWIClearMessage();
+    }
+
+    /**
+     * returns true if this message is a CPHS voicemail / message waiting
+     * indicator (MWI) set message
+     */
+    public boolean isMWISetMessage() {
+        return mWrappedSmsMessage.isMWISetMessage();
+    }
+
+    /**
+     * returns true if this message is a "Message Waiting Indication Group:
+     * Discard Message" notification and should not be stored.
+     */
+    public boolean isMwiDontStore() {
+        return mWrappedSmsMessage.isMwiDontStore();
+    }
+
+    /**
+     * returns the user data section minus the user data header if one was
+     * present.
+     */
+    public byte[] getUserData() {
+        return mWrappedSmsMessage.getUserData();
+    }
+
+    /* Not part of the SDK interface and only needed by specific classes:
+       protected SmsHeader getUserDataHeader()
+    */
+
+    /**
+     * Returns the raw PDU for the message.
+     *
+     * @return the raw PDU for the message.
+     */
+    public byte[] getPdu() {
+        return mWrappedSmsMessage.getPdu();
+    }
+
+    /**
+     * Returns the status of the message on the SIM (read, unread, sent, unsent).
+     *
+     * @return the status of the message on the SIM.  These are:
+     *         SmsManager.STATUS_ON_SIM_FREE
+     *         SmsManager.STATUS_ON_SIM_READ
+     *         SmsManager.STATUS_ON_SIM_UNREAD
+     *         SmsManager.STATUS_ON_SIM_SEND
+     *         SmsManager.STATUS_ON_SIM_UNSENT
+     * @deprecated Use getStatusOnIcc instead.
+     */
+    @Deprecated public int getStatusOnSim() {
+        return mWrappedSmsMessage.getStatusOnIcc();
+    }
+
+    /**
+     * Returns the status of the message on the ICC (read, unread, sent, unsent).
+     *
+     * @return the status of the message on the ICC.  These are:
+     *         SmsManager.STATUS_ON_ICC_FREE
+     *         SmsManager.STATUS_ON_ICC_READ
+     *         SmsManager.STATUS_ON_ICC_UNREAD
+     *         SmsManager.STATUS_ON_ICC_SEND
+     *         SmsManager.STATUS_ON_ICC_UNSENT
+     */
+    public int getStatusOnIcc() {
+
+        return mWrappedSmsMessage.getStatusOnIcc();
+    }
+
+    /**
+     * Returns the record index of the message on the SIM (1-based index).
+     * @return the record index of the message on the SIM, or -1 if this
+     *         SmsMessage was not created from a SIM SMS EF record.
+     * @deprecated Use getIndexOnIcc instead.
+     */
+    @Deprecated public int getIndexOnSim() {
+        return mWrappedSmsMessage.getIndexOnIcc();
+    }
+
+    /**
+     * Returns the record index of the message on the ICC (1-based index).
+     * @return the record index of the message on the ICC, or -1 if this
+     *         SmsMessage was not created from a ICC SMS EF record.
+     */
+    public int getIndexOnIcc() {
+
+        return mWrappedSmsMessage.getIndexOnIcc();
+    }
+
+    /**
+     * GSM:
+     * For an SMS-STATUS-REPORT message, this returns the status field from
+     * the status report.  This field indicates the status of a previously
+     * submitted SMS, if requested.  See TS 23.040, 9.2.3.15 TP-Status for a
+     * description of values.
+     * CDMA:
+     * For not interfering with status codes from GSM, the value is
+     * shifted to the bits 31-16.
+     * The value is composed of an error class (bits 25-24) and a status code (bits 23-16).
+     * Possible codes are described in C.S0015-B, v2.0, 4.5.21.
+     *
+     * @return 0 indicates the previously sent message was received.
+     *         See TS 23.040, 9.9.2.3.15 and C.S0015-B, v2.0, 4.5.21
+     *         for a description of other possible values.
+     */
+    public int getStatus() {
+        return mWrappedSmsMessage.getStatus();
+    }
+
+    /**
+     * Return true iff the message is a SMS-STATUS-REPORT message.
+     */
+    public boolean isStatusReportMessage() {
+        return mWrappedSmsMessage.isStatusReportMessage();
+    }
+
+    /**
+     * Returns true iff the <code>TP-Reply-Path</code> bit is set in
+     * this message.
+     */
+    public boolean isReplyPathPresent() {
+        return mWrappedSmsMessage.isReplyPathPresent();
+    }
+
+    /** This method returns the reference to a specific
+     *  SmsMessage object, which is used for accessing its static methods.
+     * @return Specific SmsMessage.
+     */
+    private static final SmsMessageBase getSmsFacility(){
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+        if (PHONE_TYPE_CDMA == activePhone) {
+            return new com.android.internal.telephony.cdma.SmsMessage();
+        } else {
+            return new com.android.internal.telephony.gsm.SmsMessage();
+        }
+    }
+}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index c5b1b73..921ce77 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -28,25 +28,31 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
+import android.telephony.CellLocation;
 
+import com.android.internal.telephony.IPhoneSubInfo;
+import com.android.internal.telephony.ITelephony;
+import com.android.internal.telephony.ITelephonyRegistry;
+import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.TelephonyProperties;
 
 /**
  * Provides access to information about the telephony services on
  * the device. Applications can use the methods in this class to
  * determine telephony services and states, as well as to access some
- * types of subscriber information. Applications can also register 
- * a listener to receive notification of telephony state changes. 
+ * types of subscriber information. Applications can also register
+ * a listener to receive notification of telephony state changes.
  * <p>
  * You do not instantiate this class directly; instead, you retrieve
- * a reference to an instance through 
+ * a reference to an instance through
  * {@link android.content.Context#getSystemService
  * Context.getSystemService(Context.TELEPHONY_SERVICE)}.
  * <p>
  * Note that acess to some telephony information is
- * permission-protected. Your application cannot access the protected 
- * information unless it has the appropriate permissions declared in 
- * its manifest file. Where permissions apply, they are noted in the  
- * the methods through which you access the protected information. 
+ * permission-protected. Your application cannot access the protected
+ * information unless it has the appropriate permissions declared in
+ * its manifest file. Where permissions apply, they are noted in the
+ * the methods through which you access the protected information.
  */
 public class TelephonyManager {
     private static final String TAG = "TelephonyManager";
@@ -166,10 +172,10 @@
     //
 
     /**
-     * Returns the software version number for the device, for example, 
+     * Returns the software version number for the device, for example,
      * the IMEI/SV for GSM phones.
      *
-     * <p>Requires Permission: 
+     * <p>Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
     public String getDeviceSoftwareVersion() {
@@ -181,10 +187,10 @@
     }
 
     /**
-     * Returns the unique device ID, for example,the IMEI for GSM
+     * Returns the unique device ID, for example, the IMEI for GSM and the MEID for CDMA
      * phones.
      *
-     * <p>Requires Permission: 
+     * <p>Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
     public String getDeviceId() {
@@ -214,7 +220,7 @@
      * Enables location update notifications.  {@link PhoneStateListener#onCellLocationChanged
      * PhoneStateListener.onCellLocationChanged} will be called on location updates.
      *
-     * <p>Requires Permission: {@link android.Manifest.permission#CONTROL_LOCATION_UPDATES 
+     * <p>Requires Permission: {@link android.Manifest.permission#CONTROL_LOCATION_UPDATES
      * CONTROL_LOCATION_UPDATES}
      *
      * @hide
@@ -270,23 +276,37 @@
     public static final int PHONE_TYPE_GSM = 1;
 
     /**
-     * Returns a constant indicating the device phone type. 
-     * 
+     * CDMA phone
+     * @hide
+     */
+    public static final int PHONE_TYPE_CDMA = 2;
+
+    /**
+     * Returns a constant indicating the device phone type.
+     *
      * @see #PHONE_TYPE_NONE
      * @see #PHONE_TYPE_GSM
+     * @see #PHONE_TYPE_CDMA
      */
     public int getPhoneType() {
-        // in the future, we should really check this
-        return PHONE_TYPE_GSM;
+        try{
+            if(getITelephony().getActivePhoneType() == RILConstants.CDMA_PHONE) {
+                return PHONE_TYPE_CDMA;
+            } else {
+                return PHONE_TYPE_GSM;
+            }
+        }catch(RemoteException ex){
+            return PHONE_TYPE_NONE;
+        }
     }
 
     //
-    // 
+    //
     // Current Network
     //
     //
 
-    /** 
+    /**
      * Returns the alphabetic name of current registered operator.
      * <p>
      * Availability: Only when user is registered to a network
@@ -295,7 +315,7 @@
         return SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ALPHA);
     }
 
-    /** 
+    /**
      * Returns the numeric name (MCC+MNC) of current registered operator.
      * <p>
      * Availability: Only when user is registered to a network
@@ -304,7 +324,7 @@
         return SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC);
     }
 
-    /**  
+    /**
      * Returns true if the device is considered roaming on the current
      * network, for GSM purposes.
      * <p>
@@ -314,7 +334,7 @@
         return "true".equals(SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ISROAMING));
     }
 
-    /** 
+    /**
      * Returns the ISO country code equivilent of the current registered
      * operator's MCC (Mobile Country Code).
      * <p>
@@ -332,9 +352,20 @@
     public static final int NETWORK_TYPE_EDGE = 2;
     /** Current network is UMTS */
     public static final int NETWORK_TYPE_UMTS = 3;
+    /** Current network is CDMA: Either IS95A or IS95B*/
+    /** @hide */
+    public static final int NETWORK_TYPE_CDMA = 4;
+    /** Current network is EVDO revision 0 or revision A*/
+    /** @hide */
+    public static final int NETWORK_TYPE_EVDO_0 = 5;
+    /** @hide */
+    public static final int NETWORK_TYPE_EVDO_A = 6;
+    /** Current network is 1xRTT*/
+    /** @hide */
+    public static final int NETWORK_TYPE_1xRTT = 7;
 
     /**
-     * Returns a constant indicating the radio technology (network type) 
+     * Returns a constant indicating the radio technology (network type)
      * currently in use on the device.
      * @return the network type
      *
@@ -342,6 +373,10 @@
      * @see #NETWORK_TYPE_GPRS
      * @see #NETWORK_TYPE_EDGE
      * @see #NETWORK_TYPE_UMTS
+     * @see #NETWORK_TYPE_CDMA
+     * @see #NETWORK_TYPE_EVDO_0
+     * @see #NETWORK_TYPE_EVDO_A
+     * @see #NETWORK_TYPE_1xRTT
      */
     public int getNetworkType() {
         String prop = SystemProperties.get(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE);
@@ -354,6 +389,18 @@
         else if ("UMTS".equals(prop)) {
             return NETWORK_TYPE_UMTS;
         }
+        else if ("CDMA".equals(prop)) {
+            return NETWORK_TYPE_CDMA;
+                }
+        else if ("CDMA - EvDo rev. 0".equals(prop)) {
+            return NETWORK_TYPE_EVDO_0;
+            }
+        else if ("CDMA - EvDo rev. A".equals(prop)) {
+            return NETWORK_TYPE_EVDO_A;
+            }
+        else if ("CDMA - 1xRTT".equals(prop)) {
+            return NETWORK_TYPE_1xRTT;
+            }
         else {
             return NETWORK_TYPE_UNKNOWN;
         }
@@ -374,6 +421,14 @@
                 return "EDGE";
             case NETWORK_TYPE_UMTS:
                 return "UMTS";
+            case NETWORK_TYPE_CDMA:
+                return "CDMA";
+            case NETWORK_TYPE_EVDO_0:
+                return "CDMA - EvDo rev. 0";
+            case NETWORK_TYPE_EVDO_A:
+                return "CDMA - EvDo rev. A";
+            case NETWORK_TYPE_1xRTT:
+                return "CDMA - 1xRTT";
             default:
                 return "UNKNOWN";
         }
@@ -387,7 +442,7 @@
 
     /** SIM card state: Unknown. Signifies that the SIM is in transition
      *  between states. For example, when the user inputs the SIM pin
-     *  under PIN_REQUIRED state, a query for sim status returns 
+     *  under PIN_REQUIRED state, a query for sim status returns
      *  this state before turning to SIM_STATE_READY. */
     public static final int SIM_STATE_UNKNOWN = 0;
     /** SIM card state: no SIM card is available in the device */
@@ -400,11 +455,11 @@
     public static final int SIM_STATE_NETWORK_LOCKED = 4;
     /** SIM card state: Ready */
     public static final int SIM_STATE_READY = 5;
-    
-    /** 
-     * Returns a constant indicating the state of the 
+
+    /**
+     * Returns a constant indicating the state of the
      * device SIM card.
-     * 
+     *
      * @see #SIM_STATE_UNKNOWN
      * @see #SIM_STATE_ABSENT
      * @see #SIM_STATE_PIN_REQUIRED
@@ -434,7 +489,7 @@
         }
     }
 
-    /** 
+    /**
      * Returns the MCC+MNC (mobile country code + mobile network code) of the
      * provider of the SIM. 5 or 6 decimal digits.
      * <p>
@@ -443,36 +498,36 @@
      * @see #getSimState
      */
     public String getSimOperator() {
-        return SystemProperties.get(TelephonyProperties.PROPERTY_SIM_OPERATOR_NUMERIC);
+        return SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC);
     }
 
-    /** 
-     * Returns the Service Provider Name (SPN). 
+    /**
+     * Returns the Service Provider Name (SPN).
      * <p>
      * Availability: SIM state must be {@link #SIM_STATE_READY}
      *
      * @see #getSimState
      */
     public String getSimOperatorName() {
-        return SystemProperties.get(TelephonyProperties.PROPERTY_SIM_OPERATOR_ALPHA);
+        return SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA);
     }
 
-    /** 
+    /**
      * Returns the ISO country code equivalent for the SIM provider's country code.
      */
     public String getSimCountryIso() {
-        return SystemProperties.get(TelephonyProperties.PROPERTY_SIM_OPERATOR_ISO_COUNTRY);
+        return SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY);
     }
 
     /**
      * Returns the serial number of the SIM, if applicable.
      * <p>
-     * Requires Permission: 
+     * Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
     public String getSimSerialNumber() {
         try {
-            return getSubscriberInfo().getSimSerialNumber();
+            return getSubscriberInfo().getIccSerialNumber();
         } catch (RemoteException ex) {
         }
         return null;
@@ -487,7 +542,7 @@
     /**
      * Returns the unique subscriber ID, for example, the IMSI for a GSM phone.
      * <p>
-     * Requires Permission: 
+     * Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
     public String getSubscriberId() {
@@ -499,10 +554,10 @@
     }
 
     /**
-     * Returns the phone number string for line 1, for example, the MSISDN 
+     * Returns the phone number string for line 1, for example, the MSISDN
      * for a GSM phone.
      * <p>
-     * Requires Permission: 
+     * Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
     public String getLine1Number() {
@@ -514,9 +569,9 @@
     }
 
     /**
-     * Returns the alphabetic identifier associated with the line 1 number. 
+     * Returns the alphabetic identifier associated with the line 1 number.
      * <p>
-     * Requires Permission: 
+     * Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      * @hide
      * nobody seems to call this.
@@ -532,7 +587,7 @@
     /**
      * Returns the voice mail number.
      * <p>
-     * Requires Permission: 
+     * Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
     public String getVoiceMailNumber() {
@@ -547,7 +602,7 @@
      * Retrieves the alphabetic identifier associated with the voice
      * mail number.
      * <p>
-     * Requires Permission: 
+     * Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
     public String getVoiceMailAlphaTag() {
@@ -567,10 +622,10 @@
     /** Device call state: No activity. */
     public static final int CALL_STATE_IDLE = 0;
     /** Device call state: Ringing. A new call arrived and is
-     *  ringing or waiting. In the latter case, another call is 
+     *  ringing or waiting. In the latter case, another call is
      *  already active. */
     public static final int CALL_STATE_RINGING = 1;
-    /** Device call state: Off-hook. At least one call exists 
+    /** Device call state: Off-hook. At least one call exists
       * that is dialing, active, or on hold, and no calls are ringing
       * or waiting. */
     public static final int CALL_STATE_OFFHOOK = 2;
@@ -621,13 +676,13 @@
     public static final int DATA_CONNECTING     = 1;
     /** Data connection state: Connected. IP traffic should be available. */
     public static final int DATA_CONNECTED      = 2;
-    /** Data connection state: Suspended. The connection is up, but IP 
-     * traffic is temporarily unavailable. For example, in a 2G network, 
+    /** Data connection state: Suspended. The connection is up, but IP
+     * traffic is temporarily unavailable. For example, in a 2G network,
      * data activity may be suspended when a voice call arrives. */
     public static final int DATA_SUSPENDED      = 3;
 
     /**
-     * Returns a constant indicating the current data connection state 
+     * Returns a constant indicating the current data connection state
      * (cellular).
      *
      * @see #DATA_DISCONNECTED
@@ -655,26 +710,26 @@
     //
 
     /**
-     * Registers a listener object to receive notification of changes 
-     * in specified telephony states. 
+     * Registers a listener object to receive notification of changes
+     * in specified telephony states.
      * <p>
      * To register a listener, pass a {@link PhoneStateListener}
-     * and specify at least one telephony state of interest in 
-     * the events argument. 
-     * 
+     * and specify at least one telephony state of interest in
+     * the events argument.
+     *
      * At registration, and when a specified telephony state
-     * changes, the telephony manager invokes the appropriate 
-     * callback method on the listener object and passes the 
+     * changes, the telephony manager invokes the appropriate
+     * callback method on the listener object and passes the
      * current (udpated) values.
      * <p>
      * To unregister a listener, pass the listener object and set the
-     * events argument to 
+     * events argument to
      * {@link PhoneStateListener#LISTEN_NONE LISTEN_NONE} (0).
-     * 
+     *
      * @param listener The {@link PhoneStateListener} object to register
      *                 (or unregister)
      * @param events The telephony state(s) of interest to the listener,
-     *               as a bitwise-OR combination of {@link PhoneStateListener} 
+     *               as a bitwise-OR combination of {@link PhoneStateListener}
      *               LISTEN_ flags.
      */
     public void listen(PhoneStateListener listener, int events) {
diff --git a/telephony/java/android/telephony/cdma/CdmaCellLocation.java b/telephony/java/android/telephony/cdma/CdmaCellLocation.java
new file mode 100644
index 0000000..189959b
--- /dev/null
+++ b/telephony/java/android/telephony/cdma/CdmaCellLocation.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2006 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 android.telephony.cdma;
+
+import android.os.Bundle;
+import android.telephony.CellLocation;
+
+/**
+ * Represents the cell location on a GSM phone.
+ * @hide
+ */
+public class CdmaCellLocation extends CellLocation {
+    private int mBaseStationId = -1;
+    private int mBaseStationLatitude = -1;
+    private int mBaseStationLongitude = -1;
+
+    /**
+     * Empty constructor.  Initializes the LAC and CID to -1.
+     */
+    public CdmaCellLocation() {
+        this.mBaseStationId = -1;
+        this.mBaseStationLatitude = -1;
+        this.mBaseStationLongitude = -1;
+    }
+
+    /**
+     * Initialize the object from a bundle.
+     */
+    public CdmaCellLocation(Bundle bundleWithValues) {
+        this.mBaseStationId = bundleWithValues.getInt("baseStationId");
+        this.mBaseStationLatitude = bundleWithValues.getInt("baseStationLatitude");
+        this.mBaseStationLongitude = bundleWithValues.getInt("baseStationLongitude");
+    }
+
+    /**
+     * @return cdma base station identification number, -1 if unknown
+     */
+    public int getBaseStationId() {
+        return this.mBaseStationId;
+    }
+
+    /**
+     * @return cdma base station latitude, -1 if unknown
+     */
+    public int getBaseStationLatitude() {
+        return this.mBaseStationLatitude;
+    }
+
+    /**
+     * @return cdma base station longitude, -1 if unknown
+     */
+    public int getBaseStationLongitude() {
+        return this.mBaseStationLongitude;
+    }
+
+    /**
+     * Invalidate this object.  The cell location data is set to -1.
+     */
+    public void setStateInvalid() {
+        this.mBaseStationId = -1;
+        this.mBaseStationLatitude = -1;
+        this.mBaseStationLongitude = -1;
+    }
+
+    /**
+     * Set the cell location data.
+     */
+     public void setCellLocationData(int baseStationId, int baseStationLatitude,
+         int baseStationLongitude) {
+         // The following values have to be written in the correct sequence
+         this.mBaseStationId = baseStationId;
+         this.mBaseStationLatitude = baseStationLatitude;   //values[2];
+         this.mBaseStationLongitude = baseStationLongitude; //values[3];
+    }
+
+    @Override
+    public int hashCode() {
+        return this.mBaseStationId ^ this.mBaseStationLatitude ^ this.mBaseStationLongitude;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        CdmaCellLocation s;
+
+        try {
+            s = (CdmaCellLocation)o;
+        } catch (ClassCastException ex) {
+            return false;
+        }
+
+        if (o == null) {
+            return false;
+        }
+
+        return (equalsHandlesNulls(this.mBaseStationId, s.mBaseStationId) &&
+                equalsHandlesNulls(this.mBaseStationLatitude, s.mBaseStationLatitude) &&
+                equalsHandlesNulls(this.mBaseStationLongitude, s.mBaseStationLongitude)
+        );
+    }
+
+    @Override
+    public String toString() {
+        return "[" + this.mBaseStationId + ","
+                   + this.mBaseStationLatitude + ","
+                   + this.mBaseStationLongitude + "]";
+    }
+
+    /**
+     * Test whether two objects hold the same data values or both are null
+     *
+     * @param a first obj
+     * @param b second obj
+     * @return true if two objects equal or both are null
+     */
+    private static boolean equalsHandlesNulls(Object a, Object b) {
+        return (a == null) ? (b == null) : a.equals (b);
+    }
+
+    /**
+     * Fill the cell location data into the intent notifier Bundle based on service state
+     *
+     * @param bundleToFill intent notifier Bundle
+     */
+    public void fillInNotifierBundle(Bundle bundleToFill) {
+        bundleToFill.putInt("baseStationId", this.mBaseStationId);
+        bundleToFill.putInt("baseStationLatitude", this.mBaseStationLatitude);
+        bundleToFill.putInt("baseStationLongitude", this.mBaseStationLongitude);
+    }
+
+}
+
+
diff --git a/telephony/java/android/telephony/cdma/package.html b/telephony/java/android/telephony/cdma/package.html
new file mode 100644
index 0000000..ee4af5e
--- /dev/null
+++ b/telephony/java/android/telephony/cdma/package.html
@@ -0,0 +1,5 @@
+<HTML>
+<BODY>
+Provides APIs for utilizing CDMA-specific telephony features.
+</BODY>
+</HTML>
\ No newline at end of file
diff --git a/telephony/java/android/telephony/gsm/GsmCellLocation.java b/telephony/java/android/telephony/gsm/GsmCellLocation.java
index fb9b73a..637a11c 100644
--- a/telephony/java/android/telephony/gsm/GsmCellLocation.java
+++ b/telephony/java/android/telephony/gsm/GsmCellLocation.java
@@ -17,14 +17,12 @@
 package android.telephony.gsm;
 
 import android.os.Bundle;
-import com.android.internal.telephony.Phone;
 import android.telephony.CellLocation;
 
 /**
  * Represents the cell location on a GSM phone.
  */
-public class GsmCellLocation extends CellLocation
-{
+public class GsmCellLocation extends CellLocation {
     private int mLac;
     private int mCid;
 
@@ -82,7 +80,7 @@
     @Override
     public boolean equals(Object o) {
         GsmCellLocation s;
-        
+
         try {
             s = (GsmCellLocation)o;
         } catch (ClassCastException ex) {
@@ -100,7 +98,7 @@
     public String toString() {
         return "["+ mLac + "," + mCid + "]";
     }
-    
+
     /**
      * Test whether two objects hold the same data values or both are null
      *
diff --git a/telephony/java/android/telephony/gsm/SmsManager.java b/telephony/java/android/telephony/gsm/SmsManager.java
index c63b530..cdd707e 100644
--- a/telephony/java/android/telephony/gsm/SmsManager.java
+++ b/telephony/java/android/telephony/gsm/SmsManager.java
@@ -17,28 +17,35 @@
 package android.telephony.gsm;
 
 import android.app.PendingIntent;
-import android.os.RemoteException;
-import android.os.IServiceManager;
-import android.os.ServiceManager;
-import android.os.ServiceManagerNative;
-import android.text.TextUtils;
-
-import com.android.internal.telephony.gsm.EncodeException;
-import com.android.internal.telephony.gsm.GsmAlphabet;
-import com.android.internal.telephony.gsm.ISms;
-import com.android.internal.telephony.gsm.SimConstants;
-import com.android.internal.telephony.gsm.SmsRawData;
 
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
+
 
 /**
  * Manages SMS operations such as sending data, text, and pdu SMS messages.
  * Get this object by calling the static method SmsManager.getDefault().
+ * @deprecated Replaced by android.telephony.SmsManager that supports both GSM and CDMA.
  */
-public final class SmsManager {
+@Deprecated public final class SmsManager {
     private static SmsManager sInstance;
+    private android.telephony.SmsManager mSmsMgrProxy;
+
+    /** Get the default instance of the SmsManager
+     *
+     * @return the default instance of the SmsManager
+     * @deprecated Use android.telephony.SmsManager.
+     */
+    @Deprecated
+    public static final SmsManager getDefault() {
+        if (sInstance == null) {
+            sInstance = new SmsManager();
+        }
+        return sInstance;
+    }
+
+    private SmsManager() {
+        mSmsMgrProxy = android.telephony.SmsManager.getDefault();
+    }
 
     /**
      * Send a text based SMS.
@@ -55,28 +62,21 @@
      *  <code>RESULT_ERROR_RADIO_OFF</code>
      *  <code>RESULT_ERROR_NULL_PDU</code>.
      *  The per-application based SMS control checks sentIntent. If sentIntent
-     *  is NULL the caller will be checked against all unknown applicaitons,
+     *  is NULL the caller will be checked against all unknown applications,
      *  which cause smaller number of SMS to be sent in checking period.
      * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
      *  broadcast when the message is delivered to the recipient.  The
      *  raw pdu of the status report is in the extended data ("pdu").
      *
      * @throws IllegalArgumentException if destinationAddress or text are empty
+     * @deprecated Use android.telephony.SmsManager.
      */
-    public void sendTextMessage(
+    @Deprecated
+    public final void sendTextMessage(
             String destinationAddress, String scAddress, String text,
             PendingIntent sentIntent, PendingIntent deliveryIntent) {
-        if (TextUtils.isEmpty(destinationAddress)) {
-            throw new IllegalArgumentException("Invalid destinationAddress");
-        }
-
-        if (TextUtils.isEmpty(text)) {
-            throw new IllegalArgumentException("Invalid message body");
-        }
-
-        SmsMessage.SubmitPdu pdus = SmsMessage.getSubmitPdu(
-                scAddress, destinationAddress, text, (deliveryIntent != null));
-        sendRawPdu(pdus.encodedScAddress, pdus.encodedMessage, sentIntent, deliveryIntent);
+        mSmsMgrProxy.sendTextMessage(destinationAddress, scAddress, text,
+                sentIntent, deliveryIntent);
     }
 
     /**
@@ -86,55 +86,24 @@
      * @param text the original message.  Must not be null.
      * @return an <code>ArrayList</code> of strings that, in order,
      *   comprise the original message
+     * @deprecated Use android.telephony.SmsManager.
      */
-    public ArrayList<String> divideMessage(String text) {
-        int size = text.length();
-        int[] params = SmsMessage.calculateLength(text, false);
-            /* SmsMessage.calculateLength returns an int[4] with:
-             *   int[0] being the number of SMS's required,
-             *   int[1] the number of code units used,
-             *   int[2] is the number of code units remaining until the next message.
-             *   int[3] is the encoding type that should be used for the message.
-             */
-        int messageCount = params[0];
-        int encodingType = params[3];
-        ArrayList<String> result = new ArrayList<String>(messageCount);
-
-        int start = 0;
-        int limit;
-        
-        if (messageCount > 1) {
-            limit = (encodingType == SmsMessage.ENCODING_7BIT) ?
-                    SmsMessage.MAX_USER_DATA_SEPTETS_WITH_HEADER :
-                        SmsMessage.MAX_USER_DATA_BYTES_WITH_HEADER;            
-        } else {
-            limit = (encodingType == SmsMessage.ENCODING_7BIT) ?
-                SmsMessage.MAX_USER_DATA_SEPTETS : SmsMessage.MAX_USER_DATA_BYTES;            
-        }
-
-        try {
-            while (start < size) {
-                int end = GsmAlphabet.findLimitIndex(text, start, limit, encodingType);
-                result.add(text.substring(start, end));
-                start = end;
-            }
-        } catch (EncodeException e) {
-            // ignore it.
-        }
-        return result;
+    @Deprecated
+    public final ArrayList<String> divideMessage(String text) {
+        return mSmsMgrProxy.divideMessage(text);
     }
 
     /**
      * Send a multi-part text based SMS.  The callee should have already
      * divided the message into correctly sized parts by calling
      * <code>divideMessage</code>.
-     * 
+     *
      * @param destinationAddress the address to send the message to
      * @param scAddress is the service center address or null to use
      *   the current default SMSC
      * @param parts an <code>ArrayList</code> of strings that, in order,
      *   comprise the original message
-     * @param sentIntents if not null, an <code>ArrayList</code> of 
+     * @param sentIntents if not null, an <code>ArrayList</code> of
      *   <code>PendingIntent</code>s (one for each message part) that is
      *   broadcast when the corresponding message part has been sent.
      *   The result code will be <code>Activity.RESULT_OK<code> for success,
@@ -145,44 +114,21 @@
      *   The per-application based SMS control checks sentIntent. If sentIntent
      *   is NULL the caller will be checked against all unknown applicaitons,
      *   which cause smaller number of SMS to be sent in checking period.
-     * @param deliveryIntents if not null, an <code>ArrayList</code> of 
+     * @param deliveryIntents if not null, an <code>ArrayList</code> of
      *   <code>PendingIntent</code>s (one for each message part) that is
      *   broadcast when the corresponding message part has been delivered
      *   to the recipient.  The raw pdu of the status report is in the
      *   extended data ("pdu").
+     *
+     * @throws IllegalArgumentException if destinationAddress or data are empty
+     * @deprecated Use android.telephony.SmsManager.
      */
-    public void sendMultipartTextMessage(
+    @Deprecated
+    public final void sendMultipartTextMessage(
             String destinationAddress, String scAddress, ArrayList<String> parts,
             ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) {
-        if (TextUtils.isEmpty(destinationAddress)) {
-            throw new IllegalArgumentException("Invalid destinationAddress");
-        }
-        if (parts == null || parts.size() < 1) {
-            throw new IllegalArgumentException("Invalid message body");
-        }
-        
-        if (parts.size() > 1) {
-            try {
-                ISms simISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
-                if (simISms != null) {
-                    simISms.sendMultipartText(destinationAddress, scAddress, parts,
-                            sentIntents, deliveryIntents);
-                }
-            } catch (RemoteException ex) {
-                // ignore it
-            }
-        } else {
-            PendingIntent sentIntent = null;
-            PendingIntent deliveryIntent = null;
-            if (sentIntents != null && sentIntents.size() > 0) {
-                sentIntent = sentIntents.get(0);
-            }
-            if (deliveryIntents != null && deliveryIntents.size() > 0) {
-                deliveryIntent = deliveryIntents.get(0);
-            }
-            sendTextMessage(destinationAddress, scAddress, parts.get(0),
-                    sentIntent, deliveryIntent);
-        }
+        mSmsMgrProxy.sendMultipartTextMessage(destinationAddress, scAddress, parts,
+                sentIntents, deliveryIntents);
     }
 
     /**
@@ -208,70 +154,14 @@
      *  raw pdu of the status report is in the extended data ("pdu").
      *
      * @throws IllegalArgumentException if destinationAddress or data are empty
+     * @deprecated Use android.telephony.SmsManager.
      */
-    public void sendDataMessage(
+    @Deprecated
+    public final void sendDataMessage(
             String destinationAddress, String scAddress, short destinationPort,
             byte[] data, PendingIntent sentIntent, PendingIntent deliveryIntent) {
-        if (TextUtils.isEmpty(destinationAddress)) {
-            throw new IllegalArgumentException("Invalid destinationAddress");
-        }
-
-        if (data == null || data.length == 0) {
-            throw new IllegalArgumentException("Invalid message data");
-        }
-
-        SmsMessage.SubmitPdu pdus = SmsMessage.getSubmitPdu(scAddress, destinationAddress,
-                destinationPort, data, (deliveryIntent != null));
-        sendRawPdu(pdus.encodedScAddress, pdus.encodedMessage, sentIntent, deliveryIntent);
-    }
-
-    /**
-     * Send a raw SMS PDU.
-     *
-     * @param smsc the SMSC to send the message through, or NULL for the
-     *  default SMSC
-     * @param pdu the raw PDU to send
-     * @param sentIntent if not NULL this <code>PendingIntent</code> is
-     *  broadcast when the message is sucessfully sent, or failed.
-     *  The result code will be <code>Activity.RESULT_OK<code> for success,
-     *  or one of these errors:
-     *  <code>RESULT_ERROR_GENERIC_FAILURE</code>
-     *  <code>RESULT_ERROR_RADIO_OFF</code>
-     *  <code>RESULT_ERROR_NULL_PDU</code>.
-     *  The per-application based SMS control checks sentIntent. If sentIntent
-     *  is NULL the caller will be checked against all unknown applicaitons,
-     *  which cause smaller number of SMS to be sent in checking period. 
-     * @param deliveryIntent if not NULL this <code>PendingIntent</code> is
-     *  broadcast when the message is delivered to the recipient.  The
-     *  raw pdu of the status report is in the extended data ("pdu").
-     *
-     */
-    private void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent,
-            PendingIntent deliveryIntent) {
-        try {
-            ISms simISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
-            if (simISms != null) {
-                simISms.sendRawPdu(smsc, pdu, sentIntent, deliveryIntent);
-            }
-        } catch (RemoteException ex) {
-            // ignore it
-        }
-    }
-
-    /**
-     * Get the default instance of the SmsManager
-     *
-     * @return the default instance of the SmsManager
-     */
-    public static SmsManager getDefault() {
-        if (sInstance == null) {
-            sInstance = new SmsManager();
-        }
-        return sInstance;
-    }
-
-    private SmsManager() {
-        // nothing to see here
+        mSmsMgrProxy.sendDataMessage(destinationAddress, scAddress, destinationPort,
+                data, sentIntent, deliveryIntent);
     }
 
     /**
@@ -282,22 +172,12 @@
      * @param status message status (STATUS_ON_SIM_READ, STATUS_ON_SIM_UNREAD,
      *               STATUS_ON_SIM_SENT, STATUS_ON_SIM_UNSENT)
      * @return true for success
-     *
+     * @deprecated Use android.telephony.SmsManager.
      * {@hide}
      */
-    public boolean copyMessageToSim(byte[] smsc, byte[] pdu, int status) {
-        boolean success = false;
-
-        try {
-            ISms simISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
-            if (simISms != null) {
-                success = simISms.copyMessageToSimEf(status, pdu, smsc);
-            }
-        } catch (RemoteException ex) {
-            // ignore it
-        }
-
-        return success;
+    @Deprecated
+    public final boolean copyMessageToSim(byte[] smsc, byte[] pdu, int status) {
+        return mSmsMgrProxy.copyMessageToIcc(smsc, pdu, status);
     }
 
     /**
@@ -305,26 +185,12 @@
      *
      * @param messageIndex is the record index of the message on SIM
      * @return true for success
-     *
+     * @deprecated Use android.telephony.SmsManager.
      * {@hide}
      */
-    public boolean
-    deleteMessageFromSim(int messageIndex) {
-        boolean success = false;
-        byte[] pdu = new byte[SimConstants.SMS_RECORD_LENGTH-1];
-        Arrays.fill(pdu, (byte)0xff);
-
-        try {
-            ISms simISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
-            if (simISms != null) {
-                success = simISms.updateMessageOnSimEf(messageIndex,
-                        STATUS_ON_SIM_FREE, pdu);
-            }
-        } catch (RemoteException ex) {
-            // ignore it
-        }
-
-        return success;
+    @Deprecated
+    public final boolean deleteMessageFromSim(int messageIndex) {
+        return mSmsMgrProxy.deleteMessageFromIcc(messageIndex);
     }
 
     /**
@@ -336,97 +202,59 @@
      *                  STATUS_ON_SIM_UNSENT, STATUS_ON_SIM_FREE)
      * @param pdu the raw PDU to store
      * @return true for success
-     *
+     * @deprecated Use android.telephony.SmsManager.
      * {@hide}
      */
-    public boolean updateMessageOnSim(int messageIndex, int newStatus,
-            byte[] pdu) {
-        boolean success = false;
-
-        try {
-            ISms simISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
-            if (simISms != null) {
-                success = simISms.updateMessageOnSimEf(messageIndex, newStatus, pdu);
-            }
-        } catch (RemoteException ex) {
-            // ignore it
-        }
-
-        return success;
+    @Deprecated
+    public final boolean updateMessageOnSim(int messageIndex, int newStatus, byte[] pdu) {
+        return mSmsMgrProxy.updateMessageOnIcc(messageIndex, newStatus, pdu);
     }
 
-
     /**
      * Retrieves all messages currently stored on SIM.
-     *
      * @return <code>ArrayList</code> of <code>SmsMessage</code> objects
-     *
+     * @deprecated Use android.telephony.SmsManager.
      * {@hide}
      */
-    public ArrayList<SmsMessage> getAllMessagesFromSim() {
-        List<SmsRawData> records = null;
-
-        try {
-            ISms simISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
-            if (simISms != null) {
-                records = simISms.getAllMessagesFromSimEf();
-            }
-        } catch (RemoteException ex) {
-            // ignore it
-        }
-        
-        return createMessageListFromRawRecords(records); 
-   }
-
-    /**
-     * Create a list of <code>SmsMessage</code>s from a list of RawSmsData
-     * records returned by <code>getAllMessagesFromSim()</code>
-     *
-     * @param records SMS EF records, returned by
-     *   <code>getAllMessagesFromSim</code>
-     * @return <code>ArrayList</code> of <code>SmsMessage</code> objects.
-     */
-    private ArrayList<SmsMessage> createMessageListFromRawRecords(List records) {
-        ArrayList<SmsMessage> messages = new ArrayList<SmsMessage>();
-        if (records != null) {
-            int count = records.size();
-            for (int i = 0; i < count; i++) {
-                SmsRawData data = (SmsRawData)records.get(i);
-                // List contains all records, including "free" records (null)
-                if (data != null) {
-                    SmsMessage sms =
-                            SmsMessage.createFromEfRecord(i+1, data.getBytes());
-                    messages.add(sms);
-                }
-            }
-        }
-        return messages;
+    @Deprecated
+    public final ArrayList<android.telephony.SmsMessage> getAllMessagesFromSim() {
+        return mSmsMgrProxy.getAllMessagesFromIcc();
     }
 
-    /** Free space (TS 51.011 10.5.3). */
-    static public final int STATUS_ON_SIM_FREE      = 0;
+    /** Free space (TS 51.011 10.5.3).
+     *  @deprecated Use android.telephony.SmsManager. */
+    @Deprecated static public final int STATUS_ON_SIM_FREE      = 0;
 
-    /** Received and read (TS 51.011 10.5.3). */
-    static public final int STATUS_ON_SIM_READ      = 1;
+    /** Received and read (TS 51.011 10.5.3).
+     * @deprecated Use android.telephony.SmsManager. */
+    @Deprecated static public final int STATUS_ON_SIM_READ      = 1;
 
-    /** Received and unread (TS 51.011 10.5.3). */
-    static public final int STATUS_ON_SIM_UNREAD    = 3;
+    /** Received and unread (TS 51.011 10.5.3).
+     * @deprecated Use android.telephony.SmsManager. */
+    @Deprecated static public final int STATUS_ON_SIM_UNREAD    = 3;
 
-    /** Stored and sent (TS 51.011 10.5.3). */
-    static public final int STATUS_ON_SIM_SENT      = 5;
+    /** Stored and sent (TS 51.011 10.5.3).
+     * @deprecated Use android.telephony.SmsManager. */
+    @Deprecated static public final int STATUS_ON_SIM_SENT      = 5;
 
-    /** Stored and unsent (TS 51.011 10.5.3). */
-    static public final int STATUS_ON_SIM_UNSENT    = 7;
+    /** Stored and unsent (TS 51.011 10.5.3).
+     * @deprecated Use android.telephony.SmsManager. */
+    @Deprecated static public final int STATUS_ON_SIM_UNSENT    = 7;
 
+    /** Generic failure cause
+     * @deprecated Use android.telephony.SmsManager. */
+    @Deprecated static public final int RESULT_ERROR_GENERIC_FAILURE    = 1;
 
-    // SMS send failure result codes
+    /** Failed because radio was explicitly turned off
+     * @deprecated Use android.telephony.SmsManager. */
+    @Deprecated static public final int RESULT_ERROR_RADIO_OFF          = 2;
 
-    /** Generic failure cause */
-    static public final int RESULT_ERROR_GENERIC_FAILURE    = 1;
-    /** Failed because radio was explicitly turned off */
-    static public final int RESULT_ERROR_RADIO_OFF          = 2;
-    /** Failed because no pdu provided */
-    static public final int RESULT_ERROR_NULL_PDU           = 3;
-    /** Failed because service is currently unavailable */
-    static public final int RESULT_ERROR_NO_SERVICE         = 4;
+    /** Failed because no pdu provided
+     * @deprecated Use android.telephony.SmsManager. */
+    @Deprecated static public final int RESULT_ERROR_NULL_PDU           = 3;
+
+    /** Failed because service is currently unavailable
+     * @deprecated Use android.telephony.SmsManager. */
+    @Deprecated static public final int RESULT_ERROR_NO_SERVICE         = 4;
+
 }
diff --git a/telephony/java/android/telephony/gsm/SmsMessage.java b/telephony/java/android/telephony/gsm/SmsMessage.java
index c2e0165..0928ddf 100644
--- a/telephony/java/android/telephony/gsm/SmsMessage.java
+++ b/telephony/java/android/telephony/gsm/SmsMessage.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 The Android Open Source Project
+ * Copyright (C) 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.
@@ -16,327 +16,117 @@
 
 package android.telephony.gsm;
 
-import android.telephony.PhoneNumberUtils;
-import android.util.Config;
-import android.util.Log;
-import android.telephony.PhoneNumberUtils;
-import android.text.format.Time;
+import android.os.Parcel;
+import android.telephony.TelephonyManager;
 
-import com.android.internal.telephony.gsm.EncodeException;
-import com.android.internal.telephony.gsm.GsmAlphabet;
-import com.android.internal.telephony.gsm.SimUtils;
-import com.android.internal.telephony.gsm.SmsHeader;
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.EncodeException;
+import com.android.internal.telephony.SmsMessageBase;
+import com.android.internal.telephony.SmsMessageBase.SubmitPduBase;
 
-import java.io.ByteArrayOutputStream;
-import java.io.UnsupportedEncodingException;
 import java.util.Arrays;
 
-class SmsAddress {
-    // From TS 23.040 9.1.2.5 and TS 24.008 table 10.5.118
-    static final int TON_UNKNOWN = 0;
+import static android.telephony.TelephonyManager.PHONE_TYPE_CDMA;
 
-    static final int TON_INTERNATIONAL = 1;
-
-    static final int TON_NATIONAL = 2;
-
-    static final int TON_NETWORK = 3;
-
-    static final int TON_SUBSCRIBER = 4;
-
-    static final int TON_ALPHANUMERIC = 5;
-
-    static final int TON_APPREVIATED = 6;
-
-    static final int OFFSET_ADDRESS_LENGTH = 0;
-
-    static final int OFFSET_TOA = 1;
-
-    static final int OFFSET_ADDRESS_VALUE = 2;
-
-    int ton;
-
-    String address;
-
-    byte[] origBytes;
-
-    /**
-     * New SmsAddress from TS 23.040 9.1.2.5 Address Field
-     *
-     * @param offset the offset of the Address-Length byte
-     * @param length the length in bytes rounded up, e.g. "2 +
-     *        (addressLength + 1) / 2"
-     */
-
-    SmsAddress(byte[] data, int offset, int length) {
-        origBytes = new byte[length];
-        System.arraycopy(data, offset, origBytes, 0, length);
-
-        // addressLength is the count of semi-octets, not bytes
-        int addressLength = origBytes[OFFSET_ADDRESS_LENGTH] & 0xff;
-
-        int toa = origBytes[OFFSET_TOA] & 0xff;
-        ton = 0x7 & (toa >> 4);
-
-        // TOA must have its high bit set
-        if ((toa & 0x80) != 0x80) {
-            throw new RuntimeException("Invalid TOA - high bit must be set");
-        }
-
-        if (isAlphanumeric()) {
-            // An alphanumeric address
-            int countSeptets = addressLength * 4 / 7;
-
-            address = GsmAlphabet.gsm7BitPackedToString(origBytes,
-                    OFFSET_ADDRESS_VALUE, countSeptets);
-        } else {
-            // TS 23.040 9.1.2.5 says
-            // that "the MS shall interpret reserved values as 'Unknown'
-            // but shall store them exactly as received"
-
-            byte lastByte = origBytes[length - 1];
-
-            if ((addressLength & 1) == 1) {
-                // Make sure the final unused BCD digit is 0xf
-                origBytes[length - 1] |= 0xf0;
-            }
-            address = PhoneNumberUtils.calledPartyBCDToString(origBytes,
-                    OFFSET_TOA, length - OFFSET_TOA);
-
-            // And restore origBytes
-            origBytes[length - 1] = lastByte;
-        }
-    }
-
-    public String getAddressString() {
-        return address;
-    }
-
-    /**
-     * Returns true if this is an alphanumeric addres
-     */
-    public boolean isAlphanumeric() {
-        return ton == TON_ALPHANUMERIC;
-    }
-
-    public boolean isNetworkSpecific() {
-        return ton == TON_NETWORK;
-    }
-
-    /**
-     * Returns true of this is a valid CPHS voice message waiting indicator
-     * address
-     */
-    public boolean isCphsVoiceMessageIndicatorAddress() {
-        // CPHS-style MWI message
-        // See CPHS 4.7 B.4.2.1
-        //
-        // Basically:
-        //
-        // - Originating address should be 4 bytes long and alphanumeric
-        // - Decode will result with two chars:
-        // - Char 1
-        // 76543210
-        // ^ set/clear indicator (0 = clear)
-        // ^^^ type of indicator (000 = voice)
-        // ^^^^ must be equal to 0001
-        // - Char 2:
-        // 76543210
-        // ^ line number (0 = line 1)
-        // ^^^^^^^ set to 0
-        //
-        // Remember, since the alpha address is stored in 7-bit compact form,
-        // the "line number" is really the top bit of the first address value
-        // byte
-
-        return (origBytes[OFFSET_ADDRESS_LENGTH] & 0xff) == 4
-                && isAlphanumeric() && (origBytes[OFFSET_TOA] & 0x0f) == 0;
-    }
-
-    /**
-     * Returns true if this is a valid CPHS voice message waiting indicator
-     * address indicating a "set" of "indicator 1" of type "voice message
-     * waiting"
-     */
-    public boolean isCphsVoiceMessageSet() {
-        // 0x11 means "set" "voice message waiting" "indicator 1"
-        return isCphsVoiceMessageIndicatorAddress()
-                && (origBytes[OFFSET_ADDRESS_VALUE] & 0xff) == 0x11;
-
-    }
-
-    /**
-     * Returns true if this is a valid CPHS voice message waiting indicator
-     * address indicationg a "clear" of "indicator 1" of type "voice message
-     * waiting"
-     */
-    public boolean isCphsVoiceMessageClear() {
-        // 0x10 means "clear" "voice message waiting" "indicator 1"
-        return isCphsVoiceMessageIndicatorAddress()
-                && (origBytes[OFFSET_ADDRESS_VALUE] & 0xff) == 0x10;
-
-    }
-
-    public boolean couldBeEmailGateway() {
-        // Some carriers seems to send email gateway messages in this form:
-        // from: an UNKNOWN TON, 3 or 4 digits long, beginning with a 5
-        // PID: 0x00, Data coding scheme 0x03
-        // So we just attempt to treat any message from an address length <= 4
-        // as an email gateway
-
-        return address.length() <= 4;
-    }
-
-}
 
 /**
  * A Short Message Service message.
- *
+ * @deprecated Replaced by android.telephony.SmsMessage that supports both GSM and CDMA.
  */
+@Deprecated
 public class SmsMessage {
-    static final String LOG_TAG = "GSM";
+    private static final boolean LOCAL_DEBUG = true;
+    private static final String LOG_TAG = "SMS";
 
     /**
      * SMS Class enumeration.
      * See TS 23.038.
-     *
+     * @deprecated Use android.telephony.SmsMessage.
      */
-    public enum MessageClass {
+    @Deprecated
+    public enum MessageClass{
         UNKNOWN, CLASS_0, CLASS_1, CLASS_2, CLASS_3;
     }
 
-    /** Unknown encoding scheme (see TS 23.038) */
-    public static final int ENCODING_UNKNOWN = 0;
-    /** 7-bit encoding scheme (see TS 23.038) */
-    public static final int ENCODING_7BIT = 1;
-    /** 8-bit encoding scheme (see TS 23.038) */
-    public static final int ENCODING_8BIT = 2;
-    /** 16-bit encoding scheme (see TS 23.038) */
-    public static final int ENCODING_16BIT = 3;
+    /** Unknown encoding scheme (see TS 23.038)
+     * @deprecated Use android.telephony.SmsMessage.
+     */
+    @Deprecated public static final int ENCODING_UNKNOWN = 0;
 
-    /** The maximum number of payload bytes per message */
-    public static final int MAX_USER_DATA_BYTES = 140;
+    /** 7-bit encoding scheme (see TS 23.038)
+     * @deprecated Use android.telephony.SmsMessage.
+     */
+    @Deprecated public static final int ENCODING_7BIT = 1;
+
+    /** 8-bit encoding scheme (see TS 23.038)
+     * @deprecated Use android.telephony.SmsMessage.
+     */
+    @Deprecated public static final int ENCODING_8BIT = 2;
+
+    /** 16-bit encoding scheme (see TS 23.038)
+     * @deprecated Use android.telephony.SmsMessage.
+     */
+    @Deprecated public static final int ENCODING_16BIT = 3;
+
+    /** The maximum number of payload bytes per message
+     * @deprecated Use android.telephony.SmsMessage.
+     */
+    @Deprecated public static final int MAX_USER_DATA_BYTES = 140;
 
     /**
      * The maximum number of payload bytes per message if a user data header
      * is present.  This assumes the header only contains the
      * CONCATENATED_8_BIT_REFERENCE element.
-     * 
+     *
+     * @deprecated Use android.telephony.SmsMessage.
      * @hide pending API Council approval to extend the public API
      */
-    static final int MAX_USER_DATA_BYTES_WITH_HEADER = 134;
+    @Deprecated public static final int MAX_USER_DATA_BYTES_WITH_HEADER = 134;
 
-    /** The maximum number of payload septets per message */
-    public static final int MAX_USER_DATA_SEPTETS = 160;
+    /** The maximum number of payload septets per message
+     * @deprecated Use android.telephony.SmsMessage.
+     */
+    @Deprecated public static final int MAX_USER_DATA_SEPTETS = 160;
 
     /**
      * The maximum number of payload septets per message if a user data header
      * is present.  This assumes the header only contains the
      * CONCATENATED_8_BIT_REFERENCE element.
+     * @deprecated Use android.telephony.SmsMessage.
      */
-    public static final int MAX_USER_DATA_SEPTETS_WITH_HEADER = 153;
+    @Deprecated public static final int MAX_USER_DATA_SEPTETS_WITH_HEADER = 153;
 
-    /** The address of the SMSC. May be null */
-    String scAddress;
-
-    /** The address of the sender */
-    SmsAddress originatingAddress;
-
-    /** The message body as a string. May be null if the message isn't text */
-    String messageBody;
-
-    String pseudoSubject;
-
-    /** Non-null  this is an email gateway message */
-    String emailFrom;
-
-    /** Non-null if this is an email gateway message */
-    String emailBody;
-
-    boolean isEmail;
-
-    long scTimeMillis;
-
-    /** The raw PDU of the message */
-    byte[] mPdu;
-
-    /** The raw bytes for the user data section of the message */
-    byte[] userData;
-
-    SmsHeader userDataHeader;
-
-    /**
-     * TP-Message-Type-Indicator
-     * 9.2.3
+    /** Contains actual SmsMessage. Only public for debugging and for framework layer.
+     * @deprecated Use android.telephony.SmsMessage.
+     * {@hide}
      */
-    int mti;
+    @Deprecated public SmsMessageBase mWrappedSmsMessage;
 
-    /** TP-Protocol-Identifier (TP-PID) */
-    int protocolIdentifier;
-
-    // TP-Data-Coding-Scheme
-    // see TS 23.038
-    int dataCodingScheme;
-
-    // TP-Reply-Path
-    // e.g. 23.040 9.2.2.1
-    boolean replyPathPresent = false;
-
-    // "Message Marked for Automatic Deletion Group"
-    // 23.038 Section 4
-    boolean automaticDeletion;
-
-    // "Message Waiting Indication Group"
-    // 23.038 Section 4
-    private boolean isMwi;
-
-    private boolean mwiSense;
-
-    private boolean mwiDontStore;
-
-    MessageClass messageClass;
-
-    /**
-     * Indicates status for messages stored on the SIM.
-     */
-    int statusOnSim = -1;
-
-    /**
-     * Record index of message in the EF.
-     */
-    int indexOnSim = -1;
-
-    /** TP-Message-Reference - Message Reference of sent message. @hide */
-    public int messageRef;
-
-    /** True if Status Report is for SMS-SUBMIT; false for SMS-COMMAND. */
-    boolean forSubmit;
-
-    /** The address of the receiver. */
-    SmsAddress recipientAddress;
-
-    /** Time when SMS-SUBMIT was delivered from SC to MSE. */
-    long dischargeTimeMillis;
-
-    /**
-     *  TP-Status - status of a previously submitted SMS.
-     *  This field applies to SMS-STATUS-REPORT messages.  0 indicates success;
-     *  see TS 23.040, 9.2.3.15 for description of other possible values.
-     */
-    int status;
-
-    /**
-     *  TP-Status - status of a previously submitted SMS.
-     *  This field is true iff the message is a SMS-STATUS-REPORT message.
-     */
-    boolean isStatusReportMessage = false;
-
-    /**
-     * This class represents the encoded form of an outgoing SMS.
-     */
+    /** @deprecated Use android.telephony.SmsMessage. */
+    @Deprecated
     public static class SubmitPdu {
-        public byte[] encodedScAddress; // Null if not applicable.
-        public byte[] encodedMessage;
+        /** @deprecated Use android.telephony.SmsMessage. */
+        @Deprecated public byte[] encodedScAddress; // Null if not applicable.
+        /** @deprecated Use android.telephony.SmsMessage. */
+        @Deprecated public byte[] encodedMessage;
 
+        //Constructor
+        /** @deprecated Use android.telephony.SmsMessage. */
+        @Deprecated
+        public SubmitPdu() {
+        }
+
+        /** @deprecated Use android.telephony.SmsMessage.
+         * {@hide}
+         */
+        @Deprecated
+        protected SubmitPdu(SubmitPduBase spb) {
+            this.encodedMessage = spb.encodedMessage;
+            this.encodedScAddress = spb.encodedScAddress;
+        }
+
+        /** @deprecated Use android.telephony.SmsMessage. */
+        @Deprecated
         public String toString() {
             return "SubmitPdu: encodedScAddress = "
                     + Arrays.toString(encodedScAddress)
@@ -345,18 +135,33 @@
         }
     }
 
+    // Constructor
+    /** @deprecated Use android.telephony.SmsMessage. */
+    @Deprecated
+    public SmsMessage() {
+        this(getSmsFacility());
+    }
+
+    private SmsMessage(SmsMessageBase smb) {
+        mWrappedSmsMessage = smb;
+    }
+
     /**
      * Create an SmsMessage from a raw PDU.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public static SmsMessage createFromPdu(byte[] pdu) {
-        try {
-            SmsMessage msg = new SmsMessage();
-            msg.parsePdu(pdu);
-            return msg;
-        } catch (RuntimeException ex) {
-            Log.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
-            return null;
+        SmsMessageBase wrappedMessage;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.createFromPdu(pdu);
+        } else {
+            wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.createFromPdu(pdu);
         }
+
+        return new SmsMessage(wrappedMessage);
     }
 
     /**
@@ -364,38 +169,70 @@
      * +CMT unsolicited response (PDU mode, of course)
      *  +CMT: [&lt;alpha>],<length><CR><LF><pdu>
      *
-     * Only public for debugging
-     *
+     * Only public for debugging and for RIL
+     * @deprecated Use android.telephony.SmsMessage.
      * {@hide}
      */
-    /* package */ public static SmsMessage newFromCMT(String[] lines) {
-        try {
-            SmsMessage msg = new SmsMessage();
-            msg.parsePdu(SimUtils.hexStringToBytes(lines[1]));
-            return msg;
-        } catch (RuntimeException ex) {
-            Log.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
-            return null;
+    @Deprecated
+    public static SmsMessage newFromCMT(String[] lines){
+        SmsMessageBase wrappedMessage;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.newFromCMT(lines);
+        } else {
+            wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.newFromCMT(lines);
         }
+
+        return new SmsMessage(wrappedMessage);
     }
 
-    /* pacakge */ static SmsMessage newFromCMTI(String line) {
-        // the thinking here is not to read the message immediately
-        // FTA test case
-        Log.e(LOG_TAG, "newFromCMTI: not yet supported");
-        return null;
+    /** @deprecated Use android.telephony.SmsMessage.
+     *  @hide */
+    @Deprecated
+    protected static SmsMessage newFromCMTI(String line) {
+        SmsMessageBase wrappedMessage;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.newFromCMTI(line);
+        } else {
+            wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.newFromCMTI(line);
+        }
+
+        return new SmsMessage(wrappedMessage);
     }
 
-    /** @hide */
-    /* package */ public static SmsMessage newFromCDS(String line) {
-        try {
-            SmsMessage msg = new SmsMessage();
-            msg.parsePdu(SimUtils.hexStringToBytes(line));
-            return msg;
-        } catch (RuntimeException ex) {
-            Log.e(LOG_TAG, "CDS SMS PDU parsing failed: ", ex);
-            return null;
+    /** @deprecated Use android.telephony.SmsMessage.
+     *  @hide */
+    @Deprecated
+    public static SmsMessage newFromCDS(String line) {
+        SmsMessageBase wrappedMessage;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.newFromCDS(line);
+        } else {
+            wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.newFromCDS(line);
         }
+
+        return new SmsMessage(wrappedMessage);
+    }
+
+    /** @deprecated Use android.telephony.SmsMessage.
+     *  @hide */
+    @Deprecated
+    public static SmsMessage newFromParcel(Parcel p) {
+        SmsMessageBase wrappedMessage;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+
+        if (PHONE_TYPE_CDMA == activePhone) {
+            wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.newFromParcel(p);
+        } else {
+            wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.newFromParcel(p);
+        }
+
+        return new SmsMessage(wrappedMessage);
     }
 
     /**
@@ -405,51 +242,40 @@
      *              returned by SmsManager.getAllMessagesFromSim + 1.
      * @param data Record data.
      * @return An SmsMessage representing the record.
-     * 
+     *
+     * @deprecated Use android.telephony.SmsMessage.
      * @hide
      */
+    @Deprecated
     public static SmsMessage createFromEfRecord(int index, byte[] data) {
-        try {
-            SmsMessage msg = new SmsMessage();
+        SmsMessageBase wrappedMessage;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
 
-            msg.indexOnSim = index;
-
-            // First byte is status: RECEIVED_READ, RECEIVED_UNREAD, STORED_SENT,
-            // or STORED_UNSENT
-            // See TS 51.011 10.5.3
-            if ((data[0] & 1) == 0) {
-                Log.w(LOG_TAG,
-                        "SMS parsing failed: Trying to parse a free record");
-                return null;
-            } else {
-                msg.statusOnSim = data[0] & 0x07;
-            }
-
-            int size = data.length - 1;
-
-            // Note: Data may include trailing FF's.  That's OK; message
-            // should still parse correctly.
-            byte[] pdu = new byte[size];
-            System.arraycopy(data, 1, pdu, 0, size);
-            msg.parsePdu(pdu);
-            return msg;
-        } catch (RuntimeException ex) {
-            Log.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
-            return null;
+        if (PHONE_TYPE_CDMA == activePhone) {
+            wrappedMessage = com.android.internal.telephony.cdma.SmsMessage.createFromEfRecord(
+                    index, data);
+        } else {
+            wrappedMessage = com.android.internal.telephony.gsm.SmsMessage.createFromEfRecord(
+                    index, data);
         }
+
+        return new SmsMessage(wrappedMessage);
     }
 
     /**
      * Get the TP-Layer-Length for the given SMS-SUBMIT PDU Basically, the
      * length in bytes (not hex chars) less the SMSC header
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public static int getTPLayerLengthForPDU(String pdu) {
-        int len = pdu.length() / 2;
-        int smscLen = 0;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
 
-        smscLen = Integer.parseInt(pdu.substring(0, 2), 16);
-
-        return len - smscLen - 1;
+        if (PHONE_TYPE_CDMA == activePhone) {
+            return com.android.internal.telephony.cdma.SmsMessage.getTPLayerLengthForPDU(pdu);
+        } else {
+            return com.android.internal.telephony.gsm.SmsMessage.getTPLayerLengthForPDU(pdu);
+        }
     }
 
     /**
@@ -466,7 +292,9 @@
      *         the number of code units used, and int[2] is the number of code
      *         units remaining until the next message. int[3] is the encoding
      *         type that should be used for the message.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public static int[] calculateLength(CharSequence messageBody, boolean use7bitOnly) {
         int ret[] = new int[4];
 
@@ -517,10 +345,10 @@
      *         units remaining until the next message. int[3] is the encoding
      *         type that should be used for the message.
      */
+    @Deprecated
     public static int[] calculateLength(String messageBody, boolean use7bitOnly) {
         return calculateLength((CharSequence)messageBody, use7bitOnly);
     }
-    
 
     /**
      * Get an SMS-SUBMIT PDU for a destination address and a message
@@ -529,92 +357,27 @@
      * @return a <code>SubmitPdu</code> containing the encoded SC
      *         address, if applicable, and the encoded message.
      *         Returns null on encode error.
+     * @deprecated Use android.telephony.SmsMessage.
      * @hide
      */
+    @Deprecated
     public static SubmitPdu getSubmitPdu(String scAddress,
             String destinationAddress, String message,
             boolean statusReportRequested, byte[] header) {
+        SubmitPduBase spb;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
 
-        // Perform null parameter checks.
-        if (message == null || destinationAddress == null) {
-            return null;
+        if (PHONE_TYPE_CDMA == activePhone) {
+            spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress,
+                    destinationAddress, message, statusReportRequested, header);
+        } else {
+            spb = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(scAddress,
+                    destinationAddress, message, statusReportRequested, header);
         }
 
-        SubmitPdu ret = new SubmitPdu();
-        // MTI = SMS-SUBMIT, UDHI = header != null
-        byte mtiByte = (byte)(0x01 | (header != null ? 0x40 : 0x00));
-        ByteArrayOutputStream bo = getSubmitPduHead(
-                scAddress, destinationAddress, mtiByte,
-                statusReportRequested, ret);
-
-        try {
-            // First, try encoding it with the GSM alphabet
-
-            // User Data (and length)
-            byte[] userData = GsmAlphabet.stringToGsm7BitPackedWithHeader(message, header);
-
-            if ((0xff & userData[0]) > MAX_USER_DATA_SEPTETS) {
-                // Message too long
-                return null;
-            }
-
-            // TP-Data-Coding-Scheme
-            // Default encoding, uncompressed
-            // To test writing messages to the SIM card, change this value 0x00 to 0x12, which
-            // means "bits 1 and 0 contain message class, and the class is 2". Note that this
-            // takes effect for the sender. In other words, messages sent by the phone with this
-            // change will end up on the receiver's SIM card. You can then send messages to
-            // yourself (on a phone with this change) and they'll end up on the SIM card.
-            bo.write(0x00); 
-
-            // (no TP-Validity-Period)
-
-            bo.write(userData, 0, userData.length);
-        } catch (EncodeException ex) {
-            byte[] userData, textPart;
-            // Encoding to the 7-bit alphabet failed. Let's see if we can
-            // send it as a UCS-2 encoded message
-
-            try {
-                textPart = message.getBytes("utf-16be");
-            } catch (UnsupportedEncodingException uex) {
-                Log.e(LOG_TAG,
-                      "Implausible UnsupportedEncodingException ",
-                      uex);
-                return null;
-            }
-            
-            if (header != null) {
-                userData = new byte[header.length + textPart.length];
-                
-                System.arraycopy(header, 0, userData, 0, header.length);
-                System.arraycopy(textPart, 0, userData, header.length, textPart.length);
-            } else {
-                userData = textPart;
-            }
-
-            if (userData.length > MAX_USER_DATA_BYTES) {
-                // Message too long
-                return null;
-            }
-
-            // TP-Data-Coding-Scheme
-            // Class 3, UCS-2 encoding, uncompressed
-            bo.write(0x0b);
-
-            // (no TP-Validity-Period)
-            
-            // TP-UDL
-            bo.write(userData.length);
-
-            bo.write(userData, 0, userData.length);
-        }
-
-        ret.encodedMessage = bo.toByteArray();
-        return ret;
+        return new SubmitPdu(spb);
     }
 
-
     /**
      * Get an SMS-SUBMIT PDU for a destination address and a message
      *
@@ -622,12 +385,23 @@
      * @return a <code>SubmitPdu</code> containing the encoded SC
      *         address, if applicable, and the encoded message.
      *         Returns null on encode error.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public static SubmitPdu getSubmitPdu(String scAddress,
-            String destinationAddress, String message,
-            boolean statusReportRequested) {
+            String destinationAddress, String message, boolean statusReportRequested) {
+        SubmitPduBase spb;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
 
-        return getSubmitPdu(scAddress, destinationAddress, message, statusReportRequested, null);
+        if (PHONE_TYPE_CDMA == activePhone) {
+            spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress,
+                    destinationAddress, message, statusReportRequested);
+        } else {
+            spb = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(scAddress,
+                    destinationAddress, message, statusReportRequested);
+        }
+
+        return new SubmitPdu(spb);
     }
 
     /**
@@ -641,478 +415,105 @@
      * @return a <code>SubmitPdu</code> containing the encoded SC
      *         address, if applicable, and the encoded message.
      *         Returns null on encode error.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public static SubmitPdu getSubmitPdu(String scAddress,
             String destinationAddress, short destinationPort, byte[] data,
             boolean statusReportRequested) {
-        if (data.length > (MAX_USER_DATA_BYTES - 7 /* UDH size */)) {
-            Log.e(LOG_TAG, "SMS data message may only contain "
-                    + (MAX_USER_DATA_BYTES - 7) + " bytes");
-            return null;
-        }
+        SubmitPduBase spb;
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
 
-        SubmitPdu ret = new SubmitPdu();
-        ByteArrayOutputStream bo = getSubmitPduHead(
-                scAddress, destinationAddress, (byte) 0x41, // MTI = SMS-SUBMIT,
-                                                            // TP-UDHI = true
-                statusReportRequested, ret);
-
-        // TP-Data-Coding-Scheme
-        // No class, 8 bit data
-        bo.write(0x04);
-
-        // (no TP-Validity-Period)
-
-        // User data size
-        bo.write(data.length + 7);
-
-        // User data header size
-        bo.write(0x06); // header is 6 octets
-
-        // User data header, indicating the destination port
-        bo.write(SmsHeader.APPLICATION_PORT_ADDRESSING_16_BIT); // port
-                                                                // addressing
-                                                                // header
-        bo.write(0x04); // each port is 2 octets
-        bo.write((destinationPort >> 8) & 0xFF); // MSB of destination port
-        bo.write(destinationPort & 0xFF); // LSB of destination port
-        bo.write(0x00); // MSB of originating port
-        bo.write(0x00); // LSB of originating port
-
-        // User data
-        bo.write(data, 0, data.length);
-
-        ret.encodedMessage = bo.toByteArray();
-        return ret;
-    }
-
-    /**
-     * Create the beginning of a SUBMIT PDU.  This is the part of the
-     * SUBMIT PDU that is common to the two versions of {@link #getSubmitPdu},
-     * one of which takes a byte array and the other of which takes a
-     * <code>String</code>.
-     *
-     * @param scAddress Service Centre address. null == use default
-     * @param destinationAddress the address of the destination for the message
-     * @param mtiByte
-     * @param ret <code>SubmitPdu</code> containing the encoded SC
-     *        address, if applicable, and the encoded message
-     */
-    private static ByteArrayOutputStream getSubmitPduHead(
-            String scAddress, String destinationAddress, byte mtiByte,
-            boolean statusReportRequested, SubmitPdu ret) {
-        ByteArrayOutputStream bo = new ByteArrayOutputStream(
-                MAX_USER_DATA_BYTES + 40);
-
-        // SMSC address with length octet, or 0
-        if (scAddress == null) {
-            ret.encodedScAddress = null;
+        if (PHONE_TYPE_CDMA == activePhone) {
+            spb = com.android.internal.telephony.cdma.SmsMessage.getSubmitPdu(scAddress,
+                    destinationAddress, destinationPort, data, statusReportRequested);
         } else {
-            ret.encodedScAddress = PhoneNumberUtils.networkPortionToCalledPartyBCDWithLength(
-                    scAddress);
+            spb = com.android.internal.telephony.gsm.SmsMessage.getSubmitPdu(scAddress,
+                    destinationAddress, destinationPort, data, statusReportRequested);
         }
 
-        // TP-Message-Type-Indicator (and friends)
-        if (statusReportRequested) {
-            // Set TP-Status-Report-Request bit.
-            mtiByte |= 0x20;
-            if (Config.LOGD) Log.d(LOG_TAG, "SMS status report requested");
-        }
-        bo.write(mtiByte);
-
-        // space for TP-Message-Reference
-        bo.write(0);
-
-        byte[] daBytes;
-
-        daBytes = PhoneNumberUtils.networkPortionToCalledPartyBCD(destinationAddress);
-
-        // destination address length in BCD digits, ignoring TON byte and pad
-        // TODO Should be better.
-        bo.write((daBytes.length - 1) * 2
-                - ((daBytes[daBytes.length - 1] & 0xf0) == 0xf0 ? 1 : 0));
-
-        // destination address
-        bo.write(daBytes, 0, daBytes.length);
-
-        // TP-Protocol-Identifier
-        bo.write(0);
-        return bo;
-    }
-
-    static class PduParser {
-        byte pdu[];
-
-        int cur;
-
-        SmsHeader userDataHeader;
-
-        byte[] userData;
-
-        int mUserDataSeptetPadding;
-
-        int mUserDataSize;
-
-        PduParser(String s) {
-            this(SimUtils.hexStringToBytes(s));
-        }
-
-        PduParser(byte[] pdu) {
-            this.pdu = pdu;
-            cur = 0;
-            mUserDataSeptetPadding = 0;
-        }
-
-        /**
-         * Parse and return the SC address prepended to SMS messages coming via
-         * the TS 27.005 / AT interface.  Returns null on invalid address
-         */
-        String getSCAddress() {
-            int len;
-            String ret;
-
-            // length of SC Address
-            len = getByte();
-
-            if (len == 0) {
-                // no SC address
-                ret = null;
-            } else {
-                // SC address
-                try {
-                    ret = PhoneNumberUtils
-                            .calledPartyBCDToString(pdu, cur, len);
-                } catch (RuntimeException tr) {
-                    Log.d(LOG_TAG, "invalid SC address: ", tr);
-                    ret = null;
-                }
-            }
-
-            cur += len;
-
-            return ret;
-        }
-
-        /**
-         * returns non-sign-extended byte value
-         */
-        int getByte() {
-            return pdu[cur++] & 0xff;
-        }
-
-        /**
-         * Any address except the SC address (eg, originating address) See TS
-         * 23.040 9.1.2.5
-         */
-        SmsAddress getAddress() {
-            SmsAddress ret;
-
-            // "The Address-Length field is an integer representation of
-            // the number field, i.e. excludes any semi octet containing only
-            // fill bits."
-            // The TOA field is not included as part of this
-            int addressLength = pdu[cur] & 0xff;
-            int lengthBytes = 2 + (addressLength + 1) / 2;
-
-            ret = new SmsAddress(pdu, cur, lengthBytes);
-
-            cur += lengthBytes;
-
-            return ret;
-        }
-
-        /**
-         * Parses an SC timestamp and returns a currentTimeMillis()-style
-         * timestamp
-         */
-
-        long getSCTimestampMillis() {
-            // TP-Service-Centre-Time-Stamp
-            int year = SimUtils.bcdByteToInt(pdu[cur++]);
-            int month = SimUtils.bcdByteToInt(pdu[cur++]);
-            int day = SimUtils.bcdByteToInt(pdu[cur++]);
-            int hour = SimUtils.bcdByteToInt(pdu[cur++]);
-            int minute = SimUtils.bcdByteToInt(pdu[cur++]);
-            int second = SimUtils.bcdByteToInt(pdu[cur++]);
-
-            // For the timezone, the most significant bit of the
-            // least signficant nibble is the sign byte
-            // (meaning the max range of this field is 79 quarter-hours,
-            // which is more than enough)
-
-            byte tzByte = pdu[cur++];
-
-            // Mask out sign bit.
-            int timezoneOffset = SimUtils
-                    .bcdByteToInt((byte) (tzByte & (~0x08)));
-
-            timezoneOffset = ((tzByte & 0x08) == 0) ? timezoneOffset
-                    : -timezoneOffset;
-
-            Time time = new Time(Time.TIMEZONE_UTC);
-
-            // It's 2006.  Should I really support years < 2000?
-            time.year = year >= 90 ? year + 1900 : year + 2000;
-            time.month = month - 1;
-            time.monthDay = day;
-            time.hour = hour;
-            time.minute = minute;
-            time.second = second;
-
-            // Timezone offset is in quarter hours.
-            return time.toMillis(true) - (timezoneOffset * 15 * 60 * 1000);
-        }
-
-        /**
-         * Pulls the user data out of the PDU, and separates the payload from
-         * the header if there is one.
-         *
-         * @param hasUserDataHeader true if there is a user data header
-         * @param dataInSeptets true if the data payload is in septets instead
-         *  of octets
-         * @return the number of septets or octets in the user data payload
-         */
-        int constructUserData(boolean hasUserDataHeader, boolean dataInSeptets)
-        {
-            int offset = cur;
-            int userDataLength = pdu[offset++] & 0xff;
-            int headerSeptets = 0;
-
-            if (hasUserDataHeader) {
-                int userDataHeaderLength = pdu[offset++] & 0xff;
-
-                byte[] udh = new byte[userDataHeaderLength];
-                System.arraycopy(pdu, offset, udh, 0, userDataHeaderLength);
-                userDataHeader = SmsHeader.parse(udh);
-                offset += userDataHeaderLength;
-
-                int headerBits = (userDataHeaderLength + 1) * 8;
-                headerSeptets = headerBits / 7;
-                headerSeptets += (headerBits % 7) > 0 ? 1 : 0;
-                mUserDataSeptetPadding = (headerSeptets * 7) - headerBits;
-            }
-
-            /*
-             * Here we just create the user data length to be the remainder of
-             * the pdu minus the user data hearder. This is because the count
-             * could mean the number of uncompressed sepets if the userdata is
-             * encoded in 7-bit.
-             */
-            userData = new byte[pdu.length - offset];
-            System.arraycopy(pdu, offset, userData, 0, userData.length);
-            cur = offset;
-
-            if (dataInSeptets) {
-                // Return the number of septets
-                int count = userDataLength - headerSeptets;
-                // If count < 0, return 0 (means UDL was probably incorrect)
-                return count < 0 ? 0 : count;
-            } else {
-                // Return the number of octets
-                return userData.length;
-            }
-        }
-
-        /**
-         * Returns the user data payload, not including the headers
-         *
-         * @return the user data payload, not including the headers
-         */
-        byte[] getUserData() {
-            return userData;
-        }
-
-        /**
-         * Returns the number of padding bits at the begining of the user data
-         * array before the start of the septets.
-         *
-         * @return the number of padding bits at the begining of the user data
-         * array before the start of the septets
-         */
-        int getUserDataSeptetPadding() {
-            return mUserDataSeptetPadding;
-        }
-
-        /**
-         * Returns an object representing the user data headers
-         *
-         * @return an object representing the user data headers
-         * 
-         * {@hide}
-         */
-        SmsHeader getUserDataHeader() {
-            return userDataHeader;
-        }
-
-/*
-        XXX Not sure what this one is supposed to be doing, and no one is using
-        it.
-        String getUserDataGSM8bit() {
-            // System.out.println("remainder of pud:" +
-            // HexDump.dumpHexString(pdu, cur, pdu.length - cur));
-            int count = pdu[cur++] & 0xff;
-            int size = pdu[cur++];
-
-            // skip over header for now
-            cur += size;
-
-            if (pdu[cur - 1] == 0x01) {
-                int tid = pdu[cur++] & 0xff;
-                int type = pdu[cur++] & 0xff;
-
-                size = pdu[cur++] & 0xff;
-
-                int i = cur;
-
-                while (pdu[i++] != '\0') {
-                }
-
-                int length = i - cur;
-                String mimeType = new String(pdu, cur, length);
-
-                cur += length;
-
-                if (false) {
-                    System.out.println("tid = 0x" + HexDump.toHexString(tid));
-                    System.out.println("type = 0x" + HexDump.toHexString(type));
-                    System.out.println("header size = " + size);
-                    System.out.println("mimeType = " + mimeType);
-                    System.out.println("remainder of header:" +
-                     HexDump.dumpHexString(pdu, cur, (size - mimeType.length())));
-                }
-
-                cur += size - mimeType.length();
-
-                // System.out.println("data count = " + count + " cur = " + cur
-                // + " :" + HexDump.dumpHexString(pdu, cur, pdu.length - cur));
-
-                MMSMessage msg = MMSMessage.parseEncoding(mContext, pdu, cur,
-                        pdu.length - cur);
-            } else {
-                System.out.println(new String(pdu, cur, pdu.length - cur - 1));
-            }
-
-            return SimUtils.bytesToHexString(pdu);
-        }
-*/
-
-        /**
-         * Interprets the user data payload as pack GSM 7bit characters, and
-         * decodes them into a String.
-         *
-         * @param septetCount the number of septets in the user data payload
-         * @return a String with the decoded characters
-         */
-        String getUserDataGSM7Bit(int septetCount) {
-            String ret;
-
-            ret = GsmAlphabet.gsm7BitPackedToString(pdu, cur, septetCount,
-                    mUserDataSeptetPadding);
-
-            cur += (septetCount * 7) / 8;
-
-            return ret;
-        }
-
-        /**
-         * Interprets the user data payload as UCS2 characters, and
-         * decodes them into a String.
-         *
-         * @param byteCount the number of bytes in the user data payload
-         * @return a String with the decoded characters
-         */
-        String getUserDataUCS2(int byteCount) {
-            String ret;
-
-            try {
-                ret = new String(pdu, cur, byteCount, "utf-16");
-            } catch (UnsupportedEncodingException ex) {
-                ret = "";
-                Log.e(LOG_TAG, "implausible UnsupportedEncodingException", ex);
-            }
-
-            cur += byteCount;
-            return ret;
-        }
-
-        boolean moreDataPresent() {
-            return (pdu.length > cur);
-        }
+        return new SubmitPdu(spb);
     }
 
     /**
      * Returns the address of the SMS service center that relayed this message
      * or null if there is none.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public String getServiceCenterAddress() {
-        return scAddress;
+        return mWrappedSmsMessage.getServiceCenterAddress();
     }
 
     /**
      * Returns the originating address (sender) of this SMS message in String
      * form or null if unavailable
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public String getOriginatingAddress() {
-        if (originatingAddress == null) {
-            return null;
-        }
-
-        return originatingAddress.getAddressString();
+        return mWrappedSmsMessage.getOriginatingAddress();
     }
 
     /**
      * Returns the originating address, or email from address if this message
      * was from an email gateway. Returns null if originating address
      * unavailable.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public String getDisplayOriginatingAddress() {
-        if (isEmail) {
-            return emailFrom;
-        } else {
-            return getOriginatingAddress();
-        }
+        return mWrappedSmsMessage.getDisplayOriginatingAddress();
     }
 
     /**
      * Returns the message body as a String, if it exists and is text based.
      * @return message body is there is one, otherwise null
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public String getMessageBody() {
-        return messageBody;
+        return mWrappedSmsMessage.getMessageBody();
     }
 
     /**
      * Returns the class of this message.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public MessageClass getMessageClass() {
-        return messageClass;
+        int index = mWrappedSmsMessage.getMessageClass().ordinal();
+
+        return MessageClass.values()[index];
     }
 
     /**
      * Returns the message body, or email message body if this message was from
      * an email gateway. Returns null if message body unavailable.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public String getDisplayMessageBody() {
-        if (isEmail) {
-            return emailBody;
-        } else {
-            return getMessageBody();
-        }
+        return mWrappedSmsMessage.getDisplayMessageBody();
     }
 
     /**
      * Unofficial convention of a subject line enclosed in parens empty string
      * if not present
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public String getPseudoSubject() {
-        return pseudoSubject == null ? "" : pseudoSubject;
+        return mWrappedSmsMessage.getPseudoSubject();
     }
 
     /**
      * Returns the service centre timestamp in currentTimeMillis() format
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public long getTimestampMillis() {
-        return scTimeMillis;
+        return mWrappedSmsMessage.getTimestampMillis();
     }
 
     /**
@@ -1120,129 +521,114 @@
      *
      * @return true if this message came through an email gateway and email
      *         sender / subject / parsed body are available
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public boolean isEmail() {
-        return isEmail;
+        return mWrappedSmsMessage.isEmail();
     }
 
-    /**
+     /**
      * @return if isEmail() is true, body of the email sent through the gateway.
      *         null otherwise
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public String getEmailBody() {
-        return emailBody;
+        return mWrappedSmsMessage.getEmailBody();
     }
 
     /**
      * @return if isEmail() is true, email from address of email sent through
      *         the gateway. null otherwise
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public String getEmailFrom() {
-        return emailFrom;
+        return mWrappedSmsMessage.getEmailFrom();
     }
 
     /**
      * Get protocol identifier.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public int getProtocolIdentifier() {
-        return protocolIdentifier;
+        return mWrappedSmsMessage.getProtocolIdentifier();
     }
 
     /**
-     * See TS 23.040 9.2.3.9 returns true if this is a "replace short message"
-     * SMS
+     * See TS 23.040 9.2.3.9 returns true if this is a "replace short message" SMS
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public boolean isReplace() {
-        return (protocolIdentifier & 0xc0) == 0x40
-                && (protocolIdentifier & 0x3f) > 0
-                && (protocolIdentifier & 0x3f) < 8;
+        return mWrappedSmsMessage.isReplace();
     }
 
     /**
      * Returns true for CPHS MWI toggle message.
      *
-     * @return true if this is a CPHS MWI toggle message See CPHS 4.2 section
-     *         B.4.2
+     * @return true if this is a CPHS MWI toggle message See CPHS 4.2 section B.4.2
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public boolean isCphsMwiMessage() {
-        return originatingAddress.isCphsVoiceMessageClear()
-                || originatingAddress.isCphsVoiceMessageSet();
+        return mWrappedSmsMessage.isCphsMwiMessage();
     }
 
     /**
      * returns true if this message is a CPHS voicemail / message waiting
      * indicator (MWI) clear message
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public boolean isMWIClearMessage() {
-        if (isMwi && (mwiSense == false)) {
-            return true;
-        }
-
-        return originatingAddress != null
-                && originatingAddress.isCphsVoiceMessageClear();
+        return mWrappedSmsMessage.isMWIClearMessage();
     }
 
     /**
      * returns true if this message is a CPHS voicemail / message waiting
      * indicator (MWI) set message
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public boolean isMWISetMessage() {
-        if (isMwi && (mwiSense == true)) {
-            return true;
-        }
-
-        return originatingAddress != null
-                && originatingAddress.isCphsVoiceMessageSet();
+        return mWrappedSmsMessage.isMWISetMessage();
     }
 
     /**
      * returns true if this message is a "Message Waiting Indication Group:
      * Discard Message" notification and should not be stored.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public boolean isMwiDontStore() {
-        if (isMwi && mwiDontStore) {
-            return true;
-        }
-
-        if (isCphsMwiMessage()) {
-            // See CPHS 4.2 Section B.4.2.1
-            // If the user data is a single space char, do not store
-            // the message. Otherwise, store and display as usual
-            if (" ".equals(getMessageBody())) {
-                ;
-            }
-            return true;
-        }
-
-        return false;
+        return mWrappedSmsMessage.isMwiDontStore();
     }
 
     /**
-     * returns the user data section minus the user data header if one was
-     * present.
+     * returns the user data section minus the user data header if one was present.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public byte[] getUserData() {
-        return userData;
+        return mWrappedSmsMessage.getUserData();
     }
 
-    /**
-     * Returns an object representing the user data header
-     *
-     * @return an object representing the user data header
-     * 
-     * {@hide}
-     */
-    public SmsHeader getUserDataHeader() {
-        return userDataHeader;
-    }
+    /* Not part of the SDK interface and only needed by specific classes:
+       protected SmsHeader getUserDataHeader()
+    */
 
     /**
      * Returns the raw PDU for the message.
      *
      * @return the raw PDU for the message.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public byte[] getPdu() {
-        return mPdu;
+        return mWrappedSmsMessage.getPdu();
     }
 
     /**
@@ -1254,369 +640,108 @@
      *         SmsManager.STATUS_ON_SIM_UNREAD
      *         SmsManager.STATUS_ON_SIM_SEND
      *         SmsManager.STATUS_ON_SIM_UNSENT
+     * @deprecated Use android.telephony.SmsMessage and getStatusOnIcc instead.
      */
+    @Deprecated
     public int getStatusOnSim() {
-        return statusOnSim;
+        return mWrappedSmsMessage.getStatusOnIcc();
+    }
+
+    /**
+     * Returns the status of the message on the ICC (read, unread, sent, unsent).
+     *
+     * @return the status of the message on the ICC.  These are:
+     *         SmsManager.STATUS_ON_ICC_FREE
+     *         SmsManager.STATUS_ON_ICC_READ
+     *         SmsManager.STATUS_ON_ICC_UNREAD
+     *         SmsManager.STATUS_ON_ICC_SEND
+     *         SmsManager.STATUS_ON_ICC_UNSENT
+     * @deprecated Use android.telephony.SmsMessage.
+     * @hide
+     */
+    @Deprecated
+    public int getStatusOnIcc() {
+
+        return mWrappedSmsMessage.getStatusOnIcc();
     }
 
     /**
      * Returns the record index of the message on the SIM (1-based index).
      * @return the record index of the message on the SIM, or -1 if this
      *         SmsMessage was not created from a SIM SMS EF record.
+     * @deprecated Use android.telephony.SmsMessage and getIndexOnIcc instead.
      */
+    @Deprecated
     public int getIndexOnSim() {
-        return indexOnSim;
+        return mWrappedSmsMessage.getIndexOnIcc();
     }
 
     /**
+     * Returns the record index of the message on the ICC (1-based index).
+     * @return the record index of the message on the ICC, or -1 if this
+     *         SmsMessage was not created from a ICC SMS EF record.
+     * @deprecated Use android.telephony.SmsMessage.
+     * @hide
+     */
+    @Deprecated
+    public int getIndexOnIcc() {
+
+        return mWrappedSmsMessage.getIndexOnIcc();
+    }
+
+    /**
+     * GSM:
      * For an SMS-STATUS-REPORT message, this returns the status field from
-     * the status report.  This field indicates the status of a previousely
+     * the status report.  This field indicates the status of a previously
      * submitted SMS, if requested.  See TS 23.040, 9.2.3.15 TP-Status for a
      * description of values.
+     * CDMA:
+     * For not interfering with status codes from GSM, the value is
+     * shifted to the bits 31-16.
+     * The value is composed of an error class (bits 25-24) and a status code (bits 23-16).
+     * Possible codes are described in C.S0015-B, v2.0, 4.5.21.
      *
      * @return 0 indicates the previously sent message was received.
-     *         See TS 23.040, 9.9.2.3.15 for a description of other possible
-     *         values.
+     *         See TS 23.040, 9.9.2.3.15 and C.S0015-B, v2.0, 4.5.21
+     *         for a description of other possible values.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public int getStatus() {
-        return status;
+        return mWrappedSmsMessage.getStatus();
     }
 
     /**
      * Return true iff the message is a SMS-STATUS-REPORT message.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public boolean isStatusReportMessage() {
-        return isStatusReportMessage;
+        return mWrappedSmsMessage.isStatusReportMessage();
     }
 
     /**
      * Returns true iff the <code>TP-Reply-Path</code> bit is set in
      * this message.
+     * @deprecated Use android.telephony.SmsMessage.
      */
+    @Deprecated
     public boolean isReplyPathPresent() {
-        return replyPathPresent;
+        return mWrappedSmsMessage.isReplyPathPresent();
     }
 
-    /**
-     * TS 27.005 3.1, <pdu> definition "In the case of SMS: 3GPP TS 24.011 [6]
-     * SC address followed by 3GPP TS 23.040 [3] TPDU in hexadecimal format:
-     * ME/TA converts each octet of TP data unit into two IRA character long
-     * hexad number (e.g. octet with integer value 42 is presented to TE as two
-     * characters 2A (IRA 50 and 65))" ...in the case of cell broadcast,
-     * something else...
+    /** This method returns the reference to a specific
+     *  SmsMessage object, which is used for accessing its static methods.
+     * @return Specific SmsMessage.
+     * @deprecated Use android.telephony.SmsMessage.
      */
-    private void parsePdu(byte[] pdu) {
-        mPdu = pdu;
-        // Log.d(LOG_TAG, "raw sms mesage:");
-        // Log.d(LOG_TAG, s);
-
-        PduParser p = new PduParser(pdu);
-
-        scAddress = p.getSCAddress();
-
-        if (scAddress != null) {
-            if (Config.LOGD) Log.d(LOG_TAG, "SMS SC address: " + scAddress);
-        }
-
-        // TODO(mkf) support reply path, user data header indicator
-
-        // TP-Message-Type-Indicator
-        // 9.2.3
-        int firstByte = p.getByte();
-
-        mti = firstByte & 0x3;
-        switch (mti) {
-        // TP-Message-Type-Indicator
-        // 9.2.3
-        case 0:
-            parseSmsDeliver(p, firstByte);
-            break;
-        case 2:
-            parseSmsStatusReport(p, firstByte);
-            break;
-        default:
-            // TODO(mkf) the rest of these
-            throw new RuntimeException("Unsupported message type");
-        }
-    }
-
-    /**
-     * Parses a SMS-STATUS-REPORT message.
-     *
-     * @param p A PduParser, cued past the first byte.
-     * @param firstByte The first byte of the PDU, which contains MTI, etc.
-     */
-    private void parseSmsStatusReport(PduParser p, int firstByte) {
-        isStatusReportMessage = true;
-
-        // TP-Status-Report-Qualifier bit == 0 for SUBMIT
-        forSubmit = (firstByte & 0x20) == 0x00;
-        // TP-Message-Reference
-        messageRef = p.getByte();
-        // TP-Recipient-Address
-        recipientAddress = p.getAddress();
-        // TP-Service-Centre-Time-Stamp
-        scTimeMillis = p.getSCTimestampMillis();
-        // TP-Discharge-Time
-        dischargeTimeMillis = p.getSCTimestampMillis();
-        // TP-Status
-        status = p.getByte();
-
-        // The following are optional fields that may or may not be present.
-        if (p.moreDataPresent()) {
-            // TP-Parameter-Indicator
-            int extraParams = p.getByte();
-            int moreExtraParams = extraParams;
-            while ((moreExtraParams & 0x80) != 0) {
-                // We only know how to parse a few extra parameters, all
-                // indicated in the first TP-PI octet, so skip over any
-                // additional TP-PI octets.
-                moreExtraParams = p.getByte();
-            }
-            // TP-Protocol-Identifier
-            if ((extraParams & 0x01) != 0) {
-                protocolIdentifier = p.getByte();
-            }
-            // TP-Data-Coding-Scheme
-            if ((extraParams & 0x02) != 0) {
-                dataCodingScheme = p.getByte();
-            }
-            // TP-User-Data-Length (implies existence of TP-User-Data)
-            if ((extraParams & 0x04) != 0) {
-                boolean hasUserDataHeader = (firstByte & 0x40) == 0x40;
-                parseUserData(p, hasUserDataHeader);
-            }
-        }
-    }
-
-    private void parseSmsDeliver(PduParser p, int firstByte) {
-        replyPathPresent = (firstByte & 0x80) == 0x80;
-
-        originatingAddress = p.getAddress();
-
-        if (originatingAddress != null) {
-            if (Config.LOGV) Log.v(LOG_TAG, "SMS originating address: "
-                    + originatingAddress.address);
-        }
-
-        // TP-Protocol-Identifier (TP-PID)
-        // TS 23.040 9.2.3.9
-        protocolIdentifier = p.getByte();
-
-        // TP-Data-Coding-Scheme
-        // see TS 23.038
-        dataCodingScheme = p.getByte();
-
-        if (Config.LOGV) {
-            Log.v(LOG_TAG, "SMS TP-PID:" + protocolIdentifier
-                    + " data coding scheme: " + dataCodingScheme);
-        }
-
-        scTimeMillis = p.getSCTimestampMillis();
-
-        if (Config.LOGD) Log.d(LOG_TAG, "SMS SC timestamp: " + scTimeMillis);
-
-        boolean hasUserDataHeader = (firstByte & 0x40) == 0x40;
-
-        parseUserData(p, hasUserDataHeader);
-    }
-
-    /**
-     * Parses the User Data of an SMS.
-     *
-     * @param p The current PduParser.
-     * @param hasUserDataHeader Indicates whether a header is present in the
-     *                          User Data.
-     */
-    private void parseUserData(PduParser p, boolean hasUserDataHeader) {
-        boolean hasMessageClass = false;
-        boolean userDataCompressed = false;
-
-        int encodingType = ENCODING_UNKNOWN;
-
-        // Look up the data encoding scheme
-        if ((dataCodingScheme & 0x80) == 0) {
-            // Bits 7..4 == 0xxx
-            automaticDeletion = (0 != (dataCodingScheme & 0x40));
-            userDataCompressed = (0 != (dataCodingScheme & 0x20));
-            hasMessageClass = (0 != (dataCodingScheme & 0x10));
-
-            if (userDataCompressed) {
-                Log.w(LOG_TAG, "4 - Unsupported SMS data coding scheme "
-                        + "(compression) " + (dataCodingScheme & 0xff));
-            } else {
-                switch ((dataCodingScheme >> 2) & 0x3) {
-                case 0: // GSM 7 bit default alphabet
-                    encodingType = ENCODING_7BIT;
-                    break;
-
-                case 2: // UCS 2 (16bit)
-                    encodingType = ENCODING_16BIT;
-                    break;
-
-                case 1: // 8 bit data
-                case 3: // reserved
-                    Log.w(LOG_TAG, "1 - Unsupported SMS data coding scheme "
-                            + (dataCodingScheme & 0xff));
-                    encodingType = ENCODING_8BIT;
-                    break;
-                }
-            }
-        } else if ((dataCodingScheme & 0xf0) == 0xf0) {
-            automaticDeletion = false;
-            hasMessageClass = true;
-            userDataCompressed = false;
-
-            if (0 == (dataCodingScheme & 0x04)) {
-                // GSM 7 bit default alphabet
-                encodingType = ENCODING_7BIT;
-            } else {
-                // 8 bit data
-                encodingType = ENCODING_8BIT;
-            }
-        } else if ((dataCodingScheme & 0xF0) == 0xC0
-                || (dataCodingScheme & 0xF0) == 0xD0
-                || (dataCodingScheme & 0xF0) == 0xE0) {
-            // 3GPP TS 23.038 V7.0.0 (2006-03) section 4
-
-            // 0xC0 == 7 bit, don't store
-            // 0xD0 == 7 bit, store
-            // 0xE0 == UCS-2, store
-
-            if ((dataCodingScheme & 0xF0) == 0xE0) {
-                encodingType = ENCODING_16BIT;
-            } else {
-                encodingType = ENCODING_7BIT;
-            }
-
-            userDataCompressed = false;
-            boolean active = ((dataCodingScheme & 0x08) == 0x08);
-
-            // bit 0x04 reserved
-
-            if ((dataCodingScheme & 0x03) == 0x00) {
-                isMwi = true;
-                mwiSense = active;
-                mwiDontStore = ((dataCodingScheme & 0xF0) == 0xC0);
-            } else {
-                isMwi = false;
-
-                Log.w(LOG_TAG, "MWI for fax, email, or other "
-                        + (dataCodingScheme & 0xff));
-            }
+    private static final SmsMessageBase getSmsFacility(){
+        int activePhone = TelephonyManager.getDefault().getPhoneType();
+        if (PHONE_TYPE_CDMA == activePhone) {
+            return new com.android.internal.telephony.cdma.SmsMessage();
         } else {
-            Log.w(LOG_TAG, "3 - Unsupported SMS data coding scheme "
-                    + (dataCodingScheme & 0xff));
-        }
-
-        // set both the user data and the user data header.
-        int count = p.constructUserData(hasUserDataHeader,
-                encodingType == ENCODING_7BIT);
-        this.userData = p.getUserData();
-        this.userDataHeader = p.getUserDataHeader();
-
-        switch (encodingType) {
-        case ENCODING_UNKNOWN:
-        case ENCODING_8BIT:
-            messageBody = null;
-            break;
-
-        case ENCODING_7BIT:
-            messageBody = p.getUserDataGSM7Bit(count);
-            break;
-
-        case ENCODING_16BIT:
-            messageBody = p.getUserDataUCS2(count);
-            break;
-        }
-
-        if (Config.LOGV) Log.v(LOG_TAG, "SMS message body (raw): '" + messageBody + "'");
-
-        if (messageBody != null) {
-            parseMessageBody();
-        }
-
-        if (!hasMessageClass) {
-            messageClass = MessageClass.UNKNOWN;
-        } else {
-            switch (dataCodingScheme & 0x3) {
-            case 0:
-                messageClass = MessageClass.CLASS_0;
-                break;
-            case 1:
-                messageClass = MessageClass.CLASS_1;
-                break;
-            case 2:
-                messageClass = MessageClass.CLASS_2;
-                break;
-            case 3:
-                messageClass = MessageClass.CLASS_3;
-                break;
-            }
+            return new com.android.internal.telephony.gsm.SmsMessage();
         }
     }
-
-    private void parseMessageBody() {
-        if (originatingAddress.couldBeEmailGateway()) {
-            extractEmailAddressFromMessageBody();
-        }
-    }
-
-    /**
-     * Try to parse this message as an email gateway message -> Neither
-     * of the standard ways are currently supported: There are two ways
-     * specified in TS 23.040 Section 3.8 (not supported via this mechanism) -
-     * SMS message "may have its TP-PID set for internet electronic mail - MT
-     * SMS format: [<from-address><space>]<message> - "Depending on the
-     * nature of the gateway, the destination/origination address is either
-     * derived from the content of the SMS TP-OA or TP-DA field, or the
-     * TP-OA/TP-DA field contains a generic gateway address and the to/from
-     * address is added at the beginning as shown above." - multiple addreses
-     * separated by commas, no spaces - subject field delimited by '()' or '##'
-     * and '#' Section 9.2.3.24.11
-     */
-    private void extractEmailAddressFromMessageBody() {
-
-        /*
-         * a little guesswork here. I haven't found doc for this.
-         * the format could be either
-         *
-         * 1. [x@y][ ]/[subject][ ]/[body]
-         * -or-
-         * 2. [x@y][ ]/[body]
-         */
-        int slash = 0, slash2 = 0, atSymbol = 0;
-
-        try {
-            slash = messageBody.indexOf(" /");
-            if (slash == -1) {
-                return;
-            }
-
-            atSymbol = messageBody.indexOf('@');
-            if (atSymbol == -1 || atSymbol > slash) {
-                return;
-            }
-
-            emailFrom = messageBody.substring(0, slash);
-
-            slash2 = messageBody.indexOf(" /", slash + 2);
-
-            if (slash2 == -1) {
-                pseudoSubject = null;
-                emailBody = messageBody.substring(slash + 2);
-            } else {
-                pseudoSubject = messageBody.substring(slash + 2, slash2);
-                emailBody = messageBody.substring(slash2 + 2);
-            }
-
-            isEmail = true;
-        } catch (Exception ex) {
-            Log.w(LOG_TAG,
-                    "extractEmailAddressFromMessageBody: exception slash="
-                    + slash + ", atSymbol=" + atSymbol + ", slash2="
-                    + slash2, ex);
-        }
-    }
-
 }
+
diff --git a/telephony/java/com/android/internal/telephony/ATResponseParser.java b/telephony/java/com/android/internal/telephony/ATResponseParser.java
index 93ec455..fdb0526 100644
--- a/telephony/java/com/android/internal/telephony/ATResponseParser.java
+++ b/telephony/java/com/android/internal/telephony/ATResponseParser.java
@@ -34,7 +34,7 @@
     {
         this.line = line;
     }
-    
+
     public boolean
     nextBoolean()
     {
@@ -147,7 +147,7 @@
         }
     }
 
- 
+
     /** Throws ATParseEx if whitespace extends to the end of string */
     private char
     skipWhiteSpace (char c)
diff --git a/telephony/java/com/android/internal/telephony/gsm/AdnRecord.aidl b/telephony/java/com/android/internal/telephony/AdnRecord.aidl
similarity index 93%
rename from telephony/java/com/android/internal/telephony/gsm/AdnRecord.aidl
rename to telephony/java/com/android/internal/telephony/AdnRecord.aidl
index 68d9a7c..b4a1a29 100644
--- a/telephony/java/com/android/internal/telephony/gsm/AdnRecord.aidl
+++ b/telephony/java/com/android/internal/telephony/AdnRecord.aidl
@@ -14,6 +14,7 @@
 ** limitations under the License.
 */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 parcelable AdnRecord;
+
diff --git a/telephony/java/com/android/internal/telephony/AdnRecord.java b/telephony/java/com/android/internal/telephony/AdnRecord.java
new file mode 100644
index 0000000..5f40579
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/AdnRecord.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.telephony.PhoneNumberUtils;
+import android.util.Log;
+
+import com.android.internal.telephony.GsmAlphabet;
+
+
+/**
+ *
+ * Used to load or store ADNs (Abbreviated Dialing Numbers).
+ *
+ * {@hide}
+ *
+ */
+public class AdnRecord implements Parcelable {
+    static final String LOG_TAG = "GSM";
+
+    //***** Instance Variables
+
+    String alphaTag = "";
+    String number = "";
+    int extRecord = 0xff;
+    int efid;                   // or 0 if none
+    int recordNumber;           // or 0 if none
+
+
+    //***** Constants
+
+    // In an ADN record, everything but the alpha identifier
+    // is in a footer that's 14 bytes
+    static final int FOOTER_SIZE_BYTES = 14;
+
+    // Maximum size of the un-extended number field
+    static final int MAX_NUMBER_SIZE_BYTES = 11;
+
+    static final int EXT_RECORD_LENGTH_BYTES = 13;
+    static final int EXT_RECORD_TYPE_ADDITIONAL_DATA = 2;
+    static final int EXT_RECORD_TYPE_MASK = 3;
+    static final int MAX_EXT_CALLED_PARTY_LENGTH = 0xa;
+
+    // ADN offset
+    static final int ADN_BCD_NUMBER_LENGTH = 0;
+    static final int ADN_TON_AND_NPI = 1;
+    static final int ADN_DAILING_NUMBER_START = 2;
+    static final int ADN_DAILING_NUMBER_END = 11;
+    static final int ADN_CAPABILITY_ID = 12;
+    static final int ADN_EXTENSION_ID = 13;
+
+    //***** Static Methods
+
+    public static final Parcelable.Creator<AdnRecord> CREATOR
+            = new Parcelable.Creator<AdnRecord>() {
+        public AdnRecord createFromParcel(Parcel source) {
+            int efid;
+            int recordNumber;
+            String alphaTag;
+            String number;
+
+            efid = source.readInt();
+            recordNumber = source.readInt();
+            alphaTag = source.readString();
+            number = source.readString();
+
+            return new AdnRecord(efid, recordNumber, alphaTag, number);
+        }
+
+        public AdnRecord[] newArray(int size) {
+            return new AdnRecord[size];
+        }
+    };
+
+
+    //***** Constructor
+    public
+    AdnRecord (byte[] record) {
+        this(0, 0, record);
+    }
+
+    public
+    AdnRecord (int efid, int recordNumber, byte[] record) {
+        this.efid = efid;
+        this.recordNumber = recordNumber;
+        parseRecord(record);
+    }
+
+    public
+    AdnRecord (String alphaTag, String number) {
+        this(0, 0, alphaTag, number);
+    }
+
+    public
+    AdnRecord (int efid, int recordNumber, String alphaTag, String number) {
+        this.efid = efid;
+        this.recordNumber = recordNumber;
+        this.alphaTag = alphaTag;
+        this.number = number;
+    }
+
+    //***** Instance Methods
+
+    public String getAlphaTag() {
+        return alphaTag;
+    }
+
+    public String getNumber() {
+        return number;
+    }
+
+    public String toString() {
+        return "ADN Record '" + alphaTag + "' '" + number + "'";
+    }
+
+    public boolean isEmpty() {
+        return alphaTag.equals("") && number.equals("");
+    }
+
+    public boolean hasExtendedRecord() {
+        return extRecord != 0 && extRecord != 0xff;
+    }
+
+    public boolean isEqual(AdnRecord adn) {
+        return ( alphaTag.equals(adn.getAlphaTag()) &&
+                number.equals(adn.getNumber()) );
+    }
+    //***** Parcelable Implementation
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(efid);
+        dest.writeInt(recordNumber);
+        dest.writeString(alphaTag);
+        dest.writeString(number);
+    }
+
+    /**
+     * Build adn hex byte array based on record size
+     * The format of byte array is defined in 51.011 10.5.1
+     *
+     * @param recordSize is the size X of EF record
+     * @return hex byte[recordSize] to be written to EF record
+     *          return nulll for wrong format of dialing nubmer or tag
+     */
+    public byte[] buildAdnString(int recordSize) {
+        byte[] bcdNumber;
+        byte[] byteTag;
+        byte[] adnString = null;
+        int footerOffset = recordSize - FOOTER_SIZE_BYTES;
+
+        if (number == null || number.equals("") ||
+                alphaTag == null || alphaTag.equals("")) {
+
+            Log.w(LOG_TAG, "[buildAdnString] Empty alpha tag or number");
+            adnString = new byte[recordSize];
+            for (int i = 0; i < recordSize; i++) {
+                adnString[i] = (byte) 0xFF;
+            }
+        } else if (number.length()
+                > (ADN_DAILING_NUMBER_END - ADN_DAILING_NUMBER_START + 1) * 2) {
+            Log.w(LOG_TAG,
+                    "[buildAdnString] Max length of dailing number is 20");
+        } else if (alphaTag.length() > footerOffset) {
+            Log.w(LOG_TAG,
+                    "[buildAdnString] Max length of tag is " + footerOffset);
+        } else {
+
+            adnString = new byte[recordSize];
+            for (int i = 0; i < recordSize; i++) {
+                adnString[i] = (byte) 0xFF;
+            }
+
+            bcdNumber = PhoneNumberUtils.numberToCalledPartyBCD(number);
+
+            System.arraycopy(bcdNumber, 0, adnString,
+                    footerOffset + ADN_TON_AND_NPI, bcdNumber.length);
+
+            adnString[footerOffset + ADN_BCD_NUMBER_LENGTH]
+                    = (byte) (bcdNumber.length);
+            adnString[footerOffset + ADN_CAPABILITY_ID]
+                    = (byte) 0xFF; // Capacility Id
+            adnString[footerOffset + ADN_EXTENSION_ID]
+                    = (byte) 0xFF; // Extension Record Id
+
+            byteTag = GsmAlphabet.stringToGsm8BitPacked(alphaTag);
+            System.arraycopy(byteTag, 0, adnString, 0, byteTag.length);
+
+        }
+
+        return adnString;
+    }
+
+    /**
+     * See TS 51.011 10.5.10
+     */
+    public void
+    appendExtRecord (byte[] extRecord) {
+        try {
+            if (extRecord.length != EXT_RECORD_LENGTH_BYTES) {
+                return;
+            }
+
+            if ((extRecord[0] & EXT_RECORD_TYPE_MASK)
+                    != EXT_RECORD_TYPE_ADDITIONAL_DATA) {
+                return;
+            }
+
+            if ((0xff & extRecord[1]) > MAX_EXT_CALLED_PARTY_LENGTH) {
+                // invalid or empty record
+                return;
+            }
+
+            number += PhoneNumberUtils.calledPartyBCDFragmentToString(
+                                        extRecord, 2, 0xff & extRecord[1]);
+
+            // We don't support ext record chaining.
+
+        } catch (RuntimeException ex) {
+            Log.w(LOG_TAG, "Error parsing AdnRecord ext record", ex);
+        }
+    }
+
+    //***** Private Methods
+
+    /**
+     * alphaTag and number are set to null on invalid format
+     */
+    private void
+    parseRecord(byte[] record) {
+        try {
+            alphaTag = IccUtils.adnStringFieldToString(
+                            record, 0, record.length - FOOTER_SIZE_BYTES);
+
+            int footerOffset = record.length - FOOTER_SIZE_BYTES;
+
+            int numberLength = 0xff & record[footerOffset];
+
+            if (numberLength > MAX_NUMBER_SIZE_BYTES) {
+                // Invalid number length
+                number = "";
+                return;
+            }
+
+            // Please note 51.011 10.5.1:
+            //
+            // "If the Dialling Number/SSC String does not contain
+            // a dialling number, e.g. a control string deactivating
+            // a service, the TON/NPI byte shall be set to 'FF' by
+            // the ME (see note 2)."
+
+            number = PhoneNumberUtils.calledPartyBCDToString(
+                            record, footerOffset + 1, numberLength);
+
+
+            extRecord = 0xff & record[record.length - 1];
+
+        } catch (RuntimeException ex) {
+            Log.w(LOG_TAG, "Error parsing AdnRecord", ex);
+            number = "";
+            alphaTag = "";
+        }
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/AdnRecordCache.java b/telephony/java/com/android/internal/telephony/AdnRecordCache.java
similarity index 91%
rename from telephony/java/com/android/internal/telephony/gsm/AdnRecordCache.java
rename to telephony/java/com/android/internal/telephony/AdnRecordCache.java
index 9da18e3..c270ae5 100644
--- a/telephony/java/com/android/internal/telephony/gsm/AdnRecordCache.java
+++ b/telephony/java/com/android/internal/telephony/AdnRecordCache.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 import android.util.SparseArray;
 import android.util.Log;
@@ -23,18 +23,18 @@
 import android.os.AsyncResult;
 import java.util.ArrayList;
 import java.util.Iterator;
+import com.android.internal.telephony.IccConstants;
 
 /**
  * {@hide}
  */
-public final class AdnRecordCache extends Handler implements SimConstants
-{
+public final class AdnRecordCache extends Handler implements IccConstants {
     //***** Instance Variables
 
-    GSMPhone phone;
+    PhoneBase phone;
 
     // Indexed by EF ID
-    SparseArray<ArrayList<AdnRecord>> adnLikeFiles 
+    SparseArray<ArrayList<AdnRecord>> adnLikeFiles
         = new SparseArray<ArrayList<AdnRecord>>();
 
     // People waiting for ADN-like files to be loaded
@@ -52,9 +52,8 @@
     //***** Constructor
 
 
-    /*package*/
-    AdnRecordCache(GSMPhone phone)
-    {
+
+    public AdnRecordCache(PhoneBase phone) {
         this.phone = phone;
     }
 
@@ -63,14 +62,12 @@
     /**
      * Called from SIMRecords.onRadioNotAvailable and SIMRecords.handleSimRefresh.
      */
-    /*package*/ void
-    reset()
-    {
+    public void reset() {
         adnLikeFiles.clear();
 
         clearWaiters();
         clearUserWriters();
-        
+
     }
 
     private void clearWaiters() {
@@ -95,29 +92,27 @@
      * @return List of AdnRecords for efid if we've already loaded them this
      * radio session, or null if we haven't
      */
-    /*package*/ ArrayList<AdnRecord>
-    getRecordsIfLoaded(int efid)
-    {
+    public ArrayList<AdnRecord>
+    getRecordsIfLoaded(int efid) {
         return adnLikeFiles.get(efid);
     }
 
     /**
-     * Returns extension ef associated with ADN-like EF or -1 if 
+     * Returns extension ef associated with ADN-like EF or -1 if
      * we don't know.
      *
      * See 3GPP TS 51.011 for this mapping
      */
     private int
-    extensionEfForEf(int efid)
-    {
+    extensionEfForEf(int efid) {
         switch (efid) {
             case EF_MBDN: return EF_EXT6;
             case EF_ADN: return EF_EXT1;
             case EF_SDN: return EF_EXT3;
             case EF_FDN: return EF_EXT2;
-            case EF_MSISDN: return EF_EXT1;          
+            case EF_MSISDN: return EF_EXT1;
             default: return -1;
-        } 
+        }
     }
 
     private void sendErrorResponse(Message response, String errString) {
@@ -138,7 +133,7 @@
      * @param response message to be posted when done
      *        response.exception hold the exception in error
      */
-    void updateAdnByIndex(int efid, AdnRecord adn, int recordIndex, String pin2,
+    public void updateAdnByIndex(int efid, AdnRecord adn, int recordIndex, String pin2,
             Message response) {
 
         int extensionEF = extensionEfForEf(efid);
@@ -174,7 +169,7 @@
      * @param response message to be posted when done
      *        response.exception hold the exception in error
      */
-    void updateAdnBySearch(int efid, AdnRecord oldAdn, AdnRecord newAdn,
+    public void updateAdnBySearch(int efid, AdnRecord oldAdn, AdnRecord newAdn,
             String pin2, Message response) {
 
         int extensionEF;
@@ -227,9 +222,8 @@
      * Responds with exception (in response) if efid is not a known ADN-like
      * record
      */
-    /*package*/ void
-    requestLoadAllAdnLike (int efid, Message response)
-    {
+    public void
+    requestLoadAllAdnLike (int efid, Message response) {
         ArrayList<Message> waiters;
         ArrayList<AdnRecord> result;
 
@@ -256,25 +250,25 @@
             waiters.add(response);
             return;
         }
-        
+
         // Start loading efid
-        
+
         waiters = new ArrayList<Message>();
         waiters.add(response);
 
         adnLikeWaiters.put(efid, waiters);
 
         int extensionEF = extensionEfForEf(efid);
-    
+
         if (extensionEF < 0) {
             // respond with error if not known ADN-like record
 
             if (response != null) {
-                AsyncResult.forMessage(response).exception 
+                AsyncResult.forMessage(response).exception
                     = new RuntimeException("EF is not known ADN-like EF:" + efid);
                 response.sendToTarget();
             }
-            
+
             return;
         }
 
@@ -285,8 +279,7 @@
     //***** Private methods
 
     private void
-    notifyWaiters(ArrayList<Message> waiters, AsyncResult ar)
-    {
+    notifyWaiters(ArrayList<Message> waiters, AsyncResult ar) {
 
         if (waiters == null) {
             return;
diff --git a/telephony/java/com/android/internal/telephony/AdnRecordLoader.java b/telephony/java/com/android/internal/telephony/AdnRecordLoader.java
new file mode 100644
index 0000000..cfb5aaa
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/AdnRecordLoader.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony;
+
+import java.util.ArrayList;
+
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+
+public class AdnRecordLoader extends Handler {
+    static String LOG_TAG;
+
+    //***** Instance Variables
+
+    PhoneBase phone;
+    int ef;
+    int extensionEF;
+    int pendingExtLoads;
+    Message userResponse;
+    String pin2;
+
+    // For "load one"
+    int recordNumber;
+
+    // for "load all"
+    ArrayList<AdnRecord> adns; // only valid after EVENT_ADN_LOAD_ALL_DONE
+
+    // Either an AdnRecord or a reference to adns depending
+    // if this is a load one or load all operation
+    Object result;
+
+    //***** Event Constants
+
+    static final int EVENT_ADN_LOAD_DONE = 1;
+    static final int EVENT_EXT_RECORD_LOAD_DONE = 2;
+    static final int EVENT_ADN_LOAD_ALL_DONE = 3;
+    static final int EVENT_EF_LINEAR_RECORD_SIZE_DONE = 4;
+    static final int EVENT_UPDATE_RECORD_DONE = 5;
+
+    //***** Constructor
+
+    public AdnRecordLoader(PhoneBase phone) {
+        // The telephony unit-test cases may create AdnRecords
+        // in secondary threads
+        super(phone.getHandler().getLooper());
+
+        this.phone = phone;
+        LOG_TAG = phone.getPhoneName();
+    }
+
+    /**
+     * Resulting AdnRecord is placed in response.obj.result
+     * or response.obj.exception is set
+     */
+    public void
+    loadFromEF(int ef, int extensionEF, int recordNumber,
+                Message response) {
+        this.ef = ef;
+        this.extensionEF = extensionEF;
+        this.recordNumber = recordNumber;
+        this.userResponse = response;
+
+        phone.mIccFileHandler.loadEFLinearFixed(
+                    ef, recordNumber,
+                    obtainMessage(EVENT_ADN_LOAD_DONE));
+
+    }
+
+
+    /**
+     * Resulting ArrayList&lt;adnRecord> is placed in response.obj.result
+     * or response.obj.exception is set
+     */
+    public void
+    loadAllFromEF(int ef, int extensionEF,
+                Message response) {
+        this.ef = ef;
+        this.extensionEF = extensionEF;
+        this.userResponse = response;
+
+        phone.mIccFileHandler.loadEFLinearFixedAll(
+                    ef,
+                    obtainMessage(EVENT_ADN_LOAD_ALL_DONE));
+
+    }
+
+    /**
+     * Write adn to a EF SIM record
+     * It will get the record size of EF record and compose hex adn array
+     * then write the hex array to EF record
+     *
+     * @param adn is set with alphaTag and phoneNubmer
+     * @param ef EF fileid
+     * @param extensionEF extension EF fileid
+     * @param recordNumber 1-based record index
+     * @param pin2 for CHV2 operations, must be null if pin2 is not needed
+     * @param response will be sent to its handler when completed
+     */
+    public void
+    updateEF(AdnRecord adn, int ef, int extensionEF, int recordNumber,
+            String pin2, Message response) {
+        this.ef = ef;
+        this.extensionEF = extensionEF;
+        this.recordNumber = recordNumber;
+        this.userResponse = response;
+        this.pin2 = pin2;
+
+        phone.mIccFileHandler.getEFLinearRecordSize( ef,
+            obtainMessage(EVENT_EF_LINEAR_RECORD_SIZE_DONE, adn));
+    }
+
+    //***** Overridden from Handler
+
+    public void
+    handleMessage(Message msg) {
+        AsyncResult ar;
+        byte data[];
+        AdnRecord adn;
+
+        try {
+            switch (msg.what) {
+                case EVENT_EF_LINEAR_RECORD_SIZE_DONE:
+                    ar = (AsyncResult)(msg.obj);
+                    adn = (AdnRecord)(ar.userObj);
+
+                    if (ar.exception != null) {
+                        throw new RuntimeException("get EF record size failed",
+                                ar.exception);
+                    }
+
+                    int[] recordSize = (int[])ar.result;
+                    // recordSize is int[3] array
+                    // int[0]  is the record length
+                    // int[1]  is the total length of the EF file
+                    // int[2]  is the number of records in the EF file
+                    // So int[0] * int[2] = int[1]
+                   if (recordSize.length != 3 || recordNumber > recordSize[2]) {
+                        throw new RuntimeException("get wrong EF record size format",
+                                ar.exception);
+                    }
+
+                    data = adn.buildAdnString(recordSize[0]);
+
+                    if(data == null) {
+                        throw new RuntimeException("worong ADN format",
+                                ar.exception);
+                    }
+
+                    phone.mIccFileHandler.updateEFLinearFixed(ef, recordNumber,
+                            data, pin2, obtainMessage(EVENT_UPDATE_RECORD_DONE));
+
+                    pendingExtLoads = 1;
+
+                    break;
+                case EVENT_UPDATE_RECORD_DONE:
+                    ar = (AsyncResult)(msg.obj);
+                    if (ar.exception != null) {
+                        throw new RuntimeException("update EF adn record failed",
+                                ar.exception);
+                    }
+                    pendingExtLoads = 0;
+                    result = null;
+                    break;
+                case EVENT_ADN_LOAD_DONE:
+                    ar = (AsyncResult)(msg.obj);
+                    data = (byte[])(ar.result);
+
+                    if (ar.exception != null) {
+                        throw new RuntimeException("load failed", ar.exception);
+                    }
+
+                    if (false) {
+                        Log.d(LOG_TAG,"ADN EF: 0x"
+                            + Integer.toHexString(ef)
+                            + ":" + recordNumber
+                            + "\n" + IccUtils.bytesToHexString(data));
+                    }
+
+                    adn = new AdnRecord(ef, recordNumber, data);
+                    result = adn;
+
+                    if (adn.hasExtendedRecord()) {
+                        // If we have a valid value in the ext record field,
+                        // we're not done yet: we need to read the corresponding
+                        // ext record and append it
+
+                        pendingExtLoads = 1;
+
+                        phone.mIccFileHandler.loadEFLinearFixed(
+                            extensionEF, adn.extRecord,
+                            obtainMessage(EVENT_EXT_RECORD_LOAD_DONE, adn));
+                    }
+                break;
+
+                case EVENT_EXT_RECORD_LOAD_DONE:
+                    ar = (AsyncResult)(msg.obj);
+                    data = (byte[])(ar.result);
+                    adn = (AdnRecord)(ar.userObj);
+
+                    if (ar.exception != null) {
+                        throw new RuntimeException("load failed", ar.exception);
+                    }
+
+                    Log.d(LOG_TAG,"ADN extention EF: 0x"
+                        + Integer.toHexString(extensionEF)
+                        + ":" + adn.extRecord
+                        + "\n" + IccUtils.bytesToHexString(data));
+
+                    adn.appendExtRecord(data);
+
+                    pendingExtLoads--;
+                    // result should have been set in
+                    // EVENT_ADN_LOAD_DONE or EVENT_ADN_LOAD_ALL_DONE
+                break;
+
+                case EVENT_ADN_LOAD_ALL_DONE:
+                    ar = (AsyncResult)(msg.obj);
+                    ArrayList<byte[]> datas = (ArrayList<byte[]>)(ar.result);
+
+                    if (ar.exception != null) {
+                        throw new RuntimeException("load failed", ar.exception);
+                    }
+
+                    adns = new ArrayList<AdnRecord>(datas.size());
+                    result = adns;
+                    pendingExtLoads = 0;
+
+                    for(int i = 0, s = datas.size() ; i < s ; i++) {
+                        adn = new AdnRecord(ef, 1 + i, datas.get(i));
+                        adns.add(adn);
+
+                        if (adn.hasExtendedRecord()) {
+                            // If we have a valid value in the ext record field,
+                            // we're not done yet: we need to read the corresponding
+                            // ext record and append it
+
+                            pendingExtLoads++;
+
+                            phone.mIccFileHandler.loadEFLinearFixed(
+                                extensionEF, adn.extRecord,
+                                obtainMessage(EVENT_EXT_RECORD_LOAD_DONE, adn));
+                        }
+                    }
+                break;
+            }
+        } catch (RuntimeException exc) {
+            if (userResponse != null) {
+                AsyncResult.forMessage(userResponse)
+                                .exception = exc;
+                userResponse.sendToTarget();
+                // Loading is all or nothing--either every load succeeds
+                // or we fail the whole thing.
+                userResponse = null;
+            }
+            return;
+        }
+
+        if (userResponse != null && pendingExtLoads == 0) {
+            AsyncResult.forMessage(userResponse).result
+                = result;
+
+            userResponse.sendToTarget();
+            userResponse = null;
+        }
+    }
+
+
+}
diff --git a/telephony/java/com/android/internal/telephony/BaseCommands.java b/telephony/java/com/android/internal/telephony/BaseCommands.java
new file mode 100644
index 0000000..11e7461
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/BaseCommands.java
@@ -0,0 +1,580 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony;
+
+
+import android.content.Context;
+import android.os.RegistrantList;
+import android.os.Registrant;
+import android.os.Handler;
+import android.os.AsyncResult;
+import android.provider.Checkin;
+import android.util.Config;
+import android.util.Log;
+
+/**
+ * {@hide}
+ */
+public abstract class BaseCommands implements CommandsInterface {
+    static final String LOG_TAG = "RILB";
+
+    //***** Instance Variables
+    protected Context mContext;
+    protected RadioState mState = RadioState.RADIO_UNAVAILABLE;
+    protected Object mStateMonitor = new Object();
+
+    protected RegistrantList mRadioStateChangedRegistrants = new RegistrantList();
+    protected RegistrantList mOnRegistrants = new RegistrantList();
+    protected RegistrantList mAvailRegistrants = new RegistrantList();
+    protected RegistrantList mOffOrNotAvailRegistrants = new RegistrantList();
+    protected RegistrantList mNotAvailRegistrants = new RegistrantList();
+    protected RegistrantList mSIMReadyRegistrants = new RegistrantList();
+    protected RegistrantList mSIMLockedRegistrants = new RegistrantList();
+    protected RegistrantList mRUIMReadyRegistrants = new RegistrantList();
+    protected RegistrantList mRUIMLockedRegistrants = new RegistrantList();
+    protected RegistrantList mNVReadyRegistrants = new RegistrantList();
+    protected RegistrantList mCallStateRegistrants = new RegistrantList();
+    protected RegistrantList mNetworkStateRegistrants = new RegistrantList();
+    protected RegistrantList mDataConnectionRegistrants = new RegistrantList();
+    protected RegistrantList mRadioTechnologyChangedRegistrants = new RegistrantList();
+    protected RegistrantList mIccStatusChangedRegistrants = new RegistrantList();
+    protected RegistrantList mVoicePrivacyOnRegistrants = new RegistrantList();
+    protected RegistrantList mVoicePrivacyOffRegistrants = new RegistrantList();
+    protected Registrant mSMSRegistrant;
+    protected Registrant mNITZTimeRegistrant;
+    protected Registrant mSignalStrengthRegistrant;
+    protected Registrant mUSSDRegistrant;
+    protected Registrant mSmsOnSimRegistrant;
+    /** Registrant for handling SMS Status Reports */
+    protected Registrant mSmsStatusRegistrant;
+    /** Registrant for handling Supplementary Service Notifications */
+    protected Registrant mSsnRegistrant;
+    protected Registrant mStkSessionEndRegistrant;
+    protected Registrant mStkProCmdRegistrant;
+    protected Registrant mStkEventRegistrant;
+    protected Registrant mStkCallSetUpRegistrant;
+    /** Registrant for handling SIM/RUIM SMS storage full messages */
+    protected Registrant mIccSmsFullRegistrant;
+    /** Registrant for handling Icc Refresh notifications */
+    protected Registrant mIccRefreshRegistrant;
+    /** Registrant for handling RING notifications */
+    protected Registrant mRingRegistrant;
+    /** Registrant for handling RESTRICTED STATE changed notification */
+    protected Registrant mRestrictedStateRegistrant;
+
+    //Network Mode received from PhoneFactory
+    protected int mNetworkMode;
+    //CDMA subscription received from PhoneFactory
+    protected int mCdmaSubscription;
+    //Type of Phone, GSM or CDMA. Set by CDMAPhone or GSMPhone.
+    protected int mPhoneType;
+
+
+    public BaseCommands(Context context) {
+        mContext = context;  // May be null (if so we won't log statistics)
+    }
+
+    //***** CommandsInterface implementation
+
+    public RadioState getRadioState() {
+        return mState;
+    }
+
+
+    public void registerForRadioStateChanged(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+
+        synchronized (mStateMonitor) {
+            mRadioStateChangedRegistrants.add(r);
+            r.notifyRegistrant();
+        }
+    }
+
+    public void unregisterForRadioStateChanged(Handler h) {
+        synchronized (mStateMonitor) {
+            mRadioStateChangedRegistrants.remove(h);
+        }
+    }
+
+    public void registerForOn(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+
+        synchronized (mStateMonitor) {
+            mOnRegistrants.add(r);
+
+            if (mState.isOn()) {
+                r.notifyRegistrant(new AsyncResult(null, null, null));
+            }
+        }
+    }
+    public void unregisterForOn(Handler h) {
+        synchronized (mStateMonitor) {
+            mOnRegistrants.remove(h);
+        }
+    }
+
+
+    public void registerForAvailable(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+
+        synchronized (mStateMonitor) {
+            mAvailRegistrants.add(r);
+
+            if (mState.isAvailable()) {
+                r.notifyRegistrant(new AsyncResult(null, null, null));
+            }
+        }
+    }
+
+    public void unregisterForAvailable(Handler h) {
+        synchronized(mStateMonitor) {
+            mAvailRegistrants.remove(h);
+        }
+    }
+
+    public void registerForNotAvailable(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+
+        synchronized (mStateMonitor) {
+            mNotAvailRegistrants.add(r);
+
+            if (!mState.isAvailable()) {
+                r.notifyRegistrant(new AsyncResult(null, null, null));
+            }
+        }
+    }
+
+    public void unregisterForNotAvailable(Handler h) {
+        synchronized (mStateMonitor) {
+            mNotAvailRegistrants.remove(h);
+        }
+    }
+
+    public void registerForOffOrNotAvailable(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+
+        synchronized (mStateMonitor) {
+            mOffOrNotAvailRegistrants.add(r);
+
+            if (mState == RadioState.RADIO_OFF || !mState.isAvailable()) {
+                r.notifyRegistrant(new AsyncResult(null, null, null));
+            }
+        }
+    }
+    public void unregisterForOffOrNotAvailable(Handler h) {
+        synchronized(mStateMonitor) {
+            mOffOrNotAvailRegistrants.remove(h);
+        }
+    }
+
+
+    /** Any transition into SIM_READY */
+    public void registerForSIMReady(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+
+        synchronized (mStateMonitor) {
+            mSIMReadyRegistrants.add(r);
+
+            if (mState.isSIMReady()) {
+                r.notifyRegistrant(new AsyncResult(null, null, null));
+            }
+        }
+    }
+
+    public void unregisterForSIMReady(Handler h) {
+        synchronized (mStateMonitor) {
+            mSIMReadyRegistrants.remove(h);
+        }
+    }
+
+    /** Any transition into RUIM_READY */
+    public void registerForRUIMReady(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+
+        synchronized (mStateMonitor) {
+            mRUIMReadyRegistrants.add(r);
+
+            if (mState.isRUIMReady()) {
+                r.notifyRegistrant(new AsyncResult(null, null, null));
+            }
+        }
+    }
+
+    public void unregisterForRUIMReady(Handler h) {
+        synchronized(mStateMonitor) {
+            mRUIMReadyRegistrants.remove(h);
+        }
+    }
+
+    /** Any transition into NV_READY */
+    public void registerForNVReady(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+
+        synchronized (mStateMonitor) {
+            mNVReadyRegistrants.add(r);
+
+            if (mState.isNVReady()) {
+                r.notifyRegistrant(new AsyncResult(null, null, null));
+            }
+        }
+    }
+
+    public void unregisterForNVReady(Handler h) {
+        synchronized (mStateMonitor) {
+            mNVReadyRegistrants.remove(h);
+        }
+    }
+
+    public void registerForSIMLockedOrAbsent(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+
+        synchronized (mStateMonitor) {
+            mSIMLockedRegistrants.add(r);
+
+            if (mState == RadioState.SIM_LOCKED_OR_ABSENT) {
+                r.notifyRegistrant(new AsyncResult(null, null, null));
+            }
+        }
+    }
+
+    public void unregisterForSIMLockedOrAbsent(Handler h) {
+        synchronized (mStateMonitor) {
+            mSIMLockedRegistrants.remove(h);
+        }
+    }
+
+    public void registerForRUIMLockedOrAbsent(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+
+        synchronized (mStateMonitor) {
+            mRUIMLockedRegistrants.add(r);
+
+            if (mState == RadioState.RUIM_LOCKED_OR_ABSENT) {
+                r.notifyRegistrant(new AsyncResult(null, null, null));
+            }
+        }
+    }
+
+    public void unregisterForRUIMLockedOrAbsent(Handler h) {
+        synchronized (mStateMonitor) {
+            mRUIMLockedRegistrants.remove(h);
+        }
+    }
+
+    public void registerForCallStateChanged(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+
+        mCallStateRegistrants.add(r);
+    }
+
+    public void unregisterForCallStateChanged(Handler h) {
+        mCallStateRegistrants.remove(h);
+    }
+
+    public void registerForNetworkStateChanged(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+
+        mNetworkStateRegistrants.add(r);
+    }
+
+    public void unregisterForNetworkStateChanged(Handler h) {
+        mNetworkStateRegistrants.remove(h);
+    }
+
+    public void registerForDataStateChanged(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+
+        mDataConnectionRegistrants.add(r);
+    }
+
+    public void unregisterForDataStateChanged(Handler h) {
+        mDataConnectionRegistrants.remove(h);
+    }
+
+    public void registerForRadioTechnologyChanged(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+        mRadioTechnologyChangedRegistrants.add(r);
+    }
+
+    public void unregisterForRadioTechnologyChanged(Handler h) {
+        mRadioTechnologyChangedRegistrants.remove(h);
+    }
+
+    public void registerForIccStatusChanged(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+        mIccStatusChangedRegistrants.add(r);
+    }
+
+    public void unregisterForIccStatusChanged(Handler h) {
+        mIccStatusChangedRegistrants.remove(h);
+    }
+
+    public void setOnNewSMS(Handler h, int what, Object obj) {
+        mSMSRegistrant = new Registrant (h, what, obj);
+    }
+
+    public void unSetOnNewSMS(Handler h) {
+        mSMSRegistrant.clear();
+    }
+
+    public void setOnSmsOnSim(Handler h, int what, Object obj) {
+        mSmsOnSimRegistrant = new Registrant (h, what, obj);
+    }
+
+    public void unSetOnSmsOnSim(Handler h) {
+        mSmsOnSimRegistrant.clear();
+    }
+
+    public void setOnSmsStatus(Handler h, int what, Object obj) {
+        mSmsStatusRegistrant = new Registrant (h, what, obj);
+    }
+
+    public void unSetOnSmsStatus(Handler h) {
+        mSmsStatusRegistrant.clear();
+    }
+
+    public void setOnSignalStrengthUpdate(Handler h, int what, Object obj) {
+        mSignalStrengthRegistrant = new Registrant (h, what, obj);
+    }
+
+    public void unSetOnSignalStrengthUpdate(Handler h) {
+        mSignalStrengthRegistrant.clear();
+    }
+
+    public void setOnNITZTime(Handler h, int what, Object obj) {
+        mNITZTimeRegistrant = new Registrant (h, what, obj);
+    }
+
+    public void unSetOnNITZTime(Handler h) {
+        mNITZTimeRegistrant.clear();
+    }
+
+    public void setOnUSSD(Handler h, int what, Object obj) {
+        mUSSDRegistrant = new Registrant (h, what, obj);
+    }
+
+    public void unSetOnUSSD(Handler h) {
+        mUSSDRegistrant.clear();
+    }
+
+    public void setOnSuppServiceNotification(Handler h, int what, Object obj) {
+        mSsnRegistrant = new Registrant (h, what, obj);
+    }
+
+    public void unSetOnSuppServiceNotification(Handler h) {
+        mSsnRegistrant.clear();
+    }
+
+    public void setOnStkSessionEnd(Handler h, int what, Object obj) {
+        mStkSessionEndRegistrant = new Registrant (h, what, obj);
+    }
+
+    public void unSetOnStkSessionEnd(Handler h) {
+        mStkSessionEndRegistrant.clear();
+    }
+
+    public void setOnStkProactiveCmd(Handler h, int what, Object obj) {
+        mStkProCmdRegistrant = new Registrant (h, what, obj);
+    }
+
+    public void unSetOnStkProactiveCmd(Handler h) {
+        mStkProCmdRegistrant.clear();
+    }
+
+    public void setOnStkEvent(Handler h, int what, Object obj) {
+        mStkEventRegistrant = new Registrant (h, what, obj);
+    }
+
+    public void unSetOnStkEvent(Handler h) {
+        mStkEventRegistrant.clear();
+    }
+
+    public void setOnStkCallSetUp(Handler h, int what, Object obj) {
+        mStkCallSetUpRegistrant = new Registrant (h, what, obj);
+    }
+
+    public void unSetOnStkCallSetUp(Handler h) {
+        mStkCallSetUpRegistrant.clear();
+    }
+
+    public void setOnIccSmsFull(Handler h, int what, Object obj) {
+        mIccSmsFullRegistrant = new Registrant (h, what, obj);
+    }
+
+    public void unSetOnIccSmsFull(Handler h) {
+        mIccSmsFullRegistrant.clear();
+    }
+
+    public void setOnIccRefresh(Handler h, int what, Object obj) {
+        mIccRefreshRegistrant = new Registrant (h, what, obj);
+    }
+
+    public void unSetOnIccRefresh(Handler h) {
+        mIccRefreshRegistrant.clear();
+    }
+
+    public void setOnCallRing(Handler h, int what, Object obj) {
+        mRingRegistrant = new Registrant (h, what, obj);
+    }
+
+    public void unSetOnCallRing(Handler h) {
+        mRingRegistrant.clear();
+    }
+
+    public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+        mVoicePrivacyOnRegistrants.add(r);
+    }
+
+    public void unregisterForInCallVoicePrivacyOn(Handler h){
+        mVoicePrivacyOnRegistrants.remove(h);
+    }
+
+    public void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+        mVoicePrivacyOffRegistrants.add(r);
+    }
+
+    public void unregisterForInCallVoicePrivacyOff(Handler h){
+        mVoicePrivacyOffRegistrants.remove(h);
+    }
+
+    public void setOnRestrictedStateChanged(Handler h, int what, Object obj) {
+        mRestrictedStateRegistrant = new Registrant (h, what, obj);
+    }
+    
+    public void unSetOnRestrictedStateChanged(Handler h) {
+        mRestrictedStateRegistrant.clear();
+    }
+
+    //***** Protected Methods
+    /**
+     * Store new RadioState and send notification based on the changes
+     *
+     * This function is called only by RIL.java when receiving unsolicited
+     * RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED
+     *
+     * RadioState has 5 values : RADIO_OFF, RADIO_UNAVAILABLE, SIM_NOT_READY,
+     * SIM_LOCKED_OR_ABSENT, and SIM_READY.
+     *
+     * @param newState new RadioState decoded from RIL_UNSOL_RADIO_STATE_CHANGED
+     */
+    protected void setRadioState(RadioState newState) {
+        RadioState oldState;
+
+        synchronized (mStateMonitor) {
+            if (Config.LOGV) {
+                Log.v(LOG_TAG, "setRadioState old: " + mState
+                    + " new " + newState);
+            }
+
+            oldState = mState;
+            mState = newState;
+
+            if (oldState == mState) {
+                // no state transition
+                return;
+            }
+
+            if (mContext != null &&
+                    newState == RadioState.RADIO_UNAVAILABLE &&
+                    oldState != RadioState.RADIO_OFF) {
+                Checkin.updateStats(mContext.getContentResolver(),
+                        Checkin.Stats.Tag.PHONE_RADIO_RESETS, 1, 0.0);
+            }
+
+            mRadioStateChangedRegistrants.notifyRegistrants();
+
+            if (mState.isAvailable() && !oldState.isAvailable()) {
+                Log.d(LOG_TAG,"Notifying: radio available");
+                mAvailRegistrants.notifyRegistrants();
+                onRadioAvailable();
+            }
+
+            if (!mState.isAvailable() && oldState.isAvailable()) {
+                Log.d(LOG_TAG,"Notifying: radio not available");
+                mNotAvailRegistrants.notifyRegistrants();
+            }
+
+            if (mState.isSIMReady() && !oldState.isSIMReady()) {
+                Log.d(LOG_TAG,"Notifying: SIM ready");
+                mSIMReadyRegistrants.notifyRegistrants();
+            }
+
+            if (mState == RadioState.SIM_LOCKED_OR_ABSENT) {
+                Log.d(LOG_TAG,"Notifying: SIM locked or absent");
+                mSIMLockedRegistrants.notifyRegistrants();
+            }
+
+            if (mState.isRUIMReady() && !oldState.isRUIMReady()) {
+                Log.d(LOG_TAG,"Notifying: RUIM ready");
+                mRUIMReadyRegistrants.notifyRegistrants();
+            }
+
+            if (mState == RadioState.RUIM_LOCKED_OR_ABSENT) {
+                Log.d(LOG_TAG,"Notifying: RUIM locked or absent");
+                mRUIMLockedRegistrants.notifyRegistrants();
+            }
+            if (mState.isNVReady() && !oldState.isNVReady()) {
+                Log.d(LOG_TAG,"Notifying: NV ready");
+                mNVReadyRegistrants.notifyRegistrants();
+            }
+
+            if (mState.isOn() && !oldState.isOn()) {
+                Log.d(LOG_TAG,"Notifying: Radio On");
+                mOnRegistrants.notifyRegistrants();
+            }
+
+            if ((!mState.isOn() || !mState.isAvailable())
+                && !((!oldState.isOn() || !oldState.isAvailable()))
+            ) {
+                Log.d(LOG_TAG,"Notifying: radio off or not available");
+                mOffOrNotAvailRegistrants.notifyRegistrants();
+            }
+
+            /* Radio Technology Change events
+             * NOTE: isGsm and isCdma have no common states in RADIO_OFF or RADIO_UNAVAILABLE; the
+             *   current phone is determined by mPhoneType
+             * NOTE: at startup no phone have been created and the RIL determines the mPhoneType
+             *   looking based on the networkMode set by the PhoneFactory in the constructor
+             */
+
+            if (mState.isGsm() && oldState.isCdma()) {
+                Log.d(LOG_TAG,"Notifying: radio technology change CDMA to GSM");
+                mRadioTechnologyChangedRegistrants.notifyRegistrants();
+            }
+
+            if (mState.isGsm() && !oldState.isOn() && (mPhoneType == RILConstants.CDMA_PHONE)) {
+                Log.d(LOG_TAG,"Notifying: radio technology change CDMA OFF to GSM");
+                mRadioTechnologyChangedRegistrants.notifyRegistrants();
+            }
+
+            if (mState.isCdma() && oldState.isGsm()) {
+                Log.d(LOG_TAG,"Notifying: radio technology change GSM to CDMA");
+                mRadioTechnologyChangedRegistrants.notifyRegistrants();
+            }
+
+            if (mState.isCdma() && !oldState.isOn() && (mPhoneType == RILConstants.GSM_PHONE)) {
+                Log.d(LOG_TAG,"Notifying: radio technology change GSM OFF to CDMA");
+                mRadioTechnologyChangedRegistrants.notifyRegistrants();
+            }
+        }
+    }
+
+    protected void onRadioAvailable() {
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/Call.java b/telephony/java/com/android/internal/telephony/Call.java
index 82aeb25..70471b6 100644
--- a/telephony/java/com/android/internal/telephony/Call.java
+++ b/telephony/java/com/android/internal/telephony/Call.java
@@ -17,6 +17,7 @@
 package com.android.internal.telephony;
 
 import java.util.List;
+
 /**
  * {@hide}
  */
@@ -39,6 +40,13 @@
         }
     }
 
+
+    /* Instance Variables */
+
+    public State state = State.IDLE;
+
+
+
     /* Instance Methods */
 
     /** Do not modify the List result!!! This list is not yours to keep
@@ -46,36 +54,46 @@
      */
 
     public abstract List<Connection> getConnections();
-    public abstract State getState();
     public abstract Phone getPhone();
+    public abstract boolean isMultiparty();
+    public abstract void hangup() throws CallStateException;
+
 
     /**
      * hasConnection
-     * 
+     *
      * @param c a Connection object
      * @return true if the call contains the connection object passed in
      */
     public boolean hasConnection(Connection c) {
         return c.getCall() == this;
     }
-    
+
     /**
      * hasConnections
      * @return true if the call contains one or more connections
      */
     public boolean hasConnections() {
         List connections = getConnections();
-        
+
         if (connections == null) {
             return false;
         }
-        
+
         return connections.size() > 0;
     }
-    
+
+    /**
+     * getState
+     * @return state of class call
+     */
+    public State getState() {
+        return state;
+    }
+
     /**
      * isIdle
-     * 
+     *
      * FIXME rename
      * @return true if the call contains only disconnected connections (if any)
      */
@@ -93,27 +111,27 @@
         long time = Long.MAX_VALUE;
         Connection c;
         Connection earliest = null;
-        
+
         l = getConnections();
-        
+
         if (l.size() == 0) {
             return null;
         }
-        
+
         for (int i = 0, s = l.size() ; i < s ; i++) {
             c = (Connection) l.get(i);
             long t;
-            
+
             t = c.getCreateTime();
-            
+
             if (t < time) {
                 earliest = c;
             }
         }
-        
+
         return earliest;
     }
-    
+
     public long
     getEarliestCreateTime() {
         List l;
@@ -160,9 +178,6 @@
         return time;
     }
 
-    public abstract boolean isMultiparty();
-
-    public abstract void hangup() throws CallStateException;
 
     public boolean
     isDialingOrAlerting() {
diff --git a/telephony/java/com/android/internal/telephony/gsm/CallForwardInfo.java b/telephony/java/com/android/internal/telephony/CallForwardInfo.java
similarity index 92%
rename from telephony/java/com/android/internal/telephony/gsm/CallForwardInfo.java
rename to telephony/java/com/android/internal/telephony/CallForwardInfo.java
index bf31b13..8b853b0 100644
--- a/telephony/java/com/android/internal/telephony/gsm/CallForwardInfo.java
+++ b/telephony/java/com/android/internal/telephony/CallForwardInfo.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 import android.telephony.PhoneNumberUtils;
 
@@ -23,8 +23,7 @@
  *
  * {@hide}
  */
-public class CallForwardInfo
-{
+public class CallForwardInfo {
     public int             status;      /*1 = active, 0 = not active */
     public int             reason;      /* from TS 27.007 7.11 "reason" */
     public int             serviceClass; /* Sum of CommandsInterface.SERVICE_CLASS */
@@ -32,8 +31,7 @@
     public String          number;      /* "number" from TS 27.007 7.11 */
     public int             timeSeconds; /* for CF no reply only */
 
-    public String toString()
-    {
+    public String toString() {
         return super.toString() + (status == 0 ? " not active " : " active ")
             + " reason: " + reason
             + " serviceClass: " + serviceClass
diff --git a/telephony/java/com/android/internal/telephony/CallTracker.java b/telephony/java/com/android/internal/telephony/CallTracker.java
new file mode 100644
index 0000000..eb339f8
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/CallTracker.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony;
+
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+import com.android.internal.telephony.CommandException;
+
+
+/**
+ * {@hide}
+ */
+public abstract class CallTracker extends Handler {
+
+    private static final boolean DBG_POLL = false;
+
+    //***** Constants
+
+    static final int POLL_DELAY_MSEC = 250;
+
+    protected int pendingOperations;
+    protected boolean needsPoll;
+    protected Message lastRelevantPoll;
+
+    public CommandsInterface cm;
+
+
+    //***** Events
+
+    protected static final int EVENT_POLL_CALLS_RESULT    = 1;
+    protected static final int EVENT_CALL_STATE_CHANGE    = 2;
+    protected static final int EVENT_REPOLL_AFTER_DELAY   = 3;
+    protected static final int EVENT_OPERATION_COMPLETE       = 4;
+    protected static final int EVENT_GET_LAST_CALL_FAIL_CAUSE = 5;
+
+    protected static final int EVENT_SWITCH_RESULT        = 8;
+    protected static final int EVENT_RADIO_AVAILABLE      = 9;
+    protected static final int EVENT_RADIO_NOT_AVAILABLE  = 10;
+    protected static final int EVENT_CONFERENCE_RESULT    = 11;
+    protected static final int EVENT_SEPARATE_RESULT      = 12;
+    protected static final int EVENT_ECT_RESULT           = 13;
+
+
+    protected void pollCallsWhenSafe() {
+        needsPoll = true;
+
+        if (checkNoOperationsPending()) {
+            lastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);
+            cm.getCurrentCalls(lastRelevantPoll);
+        }
+    }
+
+    protected void
+    pollCallsAfterDelay() {
+        Message msg = obtainMessage();
+
+        msg.what = EVENT_REPOLL_AFTER_DELAY;
+        sendMessageDelayed(msg, POLL_DELAY_MSEC);
+    }
+
+    protected boolean
+    isCommandExceptionRadioNotAvailable(Throwable e) {
+        return e != null && e instanceof CommandException
+                && ((CommandException)e).getCommandError()
+                        == CommandException.Error.RADIO_NOT_AVAILABLE;
+    }
+
+    protected abstract void handlePollCalls(AsyncResult ar);
+
+    protected void handleRadioAvailable() {
+        pollCallsWhenSafe();
+    }
+
+    /**
+     * Obtain a complete message that indicates that this operation
+     * does not require polling of getCurrentCalls(). However, if other
+     * operations that do need getCurrentCalls() are pending or are
+     * scheduled while this operation is pending, the invocation
+     * of getCurrentCalls() will be postponed until this
+     * operation is also complete.
+     */
+    protected Message
+    obtainNoPollCompleteMessage(int what) {
+        pendingOperations++;
+        lastRelevantPoll = null;
+        return obtainMessage(what);
+    }
+
+    /**
+     * @return true if we're idle or there's a call to getCurrentCalls() pending
+     * but nothing else
+     */
+    private boolean
+    checkNoOperationsPending() {
+        if (DBG_POLL) log("checkNoOperationsPending: pendingOperations=" +
+                pendingOperations);
+        return pendingOperations == 0;
+    }
+
+
+    //***** Overridden from Handler
+    public abstract void handleMessage (Message msg);
+
+    protected abstract void log(String msg);
+
+}
diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
index 145e5d8..04da9f7 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
@@ -37,7 +37,7 @@
 public class CallerInfoAsyncQuery {
     
     private static final boolean DBG = false;
-    private static final String LOG_TAG = "CallerInfoAsyncQuery";
+    private static final String LOG_TAG = "PHONE";
     
     private static final int EVENT_NEW_QUERY = 1;
     private static final int EVENT_ADD_LISTENER = 2;
diff --git a/telephony/java/com/android/internal/telephony/gsm/CommandException.java b/telephony/java/com/android/internal/telephony/CommandException.java
similarity index 77%
rename from telephony/java/com/android/internal/telephony/gsm/CommandException.java
rename to telephony/java/com/android/internal/telephony/CommandException.java
index 5cf48f3..a5d11cf 100644
--- a/telephony/java/com/android/internal/telephony/gsm/CommandException.java
+++ b/telephony/java/com/android/internal/telephony/CommandException.java
@@ -14,15 +14,16 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
+
+import com.android.internal.telephony.RILConstants;
 
 import android.util.Log;
 
 /**
  * {@hide}
  */
-public class CommandException extends RuntimeException
-{
+public class CommandException extends RuntimeException {
     private Error e;
 
     public enum Error {
@@ -38,30 +39,28 @@
         SMS_FAIL_RETRY,
     }
 
-    public CommandException(Error e)
-    {
+    public CommandException(Error e) {
         super(e.toString());
         this.e = e;
     }
 
     public static CommandException
-    fromRilErrno(int ril_errno)
-    {
+    fromRilErrno(int ril_errno) {
         switch(ril_errno) {
             case RILConstants.SUCCESS:                       return null;
-            case RILConstants.RIL_ERRNO_INVALID_RESPONSE:    
+            case RILConstants.RIL_ERRNO_INVALID_RESPONSE:
                 return new CommandException(Error.INVALID_RESPONSE);
-            case RILConstants.RADIO_NOT_AVAILABLE:           
+            case RILConstants.RADIO_NOT_AVAILABLE:
                 return new CommandException(Error.RADIO_NOT_AVAILABLE);
-            case RILConstants.GENERIC_FAILURE:               
+            case RILConstants.GENERIC_FAILURE:
                 return new CommandException(Error.GENERIC_FAILURE);
-            case RILConstants.PASSWORD_INCORRECT:            
+            case RILConstants.PASSWORD_INCORRECT:
                 return new CommandException(Error.PASSWORD_INCORRECT);
-            case RILConstants.SIM_PIN2:                      
+            case RILConstants.SIM_PIN2:
                 return new CommandException(Error.SIM_PIN2);
-            case RILConstants.SIM_PUK2:                      
+            case RILConstants.SIM_PUK2:
                 return new CommandException(Error.SIM_PUK2);
-            case RILConstants.REQUEST_NOT_SUPPORTED:         
+            case RILConstants.REQUEST_NOT_SUPPORTED:
                 return new CommandException(Error.REQUEST_NOT_SUPPORTED);
             case RILConstants.OP_NOT_ALLOWED_DURING_VOICE_CALL:
                 return new CommandException(Error.OP_NOT_ALLOWED_DURING_VOICE_CALL);
@@ -75,8 +74,7 @@
         }
     }
 
-    public Error getCommandError()
-    {
+    public Error getCommandError() {
         return e;
     }
 
diff --git a/telephony/java/com/android/internal/telephony/gsm/CommandsInterface.java b/telephony/java/com/android/internal/telephony/CommandsInterface.java
similarity index 68%
rename from telephony/java/com/android/internal/telephony/gsm/CommandsInterface.java
rename to telephony/java/com/android/internal/telephony/CommandsInterface.java
index 7915798..aec7238 100644
--- a/telephony/java/com/android/internal/telephony/gsm/CommandsInterface.java
+++ b/telephony/java/com/android/internal/telephony/CommandsInterface.java
@@ -14,50 +14,79 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
-import com.android.internal.telephony.*;
+package com.android.internal.telephony;
+
 import android.os.Message;
 import android.os.Handler;
 
+
 /**
  * {@hide}
  */
-public interface CommandsInterface
-{
+public interface CommandsInterface {
     enum RadioState {
         RADIO_OFF,         /* Radio explictly powered off (eg CFUN=0) */
         RADIO_UNAVAILABLE, /* Radio unavailable (eg, resetting or not booted) */
         SIM_NOT_READY,     /* Radio is on, but the SIM interface is not ready */
-        SIM_LOCKED_OR_ABSENT,  /* SIM PIN locked, PUK required, network 
+        SIM_LOCKED_OR_ABSENT,  /* SIM PIN locked, PUK required, network
                                personalization, or SIM absent */
-        SIM_READY;         /* Radio is on and SIM interface is available */
+        SIM_READY,         /* Radio is on and SIM interface is available */
+        RUIM_NOT_READY,    /* Radio is on, but the RUIM interface is not ready */
+        RUIM_READY,        /* Radio is on and the RUIM interface is available */
+        RUIM_LOCKED_OR_ABSENT, /* RUIM PIN locked, PUK required, network
+                                  personalization locked, or RUIM absent */
+        NV_NOT_READY,      /* Radio is on, but the NV interface is not available */
+        NV_READY;          /* Radio is on and the NV interface is available */
 
-        boolean isOn() /* and available...*/
-        {
+        public boolean isOn() /* and available...*/ {
+            return this == SIM_NOT_READY
+                    || this == SIM_LOCKED_OR_ABSENT
+                    || this == SIM_READY
+                    || this == RUIM_NOT_READY
+                    || this == RUIM_READY
+                    || this == RUIM_LOCKED_OR_ABSENT
+                    || this == NV_NOT_READY
+                    || this == NV_READY;
+        }
+
+        public boolean isAvailable() {
+            return this != RADIO_UNAVAILABLE;
+        }
+
+        public boolean isSIMReady() {
+            return this == SIM_READY;
+        }
+
+        public boolean isRUIMReady() {
+            return this == RUIM_READY;
+        }
+
+        public boolean isNVReady() {
+            return this == NV_READY;
+        }
+
+        public boolean isGsm() {
             return this == SIM_NOT_READY
                     || this == SIM_LOCKED_OR_ABSENT
                     || this == SIM_READY;
         }
 
-        boolean isAvailable()
-        {
-            return this != RADIO_UNAVAILABLE;
-        }
-
-        boolean isSIMReady()
-        {
-            // if you add new states after SIM_READY, include them too
-            return this == SIM_READY;
+        public boolean isCdma() {
+            return this ==  RUIM_NOT_READY
+                    || this == RUIM_READY
+                    || this == RUIM_LOCKED_OR_ABSENT
+                    || this == NV_NOT_READY
+                    || this == NV_READY;
         }
     }
 
-    enum SimStatus {
-        SIM_ABSENT,
-        SIM_NOT_READY,
-        SIM_READY,
-        SIM_PIN,
-        SIM_PUK,
-        SIM_NETWORK_PERSONALIZATION
+    enum IccStatus {
+        ICC_ABSENT,
+        ICC_NOT_READY,
+        ICC_READY,
+        ICC_PIN,
+        ICC_PUK,
+        ICC_NETWORK_PERSONALIZATION
     }
 
     //***** Constants
@@ -93,7 +122,7 @@
     static final String CB_FACILITY_BA_MT        = "AC";
     static final String CB_FACILITY_BA_SIM       = "SC";
     static final String CB_FACILITY_BA_FD        = "FD";
-                  
+
 
     // Used for various supp services apis
     // See 27.007 +CCFC or +CLCK
@@ -102,7 +131,7 @@
     static final int SERVICE_CLASS_DATA     = (1 << 1); //synoym for 16+32+64+128
     static final int SERVICE_CLASS_FAX      = (1 << 2);
     static final int SERVICE_CLASS_SMS      = (1 << 3);
-    static final int SERVICE_CLASS_DATA_SYNC = (1 << 4); 
+    static final int SERVICE_CLASS_DATA_SYNC = (1 << 4);
     static final int SERVICE_CLASS_DATA_ASYNC = (1 << 5);
     static final int SERVICE_CLASS_PACKET   = (1 << 6);
     static final int SERVICE_CLASS_PAD      = (1 << 7);
@@ -122,8 +151,8 @@
 
     RadioState getRadioState();
 
-    /** 
-     * Fires on any RadioState transition 
+    /**
+     * Fires on any RadioState transition
      * Always fires immediately as well
      *
      * do not attempt to calculate transitions by storing getRadioState() values
@@ -131,58 +160,85 @@
      * registration methods
      */
     void registerForRadioStateChanged(Handler h, int what, Object obj);
+    void unregisterForRadioStateChanged(Handler h);
 
-    /** 
-     * Fires on any transition into RadioState.isOn() 
+    /**
+     * Fires on any transition into RadioState.isOn()
      * Fires immediately if currently in that state
      * In general, actions should be idempotent. State may change
      * before event is received.
      */
     void registerForOn(Handler h, int what, Object obj);
+    void unregisterForOn(Handler h);
 
-    /** 
-     * Fires on any transition out of RadioState.isAvailable() 
+    /**
+     * Fires on any transition out of RadioState.isAvailable()
      * Fires immediately if currently in that state
      * In general, actions should be idempotent. State may change
      * before event is received.
      */
     void registerForAvailable(Handler h, int what, Object obj);
-    //void unregisterForAvailable(Handler h);
-    /** 
+    void unregisterForAvailable(Handler h);
+
+    /**
      * Fires on any transition into !RadioState.isAvailable()
      * Fires immediately if currently in that state
      * In general, actions should be idempotent. State may change
      * before event is received.
      */
     void registerForNotAvailable(Handler h, int what, Object obj);
-    //void unregisterForNotAvailable(Handler h);
-    /** 
+    void unregisterForNotAvailable(Handler h);
+
+    /**
      * Fires on any transition into RADIO_OFF or !RadioState.isAvailable()
      * Fires immediately if currently in that state
      * In general, actions should be idempotent. State may change
      * before event is received.
      */
     void registerForOffOrNotAvailable(Handler h, int what, Object obj);
-    //void unregisterForNotAvailable(Handler h);
+    void unregisterForOffOrNotAvailable(Handler h);
 
-    /** 
+    /**
      * Fires on any transition into SIM_READY
      * Fires immediately if if currently in that state
      * In general, actions should be idempotent. State may change
      * before event is received.
      */
     void registerForSIMReady(Handler h, int what, Object obj);
-    //void unregisterForSIMReady(Handler h);
+    void unregisterForSIMReady(Handler h);
+
     /** Any transition into SIM_LOCKED_OR_ABSENT */
     void registerForSIMLockedOrAbsent(Handler h, int what, Object obj);
-    //void unregisterForSIMLockedOrAbsent(Handler h);
+    void unregisterForSIMLockedOrAbsent(Handler h);
 
     void registerForCallStateChanged(Handler h, int what, Object obj);
-    //void unregisterForCallStateChanged(Handler h);
+    void unregisterForCallStateChanged(Handler h);
     void registerForNetworkStateChanged(Handler h, int what, Object obj);
-    //void unregisterForNetworkStateChanged(Handler h);
-    void registerForPDPStateChanged(Handler h, int what, Object obj);
-    //void unregisterForPDPStateChanged(Handler h);
+    void unregisterForNetworkStateChanged(Handler h);
+    void registerForDataStateChanged(Handler h, int what, Object obj);
+    void unregisterForDataStateChanged(Handler h);
+
+    void registerForRadioTechnologyChanged(Handler h, int what, Object obj);
+    void unregisterForRadioTechnologyChanged(Handler h);
+    void registerForNVReady(Handler h, int what, Object obj);
+    void unregisterForNVReady(Handler h);
+    void registerForRUIMLockedOrAbsent(Handler h, int what, Object obj);
+    void unregisterForRUIMLockedOrAbsent(Handler h);
+
+    /** InCall voice privacy notifications */
+    void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj);
+    void unregisterForInCallVoicePrivacyOn(Handler h);
+    void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj);
+    void unregisterForInCallVoicePrivacyOff(Handler h);
+
+    /**
+     * Fires on any transition into RUIM_READY
+     * Fires immediately if if currently in that state
+     * In general, actions should be idempotent. State may change
+     * before event is received.
+     */
+    void registerForRUIMReady(Handler h, int what, Object obj);
+    void unregisterForRUIMReady(Handler h);
 
     /**
      * unlike the register* methods, there's only one new SMS handler
@@ -192,21 +248,24 @@
      * AsyncResult.result is a String containing the SMS PDU
      */
     void setOnNewSMS(Handler h, int what, Object obj);
+    void unSetOnNewSMS(Handler h);
 
    /**
-     * Register for NEW_SMS_ON_SIM unsolicited message 
+     * Register for NEW_SMS_ON_SIM unsolicited message
      *
      * AsyncResult.result is an int array containing the index of new SMS
      */
     void setOnSmsOnSim(Handler h, int what, Object obj);
+    void unSetOnSmsOnSim(Handler h);
 
     /**
-     * Register for NEW_SMS_STATUS_REPORT unsolicited message 
+     * Register for NEW_SMS_STATUS_REPORT unsolicited message
      *
      * AsyncResult.result is a String containing the status report PDU
      */
     void setOnSmsStatus(Handler h, int what, Object obj);
-    
+    void unSetOnSmsStatus(Handler h);
+
     /**
      * unlike the register* methods, there's only one NITZ time handler
      *
@@ -220,13 +279,14 @@
      * seconds on system startup
      */
     void setOnNITZTime(Handler h, int what, Object obj);
+    void unSetOnNITZTime(Handler h);
 
     /**
      * unlike the register* methods, there's only one USSD notify handler
      *
      * Represents the arrival of a USSD "notify" message, which may
      * or may not have been triggered by a previous USSD send
-     * 
+     *
      * AsyncResult.result is a String[]
      * ((String[])(AsyncResult.result))[0] contains status code
      *      "0"   USSD-Notify -- text in ((const char **)data)[1]
@@ -241,26 +301,29 @@
      */
 
     void setOnUSSD(Handler h, int what, Object obj);
+    void unSetOnUSSD(Handler h);
 
     /**
      * unlike the register* methods, there's only one signal strength handler
-     * AsyncResult.result is an int[2]     
-     * response.obj.result[0] is received signal strength (0-31, 99) 
-     * response.obj.result[1] is  bit error rate (0-7, 99) 
+     * AsyncResult.result is an int[2]
+     * response.obj.result[0] is received signal strength (0-31, 99)
+     * response.obj.result[1] is  bit error rate (0-7, 99)
      * as defined in TS 27.007 8.5
      */
 
     void setOnSignalStrengthUpdate(Handler h, int what, Object obj);
+    void unSetOnSignalStrengthUpdate(Handler h);
 
     /**
-     * Sets the handler for SIM SMS storage full unsolicited message.
+     * Sets the handler for SIM/RUIM SMS storage full unsolicited message.
      * Unlike the register* methods, there's only one notification handler
      *
      * @param h Handler for notification message.
      * @param what User-defined message code.
      * @param obj User object.
      */
-    void setOnSimSmsFull(Handler h, int what, Object obj);
+    void setOnIccSmsFull(Handler h, int what, Object obj);
+    void unSetOnIccSmsFull(Handler h);
 
     /**
      * Sets the handler for SIM Refresh notifications.
@@ -270,8 +333,9 @@
      * @param what User-defined message code.
      * @param obj User object.
      */
-    void setOnSimRefresh(Handler h, int what, Object obj);
-    
+    void setOnIccRefresh(Handler h, int what, Object obj);
+    void unSetOnIccRefresh(Handler h);
+
     /**
      * Sets the handler for RING notifications.
      * Unlike the register* methods, there's only one notification handler
@@ -281,7 +345,8 @@
      * @param obj User object.
      */
     void setOnCallRing(Handler h, int what, Object obj);
-    
+    void unSetOnCallRing(Handler h);
+
     /**
      * Sets the handler for RESTRICTED_STATE changed notification, 
      * eg, for Domain Specific Access Control
@@ -292,7 +357,8 @@
      */
 
     void setOnRestrictedStateChanged(Handler h, int what, Object obj);
-    
+    void unSetOnRestrictedStateChanged(Handler h);
+
     /**
      * Sets the handler for Supplementary Service Notifications.
      * Unlike the register* methods, there's only one notification handler
@@ -302,6 +368,7 @@
      * @param obj User object.
      */
     void setOnSuppServiceNotification(Handler h, int what, Object obj);
+    void unSetOnSuppServiceNotification(Handler h);
 
     /**
      * Sets the handler for Session End Notifications for STK.
@@ -312,6 +379,7 @@
      * @param obj User object.
      */
     void setOnStkSessionEnd(Handler h, int what, Object obj);
+    void unSetOnStkSessionEnd(Handler h);
 
     /**
      * Sets the handler for Proactive Commands for STK.
@@ -322,6 +390,7 @@
      * @param obj User object.
      */
     void setOnStkProactiveCmd(Handler h, int what, Object obj);
+    void unSetOnStkProactiveCmd(Handler h);
 
     /**
      * Sets the handler for Event Notifications for STK.
@@ -332,6 +401,7 @@
      * @param obj User object.
      */
     void setOnStkEvent(Handler h, int what, Object obj);
+    void unSetOnStkEvent(Handler h);
 
     /**
      * Sets the handler for Call Set Up Notifications for STK.
@@ -342,6 +412,7 @@
      * @param obj User object.
      */
     void setOnStkCallSetUp(Handler h, int what, Object obj);
+    void unSetOnStkCallSetUp(Handler h);
 
     /**
      * Enables/disbables supplementary service related notifications from
@@ -351,19 +422,21 @@
      * @param result Message to be posted when command completes.
      */
     void setSuppServiceNotifications(boolean enable, Message result);
+    //void unSetSuppServiceNotifications(Handler h);
+
 
     /**
-     * Returns current SIM status.
+     * Returns current ICC status.
      *
-     * AsyncResult.result is SimStatus
-     * 
+     * AsyncResult.result is IccStatus
+     *
      */
 
-    void getSimStatus(Message result);    
+    void getIccStatus(Message result);
 
     /**
-     * Supply the SIM PIN to the SIM card
-     * 
+     * Supply the ICC PIN to the ICC card
+     *
      *  returned message
      *  retMsg.obj = AsyncResult ar
      *  ar.exception carries exception on failure
@@ -373,11 +446,11 @@
      * ar.exception and ar.result are null on success
      */
 
-    void supplySimPin(String pin, Message result);
+    void supplyIccPin(String pin, Message result);
 
     /**
-     * Supply the SIM PUK to the SIM card
-     * 
+     * Supply the ICC PUK to the ICC card
+     *
      *  returned message
      *  retMsg.obj = AsyncResult ar
      *  ar.exception carries exception on failure
@@ -387,13 +460,13 @@
      * ar.exception and ar.result are null on success
      */
 
-    void supplySimPuk(String puk, String newPin, Message result);
+    void supplyIccPuk(String puk, String newPin, Message result);
 
     /**
-     * Supply the SIM PIN2 to the SIM card
-     * Only called following operation where SIM_PIN2 was
+     * Supply the ICC PIN2 to the ICC card
+     * Only called following operation where ICC_PIN2 was
      * returned as a a failure from a previous operation
-     * 
+     *
      *  returned message
      *  retMsg.obj = AsyncResult ar
      *  ar.exception carries exception on failure
@@ -403,13 +476,13 @@
      * ar.exception and ar.result are null on success
      */
 
-    void supplySimPin2(String pin2, Message result);
+    void supplyIccPin2(String pin2, Message result);
 
     /**
      * Supply the SIM PUK2 to the SIM card
      * Only called following operation where SIM_PUK2 was
      * returned as a a failure from a previous operation
-     * 
+     *
      *  returned message
      *  retMsg.obj = AsyncResult ar
      *  ar.exception carries exception on failure
@@ -419,16 +492,16 @@
      * ar.exception and ar.result are null on success
      */
 
-    void supplySimPuk2(String puk2, String newPin2, Message result);
+    void supplyIccPuk2(String puk2, String newPin2, Message result);
 
-    void changeSimPin(String oldPin, String newPin, Message result);
-    void changeSimPin2(String oldPin2, String newPin2, Message result);
+    void changeIccPin(String oldPin, String newPin, Message result);
+    void changeIccPin2(String oldPin2, String newPin2, Message result);
 
     void changeBarringPassword(String facility, String oldPwd, String newPwd, Message result);
 
     void supplyNetworkDepersonalization(String netpin, Message result);
 
-    /** 
+    /**
      *  returned message
      *  retMsg.obj = AsyncResult ar
      *  ar.exception carries exception on failure
@@ -438,16 +511,26 @@
      */
     void getCurrentCalls (Message result);
 
-    /** 
+    /**
+     *  returned message
+     *  retMsg.obj = AsyncResult ar
+     *  ar.exception carries exception on failure
+     *  ar.userObject contains the orignal value of result.obj
+     *  ar.result contains a List of PDPContextState
+     *  @deprecated
+     */
+    void getPDPContextList(Message result);
+
+    /**
      *  returned message
      *  retMsg.obj = AsyncResult ar
      *  ar.exception carries exception on failure
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result contains a List of PDPContextState
      */
-    void getPDPContextList(Message result);
+    void getDataCallList(Message result);
 
-    /** 
+    /**
      *  returned message
      *  retMsg.obj = AsyncResult ar
      *  ar.exception carries exception on failure
@@ -460,7 +543,7 @@
      */
     void dial (String address, int clirMode, Message result);
 
-    /** 
+    /**
      *  returned message
      *  retMsg.obj = AsyncResult ar
      *  ar.exception carries exception on failure
@@ -469,7 +552,7 @@
      */
     void getIMSI(Message result);
 
-    /** 
+    /**
      *  returned message
      *  retMsg.obj = AsyncResult ar
      *  ar.exception carries exception on failure
@@ -478,7 +561,7 @@
      */
     void getIMEI(Message result);
 
-    /** 
+    /**
      *  returned message
      *  retMsg.obj = AsyncResult ar
      *  ar.exception carries exception on failure
@@ -487,7 +570,7 @@
      */
     void getIMEISV(Message result);
 
-    /** 
+    /**
      * Hang up one individual connection.
      *  returned message
      *  retMsg.obj = AsyncResult ar
@@ -512,7 +595,7 @@
 
     /**
      * 3GPP 22.030 6.5.5
-     * "Releases all active calls (if any exist) and accepts 
+     * "Releases all active calls (if any exist) and accepts
      *  the other (held or waiting) call."
      *
      *  ar.exception carries exception on failure
@@ -523,7 +606,7 @@
 
     /**
      * 3GPP 22.030 6.5.5
-     * "Places all active calls (if any exist) on hold and accepts 
+     * "Places all active calls (if any exist) on hold and accepts
      *  the other (held or waiting) call."
      *
      *  ar.exception carries exception on failure
@@ -539,12 +622,27 @@
      *  ar.exception carries exception on failure
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
-     */    
+     */
     void conference (Message result);
 
     /**
+     * Set preferred Voice Privacy (VP).
+     *
+     * @param enable true is enhanced and false is normal VP
+     * @param result is a callback message
+     */
+    void setPreferredVoicePrivacy(boolean enable, Message result);
+
+    /**
+     * Get currently set preferred Voice Privacy (VP) mode.
+     *
+     * @param result is a callback message
+     */
+    void getPreferredVoicePrivacy(Message result);
+
+    /**
      * 3GPP 22.030 6.5.5
-     * "Places all active calls on hold except call X with which 
+     * "Places all active calls on hold except call X with which
      *  communication shall be supported."
      */
     void separateConnection (int gsmIndex, Message result);
@@ -554,15 +652,15 @@
      *  ar.exception carries exception on failure
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
-     */    
+     */
     void acceptCall (Message result);
 
-    /** 
+    /**
      *  also known as UDUB
      *  ar.exception carries exception on failure
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
-     */    
+     */
     void rejectCall (Message result);
 
     /**
@@ -586,14 +684,21 @@
     void getLastCallFailCause (Message result);
 
 
-    /** 
+    /**
      * Reason for last PDP context deactivate or failure to activate
      * cause code returned as int[0] in Message.obj.response
      * returns an integer cause code defined in TS 24.008
      * section 6.1.3.1.3 or close approximation
+     * @deprecated
      */
     void getLastPdpFailCause (Message result);
 
+    /**
+     * The preferred new alternative to getLastPdpFailCause
+     * that is also CDMA-compatible.
+     */
+    void getLastDataCallFailCause (Message result);
+
     void setMute (boolean enableMute, Message response);
 
     void getMute (Message response);
@@ -601,8 +706,8 @@
     /**
      * response.obj is an AsyncResult
      * response.obj.result is an int[2]
-     * response.obj.result[0] is received signal strength (0-31, 99) 
-     * response.obj.result[1] is  bit error rate (0-7, 99) 
+     * response.obj.result[0] is received signal strength (0-31, 99)
+     * response.obj.result[1] is  bit error rate (0-7, 99)
      * as defined in TS 27.007 8.5
      */
     void getSignalStrength (Message response);
@@ -612,21 +717,21 @@
      * response.obj.result is an int[3]
      * response.obj.result[0] is registration state 0-5 from TS 27.007 7.2
      * response.obj.result[1] is LAC if registered or -1 if not
-     * response.obj.result[2] is CID if registered or -1 if not 
+     * response.obj.result[2] is CID if registered or -1 if not
      * valid LAC and CIDs are 0x0000 - 0xffff
-     * 
+     *
      * Please note that registration state 4 ("unknown") is treated
      * as "out of service" above
      */
     void getRegistrationState (Message response);
-                                                                                                            
+
     /**
      * response.obj.result is an int[3]
      * response.obj.result[0] is registration state 0-5 from TS 27.007 7.2
      * response.obj.result[1] is LAC if registered or -1 if not
-     * response.obj.result[2] is CID if registered or -1 if not 
+     * response.obj.result[2] is CID if registered or -1 if not
      * valid LAC and CIDs are 0x0000 - 0xffff
-     * 
+     *
      * Please note that registration state 4 ("unknown") is treated
      * as "out of service" above
      */
@@ -637,14 +742,14 @@
      * response.obj.result[0] is long alpha or null if unregistered
      * response.obj.result[1] is short alpha or null if unregistered
      * response.obj.result[2] is numeric or null if unregistered
-     */ 
+     */
     void getOperator(Message response);
 
     /**
      *  ar.exception carries exception on failure
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
-     */    
+     */
     void sendDtmf(char c, Message result);
 
 
@@ -667,26 +772,40 @@
      * smscPDU is smsc address in PDU form GSM BCD format prefixed
      *      by a length byte (as expected by TS 27.005) or NULL for default SMSC
      * pdu is SMS in PDU format as an ASCII hex string
-     *      less the SMSC address     
+     *      less the SMSC address
      */
     void sendSMS (String smscPDU, String pdu, Message response);
 
     /**
+     * @param pdu is CDMA-SMS in internal pseudo-PDU format
+     * @param response sent when operation completes
+     */
+    void sendCdmaSms(byte[] pdu, Message response);
+
+    /**
      * Deletes the specified SMS record from SIM memory (EF_SMS).
-     * 
+     *
      * @param index index of the SMS record to delete
      * @param response sent when operation completes
      */
     void deleteSmsOnSim(int index, Message response);
 
     /**
+     * Deletes the specified SMS record from RUIM memory (EF_SMS in DF_CDMA).
+     *
+     * @param index index of the SMS record to delete
+     * @param response sent when operation completes
+     */
+    void deleteSmsOnRuim(int index, Message response);
+
+    /**
      * Writes an SMS message to SIM memory (EF_SMS).
-     * 
+     *
      * @param status status of message on SIM.  One of:
-     *                  SmsManger.STATUS_ON_SIM_READ
-     *                  SmsManger.STATUS_ON_SIM_UNREAD
-     *                  SmsManger.STATUS_ON_SIM_SENT
-     *                  SmsManger.STATUS_ON_SIM_UNSENT
+     *                  SmsManger.STATUS_ON_ICC_READ
+     *                  SmsManger.STATUS_ON_ICC_UNREAD
+     *                  SmsManger.STATUS_ON_ICC_SENT
+     *                  SmsManger.STATUS_ON_ICC_UNSENT
      * @param pdu message PDU, as hex string
      * @param response sent when operation completes.
      *                  response.obj will be an AsyncResult, and will indicate
@@ -694,89 +813,105 @@
      */
     void writeSmsToSim(int status, String smsc, String pdu, Message response);
 
+    void writeSmsToRuim(int status, String pdu, Message response);
+
+    /**
+     * @deprecated
+     * @param apn
+     * @param user
+     * @param password
+     * @param response
+     */
     void setupDefaultPDP(String apn, String user, String password, Message response);
 
+    /**
+     * @deprecated
+     * @param cid
+     * @param response
+     */
     void deactivateDefaultPDP(int cid, Message response);
 
     void setRadioPower(boolean on, Message response);
 
     void acknowledgeLastIncomingSMS(boolean success, Message response);
 
-    /** 
-     * parameters equivilient to 27.007 AT+CRSM command 
+    void acknowledgeLastIncomingCdmaSms(boolean success, Message response);
+
+    /**
+     * parameters equivilient to 27.007 AT+CRSM command
      * response.obj will be an AsyncResult
-     * response.obj.userObj will be a SimIoResult on success
+     * response.obj.userObj will be a IccIoResult on success
      */
-    void simIO (int command, int fileid, String path, int p1, int p2, int p3, 
+    void iccIO (int command, int fileid, String path, int p1, int p2, int p3,
             String data, String pin2, Message response);
 
     /**
      * (AsyncResult)response.obj).result is an int[] with element [0] set to
-     * 1 for "CLIP is provisioned", and 0 for "CLIP is not provisioned". 
+     * 1 for "CLIP is provisioned", and 0 for "CLIP is not provisioned".
      *
      * @param response is callback message
      */
-    
+
     void queryCLIP(Message response);
 
     /**
      * response.obj will be a an int[2]
      *
      * response.obj[0] will be TS 27.007 +CLIR parameter 'n'
-     *  0 presentation indicator is used according to the subscription of the CLIR service 
-     *  1 CLIR invocation 
-     *  2 CLIR suppression 
+     *  0 presentation indicator is used according to the subscription of the CLIR service
+     *  1 CLIR invocation
+     *  2 CLIR suppression
      *
      * response.obj[1] will be TS 27.007 +CLIR parameter 'm'
-     *  0 CLIR not provisioned 
-     *  1 CLIR provisioned in permanent mode 
-     *  2 unknown (e.g. no network, etc.) 
-     *  3 CLIR temporary mode presentation restricted 
-     *  4 CLIR temporary mode presentation allowed 
+     *  0 CLIR not provisioned
+     *  1 CLIR provisioned in permanent mode
+     *  2 unknown (e.g. no network, etc.)
+     *  3 CLIR temporary mode presentation restricted
+     *  4 CLIR temporary mode presentation allowed
      */
 
     void getCLIR(Message response);
-    
+
     /**
      * clirMode is one of the CLIR_* constants above
      *
      * response.obj is null
      */
-    
+
     void setCLIR(int clirMode, Message response);
 
     /**
      * (AsyncResult)response.obj).result is an int[] with element [0] set to
-     * 0 for disabled, 1 for enabled. 
+     * 0 for disabled, 1 for enabled.
      *
      * @param serviceClass is a sum of SERVICE_CLASS_*
      * @param response is callback message
      */
-    
+
     void queryCallWaiting(int serviceClass, Message response);
-    
+
     /**
      * @param enable is true to enable, false to disable
      * @param serviceClass is a sum of SERVICE_CLASS_*
      * @param response is callback message
      */
-    
+
     void setCallWaiting(boolean enable, int serviceClass, Message response);
 
     /**
      * @param action is one of CF_ACTION_*
      * @param cfReason is one of CF_REASON_*
-     * @param serviceClass is a sum of SERVICE_CLASSS_* 
+     * @param serviceClass is a sum of SERVICE_CLASSS_*
      */
-    void setCallForward(int action, int cfReason, int serviceClass, 
-                String number, int timeSeconds, Message response); 
+    void setCallForward(int action, int cfReason, int serviceClass,
+                String number, int timeSeconds, Message response);
 
     /**
      * cfReason is one of CF_REASON_*
      *
      * ((AsyncResult)response.obj).result will be an array of
      * CallForwardInfo's
-     * 
+     *
      * An array of length 0 means "disabled for all codes"
      */
     void queryCallForwardStatus(int cfReason, int serviceClass,
@@ -815,7 +950,7 @@
      * @param serviceClass is a sum of SERVICE_CLASS_*
      * @param response is callback message
      */
-    
+
     void queryFacilityLock (String facility, String password, int serviceClass,
         Message response);
 
@@ -828,7 +963,7 @@
      */
     void setFacilityLock (String facility, boolean lockState, String password,
         int serviceClass, Message response);
-    
+
 
     void sendUSSD (String ussdString, Message response);
 
@@ -850,7 +985,7 @@
 
     /**
      * Query the list of band mode supported by RF.
-     * 
+     *
      * @param response is callback message
      *        ((AsyncResult)response.obj).result  is an int[] with every
      *        element representing one avialable BM_*_BAND
@@ -923,4 +1058,136 @@
      * @param response Callback message
      */
     public void handleCallSetupRequestFromSim(boolean accept, Message response);
+
+    //***** new Methods for CDMA support
+
+    /**
+     * Request the device ESN / MEID / IMEI / IMEISV.
+     * "response" is const char **
+     *   [0] is IMEI if GSM subscription is available
+     *   [1] is IMEISV if GSM subscription is available
+     *   [2] is ESN if CDMA subscription is available
+     *   [3] is MEID if CDMA subscription is available
+     */
+    public void getDeviceIdentity(Message response);
+
+    /**
+     * Request the device IMSI_M / MDN / AH_SID / H_SID / H_NID.
+     * "response" is const char **
+     *   [0] is IMSI_M if CDMA subscription is available
+     *   [1] is MDN if CDMA subscription is available
+     *   [2] is AH_SID (Analog Home SID) if CDMA subscription
+     *   [3] is H_SID (Home SID) if CDMA subscription is available
+     *   [4] is H_NID (Home SID) if CDMA subscription is available
+     */
+    public void getCDMASubscription(Message response);
+
+    /**
+     * Send Flash Code.
+     * "response" is is NULL
+     *   [0] is a FLASH string
+     */
+    public void sendCDMAFeatureCode(String FeatureCode, Message response);
+
+    /** Set the Phone type created */
+    void setPhoneType(int phoneType);
+    /**
+     *  Query the CDMA roaming preference setting
+     *
+     * @param response is callback message to report one of  CDMA_RM_*
+     */
+    void queryCdmaRoamingPreference(Message response);
+
+    /**
+     *  Requests to set the CDMA roaming preference
+     * @param cdmaRoamingType one of  CDMA_RM_*
+     * @param response is callback message
+     */
+    void setCdmaRoamingPreference(int cdmaRoamingType, Message response);
+
+    /**
+     *  Requests to set the CDMA subscription mode
+     * @param cdmaSubscriptionType one of  CDMA_SUBSCRIPTION_*
+     * @param response is callback message
+     */
+    void setCdmaSubscription(int cdmaSubscriptionType, Message response);
+
+    /**
+     *  Set the TTY mode for the CDMA phone
+     *
+     * @param enable is true to enable, false to disable
+     * @param response is callback message
+     */
+    void setTTYModeEnabled(boolean enable, Message response);
+
+    /**
+     *  Query the TTY mode for the CDMA phone
+     * (AsyncResult)response.obj).result is an int[] with element [0] set to
+     * 0 for disabled, 1 for enabled.
+     *
+     * @param response is callback message
+     */
+    void queryTTYModeEnabled(Message response);
+
+    /**
+     * Setup a packet data connection On successful completion, the result
+     * message will return the following: [0] indicating PDP CID, which is
+     * generated by RIL. This Connection ID is used in both GSM/UMTS and CDMA
+     * modes [1] indicating the network interface name for GSM/UMTS or CDMA [2]
+     * indicating the IP address for this interface for GSM/UMTS and NULL in the
+     * case of CDMA
+     *
+     * @param radioTechnology
+     *            indicates whether to setup connection on radio technology CDMA
+     *            (0) or GSM/UMTS (1)
+     * @param profile
+     *            Profile Number or NULL to indicate default profile
+     * @param apn
+     *            the APN to connect to if radio technology is GSM/UMTS.
+     *            Otherwise null for CDMA.
+     * @param user
+     *            the username for APN, or NULL
+     * @param password
+     *            the password for APN, or NULL
+     * @param result
+     *            Callback message
+     */
+    public void setupDataCall(String radioTechnology, String profile, String apn,
+            String user, String password, Message result);
+
+    /**
+     * Deactivate packet data connection
+     *
+     * @param cid
+     *            The connection ID
+     * @param result
+     *            Callback message is empty on completion
+     */
+    public void deactivateDataCall(int cid, Message result);
+
+    /**
+     * Activate or deactivate cell broadcast SMS.
+     *
+     * @param activate
+     *            0 = activate, 1 = deactivate
+     * @param result
+     *            Callback message is empty on completion
+     */
+    public void activateCdmaBroadcastSms(int activate, Message result);
+
+    /**
+     * Configure cdma cell broadcast SMS.
+     *
+     * @param result
+     *            Callback message is empty on completion
+     */
+    public void setCdmaBroadcastConfig(int[] configValuesArray, Message result);
+
+    /**
+     * Query the current configuration of cdma cell broadcast SMS.
+     *
+     * @param result
+     *            Callback message contains the configuration from the modem on completion
+     */
+    public void getCdmaBroadcastConfig(Message result);
 }
diff --git a/telephony/java/com/android/internal/telephony/Connection.java b/telephony/java/com/android/internal/telephony/Connection.java
index ead49bf..86ceb89 100644
--- a/telephony/java/com/android/internal/telephony/Connection.java
+++ b/telephony/java/com/android/internal/telephony/Connection.java
@@ -19,8 +19,8 @@
 /**
  * {@hide}
  */
-public abstract class Connection
-{
+public abstract class Connection {
+
     // Number presentation type for caller id display
     public static int PRESENTATION_ALLOWED = 1;    // normal
     public static int PRESENTATION_RESTRICTED = 2; // block by user
@@ -42,7 +42,7 @@
         INCOMING_REJECTED,  /* an incoming call that was rejected */
         POWER_OFF,          /* radio is turned off explicitly */
         OUT_OF_SERVICE,     /* out of service */
-        SIM_ERROR,          /* No SIM, SIM locked, or other SIM error */
+        ICC_ERROR,          /* No ICC, ICC locked, or other ICC error */
         CALL_BARRED,        /* call was blocked by call barrring */
         FDN_BLOCKED,        /* call was blocked by fixed dial number */
         CS_RESTRICTED,      /* call was blocked by restricted all voice access */
@@ -54,7 +54,7 @@
 
     /* Instance Methods */
 
-    /** 
+    /**
      * Gets address (e.g., phone number) associated with connection
      * TODO: distinguish reasons for unavailablity
      *
@@ -92,7 +92,7 @@
     public abstract long getDisconnectTime();
 
     /**
-     * returns the number of milliseconds the call has been connected, 
+     * returns the number of milliseconds the call has been connected,
      * or 0 if the call has never connected.
      * If the call is still connected, then returns the elapsed
      * time since connect
@@ -113,8 +113,8 @@
     public abstract DisconnectCause getDisconnectCause();
 
     /**
-     * Returns true of this connection originated elsewhere 
-     * ("MT" or mobile terminated; another party called this terminal) 
+     * Returns true of this connection originated elsewhere
+     * ("MT" or mobile terminated; another party called this terminal)
      * or false if this call originated here (MO or mobile originated)
      */
     public abstract boolean isIncoming();
@@ -122,32 +122,30 @@
     /**
      * If this Connection is connected, then it is associated with
      * a Call.
-     * 
+     *
      * Returns getCall().getState() or Call.State.IDLE if not
      * connected
      */
-    public Call.State getState()
-    {
+    public Call.State getState() {
         Call c;
 
         c = getCall();
 
-        if (c == null) { 
+        if (c == null) {
             return Call.State.IDLE;
         } else {
             return c.getState();
         }
     }
-    
+
     /**
      * isAlive()
-     * 
+     *
      * @return true if the connection isn't disconnected
      * (could be active, holding, ringing, dialing, etc)
      */
     public boolean
-    isAlive()
-    {
+    isAlive() {
         return getState().isAlive();
     }
 
@@ -155,29 +153,26 @@
      * Returns true if Connection is connected and is INCOMING or WAITING
      */
     public boolean
-    isRinging()
-    {
+    isRinging() {
         return getState().isRinging();
     }
 
     /**
-     * 
+     *
      * @return the userdata set in setUserData()
      */
-    public Object getUserData()
-    {
+    public Object getUserData() {
         return userData;
     }
 
     /**
-     * 
+     *
      * @param userdata user can store an any userdata in the Connection object.
      */
-    public void setUserData(Object userdata)
-    {
+    public void setUserData(Object userdata) {
         this.userData = userdata;
     }
-    
+
     /**
      * Hangup individual Connection
      */
@@ -191,16 +186,16 @@
     public abstract void separate() throws CallStateException;
 
     public enum PostDialState {
-        NOT_STARTED,    /* The post dial string playback hasn't 
-                           been started, or this call is not yet 
+        NOT_STARTED,    /* The post dial string playback hasn't
+                           been started, or this call is not yet
                            connected, or this is an incoming call */
         STARTED,        /* The post dial string playback has begun */
-        WAIT,           /* The post dial string playback is waiting for a 
+        WAIT,           /* The post dial string playback is waiting for a
                            call to proceedAfterWaitChar() */
-        WILD,           /* The post dial string playback is waiting for a 
+        WILD,           /* The post dial string playback is waiting for a
                            call to proceedAfterWildChar() */
         COMPLETE,       /* The post dial string playback is complete */
-        CANCELLED       /* The post dial string playback was cancelled 
+        CANCELLED       /* The post dial string playback was cancelled
                            with cancelPostDial() */
     }
 
@@ -215,7 +210,7 @@
     /**
      * See Phone.setOnPostDialWaitCharacter()
      */
-     
+
     public abstract void proceedAfterWaitChar();
 
     /**
@@ -232,5 +227,5 @@
      * @return one of PRESENTATION_*
      */
     public abstract int getNumberPresentation();
-    
+
 }
diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java
new file mode 100644
index 0000000..6e9d1ab
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/DataConnection.java
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony;
+
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+/**
+ * {@hide}
+ */
+public abstract class DataConnection extends Handler {
+
+    // the inherited class
+
+    public enum State {
+        ACTIVE, /* has active data connection */
+        ACTIVATING, /* during connecting process */
+        INACTIVE; /* has empty data connection */
+
+        public String toString() {
+            switch (this) {
+            case ACTIVE:
+                return "active";
+            case ACTIVATING:
+                return "setting up";
+            default:
+                return "inactive";
+            }
+        }
+
+        public boolean isActive() {
+            return this == ACTIVE;
+        }
+
+        public boolean isInactive() {
+            return this == INACTIVE;
+        }
+    }
+
+    public enum FailCause {
+        NONE,
+        BAD_APN,
+        BAD_PAP_SECRET,
+        BARRED,
+        USER_AUTHENTICATION,
+        SERVICE_OPTION_NOT_SUPPORTED,
+        SERVICE_OPTION_NOT_SUBSCRIBED,
+        SIM_LOCKED,
+        RADIO_OFF,
+        NO_SIGNAL,
+        NO_DATA_PLAN,
+        RADIO_NOT_AVAILABLE,
+        SUSPENED_TEMPORARY,
+        RADIO_ERROR_RETRY,
+        UNKNOWN;
+
+        public boolean isPermanentFail() {
+            return (this == RADIO_OFF);
+        }
+
+        public String toString() {
+            switch (this) {
+            case NONE:
+                return "no error";
+            case BAD_APN:
+                return "bad apn";
+            case BAD_PAP_SECRET:
+                return "bad pap secret";
+            case BARRED:
+                return "barred";
+            case USER_AUTHENTICATION:
+                return "error user autentication";
+            case SERVICE_OPTION_NOT_SUPPORTED:
+                return "data not supported";
+            case SERVICE_OPTION_NOT_SUBSCRIBED:
+                return "datt not subcribed";
+            case SIM_LOCKED:
+                return "sim locked";
+            case RADIO_OFF:
+                return "radio is off";
+            case NO_SIGNAL:
+                return "no signal";
+            case NO_DATA_PLAN:
+                return "no data plan";
+            case RADIO_NOT_AVAILABLE:
+                return "radio not available";
+            case SUSPENED_TEMPORARY:
+                return "suspend temporary";
+            case RADIO_ERROR_RETRY:
+                return "transient radio error";
+            default:
+                return "unknown data error";
+            }
+        }
+    }
+
+    // ***** Event codes
+    protected static final int EVENT_SETUP_DATA_CONNECTION_DONE = 1;
+    protected static final int EVENT_GET_LAST_FAIL_DONE = 2;
+    protected static final int EVENT_LINK_STATE_CHANGED = 3;
+    protected static final int EVENT_DEACTIVATE_DONE = 4;
+    protected static final int EVENT_FORCE_RETRY = 5;
+
+    //***** Tag IDs for EventLog
+    protected static final int EVENT_LOG_BAD_DNS_ADDRESS = 50100;
+
+
+    //***** Member Variables
+    protected PhoneBase phone;
+    protected Message onConnectCompleted;
+    protected Message onDisconnect;
+    protected int cid;
+    protected String interfaceName;
+    protected String ipAddress;
+    protected String gatewayAddress;
+    protected String[] dnsServers;
+    protected State state;
+    protected long createTime;
+    protected long lastFailTime;
+    protected FailCause lastFailCause;
+    protected static final String NULL_IP = "0.0.0.0";
+    Object userData;
+
+    // receivedDisconnectReq is set when disconnect during activation
+    protected boolean receivedDisconnectReq;
+
+    /* Instance Methods */
+    protected abstract void onSetupConnectionCompleted(AsyncResult ar);
+
+    protected abstract void onDeactivated(AsyncResult ar);
+
+    protected abstract void disconnect(Message msg);
+
+    protected abstract void notifyFail(FailCause cause, Message onCompleted);
+
+    protected abstract void notifyDisconnect(Message msg);
+
+    protected abstract void onLinkStateChanged(DataLink.LinkState linkState);
+
+    protected abstract FailCause getFailCauseFromRequest(int rilCause);
+
+    public abstract String toString();
+
+    protected abstract void log(String s);
+
+
+   //***** Constructor
+    protected DataConnection(PhoneBase phone) {
+        super();
+        this.phone = phone;
+        onConnectCompleted = null;
+        onDisconnect = null;
+        this.cid = -1;
+        receivedDisconnectReq = false;
+        this.dnsServers = new String[2];
+
+        clearSettings();
+    }
+
+    protected void setHttpProxy(String httpProxy, String httpPort) {
+        if (httpProxy == null || httpProxy.length() == 0) {
+            phone.setSystemProperty("net.gprs.http-proxy", null);
+            return;
+        }
+
+        if (httpPort == null || httpPort.length() == 0) {
+            httpPort = "8080";     // Default to port 8080
+        }
+
+        phone.setSystemProperty("net.gprs.http-proxy",
+                "http://" + httpProxy + ":" + httpPort + "/");
+    }
+
+    public String getInterface() {
+        return interfaceName;
+    }
+
+    public String getIpAddress() {
+        return ipAddress;
+    }
+
+    public String getGatewayAddress() {
+        return gatewayAddress;
+    }
+
+    public String[] getDnsServers() {
+        return dnsServers;
+    }
+
+    public void clearSettings() {
+        log("DataConnection.clearSettings()");
+
+        this.state = State.INACTIVE;
+        this.createTime = -1;
+        this.lastFailTime = -1;
+        this.lastFailCause = FailCause.NONE;
+
+        receivedDisconnectReq = false;
+        onConnectCompleted = null;
+        interfaceName = null;
+        ipAddress = null;
+        gatewayAddress = null;
+        dnsServers[0] = null;
+        dnsServers[1] = null;
+    }
+
+    protected void onGetLastFailCompleted(AsyncResult ar) {
+        if (receivedDisconnectReq) {
+            // Don't bother reporting the error if there's already a
+            // pending disconnect request, since DataConnectionTracker
+            // has already updated its state.
+            notifyDisconnect(onDisconnect);
+        } else {
+            FailCause cause = FailCause.UNKNOWN;
+
+            if (ar.exception == null) {
+                int rilFailCause = ((int[]) (ar.result))[0];
+                cause = getFailCauseFromRequest(rilFailCause);
+            }
+            notifyFail(cause, onConnectCompleted);
+        }
+    }
+
+    protected void onForceRetry() {
+        if (receivedDisconnectReq) {
+            notifyDisconnect(onDisconnect);
+        } else {
+            notifyFail(FailCause.RADIO_ERROR_RETRY, onConnectCompleted);
+        }
+    }
+
+    @Override
+    public void handleMessage(Message msg) {
+        AsyncResult ar;
+
+        log("DataConnection.handleMessage()");
+
+        switch (msg.what) {
+
+        case EVENT_SETUP_DATA_CONNECTION_DONE:
+            onSetupConnectionCompleted((AsyncResult) msg.obj);
+            break;
+
+        case EVENT_FORCE_RETRY:
+            onForceRetry();
+            break;
+
+        case EVENT_GET_LAST_FAIL_DONE:
+            onGetLastFailCompleted((AsyncResult) msg.obj);
+            break;
+
+        case EVENT_LINK_STATE_CHANGED:
+            ar = (AsyncResult) msg.obj;
+            DataLink.LinkState ls  = (DataLink.LinkState) ar.result;
+            onLinkStateChanged(ls);
+            break;
+
+        case EVENT_DEACTIVATE_DONE:
+            onDeactivated((AsyncResult) msg.obj);
+            break;
+        }
+    }
+
+    public State getState() {
+        log("DataConnection.getState()");
+        return state;
+    }
+
+    public long getConnectionTime() {
+        log("DataConnection.getConnectionTime()");
+        return createTime;
+    }
+
+    public long getLastFailTime() {
+        log("DataConnection.getLastFailTime()");
+        return lastFailTime;
+    }
+
+    public FailCause getLastFailCause() {
+        log("DataConnection.getLastFailCause()");
+        return lastFailCause;
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
new file mode 100644
index 0000000..5b826b2
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony;
+
+import android.app.PendingIntent;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.INetStatService;
+import android.os.Message;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
+import android.util.Log;
+
+/**
+ * {@hide}
+ *
+ */
+public abstract class DataConnectionTracker extends Handler {
+    private static final boolean DBG = true;
+
+    /**
+     * IDLE: ready to start data connection setup, default state
+     * INITING: state of issued setupDefaultPDP() but not finish yet
+     * CONNECTING: state of issued startPppd() but not finish yet
+     * SCANNING: data connection fails with one apn but other apns are available
+     *           ready to start data connection on other apns (before INITING)
+     * CONNECTED: IP connection is setup
+     * DISCONNECTING: Connection.disconnect() has been called, but PDP
+     *                context is not yet deactivated
+     * FAILED: data connection fail for all apns settings
+     *
+     * getDataConnectionState() maps State to DataState
+     *      FAILED or IDLE : DISCONNECTED
+     *      INITING or CONNECTING or SCANNING: CONNECTING
+     *      CONNECTED : CONNECTED or DISCONNECTING
+     */
+    public enum State {
+        IDLE,
+        INITING,
+        CONNECTING,
+        SCANNING,
+        CONNECTED,
+        DISCONNECTING,
+        FAILED
+    }
+
+    public enum Activity {
+        NONE,
+        DATAIN,
+        DATAOUT,
+        DATAINANDOUT
+    }
+
+    //***** Event Codes
+    protected static final int EVENT_DATA_SETUP_COMPLETE = 1;
+    protected static final int EVENT_RADIO_AVAILABLE = 3;
+    protected static final int EVENT_RECORDS_LOADED = 4;
+    protected static final int EVENT_TRY_SETUP_DATA = 5;
+    protected static final int EVENT_DATA_STATE_CHANGED = 6;
+    protected static final int EVENT_POLL_PDP = 7;
+    protected static final int EVENT_GET_PDP_LIST_COMPLETE = 11;
+    protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 12;
+    protected static final int EVENT_VOICE_CALL_STARTED = 14;
+    protected static final int EVENT_VOICE_CALL_ENDED = 15;
+    protected static final int EVENT_GPRS_DETACHED = 19;
+    protected static final int EVENT_LINK_STATE_CHANGED = 20;
+    protected static final int EVENT_ROAMING_ON = 21;
+    protected static final int EVENT_ROAMING_OFF = 22;
+    protected static final int EVENT_ENABLE_NEW_APN = 23;
+    protected static final int EVENT_RESTORE_DEFAULT_APN = 24;
+    protected static final int EVENT_DISCONNECT_DONE = 25;
+    protected static final int EVENT_GPRS_ATTACHED = 26;
+    protected static final int EVENT_START_NETSTAT_POLL = 27;
+    protected static final int EVENT_START_RECOVERY = 28;
+    protected static final int EVENT_APN_CHANGED = 29;
+    protected static final int EVENT_CDMA_DATA_DETACHED = 30;
+    protected static final int EVENT_NV_READY = 31;
+    protected static final int EVENT_PS_RESTRICT_ENABLED = 32;
+    protected static final int EVENT_PS_RESTRICT_DISABLED = 33;
+
+    //***** Constants
+    protected static final int RECONNECT_DELAY_INITIAL_MILLIS = 5 * 1000;
+
+    /** Cap out with 1 hour retry interval. */
+    protected static final int RECONNECT_DELAY_MAX_MILLIS = 60 * 60 * 1000;
+
+    /** Slow poll when attempting connection recovery. */
+    protected static final int POLL_NETSTAT_SLOW_MILLIS = 5000;
+    /** Default ping deadline, in seconds. */
+    protected final int DEFAULT_PING_DEADLINE = 5;
+    /** Default max failure count before attempting to network re-registration. */
+    protected final int DEFAULT_MAX_PDP_RESET_FAIL = 3;
+
+    /**
+     * After detecting a potential connection problem, this is the max number
+     * of subsequent polls before attempting a radio reset.  At this point,
+     * poll interval is 5 seconds (POLL_NETSTAT_SLOW_MILLIS), so set this to
+     * poll for about 2 more minutes.
+     */
+    protected static final int NO_RECV_POLL_LIMIT = 24;
+
+    // 1 sec. default polling interval when screen is on.
+    protected static final int POLL_NETSTAT_MILLIS = 1000;
+    // 10 min. default polling interval when screen is off.
+    protected static final int POLL_NETSTAT_SCREEN_OFF_MILLIS = 1000*60*10;
+    // 2 min for round trip time
+    protected static final int POLL_LONGEST_RTT = 120 * 1000;
+    // 10 for packets without ack
+    protected static final int NUMBER_SENT_PACKETS_OF_HANG = 10;
+    // how long to wait before switching back to default APN
+    protected static final int RESTORE_DEFAULT_APN_DELAY = 1 * 60 * 1000;
+    // system property that can override the above value
+    protected static final String APN_RESTORE_DELAY_PROP_NAME = "android.telephony.apn-restore";
+    // represents an invalid IP address
+    protected static final String NULL_IP = "0.0.0.0";
+
+
+    // member variables
+    protected PhoneBase phone;
+    protected Activity activity = Activity.NONE;
+    protected State state = State.IDLE;
+    protected Handler mDataConnectionTracker = null;
+
+
+    protected INetStatService netstat;
+    protected long txPkts, rxPkts, sentSinceLastRecv;
+    protected int netStatPollPeriod;
+    protected int mNoRecvPollCount = 0;
+    protected boolean netStatPollEnabled = false;
+
+    // wifi connection status will be updated by sticky intent
+    protected boolean mIsWifiConnected = false;
+
+    /** Intent sent when the reconnect alarm fires. */
+    protected PendingIntent mReconnectIntent = null;
+    
+    /** CID of active data connection */
+    protected int cidActive;
+
+   /**
+     * Default constructor
+     */
+    protected DataConnectionTracker(PhoneBase phone) {
+        super();
+        this.phone = phone;
+    }
+
+    public Activity getActivity() {
+        return activity;
+    }
+
+    public State getState() {
+        return state;
+    }
+
+    public String getStateInString() {
+        switch (state) {
+            case IDLE:          return "IDLE";
+            case INITING:       return "INIT";
+            case CONNECTING:    return "CING";
+            case SCANNING:      return "SCAN";
+            case CONNECTED:     return "CNTD";
+            case DISCONNECTING: return "DING";
+            case FAILED:        return "FAIL";
+            default:            return "ERRO";
+        }
+    }
+
+    /**
+     * The data connection is expected to be setup while device
+     *  1. has Icc card
+     *  2. registered for data service
+     *  3. user doesn't explicitly disable data service
+     *  4. wifi is not on
+     *
+     * @return false while no data connection if all above requirements are met.
+     */
+    public abstract boolean isDataConnectionAsDesired();
+
+    //The data roaming setting is now located in the shared preferences.
+    //  See if the requested preference value is the same as that stored in
+    //  the shared values.  If it is not, then update it.
+    public void setDataOnRoamingEnabled(boolean enabled) {
+        if (getDataOnRoamingEnabled() != enabled) {
+            Settings.Secure.putInt(phone.getContext().getContentResolver(),
+                Settings.Secure.DATA_ROAMING, enabled ? 1 : 0);
+        }
+        Message roamingMsg = phone.getServiceState().getRoaming() ?
+            obtainMessage(EVENT_ROAMING_ON) : obtainMessage(EVENT_ROAMING_OFF);
+        sendMessage(roamingMsg);
+    }
+
+    //Retrieve the data roaming setting from the shared preferences.
+    public boolean getDataOnRoamingEnabled() {
+        try {
+            return Settings.Secure.getInt(phone.getContext().getContentResolver(),
+                Settings.Secure.DATA_ROAMING) > 0;
+        } catch (SettingNotFoundException snfe) {
+            return false;
+        }
+    }
+
+    // abstract handler methods
+    protected abstract void onTrySetupData();
+    protected abstract void onRoamingOff();
+    protected abstract void onRoamingOn();
+    protected abstract void onRadioAvailable();
+    protected abstract void onRadioOffOrNotAvailable();
+    protected abstract void onDataSetupComplete(AsyncResult ar);
+    protected abstract void onDisconnectDone(AsyncResult ar);
+    protected abstract void onVoiceCallStarted();
+    protected abstract void onVoiceCallEnded();
+
+  //***** Overridden from Handler
+    public void handleMessage (Message msg) {
+        switch (msg.what) {
+
+            case EVENT_TRY_SETUP_DATA:
+                onTrySetupData();
+                break;
+
+            case EVENT_ROAMING_OFF:
+                onRoamingOff();
+                break;
+
+            case EVENT_ROAMING_ON:
+                onRoamingOn();
+                break;
+
+            case EVENT_RADIO_AVAILABLE:
+                onRadioAvailable();
+                break;
+
+            case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
+                onRadioOffOrNotAvailable();
+                break;
+
+            case EVENT_DATA_SETUP_COMPLETE:
+                cidActive = msg.arg1;
+                onDataSetupComplete((AsyncResult) msg.obj);
+                break;
+
+            case EVENT_DISCONNECT_DONE:
+                onDisconnectDone((AsyncResult) msg.obj);
+                break;
+
+            case EVENT_VOICE_CALL_STARTED:
+                onVoiceCallStarted();
+                break;
+
+            case EVENT_VOICE_CALL_ENDED:
+                onVoiceCallEnded();
+                break;
+
+            default:
+                Log.e("DATA", "Unidentified event = " + msg.what);
+                break;
+        }
+    }
+
+    /**
+     * Simply tear down data connections due to radio off 
+     * and don't setup again.
+     */
+    public abstract void cleanConnectionBeforeRadioOff();
+
+    /**
+     * Report the current state of data connectivity (enabled or disabled)
+     * @return {@code false} if data connectivity has been explicitly disabled,
+     * {@code true} otherwise.
+     */
+    public abstract boolean getDataEnabled();
+
+    /**
+     * Report on whether data connectivity is enabled
+     * @return {@code false} if data connectivity has been explicitly disabled,
+     * {@code true} otherwise.
+     */
+    public abstract boolean getAnyDataEnabled();
+
+    /**
+     * Prevent mobile data connections from being established,
+     * or once again allow mobile data connections. If the state
+     * toggles, then either tear down or set up data, as
+     * appropriate to match the new state.
+     * @param enable indicates whether to enable ({@code true}) or disable ({@code false}) data
+     * @return {@code true} if the operation succeeded
+     */
+    public abstract boolean setDataEnabled(boolean enable);
+
+    protected abstract void startNetStatPoll();
+
+    protected abstract void stopNetStatPoll();
+
+    protected abstract void restartRadio();
+
+    protected abstract void log(String s);
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/DataLink.java b/telephony/java/com/android/internal/telephony/DataLink.java
similarity index 82%
rename from telephony/java/com/android/internal/telephony/gsm/DataLink.java
rename to telephony/java/com/android/internal/telephony/DataLink.java
index b822ab4..8132d91 100644
--- a/telephony/java/com/android/internal/telephony/gsm/DataLink.java
+++ b/telephony/java/com/android/internal/telephony/DataLink.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 import android.os.Handler;
 import android.os.Registrant;
@@ -24,14 +24,13 @@
  *
  * {@hide}
  */
-abstract class DataLink extends Handler implements DataLinkInterface {
+public abstract class DataLink extends Handler implements DataLinkInterface {
 
     /** Registrant for link status change notifications. */
-    Registrant mLinkChangeRegistrant;
-    
+    protected Registrant mLinkChangeRegistrant;
     protected DataConnectionTracker dataConnection;
 
-    DataLink(DataConnectionTracker dc) {
+    protected DataLink(DataConnectionTracker dc) {
         dataConnection = dc;
     }
 
diff --git a/telephony/java/com/android/internal/telephony/gsm/DataLinkInterface.java b/telephony/java/com/android/internal/telephony/DataLinkInterface.java
similarity index 90%
rename from telephony/java/com/android/internal/telephony/gsm/DataLinkInterface.java
rename to telephony/java/com/android/internal/telephony/DataLinkInterface.java
index bca63f2..e8148a8 100644
--- a/telephony/java/com/android/internal/telephony/gsm/DataLinkInterface.java
+++ b/telephony/java/com/android/internal/telephony/DataLinkInterface.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 import android.database.Cursor;
 import android.os.Handler;
@@ -24,7 +24,7 @@
  *
  * {@hide}
  */
-interface DataLinkInterface {
+public interface DataLinkInterface {
     /**
      * Link state enumeration.
      *
@@ -35,21 +35,21 @@
         LINK_DOWN,
         LINK_EXITED
     }
-    
+
     /** Normal exit */
     final static int EXIT_OK = 0;
     /** Open failed */
     final static int EXIT_OPEN_FAILED = 7;
-    
+
     /**
      * Sets the handler for link state change events.
-     * 
+     *
      * @param h Handler
      * @param what User-defined message code
      * @param obj User object
      */
     void setOnLinkChange(Handler h, int what, Object obj);
-    
+
     /**
      * Sets up the data link.
      */
@@ -59,14 +59,14 @@
      * Tears down the data link.
      */
     void disconnect();
-    
+
     /**
-     * Returns the exit code for a data link failure. 
+     * Returns the exit code for a data link failure.
      *
      * @return exit code
      */
     int getLastLinkExitCode();
-    
+
     /**
      * Sets password information that may be required by the data link
      * (eg, PAP secrets).
diff --git a/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java b/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
index 81ef623..79b4afe 100644
--- a/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
+++ b/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
@@ -33,7 +33,7 @@
     private static final boolean DBG = true;
     private ITelephonyRegistry mRegistry;
 
-    /*package*/ 
+    /*package*/
     DefaultPhoneNotifier() {
         mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
                     "telephony.registry"));
@@ -94,7 +94,7 @@
 
     public void notifyDataConnection(Phone sender, String reason) {
         try {
-            mRegistry.notifyDataConnection(convertDataState(sender.getDataConnectionState()), 
+            mRegistry.notifyDataConnection(convertDataState(sender.getDataConnectionState()),
                     sender.isDataConnectivityPossible(), reason, sender.getActiveApn(),
                     sender.getInterfaceName(null));
         } catch (RemoteException ex) {
@@ -119,7 +119,7 @@
             // system process is dead
         }
     }
-    
+
     private void log(String s) {
         Log.d(LOG_TAG, "[PhoneNotifier] " + s);
     }
diff --git a/telephony/java/com/android/internal/telephony/gsm/DriverCall.java b/telephony/java/com/android/internal/telephony/DriverCall.java
similarity index 90%
rename from telephony/java/com/android/internal/telephony/gsm/DriverCall.java
rename to telephony/java/com/android/internal/telephony/DriverCall.java
index aab885a..6c4e71f 100644
--- a/telephony/java/com/android/internal/telephony/gsm/DriverCall.java
+++ b/telephony/java/com/android/internal/telephony/DriverCall.java
@@ -14,9 +14,8 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
-import com.android.internal.telephony.*;
-
+package com.android.internal.telephony;
+//import com.android.internal.telephony.*;
 import android.util.Log;
 import java.lang.Comparable;
 import android.telephony.PhoneNumberUtils;
@@ -24,10 +23,9 @@
 /**
  * {@hide}
  */
-public class DriverCall implements Comparable
-{
-    static final String LOG_TAG = "GSM";
-    
+public class DriverCall implements Comparable {
+    static final String LOG_TAG = "RILB";
+
     public enum State {
         ACTIVE,
         HOLDING,
@@ -48,11 +46,10 @@
     public boolean isVoice;
     public int als;
     public int numberPresentation;
-  
+
     /** returns null on error */
     static DriverCall
-    fromCLCCLine(String line)
-    {
+    fromCLCCLine(String line) {
         DriverCall ret = new DriverCall();
 
         //+CLCC: 1,0,2,0,0,\"+18005551212\",145
@@ -66,10 +63,10 @@
 
             ret.isVoice = (0 == p.nextInt());
             ret.isMpty = p.nextBoolean();
-            
+
             // use ALLOWED as default presentation while parsing CLCC
             ret.numberPresentation = Connection.PRESENTATION_ALLOWED;
-            
+
             if (p.hasMore()) {
                 // Some lame implementations return strings
                 // like "NOT AVAILABLE" in the CLCC line
@@ -98,13 +95,11 @@
     }
 
     public
-    DriverCall()
-    {
+    DriverCall() {
     }
 
     public String
-    toString()
-    {
+    toString() {
         return "id=" + index + ","
                 + (isMT ? "mt" : "mo") + ","
                 + state + ","
@@ -114,8 +109,7 @@
     }
 
     public static State
-    stateFromCLCC(int state) throws ATParseEx
-    {
+    stateFromCLCC(int state) throws ATParseEx {
         switch(state) {
             case 0: return State.ACTIVE;
             case 1: return State.HOLDING;
@@ -127,7 +121,7 @@
                 throw new ATParseEx("illegal call state " + state);
         }
     }
-    
+
     public static int
     presentationFromCLIP(int cli) throws ATParseEx
     {
@@ -141,12 +135,11 @@
         }
     }
 
-    //***** Comparable Implementation 
+    //***** Comparable Implementation
 
     /** For sorting by index */
     public int
-    compareTo (Object o)
-    {
+    compareTo (Object o) {
         DriverCall dc;
 
         dc = (DriverCall)o;
diff --git a/telephony/java/com/android/internal/telephony/gsm/EncodeException.java b/telephony/java/com/android/internal/telephony/EncodeException.java
similarity index 77%
rename from telephony/java/com/android/internal/telephony/gsm/EncodeException.java
rename to telephony/java/com/android/internal/telephony/EncodeException.java
index d546cef..0436ba0 100644
--- a/telephony/java/com/android/internal/telephony/gsm/EncodeException.java
+++ b/telephony/java/com/android/internal/telephony/EncodeException.java
@@ -14,25 +14,21 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 /**
  * {@hide}
  */
-public class EncodeException extends Exception
-{
-    public EncodeException()
-    {
+public class EncodeException extends Exception {
+    public EncodeException() {
         super();
     }
-  
-    public EncodeException(String s)
-    {
+
+    public EncodeException(String s) {
         super(s);
     }
 
-    public EncodeException(char c)
-    {
+    public EncodeException(char c) {
         super("Unencodable char: '" + c + "'");
     }
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmAlphabet.java b/telephony/java/com/android/internal/telephony/GsmAlphabet.java
similarity index 93%
rename from telephony/java/com/android/internal/telephony/gsm/GsmAlphabet.java
rename to telephony/java/com/android/internal/telephony/GsmAlphabet.java
index df34897..8f4c69c 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmAlphabet.java
+++ b/telephony/java/com/android/internal/telephony/GsmAlphabet.java
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
-import android.telephony.gsm.SmsMessage;
+import android.telephony.SmsMessage;
 import android.util.SparseIntArray;
 
 import android.util.Log;
@@ -28,16 +28,15 @@
  *
  * {@hide}
  */
-public class GsmAlphabet
-{
+public class GsmAlphabet {
     static final String LOG_TAG = "GSM";
-    
+
 
 
     //***** Constants
 
     /**
-     * This escapes extended characters, and when present indicates that the 
+     * This escapes extended characters, and when present indicates that the
      * following character should
      * be looked up in the "extended" table
      *
@@ -55,8 +54,7 @@
      * should follow GSM_EXTENDED_ESCAPE in the GSM alphabet string
      */
     public static int
-    charToGsm(char c)
-    {
+    charToGsm(char c) {
         try {
             return charToGsm(c, false);
         } catch (EncodeException ex) {
@@ -67,7 +65,7 @@
 
     /**
      * char to GSM alphabet char
-     * @param throwException If true, throws EncodeException on invalid char. 
+     * @param throwException If true, throws EncodeException on invalid char.
      *   If false, returns GSM alphabet ' ' char.
      *
      * Returns GSM_EXTENDED_ESCAPE if this character is in the extended table
@@ -76,10 +74,9 @@
      */
 
     public static int
-    charToGsm(char c, boolean throwException) throws EncodeException
-    {
+    charToGsm(char c, boolean throwException) throws EncodeException {
         int ret;
-        
+
         ret = charToGsm.get(c, -1);
 
         if (ret == -1) {
@@ -99,7 +96,7 @@
         return ret;
 
     }
-    
+
 
     /**
      * char to extended GSM alphabet char
@@ -110,10 +107,9 @@
      *
      */
     public static int
-    charToGsmExtended(char c)
-    {
+    charToGsmExtended(char c) {
         int ret;
-        
+
         ret = charToGsmExtended.get(c, -1);
 
         if (ret == -1) {
@@ -124,34 +120,32 @@
     }
 
     /**
-     * Converts a character in the GSM alphabet into a char 
+     * Converts a character in the GSM alphabet into a char
      *
      * if GSM_EXTENDED_ESCAPE is passed, 0xffff is returned. In this case,
-     * the following character in the stream should be decoded with 
+     * the following character in the stream should be decoded with
      * gsmExtendedToChar()
      *
      * If an unmappable value is passed (one greater than 127), ' ' is returned
      */
 
     public static char
-    gsmToChar(int gsmChar)
-    {
+    gsmToChar(int gsmChar) {
         return (char)gsmToChar.get(gsmChar, ' ');
     }
-    
+
     /**
-     * Converts a character in the extended GSM alphabet into a char 
+     * Converts a character in the extended GSM alphabet into a char
      *
      * if GSM_EXTENDED_ESCAPE is passed, ' ' is returned since no second
      * extension page has yet been defined (see Note 1 in table 6.2.1.1 of
      * TS 23.038 v7.00)
-     *     
+     *
      * If an unmappable value is passed , ' ' is returned
      */
 
     public static char
-    gsmExtendedToChar(int gsmChar)
-    {
+    gsmExtendedToChar(int gsmChar) {
         int ret;
 
         ret = gsmExtendedToChar.get(gsmChar, -1);
@@ -205,7 +199,7 @@
     }
 
     /**
-     * Converts a String into a byte array containing 
+     * Converts a String into a byte array containing
      * the 7-bit packed GSM Alphabet representation of the string.
      *
      * Unencodable chars are encoded as spaces
@@ -224,7 +218,7 @@
     }
 
     /**
-     * Converts a String into a byte array containing 
+     * Converts a String into a byte array containing
      * the 7-bit packed GSM Alphabet representation of the string.
      *
      * Byte 0 in the returned byte array is the count of septets used
@@ -238,7 +232,7 @@
      *  enforced maximum.
      * @param startingBitOffset the number of padding bits to put before
      *  the start of the first septet at the begining of the array
-     * @param throwException If true, throws EncodeException on invalid char. 
+     * @param throwException If true, throws EncodeException on invalid char.
      *   If false, replaces unencodable char with GSM alphabet space char.
      *
      * @throws EncodeException if String is too large to encode
@@ -294,27 +288,26 @@
      * @param bitOffset the bit offset that the septet should be packed at
      *                  (septet index * 7)
      */
-    private static void 
-    packSmsChar(byte[] packedChars, int bitOffset, int value)
-    {
+    private static void
+    packSmsChar(byte[] packedChars, int bitOffset, int value) {
         int byteOffset = bitOffset / 8;
         int shift = bitOffset % 8;
 
         packedChars[++byteOffset] |= value << shift;
 
         if (shift > 1) {
-        	packedChars[++byteOffset] = (byte)(value >> (8 - shift));
-        }    	
+            packedChars[++byteOffset] = (byte)(value >> (8 - shift));
+        }
     }
 
     /**
-     * Convert a GSM alphabet 7 bit packed string (SMS string) into a 
+     * Convert a GSM alphabet 7 bit packed string (SMS string) into a
      * {@link java.lang.String}.
      *
      * See TS 23.038 6.1.2.1 for SMS Character Packing
      *
      * @param pdu the raw data from the pdu
-     * @param offset the byte offset of 
+     * @param offset the byte offset of
      * @param lengthSeptets string length in septets, not bytes
      * @return String representation or null on decoding exception
      */
@@ -324,27 +317,26 @@
     }
 
     /**
-     * Convert a GSM alphabet 7 bit packed string (SMS string) into a 
+     * Convert a GSM alphabet 7 bit packed string (SMS string) into a
      * {@link java.lang.String}.
      *
      * See TS 23.038 6.1.2.1 for SMS Character Packing
      *
      * @param pdu the raw data from the pdu
-     * @param offset the byte offset of 
+     * @param offset the byte offset of
      * @param lengthSeptets string length in septets, not bytes
      * @param numPaddingBits the number of padding bits before the start of the
      *  string in the first byte
      * @return String representation or null on decoding exception
      */
     public static String gsm7BitPackedToString(byte[] pdu, int offset,
-            int lengthSeptets, int numPaddingBits)
-    {
+            int lengthSeptets, int numPaddingBits) {
         StringBuilder ret = new StringBuilder(lengthSeptets);
         boolean prevCharWasEscape;
-        
+
         try {
             prevCharWasEscape = false;
-            
+
             for (int i = 0 ; i < lengthSeptets ; i++) {
                 int bitOffset = (7 * i) + numPaddingBits;
 
@@ -381,15 +373,14 @@
 
 
     /**
-     * Convert a GSM alphabet string that's stored in 8-bit unpacked 
+     * Convert a GSM alphabet string that's stored in 8-bit unpacked
      * format (as it often appears in SIM records) into a String
      *
      * Field may be padded with trailing 0xff's. The decode stops
      * at the first 0xff encountered.
      */
     public static String
-    gsm8BitUnpackedToString(byte[] data, int offset, int length)
-    {
+    gsm8BitUnpackedToString(byte[] data, int offset, int length) {
         boolean prevWasEscape;
         StringBuilder ret = new StringBuilder(length);
 
@@ -420,8 +411,8 @@
                 prevWasEscape = false;
             }
         }
-        
-        return ret.toString();    
+
+        return ret.toString();
     }
 
     /**
@@ -429,8 +420,7 @@
      * array
      */
     public static byte[]
-    stringToGsm8BitPacked(String s)
-    {
+    stringToGsm8BitPacked(String s) {
         byte[] ret;
 
         int septets = 0;
@@ -452,15 +442,14 @@
      *
      * Field is padded with 0xff's, string is truncated if necessary
      */
-     
+
     public static void
-    stringToGsm8BitUnpackedField(String s, byte dest[], int offset, int length)
-    {
+    stringToGsm8BitUnpackedField(String s, byte dest[], int offset, int length) {
         int outByteIndex = offset;
 
         // Septets are stored in byte-aligned octets
         for (int i = 0, sz = s.length()
-                ; i < sz && (outByteIndex - offset) < length 
+                ; i < sz && (outByteIndex - offset) < length
                 ; i++
         ) {
             char c = s.charAt(i);
@@ -475,7 +464,7 @@
 
                 dest[outByteIndex++] = GSM_EXTENDED_ESCAPE;
 
-        		v = GsmAlphabet.charToGsmExtended(c);
+                v = GsmAlphabet.charToGsmExtended(c);
             }
 
             dest[outByteIndex++] = (byte)v;
@@ -492,8 +481,7 @@
      * needed to represent this character. Counts unencodable char as 1 septet.
      */
     public static int
-    countGsmSeptets(char c)
-    {
+    countGsmSeptets(char c) {
         try {
             return countGsmSeptets(c, false);
         } catch (EncodeException ex) {
@@ -509,21 +497,20 @@
      * char. Otherwise, counts invalid char as 1 septet
      */
     public static int
-    countGsmSeptets(char c, boolean throwsException) throws EncodeException
-    {
-    	if (charToGsm.get(c, -1) != -1) {
-    		return 1;
-    	}
-    	
-    	if (charToGsmExtended.get(c, -1) != -1) {
-    		return 2;
-    	}
+    countGsmSeptets(char c, boolean throwsException) throws EncodeException {
+        if (charToGsm.get(c, -1) != -1) {
+            return 1;
+        }
+
+        if (charToGsmExtended.get(c, -1) != -1) {
+            return 2;
+        }
 
         if (throwsException) {
             throw new EncodeException(c);
-        } else {    
-        	// count as a space char
-        	return 1;
+        } else {
+            // count as a space char
+            return 1;
         }
     }
 
@@ -532,8 +519,7 @@
      * needed to represent this string. Counts unencodable char as 1 septet.
      */
     public static int
-    countGsmSeptets(CharSequence s)
-    {
+    countGsmSeptets(CharSequence s) {
         try {
             return countGsmSeptets(s, false);
         } catch (EncodeException ex) {
@@ -549,8 +535,7 @@
      * char. Otherwise, counts invalid char as 1 septet
      */
     public static int
-    countGsmSeptets(CharSequence s, boolean throwsException) throws EncodeException
-    {
+    countGsmSeptets(CharSequence s, boolean throwsException) throws EncodeException {
         int charIndex = 0;
         int sz = s.length();
         int count = 0;
@@ -559,9 +544,9 @@
             count += countGsmSeptets(s.charAt(charIndex), throwsException);
             charIndex++;
         }
-        
+
         return count;
-    }    
+    }
 
     /**
      * Returns the index into <code>s</code> of the first character
@@ -623,7 +608,7 @@
      * @return index of first character that won't fit, or the length
      *   of the entire string if everything fits
      */
-    public static int 
+    public static int
     findLimitIndex(String s, int start, int limit, int encodingType) throws EncodeException {
         if (encodingType == SmsMessage.ENCODING_7BIT) {
             return findGsmSeptetLimitIndex(s, start, limit);
@@ -643,10 +628,10 @@
     private static final SparseIntArray gsmToChar = new SparseIntArray();
     private static final SparseIntArray charToGsmExtended = new SparseIntArray();
     private static final SparseIntArray gsmExtendedToChar = new SparseIntArray();
-    
+
     static {
         int i = 0;
-        
+
         charToGsm.put('@', i++);
         charToGsm.put('\u00a3', i++);
         charToGsm.put('$', i++);
@@ -663,7 +648,7 @@
         charToGsm.put('\r', i++);
         charToGsm.put('\u00c5', i++);
         charToGsm.put('\u00e5', i++);
-        
+
         charToGsm.put('\u0394', i++);
         charToGsm.put('_', i++);
         charToGsm.put('\u03a6', i++);
@@ -680,7 +665,7 @@
         charToGsm.put('\u00e6', i++);
         charToGsm.put('\u00df', i++);
         charToGsm.put('\u00c9', i++);
-        
+
         charToGsm.put(' ', i++);
         charToGsm.put('!', i++);
         charToGsm.put('"', i++);
@@ -697,7 +682,7 @@
         charToGsm.put('-', i++);
         charToGsm.put('.', i++);
         charToGsm.put('/', i++);
-        
+
         charToGsm.put('0', i++);
         charToGsm.put('1', i++);
         charToGsm.put('2', i++);
@@ -714,7 +699,7 @@
         charToGsm.put('=', i++);
         charToGsm.put('>', i++);
         charToGsm.put('?', i++);
-        
+
         charToGsm.put('\u00a1', i++);
         charToGsm.put('A', i++);
         charToGsm.put('B', i++);
@@ -731,7 +716,7 @@
         charToGsm.put('M', i++);
         charToGsm.put('N', i++);
         charToGsm.put('O', i++);
-        
+
         charToGsm.put('P', i++);
         charToGsm.put('Q', i++);
         charToGsm.put('R', i++);
@@ -748,7 +733,7 @@
         charToGsm.put('\u0147', i++);
         charToGsm.put('\u00dc', i++);
         charToGsm.put('\u00a7', i++);
-        
+
         charToGsm.put('\u00bf', i++);
         charToGsm.put('a', i++);
         charToGsm.put('b', i++);
@@ -765,7 +750,7 @@
         charToGsm.put('m', i++);
         charToGsm.put('n', i++);
         charToGsm.put('o', i++);
-        
+
         charToGsm.put('p', i++);
         charToGsm.put('q', i++);
         charToGsm.put('r', i++);
@@ -782,8 +767,8 @@
         charToGsm.put('\u00f1', i++);
         charToGsm.put('\u00fc', i++);
         charToGsm.put('\u00e0', i++);
-        
-        
+
+
         charToGsmExtended.put('\f', 10);
         charToGsmExtended.put('^', 20);
         charToGsmExtended.put('{', 40);
@@ -794,12 +779,12 @@
         charToGsmExtended.put(']', 62);
         charToGsmExtended.put('|', 64);
         charToGsmExtended.put('\u20ac', 101);
-                
+
         int size = charToGsm.size();
         for (int j=0; j<size; j++) {
             gsmToChar.put(charToGsm.valueAt(j), charToGsm.keyAt(j));
         }
- 
+
         size = charToGsmExtended.size();
         for (int j=0; j<size; j++) {
             gsmExtendedToChar.put(charToGsmExtended.valueAt(j), charToGsmExtended.keyAt(j));
@@ -808,6 +793,6 @@
 
         sGsmSpaceChar = charToGsm.get(' ');
     }
-    
+
 
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/ISimPhoneBook.aidl b/telephony/java/com/android/internal/telephony/IIccPhoneBook.aidl
similarity index 88%
rename from telephony/java/com/android/internal/telephony/gsm/ISimPhoneBook.aidl
rename to telephony/java/com/android/internal/telephony/IIccPhoneBook.aidl
index 77033a7..f700dfe 100644
--- a/telephony/java/com/android/internal/telephony/gsm/ISimPhoneBook.aidl
+++ b/telephony/java/com/android/internal/telephony/IIccPhoneBook.aidl
@@ -14,27 +14,27 @@
 ** limitations under the License.
 */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
-import com.android.internal.telephony.gsm.AdnRecord;
+import com.android.internal.telephony.AdnRecord;
 
-import java.util.List;
 
-/** Interface for applications to access the SIM phone book.
+
+/** Interface for applications to access the ICC phone book.
  *
  * <p>The following code snippet demonstrates a static method to
- * retrieve the ISimPhoneBook interface from Android:</p>
- * <pre>private static ISimPhoneBook getSimPhoneBookInterface()
+ * retrieve the IIccPhoneBook interface from Android:</p>
+ * <pre>private static IIccPhoneBook getSimPhoneBookInterface()
             throws DeadObjectException {
     IServiceManager sm = ServiceManagerNative.getDefault();
-    ISimPhoneBook spb;
-    spb = ISimPhoneBook.Stub.asInterface(sm.getService("simphonebook"));
+    IIccPhoneBook spb;
+    spb = IIccPhoneBook.Stub.asInterface(sm.getService("iccphonebook"));
     return spb;
 }
  * </pre>
  */
 
-interface ISimPhoneBook {
+interface IIccPhoneBook {
 
     /**
      * Loads the AdnRecords in efid and returns them as a
diff --git a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
index 00cbaf9..e74b9e4 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl
@@ -39,9 +39,9 @@
     String getSubscriberId();
 
     /**
-     * Retrieves the serial number of the SIM, if applicable.
+     * Retrieves the serial number of the ICC, if applicable.
      */
-    String getSimSerialNumber();
+    String getIccSerialNumber();
 
     /**
      * Retrieves the phone number string for line 1.
@@ -53,13 +53,13 @@
      */
     String getLine1AlphaTag();
 
-	/**
-	 * Retrieves the voice mail number.
-	 */
+    /**
+     * Retrieves the voice mail number.
+     */
     String getVoiceMailNumber();
 
-	/**
-	 * Retrieves the alpha identifier associated with the voice mail number.
-	 */
+    /**
+     * Retrieves the alpha identifier associated with the voice mail number.
+     */
     String getVoiceMailAlphaTag();
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl
similarity index 74%
rename from telephony/java/com/android/internal/telephony/gsm/ISms.aidl
rename to telephony/java/com/android/internal/telephony/ISms.aidl
index 904a54e..257f1e6 100644
--- a/telephony/java/com/android/internal/telephony/gsm/ISms.aidl
+++ b/telephony/java/com/android/internal/telephony/ISms.aidl
@@ -14,20 +14,20 @@
 ** limitations under the License.
 */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 import android.app.PendingIntent;
-import com.android.internal.telephony.gsm.SmsRawData;
+import com.android.internal.telephony.SmsRawData;
 
-/** Interface for applications to access the SIM phone book.
+/** Interface for applications to access the ICC phone book.
  *
  * <p>The following code snippet demonstrates a static method to
- * retrieve the ISimSms interface from Android:</p>
- * <pre>private static ISimSms getSimSmsInterface()
+ * retrieve the ISms interface from Android:</p>
+ * <pre>private static ISms getSmsInterface()
             throws DeadObjectException {
     IServiceManager sm = ServiceManagerNative.getDefault();
-    ISimSms ss;
-    ss = ISimSms.Stub.asInterface(sm.getService("isms"));
+    ISms ss;
+    ss = ISms.Stub.asInterface(sm.getService("isms"));
     return ss;
 }
  * </pre>
@@ -35,45 +35,45 @@
 
 interface ISms {
     /**
-     * Retrieves all messages currently stored on SIM.
+     * Retrieves all messages currently stored on ICC.
      *
-     * @return list of SmsRawData of all sms on SIM
+     * @return list of SmsRawData of all sms on ICC
      */
-     List<SmsRawData> getAllMessagesFromSimEf();
+     List<SmsRawData> getAllMessagesFromIccEf();
 
     /**
-     * Update the specified message on the SIM.
+     * Update the specified message on the ICC.
      *
      * @param messageIndex record index of message to update
-     * @param newStatus new message status (STATUS_ON_SIM_READ,
-     *                  STATUS_ON_SIM_UNREAD, STATUS_ON_SIM_SENT,
-     *                  STATUS_ON_SIM_UNSENT, STATUS_ON_SIM_FREE)
+     * @param newStatus new message status (STATUS_ON_ICC_READ,
+     *                  STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT,
+     *                  STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE)
      * @param pdu the raw PDU to store
      * @return success or not
      *
      */
-     boolean updateMessageOnSimEf(int messageIndex, int newStatus,
+     boolean updateMessageOnIccEf(int messageIndex, int newStatus,
             in byte[] pdu);
 
     /**
-     * Copy a raw SMS PDU to the SIM.
+     * Copy a raw SMS PDU to the ICC.
      *
      * @param pdu the raw PDU to store
-     * @param status message status (STATUS_ON_SIM_READ, STATUS_ON_SIM_UNREAD,
-     *               STATUS_ON_SIM_SENT, STATUS_ON_SIM_UNSENT)
+     * @param status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD,
+     *               STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT)
      * @return success or not
      *
      */
-    boolean copyMessageToSimEf(int status, in byte[] pdu, in byte[] smsc);
+    boolean copyMessageToIccEf(int status, in byte[] pdu, in byte[] smsc);
 
     /**
      * Send a SMS
      *
      * @param smsc the SMSC to send the message through, or NULL for the
-     *  defatult SMSC
+     *  default SMSC
      * @param pdu the raw PDU to send
      * @param sentIntent if not NULL this <code>Intent</code> is
-     *  broadcast when the message is sucessfully sent, or failed.
+     *  broadcast when the message is successfully sent, or failed.
      *  The result code will be <code>Activity.RESULT_OK<code> for success,
      *  or one of these errors:
      *  <code>RESULT_ERROR_GENERIC_FAILURE</code>
@@ -88,13 +88,13 @@
 
     /**
      * Send a multi-part text based SMS.
-     * 
+     *
      * @param destinationAddress the address to send the message to
      * @param scAddress is the service center address or null to use
      *   the current default SMSC
      * @param parts an <code>ArrayList</code> of strings that, in order,
      *   comprise the original message
-     * @param sentIntents if not null, an <code>ArrayList</code> of 
+     * @param sentIntents if not null, an <code>ArrayList</code> of
      *   <code>PendingIntent</code>s (one for each message part) that is
      *   broadcast when the corresponding message part has been sent.
      *   The result code will be <code>Activity.RESULT_OK<code> for success,
@@ -102,7 +102,7 @@
      *   <code>RESULT_ERROR_GENERIC_FAILURE</code>
      *   <code>RESULT_ERROR_RADIO_OFF</code>
      *   <code>RESULT_ERROR_NULL_PDU</code>.
-     * @param deliveryIntents if not null, an <code>ArrayList</code> of 
+     * @param deliveryIntents if not null, an <code>ArrayList</code> of
      *   <code>PendingIntent</code>s (one for each message part) that is
      *   broadcast when the corresponding message part has been delivered
      *   to the recipient.  The raw pdu of the status report is in the
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 2b4195b..bab0603 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -21,7 +21,7 @@
 import android.telephony.NeighboringCellInfo;
 
 /**
- * Interface used to interact with the phone.  Mostly this is used by the 
+ * Interface used to interact with the phone.  Mostly this is used by the
  * TelephonyManager class.  A few places are still using this directly.
  * Please clean them up if possible and use TelephonyManager insteadl.
  *
@@ -135,7 +135,7 @@
     /**
      * Cancels the missed calls notification.
      */
-    void cancelMissedCallsNotification(); 
+    void cancelMissedCallsNotification();
 
     /**
      * Supply a pin to unlock the SIM.  Blocks until a result is determined.
@@ -147,7 +147,7 @@
     /**
      * Handles PIN MMI commands (PIN/PIN2/PUK/PUK2), which are initiated
      * without SEND (so <code>dial</code> is not appropriate).
-     * 
+     *
      * @param dialString the MMI command to be executed.
      * @return true if MMI command is executed.
      */
@@ -213,4 +213,13 @@
      int getCallState();
      int getDataActivity();
      int getDataState();
+
+    /**
+     * Returns the current active phone type as integer.
+     * Returns TelephonyManager.PHONE_TYPE_CDMA if RILConstants.CDMA_PHONE
+     * and TelephonyManager.PHONE_TYPE_GSM if RILConstants.GSM_PHONE
+     */
+    int getActivePhoneType();
+
 }
+
diff --git a/telephony/java/com/android/internal/telephony/SimCard.java b/telephony/java/com/android/internal/telephony/IccCard.java
similarity index 70%
rename from telephony/java/com/android/internal/telephony/SimCard.java
rename to telephony/java/com/android/internal/telephony/IccCard.java
index 03b366f..d7ad492 100644
--- a/telephony/java/com/android/internal/telephony/SimCard.java
+++ b/telephony/java/com/android/internal/telephony/IccCard.java
@@ -22,35 +22,34 @@
 /**
  * {@hide}
  */
-public interface SimCard
-{
-    /* The extra data for broacasting intent INTENT_SIM_STATE_CHANGE */
-    static public final String INTENT_KEY_SIM_STATE = "ss";
-    /* NOT_READY means the SIM interface is not ready (eg, radio is off or powering on) */
-    static public final String INTENT_VALUE_SIM_NOT_READY = "NOT_READY";
-    /* ABSENT means SIM is missing */
-    static public final String INTENT_VALUE_SIM_ABSENT = "ABSENT";
-    /* LOCKED means SIM is locked by pin or by network */
-    static public final String INTENT_VALUE_SIM_LOCKED = "LOCKED";
-    /* READY means SIM is ready to access */
-    static public final String INTENT_VALUE_SIM_READY = "READY";
-    /* IMSI means SIM IMSI is ready in property */
-    static public final String INTENT_VALUE_SIM_IMSI = "IMSI";
-    /* LOADED means all SIM records, including IMSI, are loaded */
-    static public final String INTENT_VALUE_SIM_LOADED = "LOADED";
-    /* The extra data for broacasting intent INTENT_SIM_STATE_CHANGE */
+public interface IccCard {
+    /* The extra data for broacasting intent INTENT_ICC_STATE_CHANGE */
+    static public final String INTENT_KEY_ICC_STATE = "ss";
+    /* NOT_READY means the ICC interface is not ready (eg, radio is off or powering on) */
+    static public final String INTENT_VALUE_ICC_NOT_READY = "NOT_READY";
+    /* ABSENT means ICC is missing */
+    static public final String INTENT_VALUE_ICC_ABSENT = "ABSENT";
+    /* LOCKED means ICC is locked by pin or by network */
+    static public final String INTENT_VALUE_ICC_LOCKED = "LOCKED";
+    /* READY means ICC is ready to access */
+    static public final String INTENT_VALUE_ICC_READY = "READY";
+    /* IMSI means ICC IMSI is ready in property */
+    static public final String INTENT_VALUE_ICC_IMSI = "IMSI";
+    /* LOADED means all ICC records, including IMSI, are loaded */
+    static public final String INTENT_VALUE_ICC_LOADED = "LOADED";
+    /* The extra data for broacasting intent INTENT_ICC_STATE_CHANGE */
     static public final String INTENT_KEY_LOCKED_REASON = "reason";
-    /* PIN means SIM is locked on PIN1 */
+    /* PIN means ICC is locked on PIN1 */
     static public final String INTENT_VALUE_LOCKED_ON_PIN = "PIN";
-    /* PUK means SIM is locked on PUK1 */
+    /* PUK means ICC is locked on PUK1 */
     static public final String INTENT_VALUE_LOCKED_ON_PUK = "PUK";
-    /* NETWORK means SIM is locked on NETWORK PERSONALIZATION */
+    /* NETWORK means ICC is locked on NETWORK PERSONALIZATION */
     static public final String INTENT_VALUE_LOCKED_NETWORK = "NETWORK";
 
 
     /*
-      UNKNOWN is a transient state, for example, after uesr inputs sim pin under
-      PIN_REQUIRED state, the query for sim status returns UNKNOWN before it
+      UNKNOWN is a transient state, for example, after uesr inputs ICC pin under
+      PIN_REQUIRED state, the query for ICC status returns UNKNOWN before it
       turns to READY
      */
     public enum State {
@@ -73,7 +72,7 @@
      * Notifies handler of any transition into State.ABSENT
      */
     void registerForAbsent(Handler h, int what, Object obj);
-    void unregisterForAbsent(Handler h);    
+    void unregisterForAbsent(Handler h);
 
     /**
      * Notifies handler of any transition into State.isPinLocked()
@@ -88,7 +87,7 @@
     void unregisterForNetworkLocked(Handler h);
 
     /**
-     * Supply the SIM PIN to the SIM
+     * Supply the ICC PIN to the ICC
      *
      * When the operation is complete, onComplete will be sent to it's
      * Handler.
@@ -100,11 +99,11 @@
      *
      * If the supplied PIN is incorrect:
      * ((AsyncResult)onComplete.obj).exception != null
-     * && ((AsyncResult)onComplete.obj).exception 
+     * && ((AsyncResult)onComplete.obj).exception
      *       instanceof com.android.internal.telephony.gsm.CommandException)
      * && ((CommandException)(((AsyncResult)onComplete.obj).exception))
      *          .getCommandError() == CommandException.Error.PASSWORD_INCORRECT
-     * 
+     *
      *
      */
 
@@ -114,30 +113,30 @@
     void supplyPuk2 (String puk2, String newPin2, Message onComplete);
 
     /**
-     * Check whether sim pin lock is enabled
+     * Check whether ICC pin lock is enabled
      * This is a sync call which returns the cached pin enabled state
      *
-     * @return true for sim locked enabled
-     *         false for sim locked disabled
+     * @return true for ICC locked enabled
+     *         false for ICC locked disabled
      */
-    boolean getSimLockEnabled ();
+    boolean getIccLockEnabled ();
 
     /**
-     * Set the sim pin lock enabled or disabled
+     * Set the ICC pin lock enabled or disabled
      * When the operation is complete, onComplete will be sent to its handler
      *
      * @param enabled "true" for locked "false" for unlocked.
-     * @param password needed to change the sim pin state, aka. Pin1
+     * @param password needed to change the ICC pin state, aka. Pin1
      * @param onComplete
      *        onComplete.obj will be an AsyncResult
      *        ((AsyncResult)onComplete.obj).exception == null on success
      *        ((AsyncResult)onComplete.obj).exception != null on fail
      */
-    void setSimLockEnabled(boolean enabled, String password, Message onComplete);
+    void setIccLockEnabled(boolean enabled, String password, Message onComplete);
 
 
     /**
-     * Change the sim password used in sim pin lock
+     * Change the ICC password used in ICC pin lock
      * When the operation is complete, onComplete will be sent to its handler
      *
      * @param oldPassword is the old password
@@ -147,33 +146,33 @@
      *        ((AsyncResult)onComplete.obj).exception == null on success
      *        ((AsyncResult)onComplete.obj).exception != null on fail
      */
-    void changeSimLockPassword(String oldPassword, String newPassword,
+    void changeIccLockPassword(String oldPassword, String newPassword,
                            Message onComplete);
 
     /**
-     * Check whether sim fdn (fixed dialing number) is enabled
+     * Check whether ICC fdn (fixed dialing number) is enabled
      * This is a sync call which returns the cached pin enabled state
      *
-     * @return true for sim fdn enabled
-     *         false for sim fdn disabled
+     * @return true for ICC fdn enabled
+     *         false for ICC fdn disabled
      */
-    boolean getSimFdnEnabled ();
+    boolean getIccFdnEnabled ();
 
     /**
-     * Set the sim fdn enabled or disabled
+     * Set the ICC fdn enabled or disabled
      * When the operation is complete, onComplete will be sent to its handler
      *
      * @param enabled "true" for locked "false" for unlocked.
-     * @param password needed to change the sim fdn enable, aka Pin2
+     * @param password needed to change the ICC fdn enable, aka Pin2
      * @param onComplete
      *        onComplete.obj will be an AsyncResult
      *        ((AsyncResult)onComplete.obj).exception == null on success
      *        ((AsyncResult)onComplete.obj).exception != null on fail
      */
-    void setSimFdnEnabled(boolean enabled, String password, Message onComplete);
+    void setIccFdnEnabled(boolean enabled, String password, Message onComplete);
 
     /**
-     * Change the sim password used in sim fdn enable
+     * Change the ICC password used in ICC fdn enable
      * When the operation is complete, onComplete will be sent to its handler
      *
      * @param oldPassword is the old password
@@ -183,13 +182,13 @@
      *        ((AsyncResult)onComplete.obj).exception == null on success
      *        ((AsyncResult)onComplete.obj).exception != null on fail
      */
-    void changeSimFdnPassword(String oldPassword, String newPassword,
+    void changeIccFdnPassword(String oldPassword, String newPassword,
                            Message onComplete);
 
     void supplyNetworkDepersonalization (String pin, Message onComplete);
 
     /**
-     * Returns service provider name stored in SIM card.
+     * Returns service provider name stored in ICC card.
      * If there is no service provider name associated or the record is not
      * yet available, null will be returned <p>
      *
@@ -199,7 +198,7 @@
      *
      * Also available via Android property "gsm.sim.operator.alpha"
      *
-     * @return Service Provider Name stored in SIM card
+     * @return Service Provider Name stored in ICC card
      *         null if no service provider name associated or the record is not
      *         yet available
      *
diff --git a/telephony/java/com/android/internal/telephony/IccCardApplication.java b/telephony/java/com/android/internal/telephony/IccCardApplication.java
new file mode 100644
index 0000000..9f60a6c
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IccCardApplication.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony;
+
+
+/**
+ * See also RIL_AppStatus in include/telephony/ril.h
+ *
+ * {@hide}
+ */
+public class IccCardApplication {
+    public enum AppType{
+        APPTYPE_UNKNOWN,
+        APPTYPE_SIM,
+        APPTYPE_USIM,
+        APPTYPE_RUIM,
+        APPTYPE_CSIM
+    };
+
+    public enum AppState{
+        APPSTATE_UNKNOWN,
+        APPSTATE_DETECTED,
+        APPSTATE_PIN,
+        APPSTATE_PUK,
+        APPSTATE_SUBSCRIPTION_PERSO,
+        APPSTATE_READY;
+
+        boolean isPinRequired() {
+            return this == APPSTATE_PIN;
+        }
+
+        boolean isPukRequired() {
+            return this == APPSTATE_PUK;
+        }
+
+        boolean isSubscriptionPersoEnabled() {
+            return this == APPSTATE_SUBSCRIPTION_PERSO;
+        }
+
+        boolean isAppReady() {
+            return this == APPSTATE_READY;
+        }
+
+        boolean isAppNotReady() {
+            return this == APPSTATE_UNKNOWN  ||
+                   this == APPSTATE_DETECTED;
+        }
+    };
+
+    public enum PersoSubState{
+        PERSOSUBSTATE_UNKNOWN,
+        PERSOSUBSTATE_IN_PROGRESS,
+        PERSOSUBSTATE_READY,
+        PERSOSUBSTATE_SIM_NETWORK,
+        PERSOSUBSTATE_SIM_NETWORK_SUBSET,
+        PERSOSUBSTATE_SIM_CORPORATE,
+        PERSOSUBSTATE_SIM_SERVICE_PROVIDER,
+        PERSOSUBSTATE_SIM_SIM,
+        PERSOSUBSTATE_SIM_NETWORK_PUK,
+        PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK,
+        PERSOSUBSTATE_SIM_CORPORATE_PUK,
+        PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK,
+        PERSOSUBSTATE_SIM_SIM_PUK,
+        PERSOSUBSTATE_RUIM_NETWORK1,
+        PERSOSUBSTATE_RUIM_NETWORK2,
+        PERSOSUBSTATE_RUIM_HRPD,
+        PERSOSUBSTATE_RUIM_CORPORATE,
+        PERSOSUBSTATE_RUIM_SERVICE_PROVIDER,
+        PERSOSUBSTATE_RUIM_RUIM,
+        PERSOSUBSTATE_RUIM_NETWORK1_PUK,
+        PERSOSUBSTATE_RUIM_NETWORK2_PUK,
+        PERSOSUBSTATE_RUIM_HRPD_PUK,
+        PERSOSUBSTATE_RUIM_CORPORATE_PUK,
+        PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK,
+        PERSOSUBSTATE_RUIM_RUIM_PUK;
+
+        boolean isPersoSubStateUnknown() {
+            return this == PERSOSUBSTATE_UNKNOWN;
+        }
+    };
+
+    public AppType        app_type;
+    public AppState       app_state;
+    // applicable only if app_state == RIL_APPSTATE_SUBSCRIPTION_PERSO
+    public PersoSubState  perso_substate;
+    // null terminated string, e.g., from 0xA0, 0x00 -> 0x41, 0x30, 0x30, 0x30 */
+    public String         aid;
+    // null terminated string
+    public String         app_label;
+    // applicable to USIM and CSIM
+    public int            pin1_replaced;
+    public int            pin1;
+    public int            pin2;
+
+    AppType AppTypeFromRILInt(int type) {
+        AppType newType;
+        /* RIL_AppType ril.h */
+        switch(type) {
+            case 0: newType = AppType.APPTYPE_UNKNOWN; break;
+            case 1: newType = AppType.APPTYPE_SIM;     break;
+            case 2: newType = AppType.APPTYPE_USIM;    break;
+            case 3: newType = AppType.APPTYPE_RUIM;    break;
+            case 4: newType = AppType.APPTYPE_CSIM;    break;
+            default:
+                throw new RuntimeException(
+                            "Unrecognized RIL_AppType: " +type);
+        }
+        return newType;
+    }
+
+    AppState AppStateFromRILInt(int state) {
+        AppState newState;
+        /* RIL_AppState ril.h */
+        switch(state) {
+            case 0: newState = AppState.APPSTATE_UNKNOWN;  break;
+            case 1: newState = AppState.APPSTATE_DETECTED; break;
+            case 2: newState = AppState.APPSTATE_PIN; break;
+            case 3: newState = AppState.APPSTATE_PUK; break;
+            case 4: newState = AppState.APPSTATE_SUBSCRIPTION_PERSO; break;
+            case 5: newState = AppState.APPSTATE_READY; break;
+            default:
+                throw new RuntimeException(
+                            "Unrecognized RIL_AppState: " +state);
+        }
+        return newState;
+    }
+
+    PersoSubState PersoSubstateFromRILInt(int substate) {
+        PersoSubState newSubState;
+        /* RIL_PeroSubstate ril.h */
+        switch(substate) {
+            case 0:  newSubState = PersoSubState.PERSOSUBSTATE_UNKNOWN;  break;
+            case 1:  newSubState = PersoSubState.PERSOSUBSTATE_IN_PROGRESS; break;
+            case 2:  newSubState = PersoSubState.PERSOSUBSTATE_READY; break;
+            case 3:  newSubState = PersoSubState.PERSOSUBSTATE_SIM_NETWORK; break;
+            case 4:  newSubState = PersoSubState.PERSOSUBSTATE_SIM_NETWORK_SUBSET; break;
+            case 5:  newSubState = PersoSubState.PERSOSUBSTATE_SIM_CORPORATE; break;
+            case 6:  newSubState = PersoSubState.PERSOSUBSTATE_SIM_SERVICE_PROVIDER; break;
+            case 7:  newSubState = PersoSubState.PERSOSUBSTATE_SIM_SIM;  break;
+            case 8:  newSubState = PersoSubState.PERSOSUBSTATE_SIM_NETWORK_PUK; break;
+            case 9:  newSubState = PersoSubState.PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK; break;
+            case 10: newSubState = PersoSubState.PERSOSUBSTATE_SIM_CORPORATE_PUK; break;
+            case 11: newSubState = PersoSubState.PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK; break;
+            case 12: newSubState = PersoSubState.PERSOSUBSTATE_SIM_SIM_PUK; break;
+            case 13: newSubState = PersoSubState.PERSOSUBSTATE_RUIM_NETWORK1; break;
+            case 14: newSubState = PersoSubState.PERSOSUBSTATE_RUIM_NETWORK2; break;
+            case 15: newSubState = PersoSubState.PERSOSUBSTATE_RUIM_HRPD; break;
+            case 16: newSubState = PersoSubState.PERSOSUBSTATE_RUIM_CORPORATE; break;
+            case 17: newSubState = PersoSubState.PERSOSUBSTATE_RUIM_SERVICE_PROVIDER; break;
+            case 18: newSubState = PersoSubState.PERSOSUBSTATE_RUIM_RUIM; break;
+            case 19: newSubState = PersoSubState.PERSOSUBSTATE_RUIM_NETWORK1_PUK; break;
+            case 20: newSubState = PersoSubState.PERSOSUBSTATE_RUIM_NETWORK2_PUK; break;
+            case 21: newSubState = PersoSubState.PERSOSUBSTATE_RUIM_HRPD_PUK ; break;
+            case 22: newSubState = PersoSubState.PERSOSUBSTATE_RUIM_CORPORATE_PUK; break;
+            case 23: newSubState = PersoSubState.PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK; break;
+            case 24: newSubState = PersoSubState.PERSOSUBSTATE_RUIM_RUIM_PUK; break;
+            default:
+                throw new RuntimeException(
+                            "Unrecognized RIL_PersoSubstate: " +substate);
+        }
+        return newSubState;
+    }
+
+}
diff --git a/telephony/java/com/android/internal/telephony/IccCardStatus.java b/telephony/java/com/android/internal/telephony/IccCardStatus.java
new file mode 100644
index 0000000..b602b1c
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IccCardStatus.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony;
+
+import java.util.ArrayList;
+
+/**
+ * See also RIL_CardStatus in include/telephony/ril.h
+ *
+ * {@hide}
+ */
+public class IccCardStatus {
+    static final int CARD_MAX_APPS = 8;
+
+    public enum CardState {
+        CARDSTATE_ABSENT,
+        CARDSTATE_PRESENT,
+        CARDSTATE_ERROR;
+
+        boolean isCardPresent() {
+            return this == CARDSTATE_PRESENT;
+        }
+    };
+
+    public enum PinState {
+        PINSTATE_UNKNOWN,
+        PINSTATE_ENABLED_NOT_VERIFIED,
+        PINSTATE_ENABLED_VERIFIED,
+        PINSTATE_DISABLED,
+        PINSTATE_ENABLED_BLOCKED,
+        PINSTATE_ENABLED_PERM_BLOCKED
+    };
+
+    public CardState  card_state;
+    public PinState   universal_pin_state;
+    public int        gsm_umts_subscription_app_index;
+    public int        cdma_subscription_app_index;
+    public int        num_applications;
+
+    ArrayList<IccCardApplication> application = new ArrayList<IccCardApplication>(CARD_MAX_APPS);
+
+    CardState CardStateFromRILInt(int state) {
+        CardState newState;
+        /* RIL_CardState ril.h */
+        switch(state) {
+            case 0: newState = CardState.CARDSTATE_ABSENT; break;
+            case 1: newState = CardState.CARDSTATE_PRESENT; break;
+            case 2: newState = CardState.CARDSTATE_ERROR; break;
+            default:
+                throw new RuntimeException(
+                            "Unrecognized RIL_CardState: " +state);
+        }
+        return newState;
+    }
+
+    PinState PinStateFromRILInt(int state) {
+        PinState newState;
+        /* RIL_PinState ril.h */
+        switch(state) {
+            case 0: newState = PinState.PINSTATE_UNKNOWN; break;
+            case 1: newState = PinState.PINSTATE_ENABLED_NOT_VERIFIED; break;
+            case 2: newState = PinState.PINSTATE_ENABLED_VERIFIED; break;
+            case 3: newState = PinState.PINSTATE_DISABLED; break;
+            case 4: newState = PinState.PINSTATE_ENABLED_BLOCKED; break;
+            case 5: newState = PinState.PINSTATE_ENABLED_PERM_BLOCKED; break;
+            default:
+                throw new RuntimeException(
+                            "Unrecognized RIL_PinState: " +state);
+        }
+        return newState;
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimConstants.java b/telephony/java/com/android/internal/telephony/IccConstants.java
similarity index 86%
rename from telephony/java/com/android/internal/telephony/gsm/SimConstants.java
rename to telephony/java/com/android/internal/telephony/IccConstants.java
index a7e3bbc..59ce5bb 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimConstants.java
+++ b/telephony/java/com/android/internal/telephony/IccConstants.java
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 /**
  * {@hide}
  */
-public interface SimConstants {
-    // SIM file ids from TS 51.011
+public interface IccConstants {
+    // GSM SIM file ids from TS 51.011
     public static final int EF_ADN = 0x6F3A;
     public static final int EF_FDN = 0x6F3B;
     public static final int EF_SDN = 0x6F49;
@@ -42,7 +42,7 @@
     public static final int EF_CFIS = 0x6FCB;
     public static final int EF_IMG = 0x4f20;
 
-    // SIM file ids from CPHS (phase 2, version 4.2) CPHS4_2.WW6
+    // GSM SIM file ids from CPHS (phase 2, version 4.2) CPHS4_2.WW6
     public static final int EF_MAILBOX_CPHS = 0x6F17;
     public static final int EF_VOICE_MAIL_INDICATOR_CPHS = 0x6F11;
     public static final int EF_CFF_CPHS = 0x6F13;
@@ -50,6 +50,10 @@
     public static final int EF_SPN_SHORT_CPHS = 0x6f18;
     public static final int EF_INFO_CPHS = 0x6f16;
 
+    // CDMA RUIM file ids from 3GPP2 C.S0023-0
+    public static final int EF_CST = 0x6f32;
+    public static final int EF_RUIM_SPN =0x6F41;
+
     // SMS record length from TS 51.011 10.5.3
     static public final int SMS_RECORD_LENGTH = 176;
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java b/telephony/java/com/android/internal/telephony/IccException.java
similarity index 79%
copy from telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
copy to telephony/java/com/android/internal/telephony/IccException.java
index 72790d0..1659a4e 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
+++ b/telephony/java/com/android/internal/telephony/IccException.java
@@ -14,20 +14,17 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 /**
  * {@hide}
  */
-public class SimFileTypeMismatch extends SimException
-{
-    SimFileTypeMismatch()
-    {
+public class IccException extends Exception {
+    public IccException() {
 
     }
 
-    SimFileTypeMismatch(String s)
-    {
+    public IccException(String s) {
         super(s);
     }
 }
diff --git a/telephony/java/com/android/internal/telephony/IccFileHandler.java b/telephony/java/com/android/internal/telephony/IccFileHandler.java
new file mode 100644
index 0000000..e751c5e
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IccFileHandler.java
@@ -0,0 +1,513 @@
+/*
+ * Copyright (C) 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.
+ * 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.internal.telephony;
+
+import android.os.*;
+import android.util.Log;
+import java.util.ArrayList;
+
+/**
+ * {@hide}
+ */
+public abstract class IccFileHandler extends Handler {
+
+    //from TS 11.11 9.1 or elsewhere
+    static protected final int COMMAND_READ_BINARY = 0xb0;
+    static protected final int COMMAND_UPDATE_BINARY = 0xd6;
+    static protected final int COMMAND_READ_RECORD = 0xb2;
+    static protected final int COMMAND_UPDATE_RECORD = 0xdc;
+    static protected final int COMMAND_SEEK = 0xa2;
+    static protected final int COMMAND_GET_RESPONSE = 0xc0;
+
+    // from TS 11.11 9.2.5
+    static protected final int READ_RECORD_MODE_ABSOLUTE = 4;
+
+    //***** types of files  TS 11.11 9.3
+    static protected final int EF_TYPE_TRANSPARENT = 0;
+    static protected final int EF_TYPE_LINEAR_FIXED = 1;
+    static protected final int EF_TYPE_CYCLIC = 3;
+
+    //***** types of files  TS 11.11 9.3
+    static protected final int TYPE_RFU = 0;
+    static protected final int TYPE_MF  = 1;
+    static protected final int TYPE_DF  = 2;
+    static protected final int TYPE_EF  = 4;
+
+    // size of GET_RESPONSE for EF's
+    static protected final int GET_RESPONSE_EF_SIZE_BYTES = 15;
+    static protected final int GET_RESPONSE_EF_IMG_SIZE_BYTES = 10;
+
+    // Byte order received in response to COMMAND_GET_RESPONSE
+    // Refer TS 51.011 Section 9.2.1
+    static protected final int RESPONSE_DATA_RFU_1 = 0;
+    static protected final int RESPONSE_DATA_RFU_2 = 1;
+
+    static protected final int RESPONSE_DATA_FILE_SIZE_1 = 2;
+    static protected final int RESPONSE_DATA_FILE_SIZE_2 = 3;
+
+    static protected final int RESPONSE_DATA_FILE_ID_1 = 4;
+    static protected final int RESPONSE_DATA_FILE_ID_2 = 5;
+    static protected final int RESPONSE_DATA_FILE_TYPE = 6;
+    static protected final int RESPONSE_DATA_RFU_3 = 7;
+    static protected final int RESPONSE_DATA_ACCESS_CONDITION_1 = 8;
+    static protected final int RESPONSE_DATA_ACCESS_CONDITION_2 = 9;
+    static protected final int RESPONSE_DATA_ACCESS_CONDITION_3 = 10;
+    static protected final int RESPONSE_DATA_FILE_STATUS = 11;
+    static protected final int RESPONSE_DATA_LENGTH = 12;
+    static protected final int RESPONSE_DATA_STRUCTURE = 13;
+    static protected final int RESPONSE_DATA_RECORD_LENGTH = 14;
+
+
+    //***** Events
+
+    /** Finished retrieving size of transparent EF; start loading. */
+    static protected final int EVENT_GET_BINARY_SIZE_DONE = 4;
+    /** Finished loading contents of transparent EF; post result. */
+    static protected final int EVENT_READ_BINARY_DONE = 5;
+    /** Finished retrieving size of records for linear-fixed EF; now load. */
+    static protected final int EVENT_GET_RECORD_SIZE_DONE = 6;
+    /** Finished loading single record from a linear-fixed EF; post result. */
+    static protected final int EVENT_READ_RECORD_DONE = 7;
+    /** Finished retrieving record size; post result. */
+    static protected final int EVENT_GET_EF_LINEAR_RECORD_SIZE_DONE = 8;
+    /** Finished retrieving image instance record; post result. */
+    static protected final int EVENT_READ_IMG_DONE = 9;
+    /** Finished retrieving icon data; post result. */
+    static protected final int EVENT_READ_ICON_DONE = 10;
+
+     // member variables
+    protected PhoneBase phone;
+
+    static class LoadLinearFixedContext {
+
+        int efid;
+        int recordNum, recordSize, countRecords;
+        boolean loadAll;
+
+        Message onLoaded;
+
+        ArrayList<byte[]> results;
+
+        LoadLinearFixedContext(int efid, int recordNum, Message onLoaded) {
+            this.efid = efid;
+            this.recordNum = recordNum;
+            this.onLoaded = onLoaded;
+            this.loadAll = false;
+        }
+
+        LoadLinearFixedContext(int efid, Message onLoaded) {
+            this.efid = efid;
+            this.recordNum = 1;
+            this.loadAll = true;
+            this.onLoaded = onLoaded;
+        }
+    }
+
+    /**
+     * Default constructor
+     */
+    protected IccFileHandler(PhoneBase phone) {
+        super();
+        this.phone = phone;
+    }
+
+    public void dispose() {
+    }
+
+    //***** Public Methods
+
+    /**
+     * Load a record from a SIM Linear Fixed EF
+     *
+     * @param fileid EF id
+     * @param recordNum 1-based (not 0-based) record number
+     * @param onLoaded
+     *
+     * ((AsyncResult)(onLoaded.obj)).result is the byte[]
+     *
+     */
+    public void loadEFLinearFixed(int fileid, int recordNum, Message onLoaded) {
+        Message response
+            = obtainMessage(EVENT_GET_RECORD_SIZE_DONE,
+                        new LoadLinearFixedContext(fileid, recordNum, onLoaded));
+
+        phone.mCM.iccIO(COMMAND_GET_RESPONSE, fileid, null,
+                        0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, response);
+    }
+
+    /**
+     * Load a image instance record from a SIM Linear Fixed EF-IMG
+     *
+     * @param recordNum 1-based (not 0-based) record number
+     * @param onLoaded
+     *
+     * ((AsyncResult)(onLoaded.obj)).result is the byte[]
+     *
+     */
+    public void loadEFImgLinearFixed(int recordNum, Message onLoaded) {
+        Message response = obtainMessage(EVENT_READ_IMG_DONE,
+                new LoadLinearFixedContext(IccConstants.EF_IMG, recordNum,
+                        onLoaded));
+
+        phone.mCM.iccIO(COMMAND_GET_RESPONSE, IccConstants.EF_IMG, "img",
+                recordNum, READ_RECORD_MODE_ABSOLUTE,
+                GET_RESPONSE_EF_IMG_SIZE_BYTES, null, null, response);
+    }
+
+    /**
+     * get record size for a linear fixed EF
+     *
+     * @param fileid EF id
+     * @param onLoaded ((AsnyncResult)(onLoaded.obj)).result is the recordSize[]
+     *        int[0] is the record length int[1] is the total length of the EF
+     *        file int[3] is the number of records in the EF file So int[0] *
+     *        int[3] = int[1]
+     */
+    public void getEFLinearRecordSize(int fileid, Message onLoaded) {
+        Message response
+                = obtainMessage(EVENT_GET_EF_LINEAR_RECORD_SIZE_DONE,
+                        new LoadLinearFixedContext(fileid, onLoaded));
+        phone.mCM.iccIO(COMMAND_GET_RESPONSE, fileid, null,
+                    0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, response);
+    }
+
+    /**
+     * Load all records from a SIM Linear Fixed EF
+     *
+     * @param fileid EF id
+     * @param onLoaded
+     *
+     * ((AsyncResult)(onLoaded.obj)).result is an ArrayList<byte[]>
+     *
+     */
+    public void loadEFLinearFixedAll(int fileid, Message onLoaded) {
+        Message response = obtainMessage(EVENT_GET_RECORD_SIZE_DONE,
+                        new LoadLinearFixedContext(fileid,onLoaded));
+
+        phone.mCM.iccIO(COMMAND_GET_RESPONSE, fileid, null,
+                        0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, response);
+    }
+
+    /**
+     * Load a SIM Transparent EF
+     *
+     * @param fileid EF id
+     * @param onLoaded
+     *
+     * ((AsyncResult)(onLoaded.obj)).result is the byte[]
+     *
+     */
+
+    public void loadEFTransparent(int fileid, Message onLoaded) {
+        Message response = obtainMessage(EVENT_GET_BINARY_SIZE_DONE,
+                        fileid, 0, onLoaded);
+
+        phone.mCM.iccIO(COMMAND_GET_RESPONSE, fileid, null,
+                        0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, response);
+    }
+
+    /**
+     * Load a SIM Transparent EF-IMG. Used right after loadEFImgLinearFixed to
+     * retrive STK's icon data.
+     *
+     * @param fileid EF id
+     * @param onLoaded
+     *
+     * ((AsyncResult)(onLoaded.obj)).result is the byte[]
+     *
+     */
+    public void loadEFImgTransparent(int fileid, int highOffset, int lowOffset,
+            int length, Message onLoaded) {
+        Message response = obtainMessage(EVENT_READ_ICON_DONE, fileid, 0,
+                onLoaded);
+
+        phone.mCM.iccIO(COMMAND_READ_BINARY, fileid, "img", highOffset, lowOffset,
+                length, null, null, response);
+    }
+
+    /**
+     * Update a record in a linear fixed EF
+     * @param fileid EF id
+     * @param recordNum 1-based (not 0-based) record number
+     * @param data must be exactly as long as the record in the EF
+     * @param pin2 for CHV2 operations, otherwist must be null
+     * @param onComplete onComplete.obj will be an AsyncResult
+     *                   onComplete.obj.userObj will be a IccIoResult on success
+     */
+    public void updateEFLinearFixed(int fileid, int recordNum, byte[] data,
+            String pin2, Message onComplete) {
+        phone.mCM.iccIO(COMMAND_UPDATE_RECORD, fileid, null,
+                        recordNum, READ_RECORD_MODE_ABSOLUTE, data.length,
+                        IccUtils.bytesToHexString(data), pin2, onComplete);
+    }
+
+    /**
+     * Update a transparent EF
+     * @param fileid EF id
+     * @param data must be exactly as long as the EF
+     */
+    public void updateEFTransparent(int fileid, byte[] data, Message onComplete) {
+        phone.mCM.iccIO(COMMAND_UPDATE_BINARY, fileid, null,
+                        0, 0, data.length,
+                        IccUtils.bytesToHexString(data), null, onComplete);
+    }
+
+
+    //***** Abstract Methods
+
+
+    //***** Private Methods
+
+    private void sendResult(Message response, Object result, Throwable ex) {
+        if (response == null) {
+            return;
+        }
+
+        AsyncResult.forMessage(response, result, ex);
+
+        response.sendToTarget();
+    }
+
+    //***** Overridden from Handler
+
+    public void handleMessage(Message msg) {
+        AsyncResult ar;
+        IccIoResult result;
+        Message response = null;
+        String str;
+        LoadLinearFixedContext lc;
+
+        IccException iccException;
+        byte data[];
+        int size;
+        int fileid;
+        int recordNum;
+        int recordSize[];
+
+        try {
+            switch (msg.what) {
+            case EVENT_READ_IMG_DONE:
+                ar = (AsyncResult) msg.obj;
+                lc = (LoadLinearFixedContext) ar.userObj;
+                result = (IccIoResult) ar.result;
+                response = lc.onLoaded;
+
+                iccException = result.getException();
+                if (iccException != null) {
+                    sendResult(response, result.payload, ar.exception);
+                }
+                break;
+            case EVENT_READ_ICON_DONE:
+                ar = (AsyncResult) msg.obj;
+                response = (Message) ar.userObj;
+                result = (IccIoResult) ar.result;
+
+                iccException = result.getException();
+                if (iccException != null) {
+                    sendResult(response, result.payload, ar.exception);
+                }
+                break;
+            case EVENT_GET_EF_LINEAR_RECORD_SIZE_DONE:
+                ar = (AsyncResult)msg.obj;
+                lc = (LoadLinearFixedContext) ar.userObj;
+                result = (IccIoResult) ar.result;
+                response = lc.onLoaded;
+
+                if (ar.exception != null) {
+                    sendResult(response, null, ar.exception);
+                    break;
+                }
+
+                iccException = result.getException();
+                if (iccException != null) {
+                    sendResult(response, null, iccException);
+                    break;
+                }
+
+                data = result.payload;
+
+                if (TYPE_EF != data[RESPONSE_DATA_FILE_TYPE] ||
+                    EF_TYPE_LINEAR_FIXED != data[RESPONSE_DATA_STRUCTURE]) {
+                    throw new IccFileTypeMismatch();
+                }
+
+                recordSize = new int[3];
+                recordSize[0] = data[RESPONSE_DATA_RECORD_LENGTH] & 0xFF;
+                recordSize[1] = ((data[RESPONSE_DATA_FILE_SIZE_1] & 0xff) << 8)
+                       + (data[RESPONSE_DATA_FILE_SIZE_2] & 0xff);
+                recordSize[2] = recordSize[1] / recordSize[0];
+
+                sendResult(response, recordSize, null);
+                break;
+             case EVENT_GET_RECORD_SIZE_DONE:
+                ar = (AsyncResult)msg.obj;
+                lc = (LoadLinearFixedContext) ar.userObj;
+                result = (IccIoResult) ar.result;
+                response = lc.onLoaded;
+
+                if (ar.exception != null) {
+                    sendResult(response, null, ar.exception);
+                    break;
+                }
+
+                iccException = result.getException();
+
+                if (iccException != null) {
+                    sendResult(response, null, iccException);
+                    break;
+                }
+
+                data = result.payload;
+                fileid = lc.efid;
+                recordNum = lc.recordNum;
+
+                if (TYPE_EF != data[RESPONSE_DATA_FILE_TYPE]) {
+                    throw new IccFileTypeMismatch();
+                }
+
+                if (EF_TYPE_LINEAR_FIXED != data[RESPONSE_DATA_STRUCTURE]) {
+                    throw new IccFileTypeMismatch();
+                }
+
+                lc.recordSize = data[RESPONSE_DATA_RECORD_LENGTH] & 0xFF;
+
+                size = ((data[RESPONSE_DATA_FILE_SIZE_1] & 0xff) << 8)
+                       + (data[RESPONSE_DATA_FILE_SIZE_2] & 0xff);
+
+                lc.countRecords = size / lc.recordSize;
+
+                 if (lc.loadAll) {
+                     lc.results = new ArrayList<byte[]>(lc.countRecords);
+                 }
+
+                 phone.mCM.iccIO(COMMAND_READ_RECORD, lc.efid, null,
+                         lc.recordNum,
+                         READ_RECORD_MODE_ABSOLUTE,
+                         lc.recordSize, null, null,
+                         obtainMessage(EVENT_READ_RECORD_DONE, lc));
+                 break;
+            case EVENT_GET_BINARY_SIZE_DONE:
+                ar = (AsyncResult)msg.obj;
+                response = (Message) ar.userObj;
+                result = (IccIoResult) ar.result;
+
+                if (ar.exception != null) {
+                    sendResult(response, null, ar.exception);
+                    break;
+                }
+
+                iccException = result.getException();
+
+                if (iccException != null) {
+                    sendResult(response, null, iccException);
+                    break;
+                }
+
+                data = result.payload;
+
+                fileid = msg.arg1;
+
+                if (TYPE_EF != data[RESPONSE_DATA_FILE_TYPE]) {
+                    throw new IccFileTypeMismatch();
+                }
+
+                if (EF_TYPE_TRANSPARENT != data[RESPONSE_DATA_STRUCTURE]) {
+                    throw new IccFileTypeMismatch();
+                }
+
+                size = ((data[RESPONSE_DATA_FILE_SIZE_1] & 0xff) << 8)
+                       + (data[RESPONSE_DATA_FILE_SIZE_2] & 0xff);
+
+                phone.mCM.iccIO(COMMAND_READ_BINARY, fileid, null,
+                                0, 0, size, null, null,
+                                obtainMessage(EVENT_READ_BINARY_DONE,
+                                              fileid, 0, response));
+            break;
+
+            case EVENT_READ_RECORD_DONE:
+
+                ar = (AsyncResult)msg.obj;
+                lc = (LoadLinearFixedContext) ar.userObj;
+                result = (IccIoResult) ar.result;
+                response = lc.onLoaded;
+
+                if (ar.exception != null) {
+                    sendResult(response, null, ar.exception);
+                    break;
+                }
+
+                iccException = result.getException();
+
+                if (iccException != null) {
+                    sendResult(response, null, iccException);
+                    break;
+                }
+
+                if (!lc.loadAll) {
+                    sendResult(response, result.payload, null);
+                } else {
+                    lc.results.add(result.payload);
+
+                    lc.recordNum++;
+
+                    if (lc.recordNum > lc.countRecords) {
+                        sendResult(response, lc.results, null);
+                    } else {
+                        phone.mCM.iccIO(COMMAND_READ_RECORD, lc.efid, null,
+                                    lc.recordNum,
+                                    READ_RECORD_MODE_ABSOLUTE,
+                                    lc.recordSize, null, null,
+                                    obtainMessage(EVENT_READ_RECORD_DONE, lc));
+                    }
+                }
+
+            break;
+
+            case EVENT_READ_BINARY_DONE:
+                ar = (AsyncResult)msg.obj;
+                response = (Message) ar.userObj;
+                result = (IccIoResult) ar.result;
+
+                if (ar.exception != null) {
+                    sendResult(response, null, ar.exception);
+                    break;
+                }
+
+                iccException = result.getException();
+
+                if (iccException != null) {
+                    sendResult(response, null, iccException);
+                    break;
+                }
+
+                sendResult(response, result.payload, null);
+            break;
+
+        }} catch (Exception exc) {
+            if (response != null) {
+                sendResult(response, null, exc);
+            } else {
+                loge("uncaught exception" + exc);
+            }
+        }
+    }
+
+    protected abstract void logd(String s);
+
+    protected abstract void loge(String s);
+
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java b/telephony/java/com/android/internal/telephony/IccFileNotFound.java
similarity index 72%
copy from telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
copy to telephony/java/com/android/internal/telephony/IccFileNotFound.java
index 72790d0..915cea68 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
+++ b/telephony/java/com/android/internal/telephony/IccFileNotFound.java
@@ -14,20 +14,21 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 /**
  * {@hide}
  */
-public class SimFileTypeMismatch extends SimException
-{
-    SimFileTypeMismatch()
-    {
+public class IccFileNotFound extends IccException {
+    IccFileNotFound() {
 
     }
 
-    SimFileTypeMismatch(String s)
-    {
+    IccFileNotFound(String s) {
         super(s);
     }
+
+    IccFileNotFound(int ef) {
+        super("ICC EF Not Found 0x" + Integer.toHexString(ef));
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java b/telephony/java/com/android/internal/telephony/IccFileTypeMismatch.java
similarity index 79%
rename from telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
rename to telephony/java/com/android/internal/telephony/IccFileTypeMismatch.java
index 72790d0..66fcfa9 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
+++ b/telephony/java/com/android/internal/telephony/IccFileTypeMismatch.java
@@ -14,20 +14,17 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 /**
  * {@hide}
  */
-public class SimFileTypeMismatch extends SimException
-{
-    SimFileTypeMismatch()
-    {
+public class IccFileTypeMismatch extends IccException {
+    public IccFileTypeMismatch() {
 
     }
 
-    SimFileTypeMismatch(String s)
-    {
+    public IccFileTypeMismatch(String s) {
         super(s);
     }
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimIoResult.java b/telephony/java/com/android/internal/telephony/IccIoResult.java
similarity index 67%
rename from telephony/java/com/android/internal/telephony/gsm/SimIoResult.java
rename to telephony/java/com/android/internal/telephony/IccIoResult.java
index 2c4da83..a6e0ec3 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimIoResult.java
+++ b/telephony/java/com/android/internal/telephony/IccIoResult.java
@@ -14,33 +14,30 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 /**
  * {@hide}
  */
 public class
-SimIoResult
-{
+IccIoResult {
     int sw1;
     int sw2;
-    byte[] payload;
 
-    public SimIoResult(int sw1, int sw2, byte[] payload)
-    {
+    public byte[] payload;
+
+    public IccIoResult(int sw1, int sw2, byte[] payload) {
         this.sw1 = sw1;
         this.sw2 = sw2;
         this.payload = payload;
     }
 
-    public SimIoResult(int sw1, int sw2, String hexString)
-    {
-        this(sw1, sw2, SimUtils.hexStringToBytes(hexString));
+    public IccIoResult(int sw1, int sw2, String hexString) {
+        this(sw1, sw2, IccUtils.hexStringToBytes(hexString));
     }
 
-    public String toString()
-    {
-        return "SimIoResponse sw1:0x" + Integer.toHexString(sw1) + " sw2:0x" 
+    public String toString() {
+        return "IccIoResponse sw1:0x" + Integer.toHexString(sw1) + " sw2:0x"
                 + Integer.toHexString(sw2);
     }
 
@@ -49,27 +46,25 @@
      * See GSM 11.11 Section 9.4
      * (the fun stuff is absent in 51.011)
      */
-    public boolean success()
-    {
+    public boolean success() {
         return sw1 == 0x90 || sw1 == 0x91 || sw1 == 0x9e || sw1 == 0x9f;
     }
 
     /**
      * Returns exception on error or null if success
      */
-    public SimException getException()
-    {
+    public IccException getException() {
         if (success()) return null;
-        
+
         switch (sw1) {
             case 0x94:
                 if (sw2 == 0x08) {
-                    return new SimFileTypeMismatch();
+                    return new IccFileTypeMismatch();
                 } else {
-                    return new SimFileNotFound();
+                    return new IccFileNotFound();
                 }
             default:
-                return new SimException("sw1:" + sw1 + " sw2:" + sw2);
+                return new IccException("sw1:" + sw1 + " sw2:" + sw2);
         }
     }
 }
diff --git a/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java b/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java
new file mode 100644
index 0000000..0bcaaa6
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony;
+
+import android.content.pm.PackageManager;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.ServiceManager;
+import android.telephony.PhoneNumberUtils;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * SimPhoneBookInterfaceManager to provide an inter-process communication to
+ * access ADN-like SIM records.
+ */
+public abstract class IccPhoneBookInterfaceManager extends IIccPhoneBook.Stub {
+    protected static final boolean DBG = true;
+
+    protected PhoneBase phone;
+    protected AdnRecordCache adnCache;
+    protected Object mLock = new Object();
+    protected int recordSize[];
+    protected boolean success;
+    protected List<AdnRecord> records;
+
+    protected static final boolean ALLOW_SIM_OP_IN_UI_THREAD = false;
+
+    protected static final int EVENT_GET_SIZE_DONE = 1;
+    protected static final int EVENT_LOAD_DONE = 2;
+    protected static final int EVENT_UPDATE_DONE = 3;
+
+    protected Handler mBaseHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            AsyncResult ar;
+
+            switch (msg.what) {
+                case EVENT_GET_SIZE_DONE:
+                    ar = (AsyncResult) msg.obj;
+                    synchronized (mLock) {
+                        if (ar.exception == null) {
+                            recordSize = (int[])ar.result;
+                            // recordSize[0]  is the record length
+                            // recordSize[1]  is the total length of the EF file
+                            // recordSize[2]  is the number of records in the EF file
+                            logd("GET_RECORD_SIZE Size " + recordSize[0] +
+                                    " total " + recordSize[1] +
+                                    " #record " + recordSize[2]);
+                            mLock.notifyAll();
+                        }
+                    }
+                    break;
+                case EVENT_UPDATE_DONE:
+                    ar = (AsyncResult) msg.obj;
+                    synchronized (mLock) {
+                        success = (ar.exception == null);
+                        mLock.notifyAll();
+                    }
+                    break;
+                case EVENT_LOAD_DONE:
+                    ar = (AsyncResult)msg.obj;
+                    synchronized (mLock) {
+                        if (ar.exception == null) {
+                            records = (List<AdnRecord>)
+                                    ((ArrayList<AdnRecord>) ar.result);
+                        } else {
+                            if(DBG) logd("Cannot load ADN records");
+                            if (records != null) {
+                                records.clear();
+                            }
+                        }
+                        mLock.notifyAll();
+                    }
+                    break;
+            }
+        }
+    };
+
+    public IccPhoneBookInterfaceManager(PhoneBase phone) {
+        this.phone = phone;
+    }
+
+    public void dispose() {
+    }
+
+    protected void publish() {
+        //NOTE service "simphonebook" added by IccSmsInterfaceManagerProxy
+        ServiceManager.addService("simphonebook", this);
+    }
+
+    protected abstract void logd(String msg);
+
+    protected abstract void loge(String msg);
+
+    /**
+     * Replace oldAdn with newAdn in ADN-like record in EF
+     *
+     * getAdnRecordsInEf must be called at least once before this function,
+     * otherwise an error will be returned
+     * throws SecurityException if no WRITE_CONTACTS permission
+     *
+     * @param efid must be one among EF_ADN, EF_FDN, and EF_SDN
+     * @param oldTag adn tag to be replaced
+     * @param oldPhoneNumber adn number to be replaced
+     *        Set both oldTag and oldPhoneNubmer to "" means to replace an
+     *        empty record, aka, insert new record
+     * @param newTag adn tag to be stored
+     * @param newPhoneNumber adn number ot be stored
+     *        Set both newTag and newPhoneNubmer to "" means to replace the old
+     *        record with empty one, aka, delete old record
+     * @param pin2 required to update EF_FDN, otherwise must be null
+     * @return true for success
+     */
+    public boolean
+    updateAdnRecordsInEfBySearch (int efid,
+            String oldTag, String oldPhoneNumber,
+            String newTag, String newPhoneNumber, String pin2) {
+
+
+        if (phone.getContext().checkCallingOrSelfPermission(
+                android.Manifest.permission.WRITE_CONTACTS)
+            != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException(
+                    "Requires android.permission.WRITE_CONTACTS permission");
+        }
+
+
+        if (DBG) logd("updateAdnRecordsInEfBySearch: efid=" + efid +
+                " ("+ oldTag + "," + oldPhoneNumber + ")"+ "==>" +
+                " ("+ newTag + "," + newPhoneNumber + ")"+ " pin2=" + pin2);
+        synchronized(mLock) {
+            checkThread();
+            success = false;
+            Message response = mBaseHandler.obtainMessage(EVENT_UPDATE_DONE);
+            AdnRecord oldAdn = new AdnRecord(oldTag, oldPhoneNumber);
+            AdnRecord newAdn = new AdnRecord(newTag, newPhoneNumber);
+            adnCache.updateAdnBySearch(efid, oldAdn, newAdn, pin2, response);
+            try {
+                mLock.wait();
+            } catch (InterruptedException e) {
+                logd("interrupted while trying to update by search");
+            }
+        }
+        return success;
+    }
+
+    /**
+     * Update an ADN-like EF record by record index
+     *
+     * This is useful for iteration the whole ADN file, such as write the whole
+     * phone book or erase/format the whole phonebook
+     * throws SecurityException if no WRITE_CONTACTS permission
+     *
+     * @param efid must be one among EF_ADN, EF_FDN, and EF_SDN
+     * @param newTag adn tag to be stored
+     * @param newPhoneNumber adn number to be stored
+     *        Set both newTag and newPhoneNubmer to "" means to replace the old
+     *        record with empty one, aka, delete old record
+     * @param index is 1-based adn record index to be updated
+     * @param pin2 required to update EF_FDN, otherwise must be null
+     * @return true for success
+     */
+    public boolean
+    updateAdnRecordsInEfByIndex(int efid, String newTag,
+            String newPhoneNumber, int index, String pin2) {
+
+        if (phone.getContext().checkCallingOrSelfPermission(
+                android.Manifest.permission.WRITE_CONTACTS)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException(
+                    "Requires android.permission.WRITE_CONTACTS permission");
+        }
+
+        if (DBG) logd("updateAdnRecordsInEfByIndex: efid=" + efid +
+                " Index=" + index + " ==> " +
+                "("+ newTag + "," + newPhoneNumber + ")"+ " pin2=" + pin2);
+        synchronized(mLock) {
+            checkThread();
+            success = false;
+            Message response = mBaseHandler.obtainMessage(EVENT_UPDATE_DONE);
+            AdnRecord newAdn = new AdnRecord(newTag, newPhoneNumber);
+            adnCache.updateAdnByIndex(efid, newAdn, index, pin2, response);
+            try {
+                mLock.wait();
+            } catch (InterruptedException e) {
+                logd("interrupted while trying to update by index");
+            }
+        }
+        return success;
+    }
+
+    /**
+     * Get the capacity of records in efid
+     *
+     * @param efid the EF id of a ADN-like ICC
+     * @return  int[3] array
+     *            recordSizes[0]  is the single record length
+     *            recordSizes[1]  is the total length of the EF file
+     *            recordSizes[2]  is the number of records in the EF file
+     */
+    public abstract int[] getAdnRecordsSize(int efid);
+
+    /**
+     * Loads the AdnRecords in efid and returns them as a
+     * List of AdnRecords
+     *
+     * throws SecurityException if no READ_CONTACTS permission
+     *
+     * @param efid the EF id of a ADN-like ICC
+     * @return List of AdnRecord
+     */
+    public List<AdnRecord> getAdnRecordsInEf(int efid) {
+
+        if (phone.getContext().checkCallingOrSelfPermission(
+                android.Manifest.permission.READ_CONTACTS)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException(
+                    "Requires android.permission.READ_CONTACTS permission");
+        }
+
+        if (DBG) logd("getAdnRecordsInEF: efid=" + efid);
+
+        synchronized(mLock) {
+            checkThread();
+            Message response = mBaseHandler.obtainMessage(EVENT_LOAD_DONE);
+            adnCache.requestLoadAllAdnLike(efid, response);
+            try {
+                mLock.wait();
+            } catch (InterruptedException e) {
+                logd("interrupted while trying to load from the SIM");
+            }
+        }
+            return records;
+    }
+
+    protected void checkThread() {
+        if (!ALLOW_SIM_OP_IN_UI_THREAD) {
+            // Make sure this isn't the UI thread, since it will block
+            if (mBaseHandler.getLooper().equals(Looper.myLooper())) {
+                loge("query() called on the main UI thread!");
+                throw new IllegalStateException(
+                        "You cannot call query on this provder from the main UI thread.");
+            }
+        }
+    }
+}
+
diff --git a/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManagerProxy.java b/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManagerProxy.java
new file mode 100644
index 0000000..1c0fc52
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManagerProxy.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 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.
+ * 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.internal.telephony;
+
+import android.content.pm.PackageManager;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.ServiceManager;
+import android.telephony.PhoneNumberUtils;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * SimPhoneBookInterfaceManager to provide an inter-process communication to
+ * access ADN-like SIM records.
+ */
+public class IccPhoneBookInterfaceManagerProxy extends IIccPhoneBook.Stub {
+    private IccPhoneBookInterfaceManager mIccPhoneBookInterfaceManager;
+
+    public IccPhoneBookInterfaceManagerProxy(IccPhoneBookInterfaceManager
+            iccPhoneBookInterfaceManager) {
+        mIccPhoneBookInterfaceManager = iccPhoneBookInterfaceManager;
+        if(ServiceManager.getService("simphonebook") == null) {
+            ServiceManager.addService("simphonebook", this);
+        }
+    }
+
+    public void setmIccPhoneBookInterfaceManager(
+            IccPhoneBookInterfaceManager iccPhoneBookInterfaceManager) {
+        this.mIccPhoneBookInterfaceManager = iccPhoneBookInterfaceManager;
+    }
+
+    public boolean
+    updateAdnRecordsInEfBySearch (int efid,
+            String oldTag, String oldPhoneNumber,
+            String newTag, String newPhoneNumber,
+            String pin2) throws android.os.RemoteException {
+        return mIccPhoneBookInterfaceManager.updateAdnRecordsInEfBySearch(
+                efid, oldTag, oldPhoneNumber, newTag, newPhoneNumber, pin2);
+    }
+
+    public boolean
+    updateAdnRecordsInEfByIndex(int efid, String newTag,
+            String newPhoneNumber, int index, String pin2) throws android.os.RemoteException {
+        return mIccPhoneBookInterfaceManager.updateAdnRecordsInEfByIndex(efid,
+                newTag, newPhoneNumber, index, pin2);
+    }
+
+    public int[] getAdnRecordsSize(int efid) throws android.os.RemoteException {
+        return mIccPhoneBookInterfaceManager.getAdnRecordsSize(efid);
+    }
+
+    public List<AdnRecord> getAdnRecordsInEf(int efid) throws android.os.RemoteException {
+        return mIccPhoneBookInterfaceManager.getAdnRecordsInEf(efid);
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimProvider.java b/telephony/java/com/android/internal/telephony/IccProvider.java
similarity index 82%
rename from telephony/java/com/android/internal/telephony/gsm/SimProvider.java
rename to telephony/java/com/android/internal/telephony/IccProvider.java
index cece4ba..4cbd7797 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimProvider.java
+++ b/telephony/java/com/android/internal/telephony/IccProvider.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 import android.content.ContentProvider;
 import android.content.UriMatcher;
@@ -31,11 +31,16 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import com.android.internal.telephony.IccConstants;
+import com.android.internal.telephony.AdnRecord;
+import com.android.internal.telephony.IIccPhoneBook;
+
+
 /**
  * {@hide}
  */
-public class SimProvider extends ContentProvider {
-    private static final String TAG = "SimProvider";
+public class IccProvider extends ContentProvider {
+    private static final String TAG = "IccProvider";
     private static final boolean DBG = false;
 
 
@@ -56,9 +61,9 @@
                             new UriMatcher(UriMatcher.NO_MATCH);
 
     static {
-        URL_MATCHER.addURI("sim", "adn", ADN);
-        URL_MATCHER.addURI("sim", "fdn", FDN);
-        URL_MATCHER.addURI("sim", "sdn", SDN);
+        URL_MATCHER.addURI("icc", "adn", ADN);
+        URL_MATCHER.addURI("icc", "fdn", FDN);
+        URL_MATCHER.addURI("icc", "sdn", SDN);
     }
 
 
@@ -81,21 +86,21 @@
     public Cursor query(Uri url, String[] projection, String selection,
             String[] selectionArgs, String sort) {
         ArrayList<ArrayList> results;
-        
+
         if (!mSimulator) {
             switch (URL_MATCHER.match(url)) {
                 case ADN:
-                    results = loadFromEf(SimConstants.EF_ADN);
+                    results = loadFromEf(IccConstants.EF_ADN);
                     break;
-    
+
                 case FDN:
-                    results = loadFromEf(SimConstants.EF_FDN);
+                    results = loadFromEf(IccConstants.EF_FDN);
                     break;
-    
+
                 case SDN:
-                    results = loadFromEf(SimConstants.EF_SDN);
+                    results = loadFromEf(IccConstants.EF_SDN);
                     break;
-    
+
                 default:
                     throw new IllegalArgumentException("Unknown URL " + url);
             }
@@ -152,11 +157,11 @@
         int match = URL_MATCHER.match(url);
         switch (match) {
             case ADN:
-                efType = SimConstants.EF_ADN;
+                efType = IccConstants.EF_ADN;
                 break;
 
             case FDN:
-                efType = SimConstants.EF_FDN;
+                efType = IccConstants.EF_FDN;
                 pin2 = initialValues.getAsString("pin2");
                 break;
 
@@ -167,7 +172,7 @@
 
         String tag = initialValues.getAsString("tag");
         String number = initialValues.getAsString("number");
-        boolean success = addSimRecordToEf(efType, tag, number, pin2);
+        boolean success = addIccRecordToEf(efType, tag, number, pin2);
 
         if (!success) {
             return null;
@@ -183,7 +188,7 @@
                 buf.append("fdn/");
                 break;
         }
-        
+
         // TODO: we need to find out the rowId for the newly added record
         buf.append(0);
 
@@ -218,11 +223,11 @@
         int match = URL_MATCHER.match(url);
         switch (match) {
             case ADN:
-                efType = SimConstants.EF_ADN;
+                efType = IccConstants.EF_ADN;
                 break;
 
             case FDN:
-                efType = SimConstants.EF_FDN;
+                efType = IccConstants.EF_FDN;
                 break;
 
             default:
@@ -269,7 +274,7 @@
             return 0;
         }
 
-        boolean success = deleteSimRecordFromEf(efType, tag, number, pin2);
+        boolean success = deleteIccRecordFromEf(efType, tag, number, pin2);
         if (!success) {
             return 0;
         }
@@ -287,11 +292,11 @@
         int match = URL_MATCHER.match(url);
         switch (match) {
             case ADN:
-                efType = SimConstants.EF_ADN;
+                efType = IccConstants.EF_ADN;
                 break;
 
             case FDN:
-                efType = SimConstants.EF_FDN;
+                efType = IccConstants.EF_FDN;
                 pin2 = values.getAsString("pin2");
                 break;
 
@@ -305,7 +310,7 @@
         String newTag = values.getAsString("newTag");
         String newNumber = values.getAsString("newNumber");
 
-        boolean success = updateSimRecordInEf(efType, tag, number,
+        boolean success = updateIccRecordInEf(efType, tag, number,
                 newTag, newNumber, pin2);
 
         if (!success) {
@@ -322,17 +327,16 @@
         if (DBG) log("loadFromEf: efType=" + efType);
 
         try {
-            ISimPhoneBook simIpb = ISimPhoneBook.Stub.asInterface(
+            IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(
                     ServiceManager.getService("simphonebook"));
-            if (simIpb != null) {
-                adnRecords = simIpb.getAdnRecordsInEf(efType);
+            if (iccIpb != null) {
+                adnRecords = iccIpb.getAdnRecordsInEf(efType);
             }
         } catch (RemoteException ex) {
             // ignore it
         } catch (SecurityException ex) {
             if (DBG) log(ex.toString());
         }
-
         if (adnRecords != null) {
             // Load the results
 
@@ -351,8 +355,8 @@
     }
 
     private boolean
-    addSimRecordToEf(int efType, String name, String number, String pin2) {
-        if (DBG) log("addSimRecordToEf: efType=" + efType + ", name=" + name +
+    addIccRecordToEf(int efType, String name, String number, String pin2) {
+        if (DBG) log("addIccRecordToEf: efType=" + efType + ", name=" + name +
                 ", number=" + number);
 
         boolean success = false;
@@ -361,11 +365,12 @@
         // updateAdnRecordsInEfBySearch()? In any case, we will leave
         // the UI level logic to fill that prereq if necessary. But
         // hopefully, we can remove this requirement.
+
         try {
-            ISimPhoneBook simIpb = ISimPhoneBook.Stub.asInterface(
+            IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(
                     ServiceManager.getService("simphonebook"));
-            if (simIpb != null) {
-                success = simIpb.updateAdnRecordsInEfBySearch(efType, "", "",
+            if (iccIpb != null) {
+                success = iccIpb.updateAdnRecordsInEfBySearch(efType, "", "",
                         name, number, pin2);
             }
         } catch (RemoteException ex) {
@@ -373,23 +378,23 @@
         } catch (SecurityException ex) {
             if (DBG) log(ex.toString());
         }
-        if (DBG) log("addSimRecordToEf: " + success);
+        if (DBG) log("addIccRecordToEf: " + success);
         return success;
     }
 
     private boolean
-    updateSimRecordInEf(int efType, String oldName, String oldNumber,
+    updateIccRecordInEf(int efType, String oldName, String oldNumber,
             String newName, String newNumber,String pin2) {
-        if (DBG) log("updateSimRecordInEf: efType=" + efType +
+        if (DBG) log("updateIccRecordInEf: efType=" + efType +
                 ", oldname=" + oldName + ", oldnumber=" + oldNumber +
                 ", newname=" + newName + ", newnumber=" + newNumber);
         boolean success = false;
 
         try {
-            ISimPhoneBook simIpb = ISimPhoneBook.Stub.asInterface(
+            IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(
                     ServiceManager.getService("simphonebook"));
-            if (simIpb != null) {
-                success = simIpb.updateAdnRecordsInEfBySearch(efType,
+            if (iccIpb != null) {
+                success = iccIpb.updateAdnRecordsInEfBySearch(efType,
                         oldName, oldNumber, newName, newNumber, pin2);
             }
         } catch (RemoteException ex) {
@@ -397,34 +402,30 @@
         } catch (SecurityException ex) {
             if (DBG) log(ex.toString());
         }
-
-        if (DBG) log("updateSimRecordInEf: " + success);
+        if (DBG) log("updateIccRecordInEf: " + success);
         return success;
     }
 
 
-    private boolean deleteSimRecordFromEf(int efType,
-                                     String name, String number,
-                                     String pin2) {
-        if (DBG) log("deleteSimRecordFromEf: efType=" + efType +
+    private boolean deleteIccRecordFromEf(int efType, String name, String number, String pin2) {
+        if (DBG) log("deleteIccRecordFromEf: efType=" + efType +
                 ", name=" + name + ", number=" + number + ", pin2=" + pin2);
 
         boolean success = false;
 
         try {
-            ISimPhoneBook simIpb = ISimPhoneBook.Stub.asInterface(
+            IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(
                     ServiceManager.getService("simphonebook"));
-            if (simIpb != null) {
-                success = simIpb.updateAdnRecordsInEfBySearch(efType,
-                    name, number, "", "", pin2);
+            if (iccIpb != null) {
+                success = iccIpb.updateAdnRecordsInEfBySearch(efType,
+                        name, number, "", "", pin2);
             }
         } catch (RemoteException ex) {
             // ignore it
         } catch (SecurityException ex) {
             if (DBG) log(ex.toString());
         }
-
-        if (DBG) log("deleteSimRecordFromEf: " + success);
+        if (DBG) log("deleteIccRecordFromEf: " + success);
         return success;
     }
 
@@ -449,7 +450,7 @@
     }
 
     private void log(String msg) {
-        Log.d(TAG, "[SimProvider] " + msg);
+        Log.d(TAG, "[IccProvider] " + msg);
     }
 
 }
diff --git a/telephony/java/com/android/internal/telephony/IccRecords.java b/telephony/java/com/android/internal/telephony/IccRecords.java
new file mode 100644
index 0000000..114094b
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IccRecords.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony;
+
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Registrant;
+import android.os.RegistrantList;
+import android.util.Log;
+
+import java.util.ArrayList;
+
+/**
+ * {@hide}
+ */
+public abstract class IccRecords extends Handler implements IccConstants {
+
+    protected static final boolean DBG = true;
+    //***** Instance Variables
+
+    protected PhoneBase phone;
+    protected RegistrantList recordsLoadedRegistrants = new RegistrantList();
+
+    protected int recordsToLoad;  // number of pending load requests
+
+    protected AdnRecordCache adnCache;
+
+    //***** Cached SIM State; cleared on channel close
+
+    protected boolean recordsRequested = false; // true if we've made requests for the sim records
+
+    public String iccid;
+    protected String msisdn = null;  // My mobile number
+    protected String msisdnTag = null;
+    protected String voiceMailNum = null;
+    protected String voiceMailTag = null;
+    protected String newVoiceMailNum = null;
+    protected String newVoiceMailTag = null;
+    protected boolean isVoiceMailFixed = false;
+    protected int countVoiceMessages = 0;
+
+    protected int mncLength = 0;   // 0 is used to indicate that the value
+                         // is not initialized
+    protected int mailboxIndex = 0; // 0 is no mailbox dailing number associated
+
+    protected String spn;
+    protected int spnDisplayCondition;
+
+    //***** Constants
+
+    // Bitmasks for SPN display rules.
+    protected static final int SPN_RULE_SHOW_SPN  = 0x01;
+    protected static final int SPN_RULE_SHOW_PLMN = 0x02;
+
+    //***** Event Constants
+    protected static final int EVENT_SET_MSISDN_DONE = 30;
+
+    //***** Constructor
+
+    public IccRecords(PhoneBase p) {
+        this.phone = p;
+    }
+
+    protected abstract void onRadioOffOrNotAvailable();
+
+    //***** Public Methods
+    public AdnRecordCache getAdnCache() {
+        return adnCache;
+    }
+
+    public void registerForRecordsLoaded(Handler h, int what, Object obj) {
+        Registrant r = new Registrant(h, what, obj);
+        recordsLoadedRegistrants.add(r);
+
+        if (recordsToLoad == 0 && recordsRequested == true) {
+            r.notifyRegistrant(new AsyncResult(null, null, null));
+        }
+    }
+
+    public void unregisterForRecordsLoaded(Handler h) {
+        recordsLoadedRegistrants.remove(h);
+    }
+
+    public String getMsisdnNumber() {
+        return msisdn;
+    }
+
+    /**
+     * Set subscriber number to SIM record
+     *
+     * The subscriber number is stored in EF_MSISDN (TS 51.011)
+     *
+     * When the operation is complete, onComplete will be sent to its handler
+     *
+     * @param alphaTag alpha-tagging of the dailing nubmer (up to 10 characters)
+     * @param number dailing nubmer (up to 20 digits)
+     *        if the number starts with '+', then set to international TOA
+     * @param onComplete
+     *        onComplete.obj will be an AsyncResult
+     *        ((AsyncResult)onComplete.obj).exception == null on success
+     *        ((AsyncResult)onComplete.obj).exception != null on fail
+     */
+    public void setMsisdnNumber(String alphaTag, String number,
+            Message onComplete) {
+
+        msisdn = number;
+        msisdnTag = alphaTag;
+
+        if(DBG) log("Set MSISDN: " + msisdnTag +" " + msisdn);
+
+
+        AdnRecord adn = new AdnRecord(msisdnTag, msisdn);
+
+        new AdnRecordLoader(phone).updateEF(adn, EF_MSISDN, EF_EXT1, 1, null,
+                obtainMessage(EVENT_SET_MSISDN_DONE, onComplete));
+    }
+
+    public String getMsisdnAlphaTag() {
+        return msisdnTag;
+    }
+
+    public String getVoiceMailNumber() {
+        return voiceMailNum;
+    }
+
+    /**
+     * Return Service Provider Name stored in SIM (EF_SPN=0x6F46) or in RUIM (EF_RUIM_SPN=0x6F41)
+     * @return null if SIM is not yet ready or no RUIM entry
+     */
+    public String getServiceProviderName() {
+        return spn;
+    }
+
+    /**
+     * Set voice mail number to SIM record
+     *
+     * The voice mail number can be stored either in EF_MBDN (TS 51.011) or
+     * EF_MAILBOX_CPHS (CPHS 4.2)
+     *
+     * If EF_MBDN is available, store the voice mail number to EF_MBDN
+     *
+     * If EF_MAILBOX_CPHS is enabled, store the voice mail number to EF_CHPS
+     *
+     * So the voice mail number will be stored in both EFs if both are available
+     *
+     * Return error only if both EF_MBDN and EF_MAILBOX_CPHS fail.
+     *
+     * When the operation is complete, onComplete will be sent to its handler
+     *
+     * @param alphaTag alpha-tagging of the dailing nubmer (upto 10 characters)
+     * @param voiceNumber dailing nubmer (upto 20 digits)
+     *        if the number is start with '+', then set to international TOA
+     * @param onComplete
+     *        onComplete.obj will be an AsyncResult
+     *        ((AsyncResult)onComplete.obj).exception == null on success
+     *        ((AsyncResult)onComplete.obj).exception != null on fail
+     */
+    public abstract void setVoiceMailNumber(String alphaTag, String voiceNumber,
+            Message onComplete);
+
+    public String getVoiceMailAlphaTag() {
+        return voiceMailTag;
+    }
+
+    /**
+     * Sets the SIM voice message waiting indicator records
+     * @param line GSM Subscriber Profile Number, one-based. Only '1' is supported
+     * @param countWaiting The number of messages waiting, if known. Use
+     *                     -1 to indicate that an unknown number of
+     *                      messages are waiting
+     */
+    public abstract void setVoiceMessageWaiting(int line, int countWaiting);
+
+    /** @return  true if there are messages waiting, false otherwise. */
+    public boolean getVoiceMessageWaiting() {
+        return countVoiceMessages != 0;
+    }
+
+    /**
+     * Returns number of voice messages waiting, if available
+     * If not available (eg, on an older CPHS SIM) -1 is returned if
+     * getVoiceMessageWaiting() is true
+     */
+    public int getCountVoiceMessages() {
+        return countVoiceMessages;
+    }
+
+    /**
+     * Called by STK Service when REFRESH is received.
+     * @param fileChanged indicates whether any files changed
+     * @param fileList if non-null, a list of EF files that changed
+     */
+    public abstract void onRefresh(boolean fileChanged, int[] fileList);
+
+
+    public boolean getRecordsLoaded() {
+        if (recordsToLoad == 0 && recordsRequested == true) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    //***** Overridden from Handler
+    public abstract void handleMessage(Message msg);
+
+    protected abstract void onRecordLoaded();
+
+    protected abstract void onAllRecordsLoaded();
+
+    /**
+     * Returns the SpnDisplayRule based on settings on the SIM and the
+     * specified plmn (currently-registered PLMN).  See TS 22.101 Annex A
+     * and TS 51.011 10.3.11 for details.
+     *
+     * If the SPN is not found on the SIM, the rule is always PLMN_ONLY.
+     */
+    protected abstract int getDisplayRule(String plmn);
+
+    protected abstract void log(String s);
+}
+
diff --git a/telephony/java/com/android/internal/telephony/IccSmsInterfaceManager.java b/telephony/java/com/android/internal/telephony/IccSmsInterfaceManager.java
new file mode 100644
index 0000000..620f2de
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IccSmsInterfaceManager.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 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.
+ * 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.internal.telephony;
+
+import android.app.PendingIntent;
+import android.content.Context;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static android.telephony.SmsManager.STATUS_ON_ICC_FREE;
+
+/**
+ * IccSmsInterfaceManager to provide an inter-process communication to
+ * access Sms in Icc.
+ */
+public abstract class IccSmsInterfaceManager extends ISms.Stub {
+    static final boolean DBG = true;
+
+    protected PhoneBase mPhone;
+    protected Context mContext;
+    protected SMSDispatcher mDispatcher;
+
+    protected IccSmsInterfaceManager(PhoneBase phone){
+        mPhone = phone;
+        mContext = phone.getContext();
+    }
+
+    protected void enforceReceiveAndSend(String message) {
+        mContext.enforceCallingPermission(
+                "android.permission.RECEIVE_SMS", message);
+        mContext.enforceCallingPermission(
+                "android.permission.SEND_SMS", message);
+    }
+
+    /**
+     * Send a Raw PDU SMS
+     *
+     * @param smsc the SMSC to send the message through, or NULL for the
+     *  defatult SMSC
+     * @param pdu the raw PDU to send
+     * @param sentIntent if not NULL this <code>Intent</code> is
+     *  broadcast when the message is sucessfully sent, or failed.
+     *  The result code will be <code>Activity.RESULT_OK<code> for success,
+     *  or one of these errors:
+     *  <code>RESULT_ERROR_GENERIC_FAILURE</code>
+     *  <code>RESULT_ERROR_RADIO_OFF</code>
+     *  <code>RESULT_ERROR_NULL_PDU</code>.
+     * @param deliveryIntent if not NULL this <code>Intent</code> is
+     *  broadcast when the message is delivered to the recipient.  The
+     *  raw pdu of the status report is in the extended data ("pdu").
+     */
+    public void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent,
+            PendingIntent deliveryIntent) {
+        Context context = mPhone.getContext();
+
+        context.enforceCallingPermission(
+                "android.permission.SEND_SMS",
+                "Sending SMS message");
+        if (DBG) log("sendRawPdu: smsc=" + smsc +
+                " pdu="+ pdu + " sentIntent" + sentIntent +
+                " deliveryIntent" + deliveryIntent);
+        mDispatcher.sendRawPdu(smsc, pdu, sentIntent, deliveryIntent);
+    }
+
+    /**
+     * Send a multi-part text based SMS.
+     *
+     * @param destinationAddress the address to send the message to
+     * @param scAddress is the service center address or null to use
+     *   the current default SMSC
+     * @param parts an <code>ArrayList</code> of strings that, in order,
+     *   comprise the original message
+     * @param sentIntents if not null, an <code>ArrayList</code> of
+     *   <code>PendingIntent</code>s (one for each message part) that is
+     *   broadcast when the corresponding message part has been sent.
+     *   The result code will be <code>Activity.RESULT_OK<code> for success,
+     *   or one of these errors:
+     *   <code>RESULT_ERROR_GENERIC_FAILURE</code>
+     *   <code>RESULT_ERROR_RADIO_OFF</code>
+     *   <code>RESULT_ERROR_NULL_PDU</code>.
+     * @param deliveryIntents if not null, an <code>ArrayList</code> of
+     *   <code>PendingIntent</code>s (one for each message part) that is
+     *   broadcast when the corresponding message part has been delivered
+     *   to the recipient.  The raw pdu of the status report is in the
+     *   extended data ("pdu").
+     */
+    public void sendMultipartText(String destinationAddress, String scAddress, List<String> parts,
+            List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents) {
+        Context context = mPhone.getContext();
+
+        context.enforceCallingPermission(
+                "android.permission.SEND_SMS",
+                "Sending SMS message");
+        if (DBG) log("sendMultipartText");
+        mDispatcher.sendMultipartText(destinationAddress, scAddress, (ArrayList<String>) parts,
+                (ArrayList<PendingIntent>) sentIntents, (ArrayList<PendingIntent>) deliveryIntents);
+    }
+
+    /**
+     * create SmsRawData lists from all sms record byte[]
+     * Use null to indicate "free" record
+     *
+     * @param messages List of message records from EF_SMS.
+     * @return SmsRawData list of all in-used records
+     */
+    protected ArrayList<SmsRawData> buildValidRawData(ArrayList<byte[]> messages) {
+        int count = messages.size();
+        ArrayList<SmsRawData> ret;
+
+        ret = new ArrayList<SmsRawData>(count);
+
+        for (int i = 0; i < count; i++) {
+            byte[] ba = messages.get(i);
+            if (ba[0] == STATUS_ON_ICC_FREE) {
+                ret.add(null);
+            } else {
+                ret.add(new SmsRawData(messages.get(i)));
+            }
+        }
+
+        return ret;
+    }
+
+    /**
+     * Generates an EF_SMS record from status and raw PDU.
+     *
+     * @param status Message status.  See TS 51.011 10.5.3.
+     * @param pdu Raw message PDU.
+     * @return byte array for the record.
+     */
+    protected byte[] makeSmsRecordData(int status, byte[] pdu) {
+        byte[] data = new byte[IccConstants.SMS_RECORD_LENGTH];
+
+        // Status bits for this record.  See TS 51.011 10.5.3
+        data[0] = (byte)(status & 7);
+
+        System.arraycopy(pdu, 0, data, 1, pdu.length);
+
+        // Pad out with 0xFF's.
+        for (int j = pdu.length+1; j < IccConstants.SMS_RECORD_LENGTH; j++) {
+            data[j] = -1;
+        }
+
+        return data;
+    }
+
+    protected abstract void log(String msg);
+
+}
+
diff --git a/telephony/java/com/android/internal/telephony/IccSmsInterfaceManagerProxy.java b/telephony/java/com/android/internal/telephony/IccSmsInterfaceManagerProxy.java
new file mode 100644
index 0000000..a51d074
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IccSmsInterfaceManagerProxy.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 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.
+ * 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.internal.telephony;
+
+import android.app.PendingIntent;
+import android.os.ServiceManager;
+
+import java.util.List;
+
+public class IccSmsInterfaceManagerProxy extends ISms.Stub {
+    private IccSmsInterfaceManager mIccSmsInterfaceManager;
+
+    public IccSmsInterfaceManagerProxy(IccSmsInterfaceManager
+            iccSmsInterfaceManager) {
+        this.mIccSmsInterfaceManager = iccSmsInterfaceManager;
+        if(ServiceManager.getService("isms") == null) {
+            ServiceManager.addService("isms", this);
+        }
+    }
+
+    public void setmIccSmsInterfaceManager(IccSmsInterfaceManager iccSmsInterfaceManager) {
+        this.mIccSmsInterfaceManager = iccSmsInterfaceManager;
+    }
+
+    public boolean
+    updateMessageOnIccEf(int index, int status, byte[] pdu) throws android.os.RemoteException {
+         return mIccSmsInterfaceManager.updateMessageOnIccEf(index, status, pdu);
+    }
+
+    public boolean copyMessageToIccEf(int status, byte[] pdu,
+            byte[] smsc) throws android.os.RemoteException {
+        return mIccSmsInterfaceManager.copyMessageToIccEf(status, pdu, smsc);
+    }
+
+    public List<SmsRawData> getAllMessagesFromIccEf() throws android.os.RemoteException {
+        return mIccSmsInterfaceManager.getAllMessagesFromIccEf();
+    }
+
+    public void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent,
+            PendingIntent deliveryIntent) throws android.os.RemoteException {
+        mIccSmsInterfaceManager.sendRawPdu(smsc, pdu, sentIntent,
+                deliveryIntent);
+    }
+
+    public void sendMultipartText(String destinationAddress, String scAddress,
+            List<String> parts, List<PendingIntent> sentIntents,
+            List<PendingIntent> deliveryIntents) throws android.os.RemoteException {
+        mIccSmsInterfaceManager.sendMultipartText(destinationAddress, scAddress,
+                parts, sentIntents, deliveryIntents);
+    }
+
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimUtils.java b/telephony/java/com/android/internal/telephony/IccUtils.java
similarity index 90%
rename from telephony/java/com/android/internal/telephony/gsm/SimUtils.java
rename to telephony/java/com/android/internal/telephony/IccUtils.java
index 2eecdba..881ed2d 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimUtils.java
+++ b/telephony/java/com/android/internal/telephony/IccUtils.java
@@ -14,48 +14,48 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
-
-import java.io.UnsupportedEncodingException;
+package com.android.internal.telephony;
 
 import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.util.Log;
 
+import com.android.internal.telephony.GsmAlphabet;
+
+import java.io.UnsupportedEncodingException;
+
 /**
  * Various methods, useful for dealing with SIM data.
  */
-public class SimUtils
-{
-    static final String LOG_TAG="GSM";
+public class IccUtils {
+    static final String LOG_TAG="IccUtils";
 
     /**
      * Many fields in GSM SIM's are stored as nibble-swizzled BCD
      *
-     * Assumes left-justified field that may be padded right with 0xf 
+     * Assumes left-justified field that may be padded right with 0xf
      * values.
      *
      * Stops on invalid BCD value, returning string so far
      */
     public static String
-    bcdToString(byte[] data, int offset, int length)
-    {
+    bcdToString(byte[] data, int offset, int length) {
         StringBuilder ret = new StringBuilder(length*2);
- 
+
         for (int i = offset ; i < offset + length ; i++) {
             byte b;
             int v;
-                        
+
             v = data[i] & 0xf;
             if (v > 9)  break;
             ret.append((char)('0' + v));
 
             v = (data[i] >> 4) & 0xf;
             if (v > 9)  break;
-            ret.append((char)('0' + v));        
+            ret.append((char)('0' + v));
         }
-        
-        return ret.toString();    
+
+        return ret.toString();
     }
 
 
@@ -66,7 +66,7 @@
      * significant nibble.
      *
      * Out-of-range digits are treated as 0 for the sake of the time stamp,
-     * because of this: 
+     * because of this:
      *
      * TS 23.040 section 9.2.3.11
      * "if the MS receives a non-integer value in the SCTS, it shall
@@ -74,13 +74,12 @@
      * exactly as received"
      */
     public static int
-    bcdByteToInt(byte b)
-    {
+    bcdByteToInt(byte b) {
         int ret = 0;
 
         // treat out-of-range BCD values as 0
         if ((b & 0xf0) <= 0x90) {
-            ret = (b >> 4) & 0xf; 
+            ret = (b >> 4) & 0xf;
         }
 
         if ((b & 0x0f) <= 0x09) {
@@ -90,6 +89,24 @@
         return ret;
     }
 
+    /** Decodes BCD byte like {@link bcdByteToInt}, but the most significant BCD
+     *  digit is expected in the most significant nibble.
+     */
+    public static int
+    beBcdByteToInt(byte b) {
+        int ret = 0;
+
+        // treat out-of-range BCD values as 0
+        if ((b & 0xf0) <= 0x90) {
+            ret = ((b >> 4) & 0xf) * 10;
+        }
+
+        if ((b & 0x0f) <= 0x09) {
+            ret +=  (b & 0xf);
+        }
+
+        return ret;
+    }
 
     /**
      * Decodes a string field that's formatted like the EF[ADN] alpha
@@ -97,11 +114,11 @@
      *
      * From TS 51.011 10.5.1:
      *   Coding:
-     *   	this alpha tagging shall use either
-     *      -	the SMS default 7 bit coded alphabet as defined in 
-     *          TS 23.038 [12] with bit 8 set to 0. The alpha identifier 
+     *       this alpha tagging shall use either
+     *      -    the SMS default 7 bit coded alphabet as defined in
+     *          TS 23.038 [12] with bit 8 set to 0. The alpha identifier
      *          shall be left justified. Unused bytes shall be set to 'FF'; or
-     *      -	one of the UCS2 coded options as defined in annex B.
+     *      -    one of the UCS2 coded options as defined in annex B.
      *
      * Annex B from TS 11.11 V8.13.0:
      *      1)  If the first octet in the alpha string is '80', then the
@@ -109,7 +126,7 @@
      *      2)  if the first octet in the alpha string is '81', then the
      *          second octet contains a value indicating the number of
      *          characters in the string, and the third octet contains an
-     *          8 bit number which defines bits 15 to 8 of a 16 bit 
+     *          8 bit number which defines bits 15 to 8 of a 16 bit
      *          base pointer, where bit 16 is set to zero and bits 7 to 1
      *          are also set to zero.  These sixteen bits constitute a
      *          base pointer to a "half page" in the UCS2 code space, to be
@@ -127,8 +144,7 @@
      *          base pointer to a "half page" in the UCS2 code space...
      */
     public static String
-    adnStringFieldToString(byte[] data, int offset, int length)
-    {
+    adnStringFieldToString(byte[] data, int offset, int length) {
         if (length >= 1) {
             if (data[offset] == (byte) 0x80) {
                 int ucslen = (length - 1) / 2;
@@ -208,8 +224,7 @@
     }
 
     static int
-    hexCharToInt(char c)
-    {
+    hexCharToInt(char c) {
         if (c >= '0' && c <= '9') return (c - '0');
         if (c >= 'A' && c <= 'F') return (c - 'A' + 10);
         if (c >= 'a' && c <= 'f') return (c - 'a' + 10);
@@ -219,17 +234,16 @@
 
     /**
      * Converts a hex String to a byte array.
-     * 
+     *
      * @param s A string of hexadecimal characters, must be an even number of
      *          chars long
      *
      * @return byte array representation
-     * 
+     *
      * @throws RuntimeException on invalid format
      */
     public static byte[]
-    hexStringToBytes(String s)
-    {
+    hexStringToBytes(String s) {
         byte[] ret;
 
         if (s == null) return null;
@@ -239,10 +253,10 @@
         ret = new byte[sz/2];
 
         for (int i=0 ; i <sz ; i+=2) {
-            ret[i/2] = (byte) ((hexCharToInt(s.charAt(i)) << 4) 
+            ret[i/2] = (byte) ((hexCharToInt(s.charAt(i)) << 4)
                                 | hexCharToInt(s.charAt(i+1)));
         }
-        
+
         return ret;
     }
 
@@ -253,10 +267,9 @@
      * null returns null
      */
     public static String
-    bytesToHexString(byte[] bytes)
-    {
+    bytesToHexString(byte[] bytes) {
         if (bytes == null) return null;
-        
+
         StringBuilder ret = new StringBuilder(2*bytes.length);
 
         for (int i = 0 ; i < bytes.length ; i++) {
@@ -281,10 +294,9 @@
      * empty string returned on decode error
      */
     public static String
-    networkNameToString(byte[] data, int offset, int length)
-    {
+    networkNameToString(byte[] data, int offset, int length) {
         String ret;
-        
+
         if ((data[offset] & 0x80) != 0x80 || length < 1) {
             return "";
         }
@@ -295,13 +307,12 @@
                 int countSeptets;
                 int unusedBits = data[offset] & 7;
                 countSeptets = (((length - 1) * 8) - unusedBits) / 7 ;
-                ret =  GsmAlphabet.gsm7BitPackedToString(
-                                data, offset + 1, countSeptets);
+                ret =  GsmAlphabet.gsm7BitPackedToString(data, offset + 1, countSeptets);
             break;
             case 1:
                 // UCS2
                 try {
-                    ret = new String(data, 
+                    ret = new String(data,
                             offset + 1, length - 1, "utf-16");
                 } catch (UnsupportedEncodingException ex) {
                     ret = "";
@@ -332,7 +343,7 @@
      * @param data The raw data
      * @param length The length of image body
      * @return The bitmap
-     */    
+     */
     public static Bitmap parseToBnW(byte[] data, int length){
         int valueIndex = 0;
         int width = data[valueIndex++] & 0xFF;
@@ -369,7 +380,7 @@
 
     /**
      * a TS 131.102 image instance of code scheme '11' into color Bitmap
-     * 
+     *
      * @param data The raw data
      * @param length the length of image body
      * @param transparency with or without transparency
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java b/telephony/java/com/android/internal/telephony/IccVmFixedException.java
similarity index 72%
copy from telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
copy to telephony/java/com/android/internal/telephony/IccVmFixedException.java
index 72790d0..45679c1 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
+++ b/telephony/java/com/android/internal/telephony/IccVmFixedException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 The Android Open Source Project
+ * Copyright (C) 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.
@@ -14,20 +14,19 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 /**
  * {@hide}
  */
-public class SimFileTypeMismatch extends SimException
-{
-    SimFileTypeMismatch()
+public final class IccVmFixedException extends IccException {
+    IccVmFixedException()
     {
 
     }
 
-    SimFileTypeMismatch(String s)
+    public IccVmFixedException(String s)
     {
         super(s);
-    }
-}
+    }    
+}
\ No newline at end of file
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java b/telephony/java/com/android/internal/telephony/IccVmNotSupportedException.java
similarity index 70%
copy from telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
copy to telephony/java/com/android/internal/telephony/IccVmNotSupportedException.java
index 72790d0..7e90d24 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimFileTypeMismatch.java
+++ b/telephony/java/com/android/internal/telephony/IccVmNotSupportedException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 The Android Open Source Project
+ * Copyright (C) 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.
@@ -14,20 +14,19 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 /**
  * {@hide}
  */
-public class SimFileTypeMismatch extends SimException
-{
-    SimFileTypeMismatch()
+public final class IccVmNotSupportedException extends IccException {
+    IccVmNotSupportedException()
     {
 
     }
 
-    SimFileTypeMismatch(String s)
+    public IccVmNotSupportedException(String s)
     {
         super(s);
-    }
+    }    
 }
diff --git a/telephony/java/com/android/internal/telephony/MmiCode.java b/telephony/java/com/android/internal/telephony/MmiCode.java
index 925b06f..c71ff77 100644
--- a/telephony/java/com/android/internal/telephony/MmiCode.java
+++ b/telephony/java/com/android/internal/telephony/MmiCode.java
@@ -41,14 +41,14 @@
      * @return Localized message for UI display, valid only in COMPLETE
      * or FAILED states. null otherwise
      */
-     
+
     public CharSequence getMessage();
 
     /**
      * Cancels pending MMI request.
      * State becomes CANCELLED unless already COMPLETE or FAILED
      */
-    public void cancel();    
+    public void cancel();
 
     /**
      * @return true if the network response is a REQUEST for more user input.
diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java
index 05e61f2..ed90d32 100644
--- a/telephony/java/com/android/internal/telephony/Phone.java
+++ b/telephony/java/com/android/internal/telephony/Phone.java
@@ -17,10 +17,14 @@
 package com.android.internal.telephony;
 
 import android.content.Context;
+import android.content.SharedPreferences;
 import android.os.Handler;
 import android.os.Message;
+import android.preference.PreferenceManager;
 import android.telephony.CellLocation;
 import android.telephony.ServiceState;
+
+import com.android.internal.telephony.DataConnection;
 import com.android.internal.telephony.gsm.NetworkInfo;
 import com.android.internal.telephony.gsm.PdpConnection;
 import com.android.internal.telephony.test.SimulatedRadioControl;
@@ -38,13 +42,13 @@
 
     /** used to enable additional debug messages */
     static final boolean DEBUG_PHONE = true;
-    
 
-    /** 
+
+    /**
      * The phone state. One of the following:<p>
      * <ul>
      * <li>IDLE = no phone activity</li>
-     * <li>RINGING = a phone call is ringing or call waiting. 
+     * <li>RINGING = a phone call is ringing or call waiting.
      *  In the latter case, another call is active as well</li>
      * <li>OFFHOOK = The phone is off hook. At least one call
      * exists that is dialing, active or holding and no calls are
@@ -70,7 +74,7 @@
         CONNECTED, CONNECTING, DISCONNECTED, SUSPENDED;
     };
 
-    enum DataActivityState {
+    public enum DataActivityState {
         /**
          * The state of a data activity.
          * <ul>
@@ -131,6 +135,8 @@
     static final String REASON_DATA_ENABLED = "dataEnabled";
     static final String REASON_GPRS_ATTACHED = "gprsAttached";
     static final String REASON_GPRS_DETACHED = "gprsDetached";
+    static final String REASON_CDMA_DATA_ATTACHED = "cdmaDataAttached";
+    static final String REASON_CDMA_DATA_DETACHED = "cdmaDataDetached";
     static final String REASON_APN_CHANGED = "apnChanged";
     static final String REASON_APN_SWITCHED = "apnSwitched";
     static final String REASON_RESTORE_DEFAULT_APN = "restoreDefaultApn";
@@ -152,12 +158,32 @@
     static final int BM_BOUNDARY    = 6; // upper band boundary
 
     // Used for preferred network type
-    static final int NT_AUTO_TYPE  = 0;  //   WCDMA preferred (auto mode)
-    static final int NT_GSM_TYPE   = 1;  //   GSM only
-    static final int NT_WCDMA_TYPE = 2;  //   WCDMA only
+    // Note NT_* substitute RILConstants.NETWORK_MODE_* above the Phone
+    int NT_MODE_WCDMA_PREF   = 0; /* GSM/WCDMA (WCDMA preferred) */
+    int NT_MODE_GSM_ONLY     = 1; /* GSM only */
+    int NT_MODE_WCDMA_ONLY   = 2; /* WCDMA only */
+    int NT_MODE_GSM_UMTS     = 3; /* GSM/WCDMA (auto mode, according to PRL)
+                                     AVAILABLE Application Settings menu*/
+    int NT_MODE_CDMA         = 4; /* CDMA and EvDo (auto mode, according to PRL)
+                                     AVAILABLE Application Settings menu*/
+    int NT_MODE_CDMA_NO_EVDO = 5; /* CDMA only */
+    int NT_MODE_EVDO_NO_CDMA = 6; /* EvDo only */
+    int NT_MODE_GLOBAL       = 7; /* GSM/WCDMA, CDMA, and EvDo (auto mode, according to PRL)
+                                     AVAILABLE Application Settings menu*/
+    int PREFERRED_NT_MODE    = NT_MODE_GLOBAL;
+
+
+    // Used for CDMA roaming mode
+    static final int CDMA_RM_HOME        = 0;  //Home Networks only, as defined in PRL
+    static final int CDMA_RM_AFFILIATED = 1;  //Roaming an Affiliated networks, as defined in PRL
+    static final int CDMA_RM_ANY        = 2;  //Roaming on Any Network, as defined in PRL
+
+    // Used for CDMA subscription mode
+    static final int CDMA_SUBSCRIPTION_RUIM_SIM    = 0; //RUIM/SIM (default)
+    static final int CDMA_SUBSCRIPTION_NV        = 1; //NV -> non-volatile memory
 
     /**
-     * Get the current ServiceState. Use 
+     * Get the current ServiceState. Use
      * <code>registerForServiceStateChanged</code> to be informed of
      * updates.
      */
@@ -167,11 +193,12 @@
      * Get the current CellLocation.
      */
     CellLocation getCellLocation();
-    
+
     /**
      * Get the current DataState. No change notification exists at this
-     * interface -- use 
-     * {@link com.android.internal.telephony.PhoneStateIntentReceiver PhoneStateIntentReceiver} instead.
+     * interface -- use
+     * {@link com.android.internal.telephony.PhoneStateIntentReceiver PhoneStateIntentReceiver}
+     * instead.
      */
     DataState getDataConnectionState();
 
@@ -181,58 +208,70 @@
      * {@link TelephonyManager} instead.
      */
     DataActivityState getDataActivityState();
-    
+
     /**
      * Gets the context for the phone, as set at initialization time.
      */
     Context getContext();
 
-    /** 
+    /**
+     * Disables the DNS check (i.e., allows "0.0.0.0").
+     * Useful for lab testing environment.
+     * @param b true disables the check, false enables.
+     */
+    void disableDnsCheck(boolean b);
+
+    /**
+     * Returns true if the DNS check is currently disabled.
+     */
+    boolean isDnsCheckDisabled();
+
+    /**
      * Get current coarse-grained voice call state.
-     * Use {@link #registerForPhoneStateChanged(Handler, int, Object) 
+     * Use {@link #registerForPhoneStateChanged(Handler, int, Object)
      * registerForPhoneStateChanged()} for change notification. <p>
      * If the phone has an active call and call waiting occurs,
      * then the phone state is RINGING not OFFHOOK
-     * <strong>Note:</strong> 
+     * <strong>Note:</strong>
      * This registration point provides notification of finer-grained
      * changes.<p>
      *
      */
     State getState();
 
-    /** 
+    /**
      * Returns a string identifier for this phone interface for parties
      *  outside the phone app process.
      *  @return The string name.
      */
     String getPhoneName();
 
-    /** 
+    /**
      * Returns an array of string identifiers for the APN types serviced by the
      * currently active or last connected APN.
      *  @return The string array.
      */
     String[] getActiveApnTypes();
-    
-    /** 
+
+    /**
      * Returns a string identifier for currently active or last connected APN.
      *  @return The string name.
      */
     String getActiveApn();
-    
-    /** 
+
+    /**
      * Get current signal strength. No change notification available on this
      * interface. Use <code>PhoneStateNotifier</code> or an equivalent.
-     * An ASU is 0-31 or -1 if unknown (for GSM, dBm = -113 - 2 * asu). 
+     * An ASU is 0-31 or -1 if unknown (for GSM, dBm = -113 - 2 * asu).
      * The following special values are defined:</p>
      * <ul><li>0 means "-113 dBm or less".</li>
      * <li>31 means "-51 dBm or greater".</li></ul>
-     * 
+     *
      * @return Current signal strength in ASU's.
      */
     int getSignalStrengthASU();
-    
-    /** 
+
+    /**
      * Notifies when a previously untracked non-ringing/waiting connection has appeared.
      * This is likely due to some other entity (eg, SIM card application) initiating a call.
      */
@@ -243,7 +282,7 @@
      */
     void unregisterForUnknownConnection(Handler h);
 
-    /** 
+    /**
      * Notifies when any aspect of the voice call state changes.
      * Resulting events will have an AsyncResult in <code>Message.obj</code>.
      * AsyncResult.userData will be set to the obj argument here.
@@ -252,13 +291,13 @@
     void registerForPhoneStateChanged(Handler h, int what, Object obj);
 
     /**
-     * Unregisters for voice call state change notifications. 
+     * Unregisters for voice call state change notifications.
      * Extraneous calls are tolerated silently.
      */
     void unregisterForPhoneStateChanged(Handler h);
 
 
-    /** 
+    /**
      * Notifies when a new ringing or waiting connection has appeared.<p>
      *
      *  Messages received from this:
@@ -267,19 +306,19 @@
      *  AsyncResult.result = a Connection. <p>
      *  Please check Connection.isRinging() to make sure the Connection
      *  has not dropped since this message was posted.
-     *  If Connection.isRinging() is true, then 
+     *  If Connection.isRinging() is true, then
      *   Connection.getCall() == Phone.getRingingCall()
      */
     void registerForNewRingingConnection(Handler h, int what, Object obj);
 
     /**
-     * Unregisters for new ringing connection notification. 
+     * Unregisters for new ringing connection notification.
      * Extraneous calls are tolerated silently
      */
 
     void unregisterForNewRingingConnection(Handler h);
 
-    /** 
+    /**
      * Notifies when an incoming call rings.<p>
      *
      *  Messages received from this:
@@ -288,29 +327,29 @@
      *  AsyncResult.result = a Connection. <p>
      */
     void registerForIncomingRing(Handler h, int what, Object obj);
-    
+
     /**
-     * Unregisters for ring notification. 
+     * Unregisters for ring notification.
      * Extraneous calls are tolerated silently
      */
-    
+
     void unregisterForIncomingRing(Handler h);
-    
-    
-    /** 
+
+
+    /**
      * Notifies when a voice connection has disconnected, either due to local
      * or remote hangup or error.
-     * 
+     *
      *  Messages received from this will have the following members:<p>
      *  <ul><li>Message.obj will be an AsyncResult</li>
      *  <li>AsyncResult.userObj = obj</li>
-     *  <li>AsyncResult.result = a Connection object that is 
+     *  <li>AsyncResult.result = a Connection object that is
      *  no longer connected.</li></ul>
      */
     void registerForDisconnect(Handler h, int what, Object obj);
 
     /**
-     * Unregisters for voice disconnection notification. 
+     * Unregisters for voice disconnection notification.
      * Extraneous calls are tolerated silently
      */
     void unregisterForDisconnect(Handler h);
@@ -330,7 +369,7 @@
     void registerForMmiInitiate(Handler h, int what, Object obj);
 
     /**
-     * Unregisters for new MMI initiate notification. 
+     * Unregisters for new MMI initiate notification.
      * Extraneous calls are tolerated silently
      */
     void unregisterForMmiInitiate(Handler h);
@@ -346,7 +385,7 @@
     void registerForMmiComplete(Handler h, int what, Object obj);
 
     /**
-     * Unregisters for MMI complete notification. 
+     * Unregisters for MMI complete notification.
      * Extraneous calls are tolerated silently
      */
     void unregisterForMmiComplete(Handler h);
@@ -355,7 +394,7 @@
      * Returns a list of MMI codes that are pending. (They have initiated
      * but have not yet completed).
      * Presently there is only ever one.
-     * Use <code>registerForMmiInitiate</code> 
+     * Use <code>registerForMmiInitiate</code>
      * and <code>registerForMmiComplete</code> for change notification.
      */
     public List<? extends MmiCode> getPendingMmiCodes();
@@ -370,14 +409,14 @@
     public void sendUssdResponse(String ussdMessge);
 
     /**
-     * Register for ServiceState changed. 
+     * Register for ServiceState changed.
      * Message.obj will contain an AsyncResult.
      * AsyncResult.result will be a ServiceState instance
      */
     void registerForServiceStateChanged(Handler h, int what, Object obj);
 
     /**
-     * Unregisters for ServiceStateChange notification. 
+     * Unregisters for ServiceStateChange notification.
      * Extraneous calls are tolerated silently
      */
     void unregisterForServiceStateChanged(Handler h);
@@ -394,9 +433,9 @@
     void registerForSuppServiceNotification(Handler h, int what, Object obj);
 
     /**
-     * Unregisters for Supplementary Service notifications. 
+     * Unregisters for Supplementary Service notifications.
      * Extraneous calls are tolerated silently
-     * 
+     *
      * @param h Handler to be removed from the registrant list.
      */
     void unregisterForSuppServiceNotification(Handler h);
@@ -414,53 +453,85 @@
     /**
      * Unregister for notifications when a supplementary service attempt fails.
      * Extraneous calls are tolerated silently
-     * 
+     *
      * @param h Handler to be removed from the registrant list.
      */
     void unregisterForSuppServiceFailed(Handler h);
 
-    /** 
-     * Returns SIM record load state. Use 
+    /**
+     * Register for notifications when a sInCall VoicePrivacy is enabled
+     *
+     * @param h Handler that receives the notification message.
+     * @param what User-defined message code.
+     * @param obj User object.
+     */
+    void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj);
+
+    /**
+     * Unegister for notifications when a sInCall VoicePrivacy is enabled
+     *
+     * @param h Handler to be removed from the registrant list.
+     */
+    void unregisterForInCallVoicePrivacyOn(Handler h);
+
+    /**
+     * Register for notifications when a sInCall VoicePrivacy is disabled
+     *
+     * @param h Handler that receives the notification message.
+     * @param what User-defined message code.
+     * @param obj User object.
+     */
+    void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj);
+
+    /**
+     * Unegister for notifications when a sInCall VoicePrivacy is disabled
+     *
+     * @param h Handler to be removed from the registrant list.
+     */
+    void unregisterForInCallVoicePrivacyOff(Handler h);
+
+    /**
+     * Returns SIM record load state. Use
      * <code>getSimCard().registerForReady()</code> for change notification.
      *
-     * @return true if records from the SIM have been loaded and are 
+     * @return true if records from the SIM have been loaded and are
      * available (if applicable). If not applicable to the underlying
      * technology, returns true as well.
      */
-    boolean getSimRecordsLoaded();
+    boolean getIccRecordsLoaded();
 
     /**
-     * Returns the SIM card interface for this phone, or null
+     * Returns the ICC card interface for this phone, or null
      * if not applicable to underlying technology.
      */
-    SimCard getSimCard();
+    IccCard getIccCard();
 
     /**
-     * Answers a ringing or waiting call. Active calls, if any, go on hold. 
+     * Answers a ringing or waiting call. Active calls, if any, go on hold.
      * Answering occurs asynchronously, and final notification occurs via
-     * {@link #registerForPhoneStateChanged(android.os.Handler, int, 
+     * {@link #registerForPhoneStateChanged(android.os.Handler, int,
      * java.lang.Object) registerForPhoneStateChanged()}.
      *
      * @exception CallStateException when no call is ringing or waiting
      */
     void acceptCall() throws CallStateException;
 
-    /** 
-     * Reject (ignore) a ringing call. In GSM, this means UDUB  
-     * (User Determined User Busy). Reject occurs asynchronously, 
-     * and final notification occurs via 
-     * {@link #registerForPhoneStateChanged(android.os.Handler, int, 
+    /**
+     * Reject (ignore) a ringing call. In GSM, this means UDUB
+     * (User Determined User Busy). Reject occurs asynchronously,
+     * and final notification occurs via
+     * {@link #registerForPhoneStateChanged(android.os.Handler, int,
      * java.lang.Object) registerForPhoneStateChanged()}.
      *
      * @exception CallStateException when no call is ringing or waiting
      */
     void rejectCall() throws CallStateException;
 
-    /** 
+    /**
      * Places any active calls on hold, and makes any held calls
      *  active. Switch occurs asynchronously and may fail.
-     * Final notification occurs via 
-     * {@link #registerForPhoneStateChanged(android.os.Handler, int, 
+     * Final notification occurs via
+     * {@link #registerForPhoneStateChanged(android.os.Handler, int,
      * java.lang.Object) registerForPhoneStateChanged()}.
      *
      * @exception CallStateException if a call is ringing, waiting, or
@@ -469,24 +540,40 @@
     void switchHoldingAndActive() throws CallStateException;
 
     /**
-     * Whether or not the phone can conference in the current phone 
+     * Whether or not the phone can conference in the current phone
      * state--that is, one call holding and one call active.
-     * @return true if the phone can conference; false otherwise. 
+     * @return true if the phone can conference; false otherwise.
      */
     boolean canConference();
 
     /**
-     * Conferences holding and active. Conference occurs asynchronously 
-     * and may fail. Final notification occurs via 
-     * {@link #registerForPhoneStateChanged(android.os.Handler, int, 
-     * java.lang.Object) registerForPhoneStateChanged()}.    
-     * 
+     * Conferences holding and active. Conference occurs asynchronously
+     * and may fail. Final notification occurs via
+     * {@link #registerForPhoneStateChanged(android.os.Handler, int,
+     * java.lang.Object) registerForPhoneStateChanged()}.
+     *
      * @exception CallStateException if canConference() would return false.
      * In these cases, this operation may not be performed.
      */
     void conference() throws CallStateException;
 
     /**
+     * Enable or disable enhanced Voice Privacy (VP). If enhanced VP is
+     * disabled, normal VP is enabled.
+     *
+     * @param enable whether true or false to enable or disable.
+     * @param onComplete a callback message when the action is completed.
+     */
+    void enableEnhancedVoicePrivacy(boolean enable, Message onComplete);
+
+    /**
+     * Get the currently set Voice Privacy (VP) mode.
+     *
+     * @param onComplete a callback message when the action is completed.
+     */
+    void getEnhancedVoicePrivacy(Message onComplete);
+
+    /**
      * Whether or not the phone can do explicit call transfer in the current
      * phone state--that is, one call holding and one call active.
      * @return true if the phone can do explicit call transfer; false otherwise.
@@ -513,65 +600,65 @@
     void clearDisconnected();
 
 
-    /** 
-     * Gets the foreground call object, which represents all connections that 
-     * are dialing or active (all connections 
+    /**
+     * Gets the foreground call object, which represents all connections that
+     * are dialing or active (all connections
      * that have their audio path connected).<p>
      *
      * The foreground call is a singleton object. It is constant for the life
      * of this phone. It is never null.<p>
-     * 
+     *
      * The foreground call will only ever be in one of these states:
-     * IDLE, ACTIVE, DIALING, ALERTING, or DISCONNECTED. 
+     * IDLE, ACTIVE, DIALING, ALERTING, or DISCONNECTED.
      *
      * State change notification is available via
-     * {@link #registerForPhoneStateChanged(android.os.Handler, int, 
+     * {@link #registerForPhoneStateChanged(android.os.Handler, int,
      * java.lang.Object) registerForPhoneStateChanged()}.
      */
     Call getForegroundCall();
 
-    /** 
+    /**
      * Gets the background call object, which represents all connections that
      * are holding (all connections that have been accepted or connected, but
      * do not have their audio path connected). <p>
      *
      * The background call is a singleton object. It is constant for the life
      * of this phone object . It is never null.<p>
-     * 
+     *
      * The background call will only ever be in one of these states:
      * IDLE, HOLDING or DISCONNECTED.
      *
      * State change notification is available via
-     * {@link #registerForPhoneStateChanged(android.os.Handler, int, 
+     * {@link #registerForPhoneStateChanged(android.os.Handler, int,
      * java.lang.Object) registerForPhoneStateChanged()}.
      */
     Call getBackgroundCall();
 
-    /** 
-     * Gets the ringing call object, which represents an incoming 
+    /**
+     * Gets the ringing call object, which represents an incoming
      * connection (if present) that is pending answer/accept. (This connection
      * may be RINGING or WAITING, and there may be only one.)<p>
 
      * The ringing call is a singleton object. It is constant for the life
      * of this phone. It is never null.<p>
-     * 
+     *
      * The ringing call will only ever be in one of these states:
      * IDLE, INCOMING, WAITING or DISCONNECTED.
      *
      * State change notification is available via
-     * {@link #registerForPhoneStateChanged(android.os.Handler, int, 
+     * {@link #registerForPhoneStateChanged(android.os.Handler, int,
      * java.lang.Object) registerForPhoneStateChanged()}.
      */
     Call getRingingCall();
 
-    /** 
+    /**
      * Initiate a new voice connection. This happens asynchronously, so you
      * cannot assume the audio path is connected (or a call index has been
      * assigned) until PhoneStateChanged notification has occurred.
      *
      * @exception CallStateException if a new outgoing call is not currently
-     * possible because no more call slots exist or a call exists that is 
-     * dialing, alerting, ringing, or waiting.  Other errors are 
+     * possible because no more call slots exist or a call exists that is
+     * dialing, alerting, ringing, or waiting.  Other errors are
      * handled asynchronously.
      */
     Connection dial(String dialString) throws CallStateException;
@@ -579,7 +666,7 @@
     /**
      * Handles PIN MMI commands (PIN/PIN2/PUK/PUK2), which are initiated
      * without SEND (so <code>dial</code> is not appropriate).
-     * 
+     *
      * @param dialString the MMI command to be executed.
      * @return true if MMI command is executed.
      */
@@ -597,7 +684,7 @@
     boolean handleInCallMmiCommands(String command) throws CallStateException;
 
     /**
-     * Play a DTMF tone on the active call. Ignored if there is no active call. 
+     * Play a DTMF tone on the active call. Ignored if there is no active call.
      * @param c should be one of 0-9, '*' or '#'. Other values will be
      * silently ignored.
      */
@@ -619,20 +706,20 @@
 
 
     /**
-     * Sets the radio power on/off state (off is sometimes 
-     * called "airplane mode"). Current state can be gotten via 
-     * {@link #getServiceState()}.{@link 
+     * Sets the radio power on/off state (off is sometimes
+     * called "airplane mode"). Current state can be gotten via
+     * {@link #getServiceState()}.{@link
      * android.telephony.ServiceState#getState() getState()}.
-     * <strong>Note: </strong>This request is asynchronous. 
+     * <strong>Note: </strong>This request is asynchronous.
      * getServiceState().getState() will not change immediately after this call.
-     * registerForServiceStateChanged() to find out when the 
+     * registerForServiceStateChanged() to find out when the
      * request is complete.
      *
-     * @param power true means "on", false means "off". 
+     * @param power true means "on", false means "off".
      */
     void setRadioPower(boolean power);
 
-    /** 
+    /**
      * Get voice message waiting indicator status. No change notification
      * available on this interface. Use PhoneStateNotifier or similar instead.
      *
@@ -674,8 +761,8 @@
     void setLine1Number(String alphaTag, String number, Message onComplete);
 
     /**
-     * Get the voice mail access phone number. Typically dialed when the 
-     * user holds the "1" key in the phone app. May return null if not 
+     * Get the voice mail access phone number. Typically dialed when the
+     * user holds the "1" key in the phone app. May return null if not
      * available or the SIM is not ready.<p>
      */
     String getVoiceMailNumber();
@@ -684,8 +771,8 @@
      * Returns the alpha tag associated with the voice mail number.
      * If there is no alpha tag associated or the record is not yet available,
      * returns a default localized string. <p>
-     * 
-     * Please use this value instead of some other localized string when 
+     *
+     * Please use this value instead of some other localized string when
      * showing a name for this number in the UI. For example, call log
      * entries should show this alpha tag. <p>
      *
@@ -708,29 +795,29 @@
 
     /**
      * getCallForwardingOptions
-     * gets a call forwarding option. The return value of 
-     * ((AsyncResult)onComplete.obj) is an array of CallForwardInfo. 
-     * 
-     * @param commandInterfaceCFReason is one of the valid call forwarding 
-     *        CF_REASONS, as defined in 
-     *        <code>com.android.internal.telephony.gsm.CommandsInterface</code>
+     * gets a call forwarding option. The return value of
+     * ((AsyncResult)onComplete.obj) is an array of CallForwardInfo.
+     *
+     * @param commandInterfaceCFReason is one of the valid call forwarding
+     *        CF_REASONS, as defined in
+     *        <code>com.android.internal.telephony.CommandsInterface./code>
      * @param onComplete a callback message when the action is completed.
-     *        @see com.android.internal.telephony.gsm.CallForwardInfo for details.
+     *        @see com.android.internal.telephony.CallForwardInfo for details.
      */
     void getCallForwardingOption(int commandInterfaceCFReason,
                                   Message onComplete);
-    
+
     /**
      * setCallForwardingOptions
      * sets a call forwarding option.
-     * 
-     * @param commandInterfaceCFReason is one of the valid call forwarding 
-     *        CF_REASONS, as defined in 
-     *        <code>com.android.internal.telephony.gsm.CommandsInterface</code>
-     * @param commandInterfaceCFAction is one of the valid call forwarding 
-     *        CF_ACTIONS, as defined in 
-     *        <code>com.android.internal.telephony.gsm.CommandsInterface</code>
-     * @param dialingNumber is the target phone number to forward calls to 
+     *
+     * @param commandInterfaceCFReason is one of the valid call forwarding
+     *        CF_REASONS, as defined in
+     *        <code>com.android.internal.telephony.CommandsInterface./code>
+     * @param commandInterfaceCFAction is one of the valid call forwarding
+     *        CF_ACTIONS, as defined in
+     *        <code>com.android.internal.telephony.CommandsInterface./code>
+     * @param dialingNumber is the target phone number to forward calls to
      * @param timerSeconds is used by CFNRy to indicate the timeout before
      *        forwarding is attempted.
      * @param onComplete a callback message when the action is completed.
@@ -740,83 +827,83 @@
                                  String dialingNumber,
                                  int timerSeconds,
                                  Message onComplete);
-    
+
     /**
      * getOutgoingCallerIdDisplay
-     * gets outgoing caller id display. The return value of 
+     * gets outgoing caller id display. The return value of
      * ((AsyncResult)onComplete.obj) is an array of int, with a length of 2.
-     * 
+     *
      * @param onComplete a callback message when the action is completed.
-     *        @see com.android.internal.telephony.gsm.CommandsInterface.getCLIR for details.
+     *        @see com.android.internal.telephony.CommandsInterface.getCLIR for details.
      */
     void getOutgoingCallerIdDisplay(Message onComplete);
-    
+
     /**
      * setOutgoingCallerIdDisplay
-     * sets a call forwarding option. 
-     * 
-     * @param commandInterfaceCLIRMode is one of the valid call CLIR 
-     *        modes, as defined in 
-     *        <code>com.android.internal.telephony.gsm.CommandsInterface</code>
+     * sets a call forwarding option.
+     *
+     * @param commandInterfaceCLIRMode is one of the valid call CLIR
+     *        modes, as defined in
+     *        <code>com.android.internal.telephony.CommandsInterface./code>
      * @param onComplete a callback message when the action is completed.
      */
     void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode,
                                     Message onComplete);
-    
+
     /**
      * getCallWaiting
-     * gets call waiting activation state. The return value of 
+     * gets call waiting activation state. The return value of
      * ((AsyncResult)onComplete.obj) is an array of int, with a length of 1.
-     * 
+     *
      * @param onComplete a callback message when the action is completed.
-     *        @see com.android.internal.telephony.gsm.CommandsInterface.queryCallWaiting for details.
+     *        @see com.android.internal.telephony.CommandsInterface.queryCallWaiting for details.
      */
     void getCallWaiting(Message onComplete);
-    
+
     /**
      * setCallWaiting
-     * sets a call forwarding option. 
-     * 
-     * @param enable is a boolean representing the state that you are 
+     * sets a call forwarding option.
+     *
+     * @param enable is a boolean representing the state that you are
      *        requesting, true for enabled, false for disabled.
      * @param onComplete a callback message when the action is completed.
      */
     void setCallWaiting(boolean enable, Message onComplete);
-    
+
     /**
      * Scan available networks. This method is asynchronous; .
      * On completion, <code>response.obj</code> is set to an AsyncResult with
      * one of the following members:.<p>
      *<ul>
-     * <li><code>response.obj.result</code> will be a <code>List</code> of 
-     * <code>com.android.internal.telephony.gsm.NetworkInfo</code> objects, or</li> 
-     * <li><code>response.obj.exception</code> will be set with an exception 
+     * <li><code>response.obj.result</code> will be a <code>List</code> of
+     * <code>com.android.internal.telephony.gsm.NetworkInfo</code> objects, or</li>
+     * <li><code>response.obj.exception</code> will be set with an exception
      * on failure.</li>
      * </ul>
      */
-    void getAvailableNetworks(Message response);    
+    void getAvailableNetworks(Message response);
 
     /**
      * Switches network selection mode to "automatic", re-scanning and
      * re-selecting a network if appropriate.
-     * 
-     * @param response The message to dispatch when the network selection 
+     *
+     * @param response The message to dispatch when the network selection
      * is complete.
-     * 
-     * @see #selectNetworkManually(com.android.internal.telephony.gsm.NetworkInfo, 
+     *
+     * @see #selectNetworkManually(com.android.internal.telephony.gsm.NetworkInfo,
      * android.os.Message )
      */
     void setNetworkSelectionModeAutomatic(Message response);
 
     /**
-     * Manually selects a network. <code>response</code> is 
+     * Manually selects a network. <code>response</code> is
      * dispatched when this is complete.  <code>response.obj</code> will be
      * an AsyncResult, and <code>response.obj.exception</code> will be non-null
      * on failure.
-     * 
+     *
      * @see #setNetworkSelectionModeAutomatic(Message)
      */
-    void selectNetworkManually(NetworkInfo network, 
+    void selectNetworkManually(NetworkInfo network,
                             Message response);
 
     /**
@@ -843,7 +930,7 @@
      * of available cell IDs.  Cell IDs are in hexadecimal format.
      *
      * @param response callback message that is dispatched when the query
-     * completes. 
+     * completes.
      */
     void getNeighboringCids(Message response);
 
@@ -856,28 +943,28 @@
      * <code>AsyncResult</code>. <code>Message.obj.result</code> will be
      * a Connection object.<p>
      *
-     * Message.arg1 will be the post dial character being processed, 
+     * Message.arg1 will be the post dial character being processed,
      * or 0 ('\0') if end of string.<p>
      *
-     * If Connection.getPostDialState() == WAIT, 
-     * the application must call 
-     * {@link com.android.internal.telephony.Connection#proceedAfterWaitChar() 
-     * Connection.proceedAfterWaitChar()} or 
-     * {@link com.android.internal.telephony.Connection#cancelPostDial() 
+     * If Connection.getPostDialState() == WAIT,
+     * the application must call
+     * {@link com.android.internal.telephony.Connection#proceedAfterWaitChar()
+     * Connection.proceedAfterWaitChar()} or
+     * {@link com.android.internal.telephony.Connection#cancelPostDial()
      * Connection.cancelPostDial()}
-     * for the telephony system to continue playing the post-dial 
+     * for the telephony system to continue playing the post-dial
      * DTMF sequence.<p>
      *
-     * If Connection.getPostDialState() == WILD, 
-     * the application must call 
+     * If Connection.getPostDialState() == WILD,
+     * the application must call
      * {@link com.android.internal.telephony.Connection#proceedAfterWildChar
      * Connection.proceedAfterWildChar()}
-     * or 
-     * {@link com.android.internal.telephony.Connection#cancelPostDial() 
+     * or
+     * {@link com.android.internal.telephony.Connection#cancelPostDial()
      * Connection.cancelPostDial()}
-     * for the telephony system to continue playing the 
+     * for the telephony system to continue playing the
      * post-dial DTMF sequence.<p>
-     * 
+     *
      * Only one post dial character handler may be set. <p>
      * Calling this method with "h" equal to null unsets this handler.<p>
      */
@@ -885,19 +972,19 @@
 
 
     /**
-     * Mutes or unmutes the microphone for the active call. The microphone 
-     * is automatically unmuted if a call is answered, dialed, or resumed 
+     * Mutes or unmutes the microphone for the active call. The microphone
+     * is automatically unmuted if a call is answered, dialed, or resumed
      * from a holding state.
-     * 
-     * @param muted true to mute the microphone, 
+     *
+     * @param muted true to mute the microphone,
      * false to activate the microphone.
      */
 
     void setMute(boolean muted);
 
     /**
-     * Gets current mute status. Use 
-     * {@link #registerForPhoneStateChanged(android.os.Handler, int, 
+     * Gets current mute status. Use
+     * {@link #registerForPhoneStateChanged(android.os.Handler, int,
      * java.lang.Object) registerForPhoneStateChanged()}
      * as a change notifcation, although presently phone state changed is not
      * fired when setMute() is called.
@@ -908,12 +995,12 @@
 
     /**
      * Invokes RIL_REQUEST_OEM_HOOK_RAW on RIL implementation.
-     * 
+     *
      * @param data The data for the request.
-     * @param response <strong>On success</strong>, 
+     * @param response <strong>On success</strong>,
      * (byte[])(((AsyncResult)response.obj).result)
-     * <strong>On failure</strong>, 
-     * (((AsyncResult)response.obj).result) == null and 
+     * <strong>On failure</strong>,
+     * (((AsyncResult)response.obj).result) == null and
      * (((AsyncResult)response.obj).exception) being an instance of
      * com.android.internal.telephony.gsm.CommandException
      *
@@ -923,13 +1010,13 @@
 
     /**
      * Invokes RIL_REQUEST_OEM_HOOK_Strings on RIL implementation.
-     * 
+     *
      * @param strings The strings to make available as the request data.
-     * @param response <strong>On success</strong>, "response" bytes is 
+     * @param response <strong>On success</strong>, "response" bytes is
      * made available as:
      * (String[])(((AsyncResult)response.obj).result).
-     * <strong>On failure</strong>, 
-     * (((AsyncResult)response.obj).result) == null and 
+     * <strong>On failure</strong>,
+     * (((AsyncResult)response.obj).result) == null and
      * (((AsyncResult)response.obj).exception) being an instance of
      * com.android.internal.telephony.gsm.CommandException
      *
@@ -940,6 +1027,7 @@
     /**
      * Get the current active PDP context list
      *
+     * @deprecated
      * @param response <strong>On success</strong>, "response" bytes is
      * made available as:
      * (String[])(((AsyncResult)response.obj).result).
@@ -951,13 +1039,34 @@
     void getPdpContextList(Message response);
 
     /**
+     * Get the current active Data Call list, substitutes getPdpContextList
+     *
+     * @param response <strong>On success</strong>, "response" bytes is
+     * made available as:
+     * (String[])(((AsyncResult)response.obj).result).
+     * <strong>On failure</strong>,
+     * (((AsyncResult)response.obj).result) == null and
+     * (((AsyncResult)response.obj).exception) being an instance of
+     * com.android.internal.telephony.gsm.CommandException
+     */
+    void getDataCallList(Message response);
+
+    /**
      * Get current mutiple PDP link status
-     * 
+     *
+     * @deprecated
      * @return list of pdp link connections
      */
     List<PdpConnection> getCurrentPdpList ();
 
     /**
+     * Get current mutiple data connection status
+     *
+     * @return list of data connections
+     */
+    List<DataConnection> getCurrentDataConnectionList ();
+
+    /**
      * Udpate LAC and CID in service state for currnet GSM netowrk registration
      *
      * If get different LAC and/or CID, notifyServiceState will be sent
@@ -981,11 +1090,11 @@
     void disableLocationUpdates();
 
     /**
-     * For unit tests; don't send notifications to "Phone" 
+     * For unit tests; don't send notifications to "Phone"
      * mailbox registrants if true.
      */
     void setUnitTestMode(boolean f);
-    
+
     /**
      * @return true If unit test mode is enabled
      */
@@ -1019,8 +1128,29 @@
     void setDataRoamingEnabled(boolean enable);
 
     /**
+     *  Query the CDMA roaming preference setting
+     *
+     * @param response is callback message to report one of  CDMA_RM_*
+     */
+    void queryCdmaRoamingPreference(Message response);
+
+    /**
+     *  Requests to set the CDMA roaming preference
+     * @param cdmaRoamingType one of  CDMA_RM_*
+     * @param response is callback message
+     */
+    void setCdmaRoamingPreference(int cdmaRoamingType, Message response);
+
+    /**
+     *  Requests to set the CDMA subscription mode
+     * @param cdmaSubscriptionType one of  CDMA_SUBSCRIPTION_*
+     * @param response is callback message
+     */
+    void setCdmaSubscription(int cdmaSubscriptionType, Message response);
+
+    /**
      * If this is a simulated phone interface, returns a SimulatedRadioControl.
-     * @ return A SimulatedRadioControl if this is a simulated interface; 
+     * @ return A SimulatedRadioControl if this is a simulated interface;
      * otherwise, null.
      */
     SimulatedRadioControl getSimulatedRadioControl();
@@ -1109,7 +1239,7 @@
     public String[] getDnsServers(String apnType);
 
     /**
-     * Retrieves the unique device ID, e.g., IMEI for GSM phones.
+     * Retrieves the unique device ID, e.g., IMEI for GSM phones and MEID for CDMA phones.
      */
     String getDeviceId();
 
@@ -1125,7 +1255,81 @@
     String getSubscriberId();
 
     /**
-     * Retrieves the serial number of the SIM, if applicable.
+     * Retrieves the serial number of the ICC, if applicable.
      */
-    String getSimSerialNumber();
+    String getIccSerialNumber();
+
+    //***** CDMA support methods
+
+
+    /**
+     * Retrieves the ESN for CDMA phones.
+     */
+    String getEsn();
+
+    /**
+     * Retrieves MEID for CDMA phones.
+     */
+    String getMeid();
+
+    /**
+     * Retrieves the PhoneSubInfo of the Phone
+     */
+    public PhoneSubInfo getPhoneSubInfo();
+
+    /**
+     * Retrieves the IccSmsInterfaceManager of the Phone
+     */
+    public IccSmsInterfaceManager getIccSmsInterfaceManager();
+
+    /**
+     * Retrieves the IccPhoneBookInterfaceManager of the Phone
+     */
+    public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager();
+
+    /**
+     * setTTYModeEnabled
+     * sets a TTY mode option.
+     *
+     * @param enable is a boolean representing the state that you are
+     *        requesting, true for enabled, false for disabled.
+     * @param onComplete a callback message when the action is completed
+     */
+    void setTTYModeEnabled(boolean enable, Message onComplete);
+
+    /**
+     * queryTTYModeEnabled
+     * query the status of the TTY mode
+     *
+     * @param onComplete a callback message when the action is completed.
+     */
+    void queryTTYModeEnabled(Message onComplete);
+
+    /**
+     * Activate or deactivate cell broadcast SMS.
+     *
+     * @param activate
+     *            0 = activate, 1 = deactivate
+     * @param response
+     *            Callback message is empty on completion
+     */
+    void activateCellBroadcastSms(int activate, Message response);
+
+    /**
+     * Query the current configuration of cdma cell broadcast SMS.
+     *
+     * @param response
+     *            Callback message is empty on completion
+     */
+    void getCellBroadcastSmsConfig(Message response);
+
+    /**
+     * Configure cell broadcast SMS.
+     *
+     * @param response
+     *            Callback message is empty on completion
+     */
+    public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response);
+
+    public void notifyDataActivity();
 }
diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java
index 4fb5f61..259de62 100644
--- a/telephony/java/com/android/internal/telephony/PhoneBase.java
+++ b/telephony/java/com/android/internal/telephony/PhoneBase.java
@@ -20,23 +20,30 @@
 import android.app.IActivityManager;
 import android.content.Context;
 import android.content.res.Configuration;
+import android.content.SharedPreferences;
 import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.Looper;
+import android.os.Message;
 import android.os.RegistrantList;
 import android.os.SystemProperties;
+import android.preference.PreferenceManager;
 import android.telephony.ServiceState;
+import android.text.TextUtils;
 import android.util.Log;
+
 import com.android.internal.R;
+import com.android.internal.telephony.gsm.PdpConnection;
 import com.android.internal.telephony.test.SimulatedRadioControl;
 
 import java.util.List;
 import java.util.Locale;
 
+
 /**
- * (<em>Not for SDK use</em>) 
+ * (<em>Not for SDK use</em>)
  * A base implementation for the com.android.internal.telephony.Phone interface.
- * 
+ *
  * Note that implementations of Phone.java are expected to be used
  * from a single application thread. This should be the same thread that
  * originally called PhoneFactory to obtain the interface.
@@ -46,42 +53,101 @@
  */
 
 public abstract class PhoneBase implements Phone {
-    private static final String LOG_TAG = "GSM";
+    private static final String LOG_TAG = "PHONE";
+    private static final boolean LOCAL_DEBUG = true;
 
-    protected final RegistrantList mPhoneStateRegistrants 
+    // Key used to read and write the saved network selection value
+    public static final String NETWORK_SELECTION_KEY = "network_selection_key";
+
+ // Key used to read/write "disable data connection on boot" pref (used for testing)
+    public static final String DATA_DISABLED_ON_BOOT_KEY = "disabled_on_boot_key";
+
+    //***** Event Constants
+    protected static final int EVENT_RADIO_AVAILABLE             = 1;
+    /** Supplementary Service Notification received. */
+    protected static final int EVENT_SSN                         = 2;
+    protected static final int EVENT_SIM_RECORDS_LOADED          = 3;
+    protected static final int EVENT_MMI_DONE                    = 4;
+    protected static final int EVENT_RADIO_ON                    = 5;
+    protected static final int EVENT_GET_BASEBAND_VERSION_DONE   = 6;
+    protected static final int EVENT_USSD                        = 7;
+    protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE  = 8;
+    protected static final int EVENT_GET_IMEI_DONE               = 9;
+    protected static final int EVENT_GET_IMEISV_DONE             = 10;
+    protected static final int EVENT_GET_SIM_STATUS_DONE         = 11;
+    protected static final int EVENT_SET_CALL_FORWARD_DONE       = 12;
+    protected static final int EVENT_GET_CALL_FORWARD_DONE       = 13;
+    protected static final int EVENT_CALL_RING                   = 14;
+    // Used to intercept the carrier selection calls so that
+    // we can save the values.
+    protected static final int EVENT_SET_NETWORK_MANUAL_COMPLETE    = 15;
+    protected static final int EVENT_SET_NETWORK_AUTOMATIC_COMPLETE = 16;
+    protected static final int EVENT_SET_CLIR_COMPLETE              = 17;
+    protected static final int EVENT_REGISTERED_TO_NETWORK          = 18;
+    protected static final int EVENT_SET_VM_NUMBER_DONE             = 19;
+    // Events for CDMA support
+    protected static final int EVENT_GET_DEVICE_IDENTITY_DONE       = 20;
+    protected static final int EVENT_RUIM_RECORDS_LOADED            = 21;
+    protected static final int EVENT_NV_READY                       = 22;
+    protected static final int EVENT_SET_ENHANCED_VP                = 23;
+
+    // Key used to read/write current CLIR setting
+    public static final String CLIR_KEY = "clir_key";
+
+    // Key used to read/write "disable DNS server check" pref (used for testing)
+    public static final String DNS_SERVER_CHECK_DISABLED_KEY = "dns_server_check_disabled_key";
+
+    //***** Instance Variables
+    public CommandsInterface mCM;
+    protected IccFileHandler mIccFileHandler;
+    boolean mDnsCheckDisabled = false;
+
+    /**
+     * Set a system property, unless we're in unit test mode
+     */
+    public void
+    setSystemProperty(String property, String value) {
+        if(getUnitTestMode()) {
+            return;
+        }
+        SystemProperties.set(property, value);
+    }
+
+
+    protected final RegistrantList mPhoneStateRegistrants
             = new RegistrantList();
 
-    protected final RegistrantList mNewRingingConnectionRegistrants 
+    protected final RegistrantList mNewRingingConnectionRegistrants
             = new RegistrantList();
 
-    protected final RegistrantList mIncomingRingRegistrants 
-            = new RegistrantList();
-    
-    protected final RegistrantList mDisconnectRegistrants 
+    protected final RegistrantList mIncomingRingRegistrants
             = new RegistrantList();
 
-    protected final RegistrantList mServiceStateRegistrants 
-            = new RegistrantList();
-    
-    protected final RegistrantList mMmiCompleteRegistrants 
+    protected final RegistrantList mDisconnectRegistrants
             = new RegistrantList();
 
-    protected final RegistrantList mMmiRegistrants 
+    protected final RegistrantList mServiceStateRegistrants
             = new RegistrantList();
 
-    protected final RegistrantList mUnknownConnectionRegistrants 
+    protected final RegistrantList mMmiCompleteRegistrants
             = new RegistrantList();
-    
-    protected final RegistrantList mSuppServiceFailedRegistrants 
+
+    protected final RegistrantList mMmiRegistrants
             = new RegistrantList();
-    
+
+    protected final RegistrantList mUnknownConnectionRegistrants
+            = new RegistrantList();
+
+    protected final RegistrantList mSuppServiceFailedRegistrants
+            = new RegistrantList();
+
     protected Looper mLooper; /* to insure registrants are in correct thread*/
 
     protected Context mContext;
 
-    /** 
-     * PhoneNotifier is an abstraction for all system-wide 
-     * state change notification. DefaultPhoneNotifier is 
+    /**
+     * PhoneNotifier is an abstraction for all system-wide
+     * state change notification. DefaultPhoneNotifier is
      * used here unless running we're inside a unit test.
      */
     protected PhoneNotifier mNotifier;
@@ -94,7 +160,7 @@
      * Constructs a PhoneBase in normal (non-unit test) mode.
      *
      * @param context Context object from hosting application
-     * @param notifier An instance of DefaultPhoneNotifier, 
+     * @param notifier An instance of DefaultPhoneNotifier,
      * unless unit testing.
      */
     protected PhoneBase(PhoneNotifier notifier, Context context) {
@@ -105,13 +171,13 @@
      * Constructs a PhoneBase in normal (non-unit test) mode.
      *
      * @param context Context object from hosting application
-     * @param notifier An instance of DefaultPhoneNotifier, 
+     * @param notifier An instance of DefaultPhoneNotifier,
      * unless unit testing.
-     * @param unitTestMode when true, prevents notifications 
+     * @param unitTestMode when true, prevents notifications
      * of state change events
      */
-    protected PhoneBase(PhoneNotifier notifier, Context context, 
-                         boolean unitTestMode) {
+    protected PhoneBase(PhoneNotifier notifier, Context context,
+            boolean unitTestMode) {
         this.mNotifier = notifier;
         this.mContext = context;
         mLooper = Looper.myLooper();
@@ -119,6 +185,9 @@
         setLocaleByCarrier();
 
         setUnitTestMode(unitTestMode);
+
+        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
+        mDnsCheckDisabled = sp.getBoolean(DNS_SERVER_CHECK_DISABLED_KEY, false);        
     }
 
     // Inherited documentation suffices.
@@ -126,6 +195,26 @@
         return mContext;
     }
 
+    /**
+     * Disables the DNS check (i.e., allows "0.0.0.0").
+     * Useful for lab testing environment.
+     * @param b true disables the check, false enables.
+     */
+    public void disableDnsCheck(boolean b) {
+        mDnsCheckDisabled = b;
+        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
+        SharedPreferences.Editor editor = sp.edit();
+        editor.putBoolean(DNS_SERVER_CHECK_DISABLED_KEY, b);        
+        editor.commit();
+    }
+
+    /**
+     * Returns true if the DNS check is currently disabled.
+     */
+    public boolean isDnsCheckDisabled() {
+        return mDnsCheckDisabled;
+    }
+
     // Inherited documentation suffices.
     public void registerForPhoneStateChanged(Handler h, int what, Object obj) {
         checkCorrectThread(h);
@@ -137,29 +226,29 @@
     public void unregisterForPhoneStateChanged(Handler h) {
         mPhoneStateRegistrants.remove(h);
     }
-    
+
     /**
      * Notify registrants of a PhoneStateChanged.
-     * Subclasses of Phone probably want to replace this with a 
+     * Subclasses of Phone probably want to replace this with a
      * version scoped to their packages
      */
     protected void notifyCallStateChangedP() {
         AsyncResult ar = new AsyncResult(null, this, null);
         mPhoneStateRegistrants.notifyRegistrants(ar);
     }
-     
+
     // Inherited documentation suffices.
     public void registerForUnknownConnection(Handler h, int what, Object obj) {
         checkCorrectThread(h);
-        
+
         mUnknownConnectionRegistrants.addUnique(h, what, obj);
     }
-    
+
     // Inherited documentation suffices.
     public void unregisterForUnknownConnection(Handler h) {
         mUnknownConnectionRegistrants.remove(h);
     }
-    
+
     // Inherited documentation suffices.
     public void registerForNewRingingConnection(
             Handler h, int what, Object obj) {
@@ -173,12 +262,33 @@
         mNewRingingConnectionRegistrants.remove(h);
     }
 
+    // Inherited documentation suffices.
+    public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj){
+        mCM.registerForInCallVoicePrivacyOn(h,what,obj);
+    }
+
+    // Inherited documentation suffices.
+    public void unregisterForInCallVoicePrivacyOn(Handler h){
+        mCM.unregisterForInCallVoicePrivacyOn(h);
+    }
+
+    // Inherited documentation suffices.
+    public void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj){
+        mCM.registerForInCallVoicePrivacyOff(h,what,obj);
+    }
+
+    // Inherited documentation suffices.
+    public void unregisterForInCallVoicePrivacyOff(Handler h){
+        mCM.unregisterForInCallVoicePrivacyOff(h);
+    }
+
+
     /**
      * Notifiy registrants of a new ringing Connection.
-     * Subclasses of Phone probably want to replace this with a 
+     * Subclasses of Phone probably want to replace this with a
      * version scoped to their packages
      */
-    protected void notifyNewRingingConnectionP(Connection cn) {    
+    protected void notifyNewRingingConnectionP(Connection cn) {
         AsyncResult ar = new AsyncResult(null, cn, null);
         mNewRingingConnectionRegistrants.notifyRegistrants(ar);
     }
@@ -187,15 +297,15 @@
     public void registerForIncomingRing(
             Handler h, int what, Object obj) {
         checkCorrectThread(h);
-        
+
         mIncomingRingRegistrants.addUnique(h, what, obj);
     }
-    
+
     // Inherited documentation suffices.
     public void unregisterForIncomingRing(Handler h) {
         mIncomingRingRegistrants.remove(h);
     }
-    
+
     // Inherited documentation suffices.
     public void registerForDisconnect(Handler h, int what, Object obj) {
         checkCorrectThread(h);
@@ -211,15 +321,15 @@
     // Inherited documentation suffices.
     public void registerForSuppServiceFailed(Handler h, int what, Object obj) {
         checkCorrectThread(h);
-        
+
         mSuppServiceFailedRegistrants.addUnique(h, what, obj);
     }
-    
+
     // Inherited documentation suffices.
     public void unregisterForSuppServiceFailed(Handler h) {
         mSuppServiceFailedRegistrants.remove(h);
     }
-    
+
     // Inherited documentation suffices.
     public void registerForMmiInitiate(Handler h, int what, Object obj) {
         checkCorrectThread(h);
@@ -231,7 +341,7 @@
     public void unregisterForMmiInitiate(Handler h) {
         mMmiRegistrants.remove(h);
     }
-    
+
     // Inherited documentation suffices.
     public void registerForMmiComplete(Handler h, int what, Object obj) {
         checkCorrectThread(h);
@@ -247,10 +357,31 @@
     }
 
     /**
-     * Subclasses should override this. See documentation in superclass.
+     * Method to retrieve the saved operator id from the Shared Preferences
      */
-    public abstract List getPendingMmiCodes();
-    
+    private String getSavedNetworkSelection() {
+        // open the shared preferences and search with our key.
+        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
+        return sp.getString(NETWORK_SELECTION_KEY, "");
+    }
+
+    /**
+     * Method to restore the previously saved operator id, or reset to
+     * automatic selection, all depending upon the value in the shared
+     * preferences.
+     */
+    public void restoreSavedNetworkSelection(Message response) {
+        // retrieve the operator id
+        String networkSelection = getSavedNetworkSelection();
+
+        // set to auto if the id is empty, otherwise select the network.
+        if (TextUtils.isEmpty(networkSelection)) {
+            mCM.setNetworkSelectionModeAutomatic(response);
+        } else {
+            mCM.setNetworkSelectionModeManual(networkSelection, response);
+        }
+    }
+
     // Inherited documentation suffices.
     public void setUnitTestMode(boolean f) {
         mUnitTestMode = f;
@@ -260,11 +391,11 @@
     public boolean getUnitTestMode() {
         return mUnitTestMode;
     }
-    
+
     /**
      * To be invoked when a voice call Connection disconnects.
      *
-     * Subclasses of Phone probably want to replace this with a 
+     * Subclasses of Phone probably want to replace this with a
      * version scoped to their packages
      */
     protected void notifyDisconnectP(Connection cn) {
@@ -286,7 +417,7 @@
     }
 
     /**
-     * Subclasses of Phone probably want to replace this with a 
+     * Subclasses of Phone probably want to replace this with a
      * version scoped to their packages
      */
     protected void notifyServiceStateChangedP(ServiceState ss) {
@@ -312,7 +443,7 @@
     private void checkCorrectThread(Handler h) {
         if (h.getLooper() != mLooper) {
             throw new RuntimeException(
-                "com.android.internal.telephony.Phone must be used from within one thread");
+                    "com.android.internal.telephony.Phone must be used from within one thread");
         }
     }
 
@@ -401,4 +532,107 @@
             }
         }
     }
+
+    /*
+     * Retrieves the Handler of the Phone instance
+     */
+    public abstract Handler getHandler();
+
+    /**
+     * Retrieves the IccFileHandler of the Phone instance
+     */
+    public abstract IccFileHandler getIccFileHandler();
+
+
+    /**
+     *  Query the status of the CDMA roaming preference
+     */
+    public void queryCdmaRoamingPreference(Message response) {
+        mCM.queryCdmaRoamingPreference(response);
+    }
+
+    /**
+     *  Set the status of the CDMA roaming preference
+     */
+    public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) {
+        mCM.setCdmaRoamingPreference(cdmaRoamingType, response);
+    }
+
+    /**
+     *  Set the status of the CDMA subscription mode
+     */
+    public void setCdmaSubscription(int cdmaSubscriptionType, Message response) {
+        mCM.setCdmaSubscription(cdmaSubscriptionType, response);
+    }
+
+    /**
+     *  Set the preferred Network Type: Global, CDMA only or GSM/UMTS only
+     */
+    public void setPreferredNetworkType(int networkType, Message response) {
+        mCM.setPreferredNetworkType(networkType, response);
+    }
+
+    /**
+     *  Set the status of the preferred Network Type: Global, CDMA only or GSM/UMTS only
+     */
+    public void getPreferredNetworkType(Message response) {
+        mCM.getPreferredNetworkType(response);
+    }
+
+    public void setTTYModeEnabled(boolean enable, Message onComplete) {
+        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
+        Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+    }
+
+    public void queryTTYModeEnabled(Message onComplete) {
+        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
+        Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+    }
+
+    /**
+     * This should only be called in GSM mode.
+     * Only here for some backward compatibility
+     * issues concerning the GSMPhone class.
+     * @deprecated
+     */
+    public List<PdpConnection> getCurrentPdpList() {
+        return null;
+    }
+
+    public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) {
+        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
+        Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+    }
+
+    public void getEnhancedVoicePrivacy(Message onComplete) {
+        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
+        Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
+    }
+
+    public void setBandMode(int bandMode, Message response) {
+        mCM.setBandMode(bandMode, response);
+    }
+
+    public void queryAvailableBandMode(Message response) {
+        mCM.queryAvailableBandMode(response);
+    }
+
+    public void invokeOemRilRequestRaw(byte[] data, Message response) {
+        mCM.invokeOemRilRequestRaw(data, response);
+    }
+
+    public void invokeOemRilRequestStrings(String[] strings, Message response) {
+        mCM.invokeOemRilRequestStrings(strings, response);
+    }
+
+    public void notifyDataActivity() {
+        mNotifier.notifyDataActivity(this);
+    }
+
+    public void notifyDataConnection(String reason) {
+        mNotifier.notifyDataConnection(this, reason);
+    }
+
+    public abstract String getPhoneName();
+
 }
diff --git a/telephony/java/com/android/internal/telephony/PhoneFactory.java b/telephony/java/com/android/internal/telephony/PhoneFactory.java
index 0ca5f45..3db0499 100644
--- a/telephony/java/com/android/internal/telephony/PhoneFactory.java
+++ b/telephony/java/com/android/internal/telephony/PhoneFactory.java
@@ -16,80 +16,55 @@
 
 package com.android.internal.telephony;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.io.IOException;
-import java.net.InetSocketAddress;
-
-import java.util.Collections;
-
-import android.util.Log;
-import com.android.internal.telephony.gsm.GSMPhone;
-import com.android.internal.telephony.gsm.RIL;
-import com.android.internal.telephony.test.ModelInterpreter;
-import com.android.internal.telephony.test.SimulatedCommands;
-import android.os.Looper;
-import android.os.SystemProperties;
 import android.content.Context;
-import android.content.Intent;
 import android.net.LocalServerSocket;
-import android.app.ActivityManagerNative;
+import android.os.Looper;
+import android.provider.Settings;
+import android.util.Log;
+
+import com.android.internal.telephony.cdma.CDMAPhone;
+import com.android.internal.telephony.gsm.GSMPhone;
 
 /**
  * {@hide}
  */
-public class PhoneFactory
-{
-    static final String LOG_TAG="GSM";
-
+public class PhoneFactory {
+    static final String LOG_TAG = "PHONE";
     static final int SOCKET_OPEN_RETRY_MILLIS = 2 * 1000;
     static final int SOCKET_OPEN_MAX_RETRY = 3;
-    //***** Class Variables 
+    //***** Class Variables
 
-    static private ArrayList<Phone> sPhones = new ArrayList<Phone>();
+    static private Phone sProxyPhone = null;
+    static private CommandsInterface sCommandsInterface = null;
 
     static private boolean sMadeDefaults = false;
     static private PhoneNotifier sPhoneNotifier;
     static private Looper sLooper;
+    static private Context sContext;
 
-    static private Object testMailbox;
+    static final int preferredNetworkMode = RILConstants.PREFERRED_NETWORK_MODE;
+
+    static final int preferredCdmaSubscription = RILConstants.PREFERRED_CDMA_SUBSCRIPTION;
 
     //***** Class Methods
 
-    private static void
-    useNewRIL(Context context)
-    {
-        ModelInterpreter mi = null;
-        GSMPhone phone;
-
-        try {
-            if (false) {
-                mi = new ModelInterpreter(new InetSocketAddress("127.0.0.1", 6502));
-            }
-            
-            phone = new GSMPhone(context, new RIL(context), sPhoneNotifier);
-
-            registerPhone (phone);
-        } catch (IOException ex) {
-            Log.e(LOG_TAG, "Error creating ModelInterpreter", ex);
-        }
+    public static void makeDefaultPhones(Context context) {
+        makeDefaultPhone(context);
     }
 
-
     /**
      * FIXME replace this with some other way of making these
      * instances
      */
-    public static void 
-    makeDefaultPhones(Context context)
-    {
-        synchronized(Phone.class) {        
-            if (!sMadeDefaults) {  
+    public static void makeDefaultPhone(Context context) {
+        synchronized(Phone.class) {
+            if (!sMadeDefaults) {
                 sLooper = Looper.myLooper();
+                sContext = context;
 
                 if (sLooper == null) {
                     throw new RuntimeException(
-                        "PhoneFactory.makeDefaultPhones must be called from Looper thread");
+                        "PhoneFactory.makeDefaultPhone must be called from Looper thread");
                 }
 
                 int retryCount = 0;
@@ -109,7 +84,7 @@
                         break;
                     } else if (retryCount > SOCKET_OPEN_MAX_RETRY) {
                         throw new RuntimeException("PhoneFactory probably already running");
-                    }else {
+                    } else {
                         try {
                             Thread.sleep(SOCKET_OPEN_RETRY_MILLIS);
                         } catch (InterruptedException er) {
@@ -119,44 +94,71 @@
 
                 sPhoneNotifier = new DefaultPhoneNotifier();
 
-                if ((SystemProperties.get("ro.radio.noril","")).equals("")) {
-                    useNewRIL(context);
-                } else {
-                    GSMPhone phone;
-                    phone = new GSMPhone(context, new SimulatedCommands(), sPhoneNotifier);
-                    registerPhone (phone);
-                }
+                //Get preferredNetworkMode from Settings.System
+                int networkMode = Settings.Secure.getInt(context.getContentResolver(),
+                        Settings.Secure.PREFERRED_NETWORK_MODE, preferredNetworkMode);
+                Log.i(LOG_TAG, "Network Mode set to " + Integer.toString(networkMode));
 
+                //Get preferredNetworkMode from Settings.System
+                int cdmaSubscription = Settings.Secure.getInt(context.getContentResolver(),
+                        Settings.Secure.PREFERRED_CDMA_SUBSCRIPTION, preferredCdmaSubscription);
+                Log.i(LOG_TAG, "Cdma Subscription set to " + Integer.toString(cdmaSubscription));
+
+                //reads the system properties and makes commandsinterface
+                sCommandsInterface = new RIL(context, networkMode, cdmaSubscription);
+
+                switch(networkMode) {
+                    case RILConstants.NETWORK_MODE_WCDMA_PREF:
+                    case RILConstants.NETWORK_MODE_GSM_ONLY:
+                    case RILConstants.NETWORK_MODE_WCDMA_ONLY:
+                    case RILConstants.NETWORK_MODE_GSM_UMTS:
+                        sProxyPhone = new PhoneProxy(new GSMPhone(context,
+                                sCommandsInterface, sPhoneNotifier));
+                        Log.i(LOG_TAG, "Creating GSMPhone");
+                        break;
+                    case RILConstants.NETWORK_MODE_CDMA:
+                    case RILConstants.NETWORK_MODE_CDMA_NO_EVDO:
+                    case RILConstants.NETWORK_MODE_EVDO_NO_CDMA:
+                        sProxyPhone = new PhoneProxy(new CDMAPhone(context,
+                                sCommandsInterface, sPhoneNotifier));
+                        Log.i(LOG_TAG, "Creating CDMAPhone");
+                        break;
+                    case RILConstants.NETWORK_MODE_GLOBAL:
+                    default:
+                        sProxyPhone = new PhoneProxy(new CDMAPhone(context,
+                                sCommandsInterface, sPhoneNotifier));
+                        Log.i(LOG_TAG, "Creating CDMAPhone");
+                }
                 sMadeDefaults = true;
             }
         }
     }
 
-    public static Phone getDefaultPhone()
-    {
+    public static Phone getDefaultPhone() {
+        if (sLooper != Looper.myLooper()) {
+            throw new RuntimeException(
+                "PhoneFactory.getDefaultPhone must be called from Looper thread");
+        }
+
         if (!sMadeDefaults) {
             throw new IllegalStateException("Default phones haven't been made yet!");
         }
+       return sProxyPhone;
+    }
 
-        if (sLooper != Looper.myLooper()) {
-            throw new RuntimeException(
-                "PhoneFactory.getDefaultPhone must be called from Looper thread");
-        }
-
-        synchronized (sPhones) {
-            return sPhones.isEmpty() ? null : sPhones.get(0);
+    public static Phone getCdmaPhone() {
+        synchronized(PhoneProxy.lockForRadioTechnologyChange) {
+            Phone phone = new CDMAPhone(sContext, sCommandsInterface, sPhoneNotifier);
+            return phone;
         }
     }
-    
-    public static void registerPhone(Phone p)
-    {
-        if (sLooper != Looper.myLooper()) {
-            throw new RuntimeException(
-                "PhoneFactory.getDefaultPhone must be called from Looper thread");
-        }
-        synchronized (sPhones) {
-            sPhones.add(p);
+
+    public static Phone getGsmPhone() {
+        synchronized(PhoneProxy.lockForRadioTechnologyChange) {
+            Phone phone = new GSMPhone(sContext, sCommandsInterface, sPhoneNotifier);
+            return phone;
         }
     }
 }
 
+
diff --git a/telephony/java/com/android/internal/telephony/PhoneProxy.java b/telephony/java/com/android/internal/telephony/PhoneProxy.java
new file mode 100644
index 0000000..dd36f0b
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/PhoneProxy.java
@@ -0,0 +1,675 @@
+/*
+ * Copyright (C) 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.
+ * 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.internal.telephony;
+
+
+import android.app.ActivityManagerNative;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Handler;
+import android.os.Message;
+import android.preference.PreferenceManager;
+import android.telephony.CellLocation;
+import android.telephony.ServiceState;
+import android.util.Log;
+
+import com.android.internal.telephony.cdma.CDMAPhone;
+import com.android.internal.telephony.gsm.GSMPhone;
+import com.android.internal.telephony.gsm.NetworkInfo;
+import com.android.internal.telephony.gsm.PdpConnection;
+import com.android.internal.telephony.test.SimulatedRadioControl;
+
+import java.util.List;
+
+public class PhoneProxy extends Handler implements Phone {
+    public final static Object lockForRadioTechnologyChange = new Object();
+//    private static boolean radioTechnologyChangeGsmToCdma = false;
+//    private static boolean radioTechnologyChangeCdmaToGsm = false;
+
+    private Phone mActivePhone;
+    private String mOutgoingPhone;
+    private CommandsInterface mCommandsInterface;
+    private IccSmsInterfaceManagerProxy mIccSmsInterfaceManagerProxy;
+    private IccPhoneBookInterfaceManagerProxy mIccPhoneBookInterfaceManagerProxy;
+    private PhoneSubInfoProxy mPhoneSubInfoProxy;
+
+    private static final int EVENT_RADIO_TECHNOLOGY_CHANGED = 1;
+    private static final String LOG_TAG = "PHONE";
+
+    //***** Class Methods
+    public PhoneProxy(Phone phone) {
+        mActivePhone = phone;
+        mIccSmsInterfaceManagerProxy = new IccSmsInterfaceManagerProxy(
+                phone.getIccSmsInterfaceManager());
+        mIccPhoneBookInterfaceManagerProxy = new IccPhoneBookInterfaceManagerProxy(
+                phone.getIccPhoneBookInterfaceManager());
+        mPhoneSubInfoProxy = new PhoneSubInfoProxy(phone.getPhoneSubInfo());
+        mCommandsInterface = ((PhoneBase)mActivePhone).mCM;
+        mCommandsInterface.registerForRadioTechnologyChanged(
+                this, EVENT_RADIO_TECHNOLOGY_CHANGED, null);
+    }
+
+    @Override
+    public void handleMessage(Message msg) {
+        switch(msg.what) {
+        case EVENT_RADIO_TECHNOLOGY_CHANGED:
+            //switch Phone from CDMA to GSM or vice versa
+            mOutgoingPhone = ((PhoneBase)mActivePhone).getPhoneName();
+            logd("Switching phone from " + mOutgoingPhone + "Phone to " +
+                    (mOutgoingPhone.equals("GSM") ? "CDMAPhone" : "GSMPhone") );
+            boolean oldPowerState = false; //old power state to off
+            if (mCommandsInterface.getRadioState().isOn()) {
+                oldPowerState = true;
+                logd("Setting Radio Power to Off");
+                mCommandsInterface.setRadioPower(false, null);
+            }
+            if(mOutgoingPhone.equals("GSM")) {
+                logd("Make a new CDMAPhone and destroy the old GSMPhone.");
+
+                ((GSMPhone)mActivePhone).dispose();
+                Phone oldPhone = mActivePhone;
+
+                //Give the garbage collector a hint to start the garbage collection asap
+                // NOTE this has been disabled since radio technology change could happen during
+                //   e.g. a multimedia playing and could slow the system. Tests needs to be done
+                //   to see the effects of the GC call here when system is busy.
+                //System.gc();
+
+                mActivePhone = PhoneFactory.getCdmaPhone();
+                logd("Resetting Radio");
+                mCommandsInterface.setRadioPower(oldPowerState, null);
+                ((GSMPhone)oldPhone).removeReferences();
+                oldPhone = null;
+            } else {
+                logd("Make a new GSMPhone and destroy the old CDMAPhone.");
+
+                ((CDMAPhone)mActivePhone).dispose();
+                //mActivePhone = null;
+                Phone oldPhone = mActivePhone;
+
+                // Give the GC a hint to start the garbage collection asap
+                // NOTE this has been disabled since radio technology change could happen during
+                //   e.g. a multimedia playing and could slow the system. Tests needs to be done
+                //   to see the effects of the GC call here when system is busy.
+                //System.gc();
+
+                mActivePhone = PhoneFactory.getGsmPhone();
+                logd("Resetting Radio:");
+                mCommandsInterface.setRadioPower(oldPowerState, null);
+                ((CDMAPhone)oldPhone).removeReferences();
+                oldPhone = null;
+            }
+
+            //Set the new interfaces in the proxy's
+            mIccSmsInterfaceManagerProxy.setmIccSmsInterfaceManager(
+                    mActivePhone.getIccSmsInterfaceManager());
+            mIccPhoneBookInterfaceManagerProxy.setmIccPhoneBookInterfaceManager(
+                    mActivePhone.getIccPhoneBookInterfaceManager());
+            mPhoneSubInfoProxy.setmPhoneSubInfo(this.mActivePhone.getPhoneSubInfo());
+            mCommandsInterface = ((PhoneBase)mActivePhone).mCM;
+
+            //Send an Intent to the PhoneApp that we had a radio technology change
+            Intent intent = new Intent(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
+            intent.putExtra(Phone.PHONE_NAME_KEY, mActivePhone.getPhoneName());
+            ActivityManagerNative.broadcastStickyIntent(intent, null);
+
+            break;
+        default:
+            Log.e(LOG_TAG, "Error! This handler was not registered for this message type. Message: "
+                    + msg.what);
+        break;
+        }
+        super.handleMessage(msg);
+    }
+
+    private void logv(String msg) {
+        Log.v(LOG_TAG, "[PhoneProxy] " + msg);
+    }
+
+    private void logd(String msg) {
+        Log.d(LOG_TAG, "[PhoneProxy] " + msg);
+    }
+
+    private void logw(String msg) {
+        Log.w(LOG_TAG, "[PhoneProxy] " + msg);
+    }
+
+    private void loge(String msg) {
+        Log.e(LOG_TAG, "[PhoneProxy] " + msg);
+    }
+
+
+    public ServiceState getServiceState() {
+        return mActivePhone.getServiceState();
+    }
+
+    public CellLocation getCellLocation() {
+        return mActivePhone.getCellLocation();
+    }
+
+    public DataState getDataConnectionState() {
+        return mActivePhone.getDataConnectionState();
+    }
+
+    public DataActivityState getDataActivityState() {
+        return mActivePhone.getDataActivityState();
+    }
+
+    public Context getContext() {
+        return mActivePhone.getContext();
+    }
+
+    public void disableDnsCheck(boolean b) {
+        mActivePhone.disableDnsCheck(b);
+    }
+
+    public boolean isDnsCheckDisabled() {
+        return mActivePhone.isDnsCheckDisabled();
+    }
+
+    public State getState() {
+        return mActivePhone.getState();
+    }
+
+    public String getPhoneName() {
+        return mActivePhone.getPhoneName();
+    }
+
+    public String[] getActiveApnTypes() {
+        return mActivePhone.getActiveApnTypes();
+    }
+
+    public String getActiveApn() {
+        return mActivePhone.getActiveApn();
+    }
+
+    public int getSignalStrengthASU() {
+        return mActivePhone.getSignalStrengthASU();
+    }
+
+    public void registerForUnknownConnection(Handler h, int what, Object obj) {
+        mActivePhone.registerForUnknownConnection(h, what, obj);
+    }
+
+    public void unregisterForUnknownConnection(Handler h) {
+        mActivePhone.unregisterForUnknownConnection(h);
+    }
+
+    public void registerForPhoneStateChanged(Handler h, int what, Object obj) {
+        mActivePhone.registerForPhoneStateChanged(h, what, obj);
+    }
+
+    public void unregisterForPhoneStateChanged(Handler h) {
+        mActivePhone.unregisterForPhoneStateChanged(h);
+    }
+
+    public void registerForNewRingingConnection(Handler h, int what, Object obj) {
+        mActivePhone.registerForNewRingingConnection(h, what, obj);
+    }
+
+    public void unregisterForNewRingingConnection(Handler h) {
+        mActivePhone.unregisterForNewRingingConnection(h);
+    }
+
+    public void registerForIncomingRing(Handler h, int what, Object obj) {
+        mActivePhone.registerForIncomingRing(h, what, obj);
+    }
+
+    public void unregisterForIncomingRing(Handler h) {
+        mActivePhone.unregisterForIncomingRing(h);
+    }
+
+    public void registerForDisconnect(Handler h, int what, Object obj) {
+        mActivePhone.registerForDisconnect(h, what, obj);
+    }
+
+    public void unregisterForDisconnect(Handler h) {
+        mActivePhone.unregisterForDisconnect(h);
+    }
+
+    public void registerForMmiInitiate(Handler h, int what, Object obj) {
+        mActivePhone.registerForMmiInitiate(h, what, obj);
+    }
+
+    public void unregisterForMmiInitiate(Handler h) {
+        mActivePhone.unregisterForMmiInitiate(h);
+    }
+
+    public void registerForMmiComplete(Handler h, int what, Object obj) {
+        mActivePhone.registerForMmiComplete(h, what, obj);
+    }
+
+    public void unregisterForMmiComplete(Handler h) {
+        mActivePhone.unregisterForMmiComplete(h);
+    }
+
+    public List<? extends MmiCode> getPendingMmiCodes() {
+        return mActivePhone.getPendingMmiCodes();
+    }
+
+    public void sendUssdResponse(String ussdMessge) {
+        mActivePhone.sendUssdResponse(ussdMessge);
+    }
+
+    public void registerForServiceStateChanged(Handler h, int what, Object obj) {
+        mActivePhone.registerForServiceStateChanged(h, what, obj);
+    }
+
+    public void unregisterForServiceStateChanged(Handler h) {
+        mActivePhone.unregisterForServiceStateChanged(h);
+    }
+
+    public void registerForSuppServiceNotification(Handler h, int what, Object obj) {
+        mActivePhone.registerForSuppServiceNotification(h, what, obj);
+    }
+
+    public void unregisterForSuppServiceNotification(Handler h) {
+        mActivePhone.unregisterForSuppServiceNotification(h);
+    }
+
+    public void registerForSuppServiceFailed(Handler h, int what, Object obj) {
+        mActivePhone.registerForSuppServiceFailed(h, what, obj);
+    }
+
+    public void unregisterForSuppServiceFailed(Handler h) {
+        mActivePhone.unregisterForSuppServiceFailed(h);
+    }
+
+    public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj){
+        mActivePhone.registerForInCallVoicePrivacyOn(h,what,obj);
+    }
+
+    public void unregisterForInCallVoicePrivacyOn(Handler h){
+        mActivePhone.unregisterForInCallVoicePrivacyOn(h);
+    }
+
+    public void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj){
+        mActivePhone.registerForInCallVoicePrivacyOff(h,what,obj);
+    }
+
+    public void unregisterForInCallVoicePrivacyOff(Handler h){
+        mActivePhone.unregisterForInCallVoicePrivacyOff(h);
+    }
+
+    public boolean getIccRecordsLoaded() {
+        return mActivePhone.getIccRecordsLoaded();
+    }
+
+    public IccCard getIccCard() {
+        return mActivePhone.getIccCard();
+    }
+
+    public void acceptCall() throws CallStateException {
+        mActivePhone.acceptCall();
+    }
+
+    public void rejectCall() throws CallStateException {
+        mActivePhone.rejectCall();
+    }
+
+    public void switchHoldingAndActive() throws CallStateException {
+        mActivePhone.switchHoldingAndActive();
+    }
+
+    public boolean canConference() {
+        return mActivePhone.canConference();
+    }
+
+    public void conference() throws CallStateException {
+        mActivePhone.conference();
+    }
+
+    public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) {
+        mActivePhone.enableEnhancedVoicePrivacy(enable, onComplete);
+    }
+
+    public void getEnhancedVoicePrivacy(Message onComplete) {
+        mActivePhone.getEnhancedVoicePrivacy(onComplete);
+    }
+
+    public boolean canTransfer() {
+        return mActivePhone.canTransfer();
+    }
+
+    public void explicitCallTransfer() throws CallStateException {
+        mActivePhone.explicitCallTransfer();
+    }
+
+    public void clearDisconnected() {
+        mActivePhone.clearDisconnected();
+    }
+
+    public Call getForegroundCall() {
+        return mActivePhone.getForegroundCall();
+    }
+
+    public Call getBackgroundCall() {
+        return mActivePhone.getBackgroundCall();
+    }
+
+    public Call getRingingCall() {
+        return mActivePhone.getRingingCall();
+    }
+
+    public Connection dial(String dialString) throws CallStateException {
+        return mActivePhone.dial(dialString);
+    }
+
+    public boolean handlePinMmi(String dialString) {
+        return mActivePhone.handlePinMmi(dialString);
+    }
+
+    public boolean handleInCallMmiCommands(String command) throws CallStateException {
+        return mActivePhone.handleInCallMmiCommands(command);
+    }
+
+    public void sendDtmf(char c) {
+        mActivePhone.sendDtmf(c);
+    }
+
+    public void startDtmf(char c) {
+        mActivePhone.startDtmf(c);
+    }
+
+    public void stopDtmf() {
+        mActivePhone.stopDtmf();
+    }
+
+    public void setRadioPower(boolean power) {
+        mActivePhone.setRadioPower(power);
+    }
+
+    public boolean getMessageWaitingIndicator() {
+        return mActivePhone.getMessageWaitingIndicator();
+    }
+
+    public boolean getCallForwardingIndicator() {
+        return mActivePhone.getCallForwardingIndicator();
+    }
+
+    public String getLine1Number() {
+        return mActivePhone.getLine1Number();
+    }
+
+    public String getLine1AlphaTag() {
+        return mActivePhone.getLine1AlphaTag();
+    }
+
+    public void setLine1Number(String alphaTag, String number, Message onComplete) {
+        mActivePhone.setLine1Number(alphaTag, number, onComplete);
+    }
+
+    public String getVoiceMailNumber() {
+        return mActivePhone.getVoiceMailNumber();
+    }
+
+    public String getVoiceMailAlphaTag() {
+        return mActivePhone.getVoiceMailAlphaTag();
+    }
+
+    public void setVoiceMailNumber(String alphaTag,String voiceMailNumber,
+            Message onComplete) {
+        mActivePhone.setVoiceMailNumber(alphaTag, voiceMailNumber, onComplete);
+    }
+
+    public void getCallForwardingOption(int commandInterfaceCFReason,
+            Message onComplete) {
+        mActivePhone.getCallForwardingOption(commandInterfaceCFReason,
+                onComplete);
+    }
+
+    public void setCallForwardingOption(int commandInterfaceCFReason,
+            int commandInterfaceCFAction, String dialingNumber,
+            int timerSeconds, Message onComplete) {
+        mActivePhone.setCallForwardingOption(commandInterfaceCFReason,
+            commandInterfaceCFAction, dialingNumber, timerSeconds, onComplete);
+    }
+
+    public void getOutgoingCallerIdDisplay(Message onComplete) {
+        mActivePhone.getOutgoingCallerIdDisplay(onComplete);
+    }
+
+    public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode,
+            Message onComplete) {
+        mActivePhone.setOutgoingCallerIdDisplay(commandInterfaceCLIRMode,
+                onComplete);
+    }
+
+    public void getCallWaiting(Message onComplete) {
+        mActivePhone.getCallWaiting(onComplete);
+    }
+
+    public void setCallWaiting(boolean enable, Message onComplete) {
+        mActivePhone.setCallWaiting(enable, onComplete);
+    }
+
+    public void getAvailableNetworks(Message response) {
+        mActivePhone.getAvailableNetworks(response);
+    }
+
+    public void setNetworkSelectionModeAutomatic(Message response) {
+        mActivePhone.setNetworkSelectionModeAutomatic(response);
+    }
+
+    public void selectNetworkManually(NetworkInfo network, Message response) {
+        mActivePhone.selectNetworkManually(network, response);
+    }
+
+    public void setPreferredNetworkType(int networkType, Message response) {
+        mActivePhone.setPreferredNetworkType(networkType, response);
+    }
+
+    public void getPreferredNetworkType(Message response) {
+        mActivePhone.getPreferredNetworkType(response);
+    }
+
+    public void getNeighboringCids(Message response) {
+        mActivePhone.getNeighboringCids(response);
+    }
+
+    public void setOnPostDialCharacter(Handler h, int what, Object obj) {
+        mActivePhone.setOnPostDialCharacter(h, what, obj);
+    }
+
+    public void setMute(boolean muted) {
+        mActivePhone.setMute(muted);
+    }
+
+    public boolean getMute() {
+        return mActivePhone.getMute();
+    }
+
+    public void invokeOemRilRequestRaw(byte[] data, Message response) {
+        mActivePhone.invokeOemRilRequestRaw(data, response);
+    }
+
+    public void invokeOemRilRequestStrings(String[] strings, Message response) {
+        mActivePhone.invokeOemRilRequestStrings(strings, response);
+    }
+
+    /**
+     * @deprecated
+     */
+    public void getPdpContextList(Message response) {
+        mActivePhone.getPdpContextList(response);
+    }
+
+    public void getDataCallList(Message response) {
+        mActivePhone.getDataCallList(response);
+    }
+
+    /**
+     * @deprecated
+     */
+    public List<PdpConnection> getCurrentPdpList() {
+        return mActivePhone.getCurrentPdpList();
+    }
+
+    public List<DataConnection> getCurrentDataConnectionList() {
+        return mActivePhone.getCurrentDataConnectionList();
+    }
+
+    public void updateServiceLocation(Message response) {
+        mActivePhone.updateServiceLocation(response);
+    }
+
+    public void enableLocationUpdates() {
+        mActivePhone.enableLocationUpdates();
+    }
+
+    public void disableLocationUpdates() {
+        mActivePhone.disableLocationUpdates();
+    }
+
+    public void setUnitTestMode(boolean f) {
+        mActivePhone.setUnitTestMode(f);
+    }
+
+    public boolean getUnitTestMode() {
+        return mActivePhone.getUnitTestMode();
+    }
+
+    public void setBandMode(int bandMode, Message response) {
+        mActivePhone.setBandMode(bandMode, response);
+    }
+
+    public void queryAvailableBandMode(Message response) {
+        mActivePhone.queryAvailableBandMode(response);
+    }
+
+    public boolean getDataRoamingEnabled() {
+        return mActivePhone.getDataRoamingEnabled();
+    }
+
+    public void setDataRoamingEnabled(boolean enable) {
+        mActivePhone.setDataRoamingEnabled(enable);
+    }
+
+    public void queryCdmaRoamingPreference(Message response) {
+        mActivePhone.queryCdmaRoamingPreference(response);
+    }
+
+    public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) {
+        mActivePhone.setCdmaRoamingPreference(cdmaRoamingType, response);
+    }
+
+    public void setCdmaSubscription(int cdmaSubscriptionType, Message response) {
+        mActivePhone.setCdmaSubscription(cdmaSubscriptionType, response);
+    }
+
+    public SimulatedRadioControl getSimulatedRadioControl() {
+        return mActivePhone.getSimulatedRadioControl();
+    }
+
+    public boolean enableDataConnectivity() {
+        return mActivePhone.enableDataConnectivity();
+    }
+
+    public boolean disableDataConnectivity() {
+        return mActivePhone.disableDataConnectivity();
+    }
+
+    public int enableApnType(String type) {
+        return mActivePhone.enableApnType(type);
+    }
+
+    public int disableApnType(String type) {
+        return mActivePhone.disableApnType(type);
+    }
+
+    public boolean isDataConnectivityPossible() {
+        return mActivePhone.isDataConnectivityPossible();
+    }
+
+    public String getInterfaceName(String apnType) {
+        return mActivePhone.getInterfaceName(apnType);
+    }
+
+    public String getIpAddress(String apnType) {
+        return mActivePhone.getIpAddress(apnType);
+    }
+
+    public String getGateway(String apnType) {
+        return mActivePhone.getGateway(apnType);
+    }
+
+    public String[] getDnsServers(String apnType) {
+        return mActivePhone.getDnsServers(apnType);
+    }
+
+    public String getDeviceId() {
+        return mActivePhone.getDeviceId();
+    }
+
+    public String getDeviceSvn() {
+        return mActivePhone.getDeviceSvn();
+    }
+
+    public String getSubscriberId() {
+        return mActivePhone.getSubscriberId();
+    }
+
+    public String getIccSerialNumber() {
+        return mActivePhone.getIccSerialNumber();
+    }
+
+    public String getEsn() {
+        return mActivePhone.getEsn();
+    }
+
+    public String getMeid() {
+        return mActivePhone.getMeid();
+    }
+
+    public PhoneSubInfo getPhoneSubInfo(){
+        return mActivePhone.getPhoneSubInfo();
+    }
+
+    public IccSmsInterfaceManager getIccSmsInterfaceManager(){
+        return mActivePhone.getIccSmsInterfaceManager();
+    }
+
+    public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager(){
+        return mActivePhone.getIccPhoneBookInterfaceManager();
+    }
+
+    public void setTTYModeEnabled(boolean enable, Message onComplete) {
+        mActivePhone.setTTYModeEnabled(enable, onComplete);
+    }
+
+    public void queryTTYModeEnabled(Message onComplete) {
+        mActivePhone.queryTTYModeEnabled(onComplete);
+    }
+
+    public void activateCellBroadcastSms(int activate, Message response) {
+        mActivePhone.activateCellBroadcastSms(activate, response);
+    }
+
+    public void getCellBroadcastSmsConfig(Message response) {
+        mActivePhone.getCellBroadcastSmsConfig(response);
+    }
+
+    public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response) {
+        mActivePhone.setCellBroadcastSmsConfig(configValuesArray, response);
+    }
+
+    public void notifyDataActivity() {
+         mActivePhone.notifyDataActivity();
+    }
+}
+
diff --git a/telephony/java/com/android/internal/telephony/PhoneStateIntentReceiver.java b/telephony/java/com/android/internal/telephony/PhoneStateIntentReceiver.java
index 61d4c9f..fd822cd 100644
--- a/telephony/java/com/android/internal/telephony/PhoneStateIntentReceiver.java
+++ b/telephony/java/com/android/internal/telephony/PhoneStateIntentReceiver.java
@@ -32,11 +32,11 @@
  *
  *      Use android.telephony.TelephonyManager and PhoneStateListener instead.
  *
- * 
+ *
  */
 @Deprecated
 public final class PhoneStateIntentReceiver extends BroadcastReceiver {
-    private static final String LOG_TAG = "PhoneStateIntRecv";
+    private static final String LOG_TAG = "PHONE";
     private static final boolean DBG = false;
 
     public static final String INTENT_KEY_ASU = "asu";
@@ -182,7 +182,7 @@
             if (TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED.equals(action)) {
                 mAsu = intent.getIntExtra(INTENT_KEY_ASU, mAsu);
                 if (DBG) Log.d(LOG_TAG, "onReceiveIntent: set asu=" + mAsu);
-                
+
                 if (mTarget != null && getNotifySignalStrength()) {
                     Message message = Message.obtain(mTarget, mAsuEventWhat);
                     mTarget.sendMessage(message);
diff --git a/telephony/java/com/android/internal/telephony/PhoneSubInfo.java b/telephony/java/com/android/internal/telephony/PhoneSubInfo.java
index 644d1f4..4d1f7e5 100644
--- a/telephony/java/com/android/internal/telephony/PhoneSubInfo.java
+++ b/telephony/java/com/android/internal/telephony/PhoneSubInfo.java
@@ -1,10 +1,25 @@
+/*
+ * Copyright (C) 2007 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.internal.telephony;
 
 import android.content.Context;
-import android.os.ServiceManager;
-import com.android.internal.telephony.*;
+import android.util.Log;
 
 public class PhoneSubInfo extends IPhoneSubInfo.Stub {
+    static final String LOG_TAG = "PHONE";
     private Phone mPhone;
     private Context mContext;
     private static final String READ_PHONE_STATE =
@@ -13,10 +28,17 @@
     public PhoneSubInfo(Phone phone) {
         mPhone = phone;
         mContext = phone.getContext();
-        ServiceManager.addService("iphonesubinfo", this);
     }
+
+    public void dispose() {
+    }
+
+    protected void finalize() {
+        Log.d(LOG_TAG, "PhoneSubInfo finalized");
+    }
+
     /**
-     * Retrieves the unique device ID, e.g., IMEI for GSM phones.
+     * Retrieves the unique device ID, e.g., IMEI for GSM phones and MEID for CDMA phones.
      */
     public String getDeviceId() {
         mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE");
@@ -41,11 +63,11 @@
     }
 
     /**
-     * Retrieves the serial number of the SIM, if applicable.
+     * Retrieves the serial number of the ICC, if applicable.
      */
-    public String getSimSerialNumber() {
+    public String getIccSerialNumber() {
         mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, "Requires READ_PHONE_STATE");
-        return mPhone.getSimSerialNumber();
+        return mPhone.getIccSerialNumber();
     }
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/PhoneSubInfoProxy.java b/telephony/java/com/android/internal/telephony/PhoneSubInfoProxy.java
new file mode 100644
index 0000000..450b3a7
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/PhoneSubInfoProxy.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony;
+
+import android.os.ServiceManager;
+
+
+public class PhoneSubInfoProxy extends IPhoneSubInfo.Stub {
+    private PhoneSubInfo mPhoneSubInfo;
+
+    public PhoneSubInfoProxy(PhoneSubInfo phoneSubInfo) {
+        mPhoneSubInfo = phoneSubInfo;
+        if(ServiceManager.getService("iphonesubinfo") == null) {
+            ServiceManager.addService("iphonesubinfo", this);
+        }
+    }
+
+    public void setmPhoneSubInfo(PhoneSubInfo phoneSubInfo) {
+        this.mPhoneSubInfo = phoneSubInfo;
+    }
+
+    public String getDeviceId() {
+        return mPhoneSubInfo.getDeviceId();
+    }
+
+    public String getDeviceSvn() {
+        return mPhoneSubInfo.getDeviceSvn();
+    }
+
+    /**
+     * Retrieves the unique sbuscriber ID, e.g., IMSI for GSM phones.
+     */
+    public String getSubscriberId() {
+        return mPhoneSubInfo.getSubscriberId();
+    }
+
+    /**
+     * Retrieves the serial number of the ICC, if applicable.
+     */
+    public String getIccSerialNumber() {
+        return mPhoneSubInfo.getIccSerialNumber();
+    }
+
+    /**
+     * Retrieves the phone number string for line 1.
+     */
+    public String getLine1Number() {
+        return mPhoneSubInfo.getLine1Number();
+    }
+
+    /**
+     * Retrieves the alpha identifier for line 1.
+     */
+    public String getLine1AlphaTag() {
+        return mPhoneSubInfo.getLine1AlphaTag();
+    }
+
+    /**
+     * Retrieves the voice mail number.
+     */
+    public String getVoiceMailNumber() {
+        return mPhoneSubInfo.getVoiceMailNumber();
+    }
+
+    /**
+     * Retrieves the alpha identifier associated with the voice mail number.
+     */
+    public String getVoiceMailAlphaTag() {
+        return mPhoneSubInfo.getVoiceMailAlphaTag();
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java
similarity index 67%
rename from telephony/java/com/android/internal/telephony/gsm/RIL.java
rename to telephony/java/com/android/internal/telephony/RIL.java
index e2d0f72..f5d3b32 100644
--- a/telephony/java/com/android/internal/telephony/gsm/RIL.java
+++ b/telephony/java/com/android/internal/telephony/RIL.java
@@ -14,9 +14,8 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
-import static com.android.internal.telephony.gsm.RILConstants.*;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -32,22 +31,36 @@
 import android.os.PowerManager;
 import android.os.PowerManager.WakeLock;
 import android.telephony.PhoneNumberUtils;
-import android.telephony.gsm.SmsManager;
-import android.telephony.gsm.SmsMessage;
 import android.telephony.NeighboringCellInfo;
-import android.util.Config;
+import android.telephony.SmsManager;
+import android.telephony.SmsMessage;
 import android.util.Log;
+import android.util.Config;
 
-import java.io.IOException;
+import static com.android.internal.telephony.RILConstants.*;
+
+import com.android.internal.telephony.CallForwardInfo;
+import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.gsm.NetworkInfo;
+import com.android.internal.telephony.gsm.PDPContextState;
+import com.android.internal.telephony.gsm.SuppServiceNotification;
+import com.android.internal.telephony.IccCardApplication;
+import com.android.internal.telephony.IccCardStatus;
+import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.SmsResponse;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
 import java.io.InputStream;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
 
 /**
  * {@hide}
  */
-class RILRequest
-{
+class RILRequest {
     static final String LOG_TAG = "RILJ";
 
     //***** Class Variables
@@ -67,14 +80,14 @@
 
     /**
      * Retrieves a new RILRequest instance from the pool.
-     * 
+     *
      * @param request RIL_REQUEST_*
      * @param result sent when operation completes
      * @return a RILRequest instance from the pool.
      */
     static RILRequest obtain(int request, Message result) {
         RILRequest rr = null;
-        
+
         synchronized(sPoolSync) {
             if (sPool != null) {
                 rr = sPool;
@@ -83,7 +96,7 @@
                 sPoolSize--;
             }
         }
-        
+
         if (rr == null) {
             rr = new RILRequest();
         }
@@ -108,7 +121,7 @@
 
     /**
      * Returns a RILRequest instance to the pool.
-     * 
+     *
      * Note: This should only be called once per use.
      */
     void release() {
@@ -121,21 +134,18 @@
         }
     }
 
-    private RILRequest()
-    {
+    private RILRequest() {
     }
 
     static void
-    resetSerial()
-    {
+    resetSerial() {
         synchronized(sSerialMonitor) {
             sNextSerial = 0;
         }
     }
 
     String
-    serialString()
-    {
+    serialString() {
         //Cheesy way to do %04d
         StringBuilder sb = new StringBuilder(8);
         String sn;
@@ -154,14 +164,13 @@
     }
 
     void
-    onError(int error)
-    {
+    onError(int error) {
         CommandException ex;
 
         ex = CommandException.fromRilErrno(error);
 
         if (RIL.RILJ_LOGD) Log.d(LOG_TAG, serialString() + "< "
-            + RIL.requestToString(mRequest) 
+            + RIL.requestToString(mRequest)
             + " error: " + ex);
 
         if (mResult != null) {
@@ -180,11 +189,10 @@
 /**
  * RIL implementation of the CommandsInterface.
  * FIXME public only for testing
- * 
+ *
  * {@hide}
  */
-public final class RIL extends BaseCommands implements CommandsInterface
-{
+public final class RIL extends BaseCommands implements CommandsInterface {
     static final String LOG_TAG = "RILJ";
     private static final boolean DBG = false;
     static final boolean RILJ_LOGD = Config.LOGD;
@@ -194,20 +202,20 @@
     //***** Instance Variables
 
     LocalSocket mSocket;
-    HandlerThread mSenderThread;    
+    HandlerThread mSenderThread;
     RILSender mSender;
     Thread mReceiverThread;
     RILReceiver mReceiver;
     private Context mContext;
     WakeLock mWakeLock;
     int mRequestMessagesPending;
-    
+
     // Is this the first radio state change?
     private boolean mInitialRadioStateChange = true;
 
     //I'd rather this be LinkedList or something
     ArrayList<RILRequest> mRequestsList = new ArrayList<RILRequest>();
-    
+
     Object     mLastNITZTimeInfo;
 
     //***** Events
@@ -238,20 +246,18 @@
             }
         }
     };
-    
-    class RILSender extends Handler implements Runnable
-    {
+
+    class RILSender extends Handler implements Runnable {
         public RILSender(Looper looper) {
             super(looper);
         }
-        
+
         // Only allocated once
         byte[] dataLength = new byte[4];
 
         //***** Runnable implementation
         public void
-        run()
-        {
+        run() {
             //setup if needed
         }
 
@@ -259,11 +265,10 @@
         //***** Handler implemementation
 
         public void
-        handleMessage(Message msg)
-        {
+        handleMessage(Message msg) {
             RILRequest rr = (RILRequest)(msg.obj);
             RILRequest req = null;
-            
+
             switch (msg.what) {
                 case EVENT_SEND:
                     /**
@@ -300,7 +305,7 @@
 
                         if (data.length > RIL_MAX_COMMAND_BYTES) {
                             throw new RuntimeException(
-                                    "Parcel larger than max bytes allowed! " 
+                                    "Parcel larger than max bytes allowed! "
                                                           + data.length);
                         }
 
@@ -311,7 +316,7 @@
 
                         //Log.v(LOG_TAG, "writing packet: " + data.length + " bytes");
 
-                        s.getOutputStream().write(dataLength);                    
+                        s.getOutputStream().write(dataLength);
                         s.getOutputStream().write(data);
                     } catch (IOException ex) {
                         Log.e(LOG_TAG, "IOException", ex);
@@ -351,12 +356,12 @@
                                     Log.d(LOG_TAG, "WAKE_LOCK_TIMEOUT " +
                                         " mReqPending=" + mRequestMessagesPending +
                                         " mRequestList=" + count);
-    
+
                                     for (int i = 0; i < count; i++) {
                                         rr = mRequestsList.get(i);
                                         Log.d(LOG_TAG, i + ": [" + rr.mSerial + "] " +
                                             requestToString(rr.mRequest));
-                                            
+
                                     }
                                 }
                             }
@@ -383,8 +388,7 @@
      * @throws IOException
      */
     private static int readRilMessage(InputStream is, byte[] buffer)
-            throws IOException
-    {
+            throws IOException {
         int countRead;
         int offset;
         int remaining;
@@ -429,20 +433,17 @@
         return messageLength;
     }
 
-    class RILReceiver implements Runnable
-    {
+    class RILReceiver implements Runnable {
         byte[] buffer;
 
-        RILReceiver()
-        {
+        RILReceiver() {
             buffer = new byte[RIL_MAX_COMMAND_BYTES];
         }
 
         public void
-        run()
-        {
+        run() {
             int retryCount = 0;
-            
+
             try {for (;;) {
                 LocalSocket s = null;
                 LocalSocketAddress l;
@@ -460,23 +461,23 @@
                     } catch (IOException ex2) {
                         //ignore failure to close after failure to connect
                     }
-                
+
                     // don't print an error message after the the first time
                     // or after the 8th time
 
                     if (retryCount == 8) {
-                        Log.e (LOG_TAG, 
+                        Log.e (LOG_TAG,
                             "Couldn't find '" + SOCKET_NAME_RIL
                             + "' socket after " + retryCount
                             + " times, continuing to retry silently");
                     } else if (retryCount > 0 && retryCount < 8) {
-                        Log.i (LOG_TAG, 
+                        Log.i (LOG_TAG,
                             "Couldn't find '" + SOCKET_NAME_RIL
                             + "' socket; retrying after timeout");
                     }
 
                     try {
-                        Thread.sleep(SOCKET_OPEN_RETRY_MILLIS);                 
+                        Thread.sleep(SOCKET_OPEN_RETRY_MILLIS);
                     } catch (InterruptedException er) {
                     }
 
@@ -492,7 +493,7 @@
                 int length = 0;
                 try {
                     InputStream is = mSocket.getInputStream();
-                
+
                     for (;;) {
                         Parcel p;
 
@@ -524,9 +525,9 @@
                       + "' socket");
 
                 setRadioState (RadioState.RADIO_UNAVAILABLE);
-                
+
                 try {
-                    mSocket.close();                    
+                    mSocket.close();
                 } catch (IOException ex) {
                 }
 
@@ -551,15 +552,39 @@
 
 
 
-    //***** Constructor
-
+    //***** Constructors
     public
-    RIL(Context context)
-    {
+    RIL(Context context) {
+        this(context, RILConstants.PREFERRED_NETWORK_MODE,
+                RILConstants.PREFERRED_CDMA_SUBSCRIPTION);
+    }
+
+    public RIL(Context context, int networkMode, int cdmaSubscription) {
         super(context);
+        mCdmaSubscription  = cdmaSubscription;
+        mNetworkMode = networkMode;
+        //At startup mPhoneType is first set from networkMode
+        switch(networkMode) {
+            case RILConstants.NETWORK_MODE_WCDMA_PREF:
+            case RILConstants.NETWORK_MODE_GSM_ONLY:
+            case RILConstants.NETWORK_MODE_WCDMA_ONLY:
+            case RILConstants.NETWORK_MODE_GSM_UMTS:
+                mPhoneType = RILConstants.GSM_PHONE;
+                break;
+            case RILConstants.NETWORK_MODE_CDMA:
+            case RILConstants.NETWORK_MODE_CDMA_NO_EVDO:
+            case RILConstants.NETWORK_MODE_EVDO_NO_CDMA:
+                mPhoneType = RILConstants.CDMA_PHONE;
+                break;
+            case RILConstants.NETWORK_MODE_GLOBAL:
+                mPhoneType = RILConstants.CDMA_PHONE;
+                break;
+            default:
+                mPhoneType = RILConstants.CDMA_PHONE;
+        }
 
         PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
-        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG); 
+        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG);
         mWakeLock.setReferenceCounted(false);
         mRequestMessagesPending = 0;
 
@@ -583,9 +608,8 @@
 
     //***** CommandsInterface implementation
 
-    @Override public void 
-    setOnNITZTime(Handler h, int what, Object obj)
-    {
+    @Override public void
+    setOnNITZTime(Handler h, int what, Object obj) {
         super.setOnNITZTime(h, what, obj);
 
         // Send the last NITZ time if we have it
@@ -597,9 +621,10 @@
         }
     }
 
-    public void 
-    getSimStatus(Message result)
-    {
+    public void
+    getIccStatus(Message result) {
+        //Note: This RIL request has not been renamed to ICC,
+        //       but this request is also valid for SIM and RUIM
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_SIM_STATUS, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -607,9 +632,10 @@
         send(rr);
     }
 
-    public void 
-    supplySimPin(String pin, Message result)
-    {
+    public void
+    supplyIccPin(String pin, Message result) {
+        //Note: This RIL request has not been renamed to ICC,
+        //       but this request is also valid for SIM and RUIM
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_ENTER_SIM_PIN, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -620,9 +646,10 @@
         send(rr);
     }
 
-    public void 
-    supplySimPuk(String puk, String newPin, Message result)
-    {
+    public void
+    supplyIccPuk(String puk, String newPin, Message result) {
+        //Note: This RIL request has not been renamed to ICC,
+        //       but this request is also valid for SIM and RUIM
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_ENTER_SIM_PUK, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -634,9 +661,10 @@
         send(rr);
     }
 
-    public void 
-    supplySimPin2(String pin, Message result)
-    {
+    public void
+    supplyIccPin2(String pin, Message result) {
+        //Note: This RIL request has not been renamed to ICC,
+        //       but this request is also valid for SIM and RUIM
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_ENTER_SIM_PIN2, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -647,9 +675,10 @@
         send(rr);
     }
 
-    public void 
-    supplySimPuk2(String puk, String newPin2, Message result)
-    {
+    public void
+    supplyIccPuk2(String puk, String newPin2, Message result) {
+        //Note: This RIL request has not been renamed to ICC,
+        //       but this request is also valid for SIM and RUIM
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_ENTER_SIM_PUK2, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -662,8 +691,9 @@
     }
 
     public void
-    changeSimPin(String oldPin, String newPin, Message result)
-    {
+    changeIccPin(String oldPin, String newPin, Message result) {
+        //Note: This RIL request has not been renamed to ICC,
+        //       but this request is also valid for SIM and RUIM
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_CHANGE_SIM_PIN, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -676,8 +706,9 @@
     }
 
     public void
-    changeSimPin2(String oldPin2, String newPin2, Message result)
-    {
+    changeIccPin2(String oldPin2, String newPin2, Message result) {
+        //Note: This RIL request has not been renamed to ICC,
+        //       but this request is also valid for SIM and RUIM
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_CHANGE_SIM_PIN2, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -690,8 +721,7 @@
     }
 
     public void
-    changeBarringPassword(String facility, String oldPwd, String newPwd, Message result)
-    {
+    changeBarringPassword(String facility, String oldPwd, String newPwd, Message result) {
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_CHANGE_BARRING_PASSWORD, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -704,9 +734,8 @@
         send(rr);
     }
 
-    public void 
-    supplyNetworkDepersonalization(String netpin, Message result)
-    {
+    public void
+    supplyNetworkDepersonalization(String netpin, Message result) {
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -716,10 +745,9 @@
 
         send(rr);
     }
-    
-    public void 
-    getCurrentCalls (Message result)
-    {
+
+    public void
+    getCurrentCalls (Message result) {
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_CURRENT_CALLS, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -727,19 +755,22 @@
         send(rr);
     }
 
-    public void 
-    getPDPContextList(Message result)
-    {
-        RILRequest rr = RILRequest.obtain(RIL_REQUEST_PDP_CONTEXT_LIST, result);
+    public void
+    getPDPContextList(Message result) {
+        getDataCallList(result);
+    }
+
+    public void
+    getDataCallList(Message result) {
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_DATA_CALL_LIST, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
 
         send(rr);
     }
 
-    public void 
-    dial (String address, int clirMode, Message result)
-    {
+    public void
+    dial (String address, int clirMode, Message result) {
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_DIAL, result);
 
         rr.mp.writeString(address);
@@ -750,19 +781,20 @@
         send(rr);
     }
 
-    public void 
-    getIMSI(Message result)
-    {
+    public void
+    getIMSI(Message result) {
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_IMSI, result);
 
-        if (RILJ_LOGD) riljLog(rr.serialString() + "> getIMSI:RIL_REQUEST_GET_IMSI " + RIL_REQUEST_GET_IMSI + " " + requestToString(rr.mRequest));
+        if (RILJ_LOGD) riljLog(rr.serialString() +
+                              "> getIMSI:RIL_REQUEST_GET_IMSI " +
+                              RIL_REQUEST_GET_IMSI +
+                              " " + requestToString(rr.mRequest));
 
         send(rr);
     }
 
     public void
-    getIMEI(Message result)
-    {
+    getIMEI(Message result) {
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_IMEI, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -771,8 +803,7 @@
     }
 
     public void
-    getIMEISV(Message result)
-    {
+    getIMEISV(Message result) {
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_IMEISV, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -781,14 +812,14 @@
     }
 
 
-    public void 
-    hangupConnection (int gsmIndex, Message result)
-    {
+    public void
+    hangupConnection (int gsmIndex, Message result) {
         if (RILJ_LOGD) riljLog("hangupConnection: gsmIndex=" + gsmIndex);
 
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_HANGUP, result);
 
-        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " " + gsmIndex);
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " " +
+                gsmIndex);
 
         rr.mp.writeInt(1);
         rr.mp.writeInt(gsmIndex);
@@ -796,10 +827,9 @@
         send(rr);
     }
 
-    public void 
-    hangupWaitingOrBackground (Message result)
-    {
-        RILRequest rr = RILRequest.obtain(RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND, 
+    public void
+    hangupWaitingOrBackground (Message result) {
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND,
                                         result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -808,11 +838,10 @@
     }
 
     public void
-    hangupForegroundResumeBackground (Message result)
-    {
-        RILRequest rr 
+    hangupForegroundResumeBackground (Message result) {
+        RILRequest rr
                 = RILRequest.obtain(
-                        RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND, 
+                        RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND,
                                         result);
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
 
@@ -820,11 +849,10 @@
     }
 
     public void
-    switchWaitingOrHoldingAndActive (Message result)
-    {
-        RILRequest rr 
+    switchWaitingOrHoldingAndActive (Message result) {
+        RILRequest rr
                 = RILRequest.obtain(
-                        RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE, 
+                        RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE,
                                         result);
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
 
@@ -832,9 +860,8 @@
     }
 
     public void
-    conference (Message result)
-    {
-        RILRequest rr 
+    conference (Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_CONFERENCE, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -843,10 +870,25 @@
     }
 
 
+    public void setPreferredVoicePrivacy(boolean enable, Message result) {
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE,
+                result);
+
+        rr.mp.writeInt(1);
+        rr.mp.writeInt(enable ? 1:0);
+
+        send(rr);
+    }
+
+    public void getPreferredVoicePrivacy(Message result) {
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE,
+                result);
+        send(rr);
+    }
+
     public void
-    separateConnection (int gsmIndex, Message result)
-    {
-        RILRequest rr 
+    separateConnection (int gsmIndex, Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_SEPARATE_CONNECTION, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
@@ -859,9 +901,8 @@
     }
 
     public void
-    acceptCall (Message result)
-    {
-        RILRequest rr 
+    acceptCall (Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_ANSWER, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -869,10 +910,9 @@
         send(rr);
     }
 
-    public void 
-    rejectCall (Message result)
-    {
-        RILRequest rr 
+    public void
+    rejectCall (Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_UDUB, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -881,8 +921,7 @@
     }
 
     public void
-    explicitCallTransfer (Message result)
-    {
+    explicitCallTransfer (Message result) {
         RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_EXPLICIT_CALL_TRANSFER, result);
 
@@ -892,9 +931,8 @@
     }
 
     public void
-    getLastCallFailCause (Message result)
-    {
-        RILRequest rr 
+    getLastCallFailCause (Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_LAST_CALL_FAIL_CAUSE, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -902,11 +940,21 @@
         send(rr);
     }
 
-    public void 
-    getLastPdpFailCause (Message result)
-    {
-        RILRequest rr 
-                = RILRequest.obtain(RIL_REQUEST_LAST_PDP_FAIL_CAUSE, result);
+    /**
+     * @deprecated
+     */
+    public void
+    getLastPdpFailCause (Message result) {
+        getLastDataCallFailCause (result);
+    }
+
+    /**
+     * The preferred new alternative to getLastPdpFailCause
+     */
+    public void
+    getLastDataCallFailCause (Message result) {
+        RILRequest rr
+                = RILRequest.obtain(RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
 
@@ -914,9 +962,8 @@
     }
 
     public void
-    setMute (boolean enableMute, Message response)
-    {
-        RILRequest rr 
+    setMute (boolean enableMute, Message response) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_SET_MUTE, response);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
@@ -929,9 +976,8 @@
     }
 
     public void
-    getMute (Message response)
-    {
-        RILRequest rr 
+    getMute (Message response) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_GET_MUTE, response);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -940,9 +986,8 @@
     }
 
     public void
-    getSignalStrength (Message result)
-    {
-        RILRequest rr 
+    getSignalStrength (Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_SIGNAL_STRENGTH, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -950,10 +995,9 @@
         send(rr);
     }
 
-    public void 
-    getRegistrationState (Message result)
-    {
-        RILRequest rr 
+    public void
+    getRegistrationState (Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_REGISTRATION_STATE, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -961,10 +1005,9 @@
         send(rr);
     }
 
-    public void 
-    getGPRSRegistrationState (Message result)
-    {
-        RILRequest rr 
+    public void
+    getGPRSRegistrationState (Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_GPRS_REGISTRATION_STATE, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -972,10 +1015,9 @@
         send(rr);
     }
 
-    public void 
-    getOperator(Message result)
-    {
-        RILRequest rr 
+    public void
+    getOperator(Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_OPERATOR, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -983,14 +1025,13 @@
         send(rr);
     }
 
-    public void 
-    sendDtmf(char c, Message result)
-    {
-        RILRequest rr 
+    public void
+    sendDtmf(char c, Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_DTMF, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
-        
+
         rr.mp.writeString(Character.toString(c));
 
         send(rr);
@@ -1020,9 +1061,8 @@
 
 
     public void
-    sendSMS (String smscPDU, String pdu, Message result)
-    {
-        RILRequest rr 
+    sendSMS (String smscPDU, String pdu, Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_SEND_SMS, result);
 
         rr.mp.writeInt(2);
@@ -1030,19 +1070,82 @@
         rr.mp.writeString(pdu);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
-        
+
+        send(rr);
+    }
+
+    public void
+    sendCdmaSms(byte[] pdu, Message result) {
+        int address_nbr_of_digits;
+        int subaddr_nbr_of_digits;
+        int bearerDataLength;
+        ByteArrayInputStream bais = new ByteArrayInputStream(pdu);
+        DataInputStream dis = new DataInputStream(bais);
+
+        RILRequest rr
+                = RILRequest.obtain(RIL_REQUEST_CDMA_SEND_SMS, result);
+
+        try {
+            rr.mp.writeInt(dis.readInt()); //teleServiceId
+            rr.mp.writeByte((byte) dis.readInt()); //servicePresent
+            rr.mp.writeInt(dis.readInt()); //serviceCategory
+            rr.mp.writeInt(dis.read()); //address_digit_mode
+            rr.mp.writeInt(dis.read()); //address_nbr_mode
+            rr.mp.writeInt(dis.read()); //address_ton
+            rr.mp.writeInt(dis.read()); //address_nbr_plan
+            address_nbr_of_digits = (byte) dis.read();
+            rr.mp.writeByte((byte) address_nbr_of_digits);
+            for(int i=0; i < address_nbr_of_digits; i++){
+                rr.mp.writeByte(dis.readByte()); // address_orig_bytes[i]
+            }
+            rr.mp.writeInt(dis.read()); //subaddressType
+            rr.mp.writeByte((byte) dis.read()); //subaddr_odd
+            subaddr_nbr_of_digits = (byte) dis.read();
+            rr.mp.writeByte((byte) subaddr_nbr_of_digits);
+            for(int i=0; i < subaddr_nbr_of_digits; i++){
+                rr.mp.writeByte(dis.readByte()); //subaddr_orig_bytes[i]
+            }
+
+            bearerDataLength = dis.read();
+            rr.mp.writeInt(bearerDataLength);
+            for(int i=0; i < bearerDataLength; i++){
+                rr.mp.writeByte(dis.readByte()); //bearerData[i]
+            }
+        }catch (IOException ex){
+            if (RILJ_LOGD) riljLog("sendSmsCdma: conversion from input stream to object failed: "
+                    + ex);
+        }
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
         send(rr);
     }
 
     public void deleteSmsOnSim(int index, Message response) {
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_DELETE_SMS_ON_SIM,
                 response);
-        
+
         rr.mp.writeInt(1);
         rr.mp.writeInt(index);
 
-        if (RILJ_LOGD) {
-          riljLog(rr.serialString() + "> "
+        if (Config.LOGD) {
+            if (RILJ_LOGD) riljLog(rr.serialString() + "> "
+                    + requestToString(rr.mRequest)
+                    + " " + index);
+        }
+
+        send(rr);
+    }
+
+    public void deleteSmsOnRuim(int index, Message response) {
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM,
+                response);
+
+        rr.mp.writeInt(1);
+        rr.mp.writeInt(index);
+
+        if (Config.LOGD) {
+            if (RILJ_LOGD) riljLog(rr.serialString() + "> "
                     + requestToString(rr.mRequest)
                     + " " + index);
         }
@@ -1052,17 +1155,35 @@
 
     public void writeSmsToSim(int status, String smsc, String pdu, Message response) {
         status = translateStatus(status);
-        
+
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_WRITE_SMS_TO_SIM,
                 response);
-        
+
         rr.mp.writeInt(status);
         rr.mp.writeString(pdu);
         rr.mp.writeString(smsc);
-        
-        if (RILJ_LOGD) {
-          riljLog(rr.serialString() + "> "
-                    + requestToString(rr.mRequest)  
+
+        if (Config.LOGD) {
+            if (RILJ_LOGD) riljLog(rr.serialString() + "> "
+                    + requestToString(rr.mRequest)
+                    + " " + status);
+        }
+
+        send(rr);
+    }
+
+    public void writeSmsToRuim(int status, String pdu, Message response) {
+        status = translateStatus(status);
+
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM,
+                response);
+
+        rr.mp.writeInt(status);
+        rr.mp.writeString(pdu);
+
+        if (Config.LOGD) {
+            if (RILJ_LOGD) riljLog(rr.serialString() + "> "
+                    + requestToString(rr.mRequest)
                     + " " + status);
         }
 
@@ -1075,101 +1196,166 @@
      */
     private int translateStatus(int status) {
         switch(status & 0x7) {
-            case SmsManager.STATUS_ON_SIM_READ:
+            case SmsManager.STATUS_ON_ICC_READ:
                 return 1;
-            case SmsManager.STATUS_ON_SIM_UNREAD:
+            case SmsManager.STATUS_ON_ICC_UNREAD:
                 return 0;
-            case SmsManager.STATUS_ON_SIM_SENT:
+            case SmsManager.STATUS_ON_ICC_SENT:
                 return 3;
-            case SmsManager.STATUS_ON_SIM_UNSENT:
+            case SmsManager.STATUS_ON_ICC_UNSENT:
                 return 2;
         }
-        
+
         // Default to READ.
         return 1;
     }
 
-    public void 
-    setupDefaultPDP(String apn, String user, String password, Message result)
-    {
-        RILRequest rr 
-                = RILRequest.obtain(RIL_REQUEST_SETUP_DEFAULT_PDP, result);
+    /**
+     * @deprecated
+     */
+    public void
+    setupDefaultPDP(String apn, String user, String password, Message result) {
+        String radioTechnology = "1"; //0 for CDMA, 1 for GSM/UMTS
+        String profile = ""; //profile number, NULL for GSM/UMTS
+        setupDataCall(radioTechnology, profile, apn, user,
+                password, result);
 
-        rr.mp.writeInt(3);
+    }
+
+    /**
+     * @deprecated
+     */
+    public void
+    deactivateDefaultPDP(int cid, Message result) {
+        deactivateDataCall(cid, result);
+    }
+
+    /**
+     * The preferred new alternative to setupDefaultPDP that is
+     * CDMA-compatible.
+     *
+     */
+    public void
+    setupDataCall(String radioTechnology, String profile, String apn,
+            String user, String password, Message result) {
+        RILRequest rr
+                = RILRequest.obtain(RIL_REQUEST_SETUP_DATA_CALL, result);
+
+        rr.mp.writeInt(5);
+
+        rr.mp.writeString(radioTechnology);
+        rr.mp.writeString(profile);
         rr.mp.writeString(apn);
         rr.mp.writeString(user);
         rr.mp.writeString(password);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " "
                 + apn);
-        
+
         send(rr);
     }
 
     public void
-    deactivateDefaultPDP(int cid, Message result)
-    {
-        RILRequest rr 
-                = RILRequest.obtain(RIL_REQUEST_DEACTIVATE_DEFAULT_PDP, result);
+    deactivateDataCall(int cid, Message result) {
+        RILRequest rr
+                = RILRequest.obtain(RIL_REQUEST_DEACTIVATE_DATA_CALL, result);
 
         rr.mp.writeInt(1);
         rr.mp.writeString(Integer.toString(cid));
 
-        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " " + cid);
-        
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " +
+                requestToString(rr.mRequest) + " " + cid);
+
         send(rr);
     }
 
     public void
-    setRadioPower(boolean on, Message result)
-    {
-        RILRequest rr 
+    setRadioPower(boolean on, Message result) {
+        //if radio is OFF set preferred NW type and cmda subscription
+        if(mInitialRadioStateChange) {
+            synchronized (mStateMonitor) {
+                if (!mState.isOn()) {
+                    RILRequest rrPnt = RILRequest.obtain(
+                                   RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, null);
+
+                    rrPnt.mp.writeInt(1);
+                    rrPnt.mp.writeInt(mNetworkMode);
+                    if (RILJ_LOGD) riljLog(rrPnt.serialString() + "> "
+                        + requestToString(rrPnt.mRequest) + " : " + mNetworkMode);
+
+                    send(rrPnt);
+
+                    RILRequest rrCs = RILRequest.obtain(
+                                   RIL_REQUEST_CDMA_SET_SUBSCRIPTION, null);
+                    rrCs.mp.writeInt(1);
+                    rrCs.mp.writeInt(mCdmaSubscription);
+                    if (RILJ_LOGD) riljLog(rrCs.serialString() + "> "
+                    + requestToString(rrCs.mRequest) + " : " + mCdmaSubscription);
+                    send(rrCs);
+                }
+            }
+        }
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_RADIO_POWER, result);
 
         rr.mp.writeInt(1);
         rr.mp.writeInt(on ? 1 : 0);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
-        
+
         send(rr);
     }
 
     public void
-    setSuppServiceNotifications(boolean enable, Message result)
-    {
-        RILRequest rr 
+    setSuppServiceNotifications(boolean enable, Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION, result);
 
         rr.mp.writeInt(1);
         rr.mp.writeInt(enable ? 1 : 0);
-        
+
         if (RILJ_LOGD) riljLog(rr.serialString() + "> "
-                    + requestToString(rr.mRequest));
+                + requestToString(rr.mRequest));
 
         send(rr);
     }
 
-    public void 
-    acknowledgeLastIncomingSMS(boolean success, Message result)
-    {
-        RILRequest rr 
+    public void
+    acknowledgeLastIncomingSMS(boolean success, Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_SMS_ACKNOWLEDGE, result);
 
         rr.mp.writeInt(1);
         rr.mp.writeInt(success ? 1 : 0);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
-        
+
         send(rr);
     }
-    
+
     public void
-    simIO (int command, int fileid, String path, int p1, int p2, int p3, 
-            String data, String pin2, Message result)
-    {
-        RILRequest rr 
+    acknowledgeLastIncomingCdmaSms(boolean success, Message result) {
+        RILRequest rr
+                = RILRequest.obtain(RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE, result);
+
+        rr.mp.writeInt(success ? 0 : 1); //RIL_CDMA_SMS_ErrorClass
+        // cause code according to X.S004-550E
+        rr.mp.writeInt(39); //39 means other terminal problem; is not interpreted for success.
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
+        send(rr);
+    }
+
+
+    public void
+    iccIO (int command, int fileid, String path, int p1, int p2, int p3,
+            String data, String pin2, Message result) {
+        //Note: This RIL request has not been renamed to ICC,
+        //       but this request is also valid for SIM and RUIM
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_SIM_IO, result);
-                
+
         rr.mp.writeInt(command);
         rr.mp.writeInt(fileid);
         rr.mp.writeString(path);
@@ -1179,51 +1365,48 @@
         rr.mp.writeString(data);
         rr.mp.writeString(pin2);
 
-        if (RILJ_LOGD) riljLog(rr.serialString() + "> simIO: " + requestToString(rr.mRequest)
-                + " 0x" + Integer.toHexString(command) 
-                + " 0x" + Integer.toHexString(fileid) + " " 
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> iccIO: " + requestToString(rr.mRequest)
+                + " 0x" + Integer.toHexString(command)
+                + " 0x" + Integer.toHexString(fileid) + " "
                 + p1 + "," + p2 + "," + p3);
-        
-        send(rr);
-    }
-    
-    public void
-    getCLIR(Message result)
-    {
-        RILRequest rr 
-                = RILRequest.obtain(RIL_REQUEST_GET_CLIR, result);
-            
-        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
-        
+
         send(rr);
     }
 
     public void
-    setCLIR(int clirMode, Message result)
-    {
-        RILRequest rr 
+    getCLIR(Message result) {
+        RILRequest rr
+                = RILRequest.obtain(RIL_REQUEST_GET_CLIR, result);
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
+        send(rr);
+    }
+
+    public void
+    setCLIR(int clirMode, Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_SET_CLIR, result);
 
         // count ints
         rr.mp.writeInt(1);
 
         rr.mp.writeInt(clirMode);
-            
+
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
                     + " " + clirMode);
-        
+
         send(rr);
     }
 
     public void
-    queryCallWaiting(int serviceClass, Message response)
-    {
-        RILRequest rr 
+    queryCallWaiting(int serviceClass, Message response) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_QUERY_CALL_WAITING, response);
 
         rr.mp.writeInt(1);
         rr.mp.writeInt(serviceClass);
-            
+
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
                     + " " + serviceClass);
 
@@ -1231,77 +1414,71 @@
     }
 
     public void
-    setCallWaiting(boolean enable, int serviceClass, Message response)
-    {
-        RILRequest rr 
+    setCallWaiting(boolean enable, int serviceClass, Message response) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_SET_CALL_WAITING, response);
-        
+
         rr.mp.writeInt(2);
         rr.mp.writeInt(enable ? 1 : 0);
         rr.mp.writeInt(serviceClass);
-        
+
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
                 + " " + enable + ", " + serviceClass);
-        
+
         send(rr);
     }
 
     public void
-    setNetworkSelectionModeAutomatic(Message response)
-    {
-        RILRequest rr 
-                = RILRequest.obtain(RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC, 
+    setNetworkSelectionModeAutomatic(Message response) {
+        RILRequest rr
+                = RILRequest.obtain(RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC,
                                     response);
-            
+
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
-        
+
         send(rr);
     }
 
-    public void 
-    setNetworkSelectionModeManual(String operatorNumeric, Message response)
-    {
-        RILRequest rr 
-                = RILRequest.obtain(RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL, 
+    public void
+    setNetworkSelectionModeManual(String operatorNumeric, Message response) {
+        RILRequest rr
+                = RILRequest.obtain(RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL,
                                     response);
-            
+
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
                     + " " + operatorNumeric);
 
         rr.mp.writeString(operatorNumeric);
-        
-        send(rr);
-    }
 
-    public void 
-    getNetworkSelectionMode(Message response)
-    {
-        RILRequest rr 
-                = RILRequest.obtain(RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE, 
-                                    response);
-            
-        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
-        
-        send(rr);
-    }
-
-    public void 
-    getAvailableNetworks(Message response)
-    {
-        RILRequest rr 
-                = RILRequest.obtain(RIL_REQUEST_QUERY_AVAILABLE_NETWORKS, 
-                                    response);
-            
-        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
-        
         send(rr);
     }
 
     public void
-    setCallForward(int action, int cfReason, int serviceClass, 
-                String number, int timeSeconds, Message response)
-    {
-        RILRequest rr 
+    getNetworkSelectionMode(Message response) {
+        RILRequest rr
+                = RILRequest.obtain(RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE,
+                                    response);
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
+        send(rr);
+    }
+
+    public void
+    getAvailableNetworks(Message response) {
+        RILRequest rr
+                = RILRequest.obtain(RIL_REQUEST_QUERY_AVAILABLE_NETWORKS,
+                                    response);
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
+        send(rr);
+    }
+
+    public void
+    setCallForward(int action, int cfReason, int serviceClass,
+                String number, int timeSeconds, Message response) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_SET_CALL_FORWARD, response);
 
         rr.mp.writeInt(action);
@@ -1310,19 +1487,18 @@
         rr.mp.writeInt(PhoneNumberUtils.toaFromString(number));
         rr.mp.writeString(number);
         rr.mp.writeInt (timeSeconds);
-            
+
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
-                    + " " + action + " " + cfReason + " " + serviceClass 
+                    + " " + action + " " + cfReason + " " + serviceClass
                     + timeSeconds);
-        
+
         send(rr);
     }
 
     public void
     queryCallForwardStatus(int cfReason, int serviceClass,
-                String number, Message response)
-    {
-        RILRequest rr 
+                String number, Message response) {
+        RILRequest rr
             = RILRequest.obtain(RIL_REQUEST_QUERY_CALL_FORWARD_STATUS, response);
 
         rr.mp.writeInt(2); // 2 is for query action, not in used anyway
@@ -1331,7 +1507,7 @@
         rr.mp.writeInt(PhoneNumberUtils.toaFromString(number));
         rr.mp.writeString(number);
         rr.mp.writeInt (0);
-                                     
+
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
                 + " " + cfReason + " " + serviceClass);
 
@@ -1339,8 +1515,7 @@
     }
 
     public void
-    queryCLIP(Message response)
-    {
+    queryCLIP(Message response) {
         RILRequest rr
             = RILRequest.obtain(RIL_REQUEST_QUERY_CLIP, response);
 
@@ -1351,11 +1526,10 @@
 
 
     public void
-    getBasebandVersion (Message response) 
-    {
-        RILRequest rr 
+    getBasebandVersion (Message response) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_BASEBAND_VERSION, response);
-        
+
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
 
         send(rr);
@@ -1363,14 +1537,13 @@
 
     public void
     queryFacilityLock (String facility, String password, int serviceClass,
-                            Message response)
-    {
+                            Message response) {
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_QUERY_FACILITY_LOCK, response);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
 
         // count strings
-        rr.mp.writeInt(3);        
+        rr.mp.writeInt(3);
 
         rr.mp.writeString(facility);
         rr.mp.writeString(password);
@@ -1382,8 +1555,7 @@
 
     public void
     setFacilityLock (String facility, boolean lockState, String password,
-                        int serviceClass, Message response)
-    {
+                        int serviceClass, Message response) {
         String lockString;
          RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_SET_FACILITY_LOCK, response);
@@ -1402,11 +1574,10 @@
         send(rr);
 
     }
-                        
+
     public void
-    sendUSSD (String ussdString, Message response)
-    {
-        RILRequest rr 
+    sendUSSD (String ussdString, Message response) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_SEND_USSD, response);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
@@ -1429,9 +1600,8 @@
     }
 
 
-    public void resetRadio(Message result)
-    {
-        RILRequest rr 
+    public void resetRadio(Message result) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_RESET_RADIO, result);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -1439,13 +1609,12 @@
         send(rr);
     }
 
-    public void invokeOemRilRequestRaw(byte[] data, Message response)
-    {
-        RILRequest rr 
+    public void invokeOemRilRequestRaw(byte[] data, Message response) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_OEM_HOOK_RAW, response);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
-               + "[" + SimUtils.bytesToHexString(data) + "]");
+               + "[" + IccUtils.bytesToHexString(data) + "]");
 
         rr.mp.writeByteArray(data);
 
@@ -1453,9 +1622,8 @@
 
     }
 
-    public void invokeOemRilRequestStrings(String[] strings, Message response)
-    {
-        RILRequest rr 
+    public void invokeOemRilRequestStrings(String[] strings, Message response) {
+        RILRequest rr
                 = RILRequest.obtain(RIL_REQUEST_OEM_HOOK_STRINGS, response);
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
@@ -1592,29 +1760,27 @@
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_SET_LOCATION_UPDATES, response);
         rr.mp.writeInt(1);
         rr.mp.writeInt(enable ? 1 : 0);
-        
+
         if (RILJ_LOGD) riljLog(rr.serialString() + "> "
                 + requestToString(rr.mRequest) + ": " + enable);
-        
+
         send(rr);
     }
 
     //***** Private Methods
 
-    private void sendScreenState(boolean on)
-    {
+    private void sendScreenState(boolean on) {
         RILRequest rr = RILRequest.obtain(RIL_REQUEST_SCREEN_STATE, null);
         rr.mp.writeInt(1);
         rr.mp.writeInt(on ? 1 : 0);
-        
+
         if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + ": " + on);
-        
+
         send(rr);
     }
-    
+
     protected void
-    onRadioAvailable()
-    {
+    onRadioAvailable() {
         // In case screen state was lost (due to process crash),
         // this ensures that the RIL knows the correct screen state.
 
@@ -1633,13 +1799,18 @@
             case 2: newState = RadioState.SIM_NOT_READY; break;
             case 3: newState = RadioState.SIM_LOCKED_OR_ABSENT; break;
             case 4: newState = RadioState.SIM_READY; break;
-            default: 
+            case 5: newState = RadioState.RUIM_NOT_READY; break;
+            case 6: newState = RadioState.RUIM_READY; break;
+            case 7: newState = RadioState.RUIM_LOCKED_OR_ABSENT; break;
+            case 8: newState = RadioState.NV_NOT_READY; break;
+            case 9: newState = RadioState.NV_READY; break;
+
+            default:
                 throw new RuntimeException(
                             "Unrecognized RIL_RadioState: " +state);
         }
 
         if (mInitialRadioStateChange) {
-            mInitialRadioStateChange = false;
             if (newState.isOn()) {
                 /* If this is our first notification, make sure the radio
                  * is powered off.  This gets the radio into a known state,
@@ -1648,12 +1819,15 @@
                  * and/or radio knowing.
                  */
                 if (RILJ_LOGD) Log.d(LOG_TAG, "Radio ON @ init; reset to OFF");
-                setRadioPower(false, null);
-                return;
+                    setRadioPower(false, null);
+            } else {
+                if (DBG) Log.d(LOG_TAG, "Radio OFF @ init");
+                setRadioState(newState);
             }
+            mInitialRadioStateChange = false;
+        } else {
+            setRadioState(newState);
         }
-
-        setRadioState(newState);
     }
 
     /**
@@ -1661,13 +1835,12 @@
      * a) There is outstanding RIL request sent to RIL deamon and no replied
      * b) There is a request waiting to be sent out.
      *
-     * There is a WAKE_LOCK_TIMEOUT to release the lock, though it shouldn't 
+     * There is a WAKE_LOCK_TIMEOUT to release the lock, though it shouldn't
      * happen often.
      */
 
     private void
-    acquireWakeLock()
-    {
+    acquireWakeLock() {
         synchronized (mWakeLock) {
             mWakeLock.acquire();
             mRequestMessagesPending++;
@@ -1679,8 +1852,7 @@
     }
 
     private void
-    releaseWakeLockIfDone()
-    {
+    releaseWakeLockIfDone() {
         synchronized (mWakeLock) {
             if (mWakeLock.isHeld() &&
                 (mRequestMessagesPending == 0) &&
@@ -1692,8 +1864,7 @@
     }
 
     private void
-    send(RILRequest rr)
-    {
+    send(RILRequest rr) {
         Message msg;
 
         msg = mSender.obtainMessage(EVENT_SEND, rr);
@@ -1704,8 +1875,7 @@
     }
 
     private void
-    processResponse (Parcel p)
-    {
+    processResponse (Parcel p) {
         int type;
 
         type = p.readInt();
@@ -1714,15 +1884,12 @@
             processUnsolicited (p);
         } else if (type == RESPONSE_SOLICITED) {
             processSolicited (p);
-        }        
+        }
 
         releaseWakeLockIfDone();
     }
 
-
-    
-    private RILRequest findAndRemoveRequestFromList(int serial)
-    {
+    private RILRequest findAndRemoveRequestFromList(int serial) {
         synchronized (mRequestsList) {
             for (int i = 0, s = mRequestsList.size() ; i < s ; i++) {
                 RILRequest rr = mRequestsList.get(i);
@@ -1738,8 +1905,7 @@
     }
 
     private void
-    processSolicited (Parcel p)
-    {
+    processSolicited (Parcel p) {
         int serial, error;
         boolean found = false;
 
@@ -1751,7 +1917,7 @@
         rr = findAndRemoveRequestFromList(serial);
 
         if (rr == null) {
-            Log.w(LOG_TAG, "Unexpected solicited response! sn: " 
+            Log.w(LOG_TAG, "Unexpected solicited response! sn: "
                             + serial + " error: " + error);
             return;
         }
@@ -1763,14 +1929,14 @@
         }
 
         Object ret;
-        
+
         try {switch (rr.mRequest) {
 /*
  cat libs/telephony/ril_commands.h \
  | egrep "^ *{RIL_" \
  | sed -re 's/\{([^,]+),[^,]+,([^}]+).+/case \1: ret = \2(p); break;/'
 */
-            case RIL_REQUEST_GET_SIM_STATUS: ret =  responseSimStatus(p); break;
+            case RIL_REQUEST_GET_SIM_STATUS: ret =  responseIccCardStatus(p); break;
             case RIL_REQUEST_ENTER_SIM_PIN: ret =  responseVoid(p); break;
             case RIL_REQUEST_ENTER_SIM_PUK: ret =  responseVoid(p); break;
             case RIL_REQUEST_ENTER_SIM_PIN2: ret =  responseVoid(p); break;
@@ -1796,8 +1962,8 @@
             case RIL_REQUEST_DTMF: ret =  responseVoid(p); break;
             case RIL_REQUEST_SEND_SMS: ret =  responseSMS(p); break;
             case RIL_REQUEST_SEND_SMS_EXPECT_MORE: ret =  responseSMS(p); break;
-            case RIL_REQUEST_SETUP_DEFAULT_PDP: ret =  responseStrings(p); break;
-            case RIL_REQUEST_SIM_IO: ret =  responseSIM_IO(p); break;
+            case RIL_REQUEST_SETUP_DATA_CALL: ret =  responseStrings(p); break;
+            case RIL_REQUEST_SIM_IO: ret =  responseICC_IO(p); break;
             case RIL_REQUEST_SEND_USSD: ret =  responseVoid(p); break;
             case RIL_REQUEST_CANCEL_USSD: ret =  responseVoid(p); break;
             case RIL_REQUEST_GET_CLIR: ret =  responseInts(p); break;
@@ -1810,7 +1976,7 @@
             case RIL_REQUEST_GET_IMEI: ret =  responseString(p); break;
             case RIL_REQUEST_GET_IMEISV: ret =  responseString(p); break;
             case RIL_REQUEST_ANSWER: ret =  responseVoid(p); break;
-            case RIL_REQUEST_DEACTIVATE_DEFAULT_PDP: ret =  responseVoid(p); break;
+            case RIL_REQUEST_DEACTIVATE_DATA_CALL: ret =  responseVoid(p); break;
             case RIL_REQUEST_QUERY_FACILITY_LOCK: ret =  responseInts(p); break;
             case RIL_REQUEST_SET_FACILITY_LOCK: ret =  responseVoid(p); break;
             case RIL_REQUEST_CHANGE_BARRING_PASSWORD: ret =  responseVoid(p); break;
@@ -1822,39 +1988,61 @@
             case RIL_REQUEST_DTMF_STOP: ret =  responseVoid(p); break;
             case RIL_REQUEST_BASEBAND_VERSION: ret =  responseString(p); break;
             case RIL_REQUEST_SEPARATE_CONNECTION: ret =  responseVoid(p); break;
-            case RIL_REQUEST_SET_MUTE: ret =responseVoid(p); break;
-            case RIL_REQUEST_GET_MUTE: ret = responseInts(p); break;
-            case RIL_REQUEST_QUERY_CLIP: ret = responseInts(p); break;
-            case RIL_REQUEST_LAST_PDP_FAIL_CAUSE: ret = responseInts(p); break;
-            case RIL_REQUEST_PDP_CONTEXT_LIST: ret =  responseContextList(p); break;
-            case RIL_REQUEST_RESET_RADIO: ret = responseVoid(p); break;
-            case RIL_REQUEST_OEM_HOOK_RAW: ret = responseRaw(p); break;
-            case RIL_REQUEST_OEM_HOOK_STRINGS: ret = responseStrings(p); break;
+            case RIL_REQUEST_SET_MUTE: ret =  responseVoid(p); break;
+            case RIL_REQUEST_GET_MUTE: ret =  responseInts(p); break;
+            case RIL_REQUEST_QUERY_CLIP: ret =  responseInts(p); break;
+            case RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE: ret =  responseInts(p); break;
+            case RIL_REQUEST_DATA_CALL_LIST: ret =  responseDataCallList(p); break;
+            case RIL_REQUEST_RESET_RADIO: ret =  responseVoid(p); break;
+            case RIL_REQUEST_OEM_HOOK_RAW: ret =  responseRaw(p); break;
+            case RIL_REQUEST_OEM_HOOK_STRINGS: ret =  responseStrings(p); break;
             case RIL_REQUEST_SCREEN_STATE: ret =  responseVoid(p); break;
-            case RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION: ret = responseVoid(p); break;
-            case RIL_REQUEST_WRITE_SMS_TO_SIM: ret = responseInts(p); break;
-            case RIL_REQUEST_DELETE_SMS_ON_SIM: ret = responseVoid(p); break;
-            case RIL_REQUEST_SET_BAND_MODE: ret = responseVoid(p); break;
-            case RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE: ret = responseInts(p); break;
-            case RIL_REQUEST_STK_GET_PROFILE: ret = responseString(p); break;
-            case RIL_REQUEST_STK_SET_PROFILE: ret = responseVoid(p); break;
-            case RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND: ret = responseString(p); break;
-            case RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE: ret = responseVoid(p); break;
-            case RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM: ret = responseInts(p); break;
-            case RIL_REQUEST_EXPLICIT_CALL_TRANSFER: ret = responseVoid(p); break;
-            case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE: ret = responseVoid(p); break;
-            case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE: ret = responseInts(p); break;
+            case RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION: ret =  responseVoid(p); break;
+            case RIL_REQUEST_WRITE_SMS_TO_SIM: ret =  responseInts(p); break;
+            case RIL_REQUEST_DELETE_SMS_ON_SIM: ret =  responseVoid(p); break;
+            case RIL_REQUEST_SET_BAND_MODE: ret =  responseVoid(p); break;
+            case RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE: ret =  responseInts(p); break;
+            case RIL_REQUEST_STK_GET_PROFILE: ret =  responseString(p); break;
+            case RIL_REQUEST_STK_SET_PROFILE: ret =  responseVoid(p); break;
+            case RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND: ret =  responseString(p); break;
+            case RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE: ret =  responseVoid(p); break;
+            case RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM: ret =  responseInts(p); break;
+            case RIL_REQUEST_EXPLICIT_CALL_TRANSFER: ret =  responseVoid(p); break;
+            case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE: ret =  responseVoid(p); break;
+            case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE: ret =  responseInts(p); break;
             case RIL_REQUEST_GET_NEIGHBORING_CELL_IDS: ret = responseCellList(p); break;
-            case  RIL_REQUEST_SET_LOCATION_UPDATES: ret = responseVoid(p); break;
-
+            case RIL_REQUEST_SET_LOCATION_UPDATES: ret =  responseVoid(p); break;
+            case RIL_REQUEST_CDMA_SET_SUBSCRIPTION: ret =  responseVoid(p); break;
+            case RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE: ret =  responseVoid(p); break;
+            case RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE: ret =  responseInts(p); break;
+            case RIL_REQUEST_SET_TTY_MODE: ret =  responseVoid(p); break;
+            case RIL_REQUEST_QUERY_TTY_MODE: ret =  responseInts(p); break;
+            case RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE: ret =  responseVoid(p); break;
+            case RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE: ret =  responseInts(p); break;
+            case RIL_REQUEST_CDMA_FLASH: ret =  responseVoid(p); break;
+            case RIL_REQUEST_CDMA_BURST_DTMF: ret =  responseVoid(p); break;
+            case RIL_REQUEST_CDMA_SEND_SMS: ret =  responseVoid(p); break;
+            case RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE: ret =  responseVoid(p); break;
+            case RIL_REQUEST_GET_BROADCAST_CONFIG: ret =  responseBR_SMS_CNF(p); break;
+            case RIL_REQUEST_SET_BROADCAST_CONFIG: ret =  responseVoid(p); break;
+            case RIL_REQUEST_CDMA_GET_BROADCAST_CONFIG: ret =  responseCDMA_BR_CNF(p); break;
+            case RIL_REQUEST_CDMA_SET_BROADCAST_CONFIG: ret =  responseVoid(p); break;
+            case RIL_REQUEST_BROADCAST_ACTIVATION: ret =  responseVoid(p); break;
+            case RIL_REQUEST_CDMA_VALIDATE_AKEY: ret =  responseVoid(p); break;
+            case RIL_REQUEST_CDMA_BROADCAST_ACTIVATION: ret =  responseVoid(p); break;
+            case RIL_REQUEST_CDMA_SUBSCRIPTION: ret =  responseStrings(p); break;
+            case RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM: ret =  responseInts(p); break;
+            case RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM: ret =  responseVoid(p); break;
+            case RIL_REQUEST_DEVICE_IDENTITY: ret =  responseStrings(p); break;
             default:
-                throw new RuntimeException("Unrecognized solicited response: " + rr.mRequest); 
+                throw new RuntimeException("Unrecognized solicited response: " + rr.mRequest);
             //break;
         }} catch (Throwable tr) {
             // Exceptions here usually mean invalid RIL responses
-            
-            Log.w(LOG_TAG, rr.serialString() + "< " 
-                    + requestToString(rr.mRequest) + " exception, possible invalid RIL response", tr);
+
+            Log.w(LOG_TAG, rr.serialString() + "< "
+                    + requestToString(rr.mRequest)
+                    + " exception, possible invalid RIL response", tr);
 
             if (rr.mResult != null) {
                 AsyncResult.forMessage(rr.mResult, null, tr);
@@ -1866,18 +2054,17 @@
 
         if (RILJ_LOGD) riljLog(rr.serialString() + "< " + requestToString(rr.mRequest)
             + " " + retToString(rr.mRequest, ret));
-        
+
         if (rr.mResult != null) {
             AsyncResult.forMessage(rr.mResult, ret, null);
             rr.mResult.sendToTarget();
         }
-        
+
         rr.release();
     }
 
     private String
-    retToString(int req, Object ret)
-    {
+    retToString(int req, Object ret) {
         if (ret == null) return "";
         switch (req) {
             // Don't log these return values, for privacy's sake.
@@ -1938,8 +2125,7 @@
     }
 
     private void
-    processUnsolicited (Parcel p)
-    {
+    processUnsolicited (Parcel p) {
         int response;
         Object ret;
 
@@ -1961,7 +2147,7 @@
             case RIL_UNSOL_ON_USSD: ret =  responseStrings(p); break;
             case RIL_UNSOL_NITZ_TIME_RECEIVED: ret =  responseString(p); break;
             case RIL_UNSOL_SIGNAL_STRENGTH: ret = responseInts(p); break;
-            case RIL_UNSOL_PDP_CONTEXT_LIST_CHANGED: ret = responseContextList(p);break;
+            case RIL_UNSOL_DATA_CALL_LIST_CHANGED: ret = responseDataCallList(p);break;
             case RIL_UNSOL_SUPP_SVC_NOTIFICATION: ret = responseSuppServiceNotification(p); break;
             case RIL_UNSOL_STK_SESSION_END: ret = responseVoid(p); break;
             case RIL_UNSOL_STK_PROACTIVE_COMMAND: ret = responseString(p); break;
@@ -1971,8 +2157,12 @@
             case RIL_UNSOL_SIM_REFRESH: ret =  responseInts(p); break;
             case RIL_UNSOL_CALL_RING: ret =  responseVoid(p); break;
             case RIL_UNSOL_RESTRICTED_STATE_CHANGED: ret = responseInts(p); break;
-            default: 
-                throw new RuntimeException("Unrecognized unsol response: " + response); 
+            case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED:  ret =  responseVoid(p); break;
+            case RIL_UNSOL_RESPONSE_CDMA_NEW_SMS:  ret =  responseCdmaSms(p); break;
+            case RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS:  ret =  responseString(p); break;
+            case RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL:  ret =  responseVoid(p); break;
+            default:
+                throw new RuntimeException("Unrecognized unsol response: " + response);
             //break; (implied)
         }} catch (Throwable tr) {
             Log.e(LOG_TAG, "Exception processing unsol response: " + response + 
@@ -1984,7 +2174,7 @@
             case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED:
                 /* has bonus radio state int */
                 setRadioStateFromRILInt(p.readInt());
-                
+
                 if (RILJ_LOGD) unsljLogMore(response, mState.toString());
             break;
             case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:
@@ -2009,7 +2199,7 @@
 
                 SmsMessage sms;
 
-                sms = SmsMessage.newFromCMT(a);                
+                sms = SmsMessage.newFromCMT(a);
                 if (mSMSRegistrant != null) {
                     mSMSRegistrant
                         .notifyRegistrant(new AsyncResult(null, sms, null));
@@ -2041,7 +2231,7 @@
             break;
             case RIL_UNSOL_ON_USSD:
                 String[] resp = (String[])ret;
-                
+
                 if (resp.length < 2) {
                     resp = new String[2];
                     resp[0] = ((String[])ret)[0];
@@ -2053,7 +2243,7 @@
                         new AsyncResult (null, resp, null));
                 }
             break;
-            case RIL_UNSOL_NITZ_TIME_RECEIVED:            
+            case RIL_UNSOL_NITZ_TIME_RECEIVED:
                 if (RILJ_LOGD) unsljLogRet(response, ret);
 
                 // has bonus long containing milliseconds since boot that the NITZ
@@ -2066,7 +2256,7 @@
                 result[1] = Long.valueOf(nitzReceiveTime);
 
                 if (mNITZTimeRegistrant != null) {
-                
+
                     mNITZTimeRegistrant
                         .notifyRegistrant(new AsyncResult (null, result, null));
                 } else {
@@ -2074,22 +2264,21 @@
                     mLastNITZTimeInfo = result;
                 }
             break;
-            
+
             case RIL_UNSOL_SIGNAL_STRENGTH:
                 // Note this is set to "verbose" because it happens
                 // frequently
                 if (RILJ_LOGV) unsljLogvRet(response, ret);
-                
+
                 if (mSignalStrengthRegistrant != null) {
                     mSignalStrengthRegistrant.notifyRegistrant(
                                         new AsyncResult (null, ret, null));
                 }
             break;
-            case RIL_UNSOL_PDP_CONTEXT_LIST_CHANGED:
+            case RIL_UNSOL_DATA_CALL_LIST_CHANGED:
                 if (RILJ_LOGD) unsljLogRet(response, ret);
 
-                mPDPRegistrants
-                    .notifyRegistrants(new AsyncResult(null, ret, null));
+                mDataConnectionRegistrants.notifyRegistrants(new AsyncResult(null, ret, null));
             break;
 
             case RIL_UNSOL_SUPP_SVC_NOTIFICATION:
@@ -2140,21 +2329,21 @@
             case RIL_UNSOL_SIM_SMS_STORAGE_FULL:
                 if (RILJ_LOGD) unsljLog(response);
 
-                if (mSimSmsFullRegistrant != null) {
-                    mSimSmsFullRegistrant.notifyRegistrant();
+                if (mIccSmsFullRegistrant != null) {
+                    mIccSmsFullRegistrant.notifyRegistrant();
                 }
                 break;
 
-            case RIL_UNSOL_SIM_REFRESH: 
+            case RIL_UNSOL_SIM_REFRESH:
                 if (RILJ_LOGD) unsljLogRet(response, ret);
 
-                if (mSimRefreshRegistrant != null) {
-                    mSimRefreshRegistrant.notifyRegistrant(
+                if (mIccRefreshRegistrant != null) {
+                    mIccRefreshRegistrant.notifyRegistrant(
                             new AsyncResult (null, ret, null));
                 }
                 break;
-                
-            case RIL_UNSOL_CALL_RING: 
+
+            case RIL_UNSOL_CALL_RING:
                 if (RILJ_LOGD) unsljLog(response);
                 
                 if (mRingRegistrant != null) {
@@ -2168,12 +2357,40 @@
                     mRestrictedStateRegistrant.notifyRegistrant(
                                         new AsyncResult (null, ret, null));
                 }
+                
+            case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED:
+                if (mIccStatusChangedRegistrants != null) {
+                    mIccStatusChangedRegistrants.notifyRegistrants();
+                }
+                break;
+
+            case RIL_UNSOL_RESPONSE_CDMA_NEW_SMS:
+                SmsMessage sms = (SmsMessage) ret;
+
+                if (mSMSRegistrant != null) {
+                    mSMSRegistrant
+                        .notifyRegistrant(new AsyncResult(null, sms, null));
+                }
+                break;
+
+            case RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS:
+                // TODO T: waiting for SMS BC feature
+                break;
+
+            case RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL:
+                if (Config.LOGD) {
+                    if (RILJ_LOGD) riljLog("[UNSL]< RUIM_SMS_STORAGE_FULL");
+                }
+
+                if (mIccSmsFullRegistrant != null) {
+                    mIccSmsFullRegistrant.notifyRegistrant();
+                }
+                break;
         }
     }
 
     private Object
-    responseInts(Parcel p)
-    {
+    responseInts(Parcel p) {
         int numInts;
         int response[];
 
@@ -2190,14 +2407,12 @@
 
 
     private Object
-    responseVoid(Parcel p)
-    {
+    responseVoid(Parcel p) {
         return null;
     }
 
     private Object
-    responseCallForward(Parcel p)
-    {
+    responseCallForward(Parcel p) {
         int numInfos;
         CallForwardInfo infos[];
 
@@ -2220,22 +2435,28 @@
     }
 
     private Object
-    responseSuppServiceNotification(Parcel p)
-    {
+    responseSuppServiceNotification(Parcel p) {
         SuppServiceNotification notification = new SuppServiceNotification();
-        
+
         notification.notificationType = p.readInt();
         notification.code = p.readInt();
         notification.index = p.readInt();
         notification.type = p.readInt();
         notification.number = p.readString();
-        
+
         return notification;
     }
-    
+
     private Object
-    responseString(Parcel p)
-    {
+    responseCdmaSms(Parcel p) {
+        SmsMessage sms;
+        sms = SmsMessage.newFromParcel(p);
+
+        return sms;
+    }
+
+    private Object
+    responseString(Parcel p) {
         String response;
 
         response = p.readString();
@@ -2244,8 +2465,7 @@
     }
 
     private Object
-    responseStrings(Parcel p)
-    {
+    responseStrings(Parcel p) {
         int num;
         String response[];
 
@@ -2259,13 +2479,12 @@
                 response[i] = p.readString();
             }
         }
-        
+
         return response;
     }
 
     private Object
-    responseRaw(Parcel p)
-    {
+    responseRaw(Parcel p) {
         int num;
         byte response[];
 
@@ -2275,8 +2494,7 @@
     }
 
     private Object
-    responseSMS(Parcel p)
-    {
+    responseSMS(Parcel p) {
         int messageRef;
         String ackPDU;
 
@@ -2290,46 +2508,110 @@
 
 
     private Object
-    responseSIM_IO(Parcel p)
-    {
+     responseICC_IO(Parcel p) {
         int sw1, sw2;
         byte data[] = null;
         Message ret;
-        
+
         sw1 = p.readInt();
         sw2 = p.readInt();
 
         String s = p.readString();
 
-        return new SimIoResult(sw1, sw2, s);
+        return new IccIoResult(sw1, sw2, s);
     }
 
     private Object
-    responseSimStatus(Parcel p)
-    {
-        int status;
+    responseIccCardStatus(Parcel p) {
+        RadioState currentRadioState;
+        IccCardApplication ca;
 
-        status = ((int[])responseInts(p))[0];
-        switch (status){
-            case RIL_SIM_ABSENT:    return SimStatus.SIM_ABSENT;
-            case RIL_SIM_NOT_READY: return SimStatus.SIM_NOT_READY;
-            case RIL_SIM_READY:     return SimStatus.SIM_READY;
-            case RIL_SIM_PIN:       return SimStatus.SIM_PIN;
-            case RIL_SIM_PUK:       return SimStatus.SIM_PUK;
-            case RIL_SIM_NETWORK_PERSONALIZATION:   
-                                    return SimStatus.SIM_NETWORK_PERSONALIZATION;
-            default:
-                // Unrecognized SIM status.  Treat it like a missing SIM.
-                Log.e(LOG_TAG, "Unrecognized RIL_REQUEST_GET_SIM_STATUS result: " + status);
-                return SimStatus.SIM_ABSENT;
+        currentRadioState = getRadioState();
+
+        IccCardStatus status = new IccCardStatus();
+        status.card_state                      = status.CardStateFromRILInt(p.readInt());
+        status.universal_pin_state             = status.PinStateFromRILInt(p.readInt());
+        status.gsm_umts_subscription_app_index = p.readInt();
+        status.cdma_subscription_app_index     = p.readInt();
+        status.num_applications                = p.readInt();
+
+        // limit to maximum allowed applications
+        if (status.num_applications > IccCardStatus.CARD_MAX_APPS) {
+            status.num_applications = IccCardStatus.CARD_MAX_APPS;
         }
+
+        for (int i = 0 ; i < status.num_applications ; i++) {
+            ca = new IccCardApplication();
+            ca.app_type       = ca.AppTypeFromRILInt(p.readInt());
+            ca.app_state      = ca.AppStateFromRILInt(p.readInt());
+            ca.perso_substate = ca.PersoSubstateFromRILInt(p.readInt());
+            ca.aid            = p.readString();
+            ca.app_label      = p.readString();
+            ca.pin1_replaced  = p.readInt();
+            ca.pin1           = p.readInt();
+            ca.pin2           = p.readInt();
+            status.application.add(ca);
+        }
+
+        // this is common for all radio technologies
+        if (!status.card_state.isCardPresent()) {
+            return IccStatus.ICC_ABSENT;
+        }
+
+        // check radio technology
+        if( currentRadioState == RadioState.RADIO_OFF         ||
+            currentRadioState == RadioState.RADIO_UNAVAILABLE ||
+            currentRadioState == RadioState.SIM_NOT_READY     ||
+            currentRadioState == RadioState.RUIM_NOT_READY    ||
+            currentRadioState == RadioState.NV_NOT_READY      ||
+            currentRadioState == RadioState.NV_READY            ) {
+            return IccStatus.ICC_NOT_READY;
+        }
+
+        if( currentRadioState == RadioState.SIM_LOCKED_OR_ABSENT  ||
+            currentRadioState == RadioState.SIM_READY             ||
+            currentRadioState == RadioState.RUIM_LOCKED_OR_ABSENT ||
+            currentRadioState == RadioState.RUIM_READY) {
+
+            int index;
+
+            // check for CDMA radio technology
+            if (currentRadioState == RadioState.RUIM_LOCKED_OR_ABSENT ||
+                currentRadioState == RadioState.RUIM_READY) {
+                index = status.cdma_subscription_app_index;
+            }
+            else {
+                index = status.gsm_umts_subscription_app_index;
+            }
+
+            // check if PIN required
+            if (status.application.get(index).app_state.isPinRequired()) {
+                return IccStatus.ICC_PIN;
+            }
+            if (status.application.get(index).app_state.isPukRequired()) {
+                return IccStatus.ICC_PUK;
+            }
+            if (status.application.get(index).app_state.isSubscriptionPersoEnabled()) {
+                return IccStatus.ICC_NETWORK_PERSONALIZATION;
+            }
+            if (status.application.get(index).app_state.isAppReady()) {
+                return IccStatus.ICC_READY;
+            }
+            if (status.application.get(index).app_state.isAppNotReady()) {
+                return IccStatus.ICC_NOT_READY;
+            }
+            return IccStatus.ICC_NOT_READY;
+        }
+
+        // Unrecognized ICC status. Treat it like a missing ICC.
+        Log.e(LOG_TAG, "Unrecognized RIL_REQUEST_GET_SIM_STATUS result: " + status);
+        return IccStatus.ICC_ABSENT;
     }
 
-
     private Object
-    responseCallList(Parcel p)
-    {
+    responseCallList(Parcel p) {
         int num;
+        int voiceSettings;
         ArrayList<DriverCall> response;
         DriverCall dc;
 
@@ -2338,17 +2620,18 @@
 
         for (int i = 0 ; i < num ; i++) {
             dc = new DriverCall();
-            
+
             dc.state = DriverCall.stateFromCLCC(p.readInt());
             dc.index = p.readInt();
             dc.TOA = p.readInt();
             dc.isMpty = (0 != p.readInt());
             dc.isMT = (0 != p.readInt());
             dc.als = p.readInt();
-            dc.isVoice = (0 == p.readInt()) ? false : true;
+            voiceSettings = p.readInt();
+            dc.isVoice = (0 == voiceSettings) ? false : true;
             dc.number = p.readString();
             dc.numberPresentation = DriverCall.presentationFromCLIP(p.readInt());
-            
+
             // Make sure there's a leading + on addresses with a TOA
             // of 145
 
@@ -2356,6 +2639,16 @@
                                     dc.number, dc.TOA);
 
             response.add(dc);
+
+            if ( RILConstants.CDMA_VOICE_PRIVACY == voiceSettings ) {
+                mVoicePrivacyOnRegistrants.notifyRegistrants();
+                Log.d(LOG_TAG, "InCall VoicePrivacy is enabled: " +
+                        Integer.toString(voiceSettings));
+            } else {
+                mVoicePrivacyOffRegistrants.notifyRegistrants();
+                Log.d(LOG_TAG, "InCall VoicePrivacy is disabled: " +
+                        Integer.toString(voiceSettings));
+            }
         }
 
         Collections.sort(response);
@@ -2364,8 +2657,7 @@
     }
 
     private Object
-    responseContextList(Parcel p)
-    {
+    responseDataCallList(Parcel p) {
         int num;
         ArrayList<PDPContextState> response;
 
@@ -2388,14 +2680,13 @@
     }
 
     private Object
-    responseNetworkInfos(Parcel p)
-    {
+    responseNetworkInfos(Parcel p) {
         String strings[] = (String [])responseStrings(p);
         ArrayList<NetworkInfo> ret;
 
         if (strings.length % 4 != 0) {
             throw new RuntimeException(
-                "RIL_REQUEST_QUERY_AVAILABLE_NETWORKS: invalid response. Got " 
+                "RIL_REQUEST_QUERY_AVAILABLE_NETWORKS: invalid response. Got "
                 + strings.length + " strings, expected multible of 4");
         }
 
@@ -2409,37 +2700,57 @@
                     strings[i+2],
                     strings[i+3]));
         }
-        
+
         return ret;
     }
 
+   private Object
+   responseCellList(Parcel p) {
+       int num;
+       ArrayList<NeighboringCellInfo> response;
+       NeighboringCellInfo cell;
+
+       num = p.readInt();
+       response = new ArrayList<NeighboringCellInfo>(num);
+
+       for (int i = 0 ; i < num ; i++) {
+           try {
+               int rssi = p.readInt();
+               int cid = Integer.valueOf(p.readString(), 16);
+               cell = new NeighboringCellInfo(rssi, cid);
+               response.add(cell);
+           } catch ( Exception e) {
+           }
+       }
+       
+    return response;
+    }
+
     private Object
-    responseCellList(Parcel p)
-    {
-        int num;
-        ArrayList<NeighboringCellInfo> response;
-        NeighboringCellInfo cell;
+    responseBR_SMS_CNF(Parcel p) {
+        // TODO
+        return null;
+    }
 
-        num = p.readInt();
-        response = new ArrayList<NeighboringCellInfo>(num);
+    private Object
+    responseCDMA_BR_CNF(Parcel p) {
+        int numInts;
+        int response[];
 
-        for (int i = 0 ; i < num ; i++) {
-            try {
-                int rssi = p.readInt();
-                int cid = Integer.valueOf(p.readString(), 16);
-                cell = new NeighboringCellInfo(rssi, cid);
-                response.add(cell);
-            } catch ( Exception e) {
-            }
+        numInts = p.readInt();
+
+        response = new int[numInts];
+
+        response[0] = numInts;
+        for (int i = 1 ; i < numInts; i++) {
+            response[i] = p.readInt();
         }
 
         return response;
     }
 
-
     static String
-    requestToString(int request) 
-    {
+    requestToString(int request) {
 /*
  cat libs/telephony/ril_commands.h \
  | egrep "^ *{RIL_" \
@@ -2472,7 +2783,7 @@
             case RIL_REQUEST_DTMF: return "DTMF";
             case RIL_REQUEST_SEND_SMS: return "SEND_SMS";
             case RIL_REQUEST_SEND_SMS_EXPECT_MORE: return "SEND_SMS_EXPECT_MORE";
-            case RIL_REQUEST_SETUP_DEFAULT_PDP: return "SETUP_DEFAULT_PDP";
+            case RIL_REQUEST_SETUP_DATA_CALL: return "SETUP_DATA_CALL";
             case RIL_REQUEST_SIM_IO: return "SIM_IO";
             case RIL_REQUEST_SEND_USSD: return "SEND_USSD";
             case RIL_REQUEST_CANCEL_USSD: return "CANCEL_USSD";
@@ -2486,7 +2797,7 @@
             case RIL_REQUEST_GET_IMEI: return "GET_IMEI";
             case RIL_REQUEST_GET_IMEISV: return "GET_IMEISV";
             case RIL_REQUEST_ANSWER: return "ANSWER";
-            case RIL_REQUEST_DEACTIVATE_DEFAULT_PDP: return "DEACTIVATE_DEFAULT_PDP";
+            case RIL_REQUEST_DEACTIVATE_DATA_CALL: return "DEACTIVATE_DATA_CALL";
             case RIL_REQUEST_QUERY_FACILITY_LOCK: return "QUERY_FACILITY_LOCK";
             case RIL_REQUEST_SET_FACILITY_LOCK: return "SET_FACILITY_LOCK";
             case RIL_REQUEST_CHANGE_BARRING_PASSWORD: return "CHANGE_BARRING_PASSWORD";
@@ -2501,8 +2812,8 @@
             case RIL_REQUEST_SET_MUTE: return "SET_MUTE";
             case RIL_REQUEST_GET_MUTE: return "GET_MUTE";
             case RIL_REQUEST_QUERY_CLIP: return "QUERY_CLIP";
-            case RIL_REQUEST_LAST_PDP_FAIL_CAUSE: return "LAST_PDP_FAIL_CAUSE";
-            case RIL_REQUEST_PDP_CONTEXT_LIST: return "PDP_CONTEXT_LIST";
+            case RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE: return "LAST_DATA_CALL_FAIL_CAUSE";
+            case RIL_REQUEST_DATA_CALL_LIST: return "DATA_CALL_LIST";
             case RIL_REQUEST_RESET_RADIO: return "RESET_RADIO";
             case RIL_REQUEST_OEM_HOOK_RAW: return "OEM_HOOK_RAW";
             case RIL_REQUEST_OEM_HOOK_STRINGS: return "OEM_HOOK_STRINGS";
@@ -2522,6 +2833,28 @@
             case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE: return "REQUEST_GET_PREFERRED_NETWORK_TYPE";
             case RIL_REQUEST_GET_NEIGHBORING_CELL_IDS: return "REQUEST_GET_NEIGHBORING_CELL_IDS";
             case RIL_REQUEST_SET_LOCATION_UPDATES: return "REQUEST_SET_LOCATION_UPDATES";
+            case RIL_REQUEST_CDMA_SET_SUBSCRIPTION: return "RIL_REQUEST_CDMA_SET_SUBSCRIPTION";
+            case RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE: return "RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE";
+            case RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE: return "RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE";
+            case RIL_REQUEST_SET_TTY_MODE: return "RIL_REQUEST_SET_TTY_MODE";
+            case RIL_REQUEST_QUERY_TTY_MODE: return "RIL_REQUEST_QUERY_TTY_MODE";
+            case RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE: return "RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE";
+            case RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE: return "RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE";
+            case RIL_REQUEST_CDMA_FLASH: return "RIL_REQUEST_CDMA_FLASH";
+            case RIL_REQUEST_CDMA_BURST_DTMF: return "RIL_REQUEST_CDMA_BURST_DTMF";
+            case RIL_REQUEST_CDMA_SEND_SMS: return "RIL_REQUEST_CDMA_SEND_SMS";
+            case RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE: return "RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE";
+            case RIL_REQUEST_GET_BROADCAST_CONFIG: return "RIL_REQUEST_GET_BROADCAST_CONFIG";
+            case RIL_REQUEST_SET_BROADCAST_CONFIG: return "RIL_REQUEST_SET_BROADCAST_CONFIG";
+            case RIL_REQUEST_CDMA_GET_BROADCAST_CONFIG: return "RIL_REQUEST_CDMA_GET_BROADCAST_CONFIG";
+            case RIL_REQUEST_CDMA_SET_BROADCAST_CONFIG: return "RIL_REQUEST_CDMA_SET_BROADCAST_CONFIG";
+            case RIL_REQUEST_BROADCAST_ACTIVATION: return "RIL_REQUEST_BROADCAST_ACTIVATION";
+            case RIL_REQUEST_CDMA_VALIDATE_AKEY: return "RIL_REQUEST_CDMA_VALIDATE_AKEY";
+            case RIL_REQUEST_CDMA_BROADCAST_ACTIVATION: return "RIL_REQUEST_CDMA_BROADCAST_ACTIVATION";
+            case RIL_REQUEST_CDMA_SUBSCRIPTION: return "RIL_REQUEST_CDMA_SUBSCRIPTION";
+            case RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM: return "RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM";
+            case RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM: return "RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM";
+            case RIL_REQUEST_DEVICE_IDENTITY: return "RIL_REQUEST_DEVICE_IDENTITY";
             default: return "<unknown request>";
         }
     }
@@ -2545,7 +2878,7 @@
             case RIL_UNSOL_ON_USSD_REQUEST: return "UNSOL_ON_USSD_REQUEST";
             case RIL_UNSOL_NITZ_TIME_RECEIVED: return "UNSOL_NITZ_TIME_RECEIVED";
             case RIL_UNSOL_SIGNAL_STRENGTH: return "UNSOL_SIGNAL_STRENGTH";
-            case RIL_UNSOL_PDP_CONTEXT_LIST_CHANGED: return "UNSOL_PDP_CONTEXT_LIST_CHANGED";
+            case RIL_UNSOL_DATA_CALL_LIST_CHANGED: return "UNSOL_DATA_CALL_LIST_CHANGED";
             case RIL_UNSOL_SUPP_SVC_NOTIFICATION: return "UNSOL_SUPP_SVC_NOTIFICATION";
             case RIL_UNSOL_STK_SESSION_END: return "UNSOL_STK_SESSION_END";
             case RIL_UNSOL_STK_PROACTIVE_COMMAND: return "UNSOL_STK_PROACTIVE_COMMAND";
@@ -2554,7 +2887,7 @@
             case RIL_UNSOL_SIM_SMS_STORAGE_FULL: return "UNSOL_SIM_SMS_STORAGE_FULL";
             case RIL_UNSOL_SIM_REFRESH: return "UNSOL_SIM_REFRESH";
             case RIL_UNSOL_CALL_RING: return "UNSOL_CALL_RING";
-            case RIL_UNSOL_RESTRICTED_STATE_CHANGED: return "RIL_UNSOL_RESTRICTED_STATE_CHANGED";
+            case RIL_UNSOL_RESTRICTED_STATE_CHANGED: return "RIL_UNSOL_RESTRICTED_STATE_CHANGED";            
             default: return "<unknown reponse>";
         }
     }
@@ -2583,4 +2916,135 @@
         riljLogv("[UNSL]< " + responseToString(response) + " " + retToString(response, ret));
     }
 
+    
+    // ***** Methods for CDMA support
+    public void
+    getDeviceIdentity(Message response) {
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_DEVICE_IDENTITY, response);
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
+        send(rr);
+    }
+
+    public void
+    getCDMASubscription(Message response) {
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_SUBSCRIPTION, response);
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
+        send(rr);
+    }
+
+    public void setPhoneType(int phoneType) { //Set by CDMAPhone and GSMPhone constructor
+        mPhoneType = phoneType;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void queryCdmaRoamingPreference(Message response) {
+        RILRequest rr = RILRequest.obtain(
+                RILConstants.RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE, response);
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
+
+        send(rr);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) {
+        RILRequest rr = RILRequest.obtain(
+                RILConstants.RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE, response);
+
+        rr.mp.writeInt(1);
+        rr.mp.writeInt(cdmaRoamingType);
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+                + " : " + cdmaRoamingType);
+
+        send(rr);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setCdmaSubscription(int cdmaSubscription , Message response) {
+        RILRequest rr = RILRequest.obtain(
+                RILConstants.RIL_REQUEST_CDMA_SET_SUBSCRIPTION, response);
+
+        rr.mp.writeInt(1);
+        rr.mp.writeInt(cdmaSubscription);
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+                + " : " + cdmaSubscription);
+
+        send(rr);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void queryTTYModeEnabled(Message response) {
+        RILRequest rr = RILRequest.obtain(
+                RILConstants.RIL_REQUEST_QUERY_TTY_MODE, response);
+
+        send(rr);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setTTYModeEnabled(boolean enable, Message response) {
+        RILRequest rr = RILRequest.obtain(
+                RILConstants.RIL_REQUEST_SET_TTY_MODE, response);
+
+        rr.mp.writeInt(1);
+        rr.mp.writeInt(enable ? 1 : 0);
+
+        send(rr);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void
+    sendCDMAFeatureCode(String FeatureCode, Message response) {
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_FLASH, response);
+
+        rr.mp.writeInt(1);
+        rr.mp.writeString(FeatureCode);
+
+        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+                + " : " + FeatureCode);
+
+        send(rr);
+    }
+
+    public void getCdmaBroadcastConfig(Message response) {
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_GET_BROADCAST_CONFIG, response);
+
+        send(rr);
+    }
+
+    public void setCdmaBroadcastConfig(int[] configValuesArray, Message response) {
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_SET_BROADCAST_CONFIG, response);
+
+        for(int i = 0; i < configValuesArray.length; i++) {
+            rr.mp.writeInt(configValuesArray[i]);
+        }
+
+        send(rr);
+    }
+
+    public void activateCdmaBroadcastSms(int activate, Message response) {
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_BROADCAST_ACTIVATION, response);
+
+        rr.mp.writeInt(1);
+        rr.mp.writeInt(activate);
+
+        send(rr);
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
similarity index 61%
rename from telephony/java/com/android/internal/telephony/gsm/RILConstants.java
rename to telephony/java/com/android/internal/telephony/RILConstants.java
index 4463b20..ba3b754 100644
--- a/telephony/java/com/android/internal/telephony/gsm/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -14,29 +14,62 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 
 /**
  * {@hide}
  */
-interface RILConstants
-{
+public interface RILConstants {
     // From the top of ril.cpp
     int RIL_ERRNO_INVALID_RESPONSE = -1;
 
     // from RIL_Errno
     int SUCCESS = 0;
-    int RADIO_NOT_AVAILABLE = 1;     /* If radio did not start or is resetting */
+    int RADIO_NOT_AVAILABLE = 1;              /* If radio did not start or is resetting */
     int GENERIC_FAILURE = 2;
-    int PASSWORD_INCORRECT = 3;      /* for PIN/PIN2 methods only! */
-    int SIM_PIN2 = 4;                /* Operation requires SIM PIN2 to be entered */
-    int SIM_PUK2 = 5;                /* Operation requires SIM PIN2 to be entered */
+    int PASSWORD_INCORRECT = 3;               /* for PIN/PIN2 methods only! */
+    int SIM_PIN2 = 4;                         /* Operation requires SIM PIN2 to be entered */
+    int SIM_PUK2 = 5;                         /* Operation requires SIM PIN2 to be entered */
     int REQUEST_NOT_SUPPORTED = 6;
     int REQUEST_CANCELLED = 7;
-    int OP_NOT_ALLOWED_DURING_VOICE_CALL = 8; /* data operation is not allowed during voice call in class C */
-    int OP_NOT_ALLOWED_BEFORE_REG_NW = 9;     /* request is not allowed before device registers to network */
-    int SMS_SEND_FAIL_RETRY = 10;         /* send sms fail and need retry */
+    int OP_NOT_ALLOWED_DURING_VOICE_CALL = 8; /* data operation is not allowed during voice call in
+                                                 class C */
+    int OP_NOT_ALLOWED_BEFORE_REG_NW = 9;     /* request is not allowed before device registers to
+                                                 network */
+    int SMS_SEND_FAIL_RETRY = 10;             /* send sms fail and need retry */
+
+    /* NETWORK_MODE_* See ril.h RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE */
+    int NETWORK_MODE_WCDMA_PREF     = 0; /* GSM/WCDMA (WCDMA preferred) */
+    int NETWORK_MODE_GSM_ONLY       = 1; /* GSM only */
+    int NETWORK_MODE_WCDMA_ONLY     = 2; /* WCDMA only */
+    int NETWORK_MODE_GSM_UMTS       = 3; /* GSM/WCDMA (auto mode, according to PRL)
+                                            AVAILABLE Application Settings menu*/
+    int NETWORK_MODE_CDMA           = 4; /* CDMA and EvDo (auto mode, according to PRL)
+                                            AVAILABLE Application Settings menu*/
+    int NETWORK_MODE_CDMA_NO_EVDO   = 5; /* CDMA only */
+    int NETWORK_MODE_EVDO_NO_CDMA   = 6; /* EvDo only */
+    int NETWORK_MODE_GLOBAL         = 7; /* GSM/WCDMA, CDMA, and EvDo (auto mode, according to PRL)
+                                            AVAILABLE Application Settings menu*/
+    int PREFERRED_NETWORK_MODE      = NETWORK_MODE_GLOBAL;
+
+    /* CDMA subscription source. See ril.h RIL_REQUEST_CDMA_SET_SUBSCRIPTION */
+    int SUBSCRIPTION_FROM_RUIM      = 0; /* CDMA subscription from RUIM when available */
+    int SUBSCRIPTION_FROM_NV        = 1; /* CDMA subscription from NV */
+    int PREFERRED_CDMA_SUBSCRIPTION = SUBSCRIPTION_FROM_NV;
+
+    int CDMA_CELL_BROADCAST_SMS_DISABLED = 1;
+    int CDMA_CELL_BROADCAST_SMS_ENABLED  = 0;
+
+    int CDMA_PHONE = 0;
+    int GSM_PHONE = 1;
+
+    int CDM_TTY_MODE_DISABLED = 0;
+    int CDM_TTY_MODE_ENABLED = 1;
+
+    byte CDMA_VOICE_PRIVACY = 0x70;           /* "p" value used in Ril_Call.isVoice if Privacy
+                                                 is active  */
+
 /*
 cat include/telephony/ril.h | \
    egrep '^#define' | \
@@ -76,7 +109,7 @@
      * Block packet data access due to restriction. 
      */  
     int RIL_RESTRICTED_STATE_PS_ALL = 0x10;
-    
+
     int RIL_REQUEST_GET_SIM_STATUS = 1;
     int RIL_REQUEST_ENTER_SIM_PIN = 2;
     int RIL_REQUEST_ENTER_SIM_PUK = 3;
@@ -103,7 +136,7 @@
     int RIL_REQUEST_DTMF = 24;
     int RIL_REQUEST_SEND_SMS = 25;
     int RIL_REQUEST_SEND_SMS_EXPECT_MORE = 26;
-    int RIL_REQUEST_SETUP_DEFAULT_PDP = 27;
+    int RIL_REQUEST_SETUP_DATA_CALL = 27;
     int RIL_REQUEST_SIM_IO = 28;
     int RIL_REQUEST_SEND_USSD = 29;
     int RIL_REQUEST_CANCEL_USSD = 30;
@@ -117,7 +150,7 @@
     int RIL_REQUEST_GET_IMEI = 38;
     int RIL_REQUEST_GET_IMEISV = 39;
     int RIL_REQUEST_ANSWER = 40;
-    int RIL_REQUEST_DEACTIVATE_DEFAULT_PDP = 41;
+    int RIL_REQUEST_DEACTIVATE_DATA_CALL = 41;
     int RIL_REQUEST_QUERY_FACILITY_LOCK = 42;
     int RIL_REQUEST_SET_FACILITY_LOCK = 43;
     int RIL_REQUEST_CHANGE_BARRING_PASSWORD = 44;
@@ -132,8 +165,8 @@
     int RIL_REQUEST_SET_MUTE = 53;
     int RIL_REQUEST_GET_MUTE = 54;
     int RIL_REQUEST_QUERY_CLIP = 55;
-    int RIL_REQUEST_LAST_PDP_FAIL_CAUSE = 56;
-    int RIL_REQUEST_PDP_CONTEXT_LIST = 57;
+    int RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE = 56;
+    int RIL_REQUEST_DATA_CALL_LIST = 57;
     int RIL_REQUEST_RESET_RADIO = 58;
     int RIL_REQUEST_OEM_HOOK_RAW = 59;
     int RIL_REQUEST_OEM_HOOK_STRINGS = 60;
@@ -153,6 +186,28 @@
     int RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE = 74;
     int RIL_REQUEST_GET_NEIGHBORING_CELL_IDS = 75;
     int RIL_REQUEST_SET_LOCATION_UPDATES = 76;
+    int RIL_REQUEST_CDMA_SET_SUBSCRIPTION = 77;
+    int RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE = 78;
+    int RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE = 79;
+    int RIL_REQUEST_SET_TTY_MODE = 80;
+    int RIL_REQUEST_QUERY_TTY_MODE = 81;
+    int RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE = 82;
+    int RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE = 83;
+    int RIL_REQUEST_CDMA_FLASH = 84;
+    int RIL_REQUEST_CDMA_BURST_DTMF = 85;
+    int RIL_REQUEST_CDMA_VALIDATE_AKEY = 86;
+    int RIL_REQUEST_CDMA_SEND_SMS = 87;
+    int RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE = 88;
+    int RIL_REQUEST_GET_BROADCAST_CONFIG = 89;
+    int RIL_REQUEST_SET_BROADCAST_CONFIG = 90;
+    int RIL_REQUEST_BROADCAST_ACTIVATION = 91;
+    int RIL_REQUEST_CDMA_GET_BROADCAST_CONFIG = 92;
+    int RIL_REQUEST_CDMA_SET_BROADCAST_CONFIG = 93;
+    int RIL_REQUEST_CDMA_BROADCAST_ACTIVATION = 94;
+    int RIL_REQUEST_CDMA_SUBSCRIPTION = 99;
+    int RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM = 100;
+    int RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM = 101;
+    int RIL_REQUEST_DEVICE_IDENTITY = 102;
     int RIL_UNSOL_RESPONSE_BASE = 1000;
     int RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED = 1000;
     int RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED = 1001;
@@ -164,7 +219,7 @@
     int RIL_UNSOL_ON_USSD_REQUEST = 1007;
     int RIL_UNSOL_NITZ_TIME_RECEIVED = 1008;
     int RIL_UNSOL_SIGNAL_STRENGTH = 1009;
-    int RIL_UNSOL_PDP_CONTEXT_LIST_CHANGED = 1010;
+    int RIL_UNSOL_DATA_CALL_LIST_CHANGED = 1010;
     int RIL_UNSOL_SUPP_SVC_NOTIFICATION = 1011;
     int RIL_UNSOL_STK_SESSION_END = 1012;
     int RIL_UNSOL_STK_PROACTIVE_COMMAND = 1013;
@@ -173,5 +228,9 @@
     int RIL_UNSOL_SIM_SMS_STORAGE_FULL = 1016;
     int RIL_UNSOL_SIM_REFRESH = 1017;
     int RIL_UNSOL_CALL_RING = 1018;
+    int RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED = 1019;
+    int RIL_UNSOL_RESPONSE_CDMA_NEW_SMS = 1020;
+    int RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS = 1021;
+    int RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL = 1022;
     int RIL_UNSOL_RESTRICTED_STATE_CHANGED = 1023;
 }
diff --git a/telephony/java/com/android/internal/telephony/SMSDispatcher.java b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
new file mode 100644
index 0000000..f2bd361
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
@@ -0,0 +1,744 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.app.AlertDialog;
+import android.app.PendingIntent.CanceledException;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.Intent;
+import android.content.DialogInterface;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.net.Uri;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.provider.Telephony;
+import android.provider.Telephony.Sms.Intents;
+import android.provider.Settings;
+import android.telephony.SmsMessage;
+import android.telephony.ServiceState;
+import android.util.Config;
+import android.util.Log;
+import android.view.WindowManager;
+
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.SmsMessageBase;
+import com.android.internal.telephony.SmsResponse;
+import com.android.internal.telephony.WapPushOverSms;
+import com.android.internal.util.HexDump;
+
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Random;
+
+import com.android.internal.R;
+
+import static android.telephony.SmsManager.RESULT_ERROR_GENERIC_FAILURE;
+import static android.telephony.SmsManager.RESULT_ERROR_NO_SERVICE;
+import static android.telephony.SmsManager.RESULT_ERROR_NULL_PDU;
+import static android.telephony.SmsManager.RESULT_ERROR_RADIO_OFF;
+
+
+public abstract class SMSDispatcher extends Handler {
+    private static final String TAG = "SMS";
+
+    /** Default checking period for SMS sent without user permit */
+    private static final int DEFAULT_SMS_CHECK_PERIOD = 3600000;
+
+    /** Default number of SMS sent in checking period without user permit */
+    private static final int DEFAULT_SMS_MAX_COUNT = 100;
+
+    /** Default timeout for SMS sent query */
+    private static final int DEFAULT_SMS_TIMOUEOUT = 6000;
+
+    protected static final String[] RAW_PROJECTION = new String[] {
+        "pdu",
+        "sequence",
+    };
+
+    static final int MAIL_SEND_SMS = 1;
+
+    static final protected int EVENT_NEW_SMS = 1;
+
+    static final protected int EVENT_SEND_SMS_COMPLETE = 2;
+
+    /** Retry sending a previously failed SMS message */
+    static final protected int EVENT_SEND_RETRY = 3;
+
+    /** Status report received */
+    static final protected int EVENT_NEW_SMS_STATUS_REPORT = 5;
+
+    /** SIM/RUIM storage is full */
+    static final protected int EVENT_ICC_FULL = 6;
+
+    /** SMS confirm required */
+    static final protected int EVENT_POST_ALERT = 7;
+
+    /** Send the user confirmed SMS */
+    static final protected int EVENT_SEND_CONFIRMED_SMS = 8;
+
+    /** Alert is timeout */
+    static final protected int EVENT_ALERT_TIMEOUT = 9;
+
+    protected Phone mPhone;
+    protected Context mContext;
+    protected ContentResolver mResolver;
+    protected CommandsInterface mCm;
+
+    protected final WapPushOverSms mWapPush;
+
+    protected final Uri mRawUri = Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, "raw");
+
+    /** Maximum number of times to retry sending a failed SMS. */
+    private static final int MAX_SEND_RETRIES = 3;
+    /** Delay before next send attempt on a failed SMS, in milliseconds. */
+    private static final int SEND_RETRY_DELAY = 2000; 
+    /** single part SMS */
+    private static final int SINGLE_PART_SMS = 1;
+
+    /**
+     * Message reference for a CONCATENATED_8_BIT_REFERENCE or
+     * CONCATENATED_16_BIT_REFERENCE message set.  Should be
+     * incremented for each set of concatenated messages.
+     */
+    protected static int sConcatenatedRef;
+
+    private SmsCounter mCounter;
+
+    private SmsTracker mSTracker;
+
+    private static SmsMessage mSmsMessage;
+    private static SmsMessageBase mSmsMessageBase;
+    private SmsMessageBase.SubmitPduBase mSubmitPduBase;
+
+    /**
+     *  Implement the per-application based SMS control, which only allows
+     *  a limit on the number of SMS/MMS messages an app can send in checking
+     *  period.
+     */
+    private class SmsCounter {
+        private int mCheckPeriod;
+        private int mMaxAllowed;
+        private HashMap<String, ArrayList<Long>> mSmsStamp;
+
+        /**
+         * Create SmsCounter
+         * @param mMax is the number of SMS allowed without user permit
+         * @param mPeriod is the checking period
+         */
+        SmsCounter(int mMax, int mPeriod) {
+            mMaxAllowed = mMax;
+            mCheckPeriod = mPeriod;
+            mSmsStamp = new HashMap<String, ArrayList<Long>> ();
+        }
+
+        /**
+         * Check to see if an application allow to send new SMS messages
+         *  
+         * @param appName is the application sending sms
+         * @param smsWaiting is the number of new sms wants to be sent
+         * @return true if application is allowed to send the requested number 
+         *         of new sms messages 
+         */
+        boolean check(String appName, int smsWaiting) {
+            if (!mSmsStamp.containsKey(appName)) {
+                mSmsStamp.put(appName, new ArrayList<Long>());
+            }
+
+            return isUnderLimit(mSmsStamp.get(appName), smsWaiting);
+        }
+
+        private boolean isUnderLimit(ArrayList<Long> sent, int smsWaiting) {
+            Long ct =  System.currentTimeMillis();
+
+            Log.d(TAG, "SMS send size=" + sent.size() + "time=" + ct);
+
+            while (sent.size() > 0 && (ct - sent.get(0)) > mCheckPeriod ) {
+                    sent.remove(0);
+            }
+
+            
+            if ( (sent.size() + smsWaiting) <= mMaxAllowed) {
+                for (int i = 0; i < smsWaiting; i++ ) {
+                    sent.add(ct);
+                }
+                return true;
+            }
+            return false;
+        }
+    }
+
+    protected SMSDispatcher(PhoneBase phone) {
+        mPhone = phone;
+        mWapPush = new WapPushOverSms(phone);
+        mContext = phone.getContext();
+        mResolver = mContext.getContentResolver();
+        mCm = phone.mCM;
+        mSTracker = null;
+
+        int check_period = Settings.Gservices.getInt(mResolver,
+                Settings.Gservices.SMS_OUTGOING_CEHCK_INTERVAL_MS,
+                DEFAULT_SMS_CHECK_PERIOD);
+        int max_count = Settings.Gservices.getInt(mResolver,
+                Settings.Gservices.SMS_OUTGOING_CEHCK_MAX_COUNT,
+                DEFAULT_SMS_MAX_COUNT);
+        mCounter = new SmsCounter(max_count, check_period);
+
+        mCm.setOnNewSMS(this, EVENT_NEW_SMS, null);
+        mCm.setOnSmsStatus(this, EVENT_NEW_SMS_STATUS_REPORT, null);
+        mCm.setOnIccSmsFull(this, EVENT_ICC_FULL, null);
+
+        // Don't always start message ref at 0.
+        sConcatenatedRef = new Random().nextInt(256);
+    }
+
+    public void dispose() {
+        mCm.unSetOnNewSMS(this);
+        mCm.unSetOnSmsStatus(this);
+        mCm.unSetOnIccSmsFull(this);
+    }
+
+    protected void finalize() {
+        Log.d(TAG, "SMSDispatcher finalized");
+    }
+
+
+    /* TODO: Need to figure out how to keep track of status report routing in a
+     *       persistent manner. If the phone process restarts (reboot or crash),
+     *       we will lose this list and any status reports that come in after
+     *       will be dropped.
+     */
+    /** Sent messages awaiting a delivery status report. */
+    protected final ArrayList<SmsTracker> deliveryPendingList = new ArrayList<SmsTracker>();
+
+    /**
+     * Handles events coming from the phone stack. Overridden from handler.
+     *
+     * @param msg the message to handle
+     */
+    @Override
+    public void handleMessage(Message msg) {
+        AsyncResult ar;
+
+        switch (msg.what) {
+        case EVENT_NEW_SMS:
+            // A new SMS has been received by the device
+            if (Config.LOGD) {
+                Log.d(TAG, "New SMS Message Received");
+            }
+
+            SmsMessage sms;
+
+            ar = (AsyncResult) msg.obj;
+
+                // FIXME only acknowledge on store
+            acknowledgeLastIncomingSms(true, null);
+
+            if (ar.exception != null) {
+                Log.e(TAG, "Exception processing incoming SMS. Exception:" + ar.exception);
+                return;
+            }
+
+            sms = (SmsMessage) ar.result;
+            dispatchMessage(sms.mWrappedSmsMessage);
+
+            break;
+
+        case EVENT_SEND_SMS_COMPLETE:
+            // An outbound SMS has been successfully transferred, or failed.
+            handleSendComplete((AsyncResult) msg.obj);
+            break;
+
+        case EVENT_SEND_RETRY:
+            sendSms((SmsTracker) msg.obj);
+            break;
+
+        case EVENT_NEW_SMS_STATUS_REPORT:
+            handleStatusReport((AsyncResult)msg.obj);
+            break;
+
+        case EVENT_ICC_FULL:
+            handleIccFull();
+            break;
+
+        case EVENT_POST_ALERT:
+            handleReachSentLimit((SmsTracker)(msg.obj));
+            break;
+
+        case EVENT_ALERT_TIMEOUT:
+            ((AlertDialog)(msg.obj)).dismiss();
+            msg.obj = null;
+            mSTracker = null;
+            break;
+
+        case EVENT_SEND_CONFIRMED_SMS:
+            if (mSTracker!=null) {
+                if (isMultipartTracker(mSTracker)) {
+                    sendMultipartSms(mSTracker);
+                } else {
+                    sendSms(mSTracker);
+                } 
+                mSTracker = null;
+            }
+            break;
+        }
+    }
+
+    /**
+     * Called when SIM_FULL message is received from the RIL.  Notifies interested
+     * parties that SIM storage for SMS messages is full.
+     */
+    private void handleIccFull(){
+        // broadcast SIM_FULL intent
+        Intent intent = new Intent(Intents.SIM_FULL_ACTION);
+        mPhone.getContext().sendBroadcast(intent, "android.permission.RECEIVE_SMS");
+    }
+
+    /**
+     * Called when a status report is received.  This should correspond to
+     * a previously successful SEND.
+     *
+     * @param ar AsyncResult passed into the message handler.  ar.result should
+     *           be a String representing the status report PDU, as ASCII hex.
+     */
+    protected abstract void handleStatusReport(AsyncResult ar);
+
+    /**
+     * Called when SMS send completes. Broadcasts a sentIntent on success.
+     * On failure, either sets up retries or broadcasts a sentIntent with
+     * the failure in the result code.
+     *
+     * @param ar AsyncResult passed into the message handler.  ar.result should
+     *           an SmsResponse instance if send was successful.  ar.userObj
+     *           should be an SmsTracker instance.
+     */
+    protected void handleSendComplete(AsyncResult ar) {
+        SmsTracker tracker = (SmsTracker) ar.userObj;
+        PendingIntent sentIntent = tracker.mSentIntent;
+
+        if (ar.exception == null) {
+            if (Config.LOGD) {
+                Log.d(TAG, "SMS send complete. Broadcasting "
+                        + "intent: " + sentIntent);
+            }
+
+            if (tracker.mDeliveryIntent != null) {
+                // Expecting a status report.  Add it to the list.
+                int messageRef = ((SmsResponse)ar.result).messageRef;
+                tracker.mMessageRef = messageRef;
+                deliveryPendingList.add(tracker);
+            }
+
+            if (sentIntent != null) {
+                try {
+                    sentIntent.send(Activity.RESULT_OK);
+                } catch (CanceledException ex) {}
+            }
+        } else {
+            if (Config.LOGD) {
+                Log.d(TAG, "SMS send failed");
+            }
+
+            int ss = mPhone.getServiceState().getState();
+
+            if (ss != ServiceState.STATE_IN_SERVICE) {
+                handleNotInService(ss, tracker);
+            } else if ((((CommandException)(ar.exception)).getCommandError()
+                    == CommandException.Error.SMS_FAIL_RETRY) &&
+                   tracker.mRetryCount < MAX_SEND_RETRIES) {
+                // Retry after a delay if needed.
+                // TODO: According to TS 23.040, 9.2.3.6, we should resend
+                //       with the same TP-MR as the failed message, and
+                //       TP-RD set to 1.  However, we don't have a means of
+                //       knowing the MR for the failed message (EF_SMSstatus
+                //       may or may not have the MR corresponding to this
+                //       message, depending on the failure).  Also, in some
+                //       implementations this retry is handled by the baseband.
+                tracker.mRetryCount++;
+                Message retryMsg = obtainMessage(EVENT_SEND_RETRY, tracker);
+                sendMessageDelayed(retryMsg, SEND_RETRY_DELAY);
+            } else if (tracker.mSentIntent != null) {
+                // Done retrying; return an error to the app.
+                try {
+                    tracker.mSentIntent.send(RESULT_ERROR_GENERIC_FAILURE);
+                } catch (CanceledException ex) {}
+            }
+        }
+    }
+
+    /**
+     * Handles outbound message when the phone is not in service.
+     *
+     * @param ss     Current service state.  Valid values are:
+     *                  OUT_OF_SERVICE
+     *                  EMERGENCY_ONLY
+     *                  POWER_OFF
+     * @param tracker   An SmsTracker for the current message.
+     */
+    protected void handleNotInService(int ss, SmsTracker tracker) {
+        if (tracker.mSentIntent != null) {
+            try {
+                if (ss == ServiceState.STATE_POWER_OFF) {
+                    tracker.mSentIntent.send(RESULT_ERROR_RADIO_OFF);
+                } else {
+                    tracker.mSentIntent.send(RESULT_ERROR_NO_SERVICE);
+                }
+            } catch (CanceledException ex) {}
+        }
+    }
+
+    /**
+     * Dispatches an incoming SMS messages.
+     *
+     * @param sms the incoming message from the phone
+     */
+    protected abstract void dispatchMessage(SmsMessageBase sms);
+
+
+    /**
+     * If this is the last part send the parts out to the application, otherwise
+     * the part is stored for later processing.
+     */
+    protected void processMessagePart(SmsMessageBase sms, int referenceNumber,
+            int sequence, int count, int destinationPort) {
+        // Lookup all other related parts
+        StringBuilder where = new StringBuilder("reference_number =");
+        where.append(referenceNumber);
+        where.append(" AND address = ?");
+        String[] whereArgs = new String[] {sms.getOriginatingAddress()};
+
+        byte[][] pdus = null;
+        Cursor cursor = null;
+        try {
+            cursor = mResolver.query(mRawUri, RAW_PROJECTION, where.toString(), whereArgs, null);
+            int cursorCount = cursor.getCount();
+            if (cursorCount != count - 1) {
+                // We don't have all the parts yet, store this one away
+                ContentValues values = new ContentValues();
+                values.put("date", new Long(sms.getTimestampMillis()));
+                values.put("pdu", HexDump.toHexString(sms.getPdu()));
+                values.put("address", sms.getOriginatingAddress());
+                values.put("reference_number", referenceNumber);
+                values.put("count", count);
+                values.put("sequence", sequence);
+                if (destinationPort != -1) {
+                    values.put("destination_port", destinationPort);
+                }
+                mResolver.insert(mRawUri, values);
+
+                return;
+            }
+
+            // All the parts are in place, deal with them
+            int pduColumn = cursor.getColumnIndex("pdu");
+            int sequenceColumn = cursor.getColumnIndex("sequence");
+
+            pdus = new byte[count][];
+            for (int i = 0; i < cursorCount; i++) {
+                cursor.moveToNext();
+                int cursorSequence = (int)cursor.getLong(sequenceColumn);
+                pdus[cursorSequence - 1] = HexDump.hexStringToByteArray(
+                        cursor.getString(pduColumn));
+            }
+            // This one isn't in the DB, so add it
+            pdus[sequence - 1] = sms.getPdu();
+
+            // Remove the parts from the database
+            mResolver.delete(mRawUri, where.toString(), whereArgs);
+        } catch (SQLException e) {
+            Log.e(TAG, "Can't access multipart SMS database", e);
+            return;  // TODO: NACK the message or something, don't just discard.
+        } finally {
+            if (cursor != null) cursor.close();
+        }
+
+        // Dispatch the PDUs to applications
+        switch (destinationPort) {
+        case SmsHeader.PORT_WAP_PUSH: {
+            // Build up the data stream
+            ByteArrayOutputStream output = new ByteArrayOutputStream();
+            for (int i = 0; i < count; i++) {
+                SmsMessage msg = SmsMessage.createFromPdu(pdus[i]);
+                byte[] data = msg.getUserData();
+                output.write(data, 0, data.length);
+            }
+
+            // Handle the PUSH
+            mWapPush.dispatchWapPdu(output.toByteArray());
+            break;
+        }
+
+        case -1:
+            // The messages were not sent to a port
+            dispatchPdus(pdus);
+            break;
+
+        default:
+            // The messages were sent to a port, so concoct a URI for it
+            dispatchPortAddressedPdus(pdus, destinationPort);
+            break;
+        }
+    }
+
+    /**
+     * Dispatches standard PDUs to interested applications
+     *
+     * @param pdus The raw PDUs making up the message
+     */
+    protected void dispatchPdus(byte[][] pdus) {
+        Intent intent = new Intent(Intents.SMS_RECEIVED_ACTION);
+        intent.putExtra("pdus", pdus);
+        mPhone.getContext().sendBroadcast(
+                intent, "android.permission.RECEIVE_SMS");
+    }
+
+    /**
+     * Dispatches port addressed PDUs to interested applications
+     *
+     * @param pdus The raw PDUs making up the message
+     * @param port The destination port of the messages
+     */
+    protected void dispatchPortAddressedPdus(byte[][] pdus, int port) {
+        Uri uri = Uri.parse("sms://localhost:" + port);
+        Intent intent = new Intent(Intents.DATA_SMS_RECEIVED_ACTION, uri);
+        intent.putExtra("pdus", pdus);
+        mPhone.getContext().sendBroadcast(
+                intent, "android.permission.RECEIVE_SMS");
+    }
+
+
+    /**
+     * Send a multi-part text based SMS.
+     *
+     * @param destinationAddress the address to send the message to
+     * @param scAddress is the service center address or null to use
+     *   the current default SMSC
+     * @param parts an <code>ArrayList</code> of strings that, in order,
+     *   comprise the original message
+     * @param sentIntents if not null, an <code>ArrayList</code> of
+     *   <code>PendingIntent</code>s (one for each message part) that is
+     *   broadcast when the corresponding message part has been sent.
+     *   The result code will be <code>Activity.RESULT_OK<code> for success,
+     *   or one of these errors:
+     *   <code>RESULT_ERROR_GENERIC_FAILURE</code>
+     *   <code>RESULT_ERROR_RADIO_OFF</code>
+     *   <code>RESULT_ERROR_NULL_PDU</code>.
+     *  The per-application based SMS control checks sentIntent. If sentIntent
+     *  is NULL the caller will be checked against all unknown applicaitons,
+     *  which cause smaller number of SMS to be sent in checking period.
+     * @param deliveryIntents if not null, an <code>ArrayList</code> of
+     *   <code>PendingIntent</code>s (one for each message part) that is
+     *   broadcast when the corresponding message part has been delivered
+     *   to the recipient.  The raw pdu of the status report is in the
+     *   extended data ("pdu").
+     */
+    protected abstract void sendMultipartText(String destinationAddress, String scAddress,
+            ArrayList<String> parts, ArrayList<PendingIntent> sentIntents,
+            ArrayList<PendingIntent> deliveryIntents);
+
+    /**
+     * Send a SMS
+     *
+     * @param smsc the SMSC to send the message through, or NULL for the
+     *  defatult SMSC
+     * @param pdu the raw PDU to send
+     * @param sentIntent if not NULL this <code>Intent</code> is
+     *  broadcast when the message is sucessfully sent, or failed.
+     *  The result code will be <code>Activity.RESULT_OK<code> for success,
+     *  or one of these errors:
+     *  <code>RESULT_ERROR_GENERIC_FAILURE</code>
+     *  <code>RESULT_ERROR_RADIO_OFF</code>
+     *  <code>RESULT_ERROR_NULL_PDU</code>.
+     *  The per-application based SMS control checks sentIntent. If sentIntent
+     *  is NULL the caller will be checked against all unknown applicaitons,
+     *  which cause smaller number of SMS to be sent in checking period.
+     * @param deliveryIntent if not NULL this <code>Intent</code> is
+     *  broadcast when the message is delivered to the recipient.  The
+     *  raw pdu of the status report is in the extended data ("pdu").
+     */
+    protected void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent,
+            PendingIntent deliveryIntent) {
+        if (pdu == null) {
+            if (sentIntent != null) {
+                try {
+                    sentIntent.send(RESULT_ERROR_NULL_PDU);
+                } catch (CanceledException ex) {}
+            }
+            return;
+        }
+
+        HashMap<String, Object> map = new HashMap<String, Object>();
+        map.put("smsc", smsc);
+        map.put("pdu", pdu);
+
+        SmsTracker tracker = new SmsTracker(map, sentIntent,
+                deliveryIntent);
+        int ss = mPhone.getServiceState().getState();
+
+        if (ss != ServiceState.STATE_IN_SERVICE) {
+            handleNotInService(ss, tracker);
+        } else {
+            String appName = getAppNameByIntent(sentIntent);
+            if (mCounter.check(appName, SINGLE_PART_SMS)) {
+                sendSms(tracker);
+            } else {
+                sendMessage(obtainMessage(EVENT_POST_ALERT, tracker));
+            }
+        }
+    }
+
+    /**
+     * Post an alert while SMS needs user confirm.
+     *
+     * An SmsTracker for the current message.
+     */
+    protected void handleReachSentLimit(SmsTracker tracker) {
+
+        Resources r = Resources.getSystem();
+
+        String appName = getAppNameByIntent(tracker.mSentIntent);
+
+        AlertDialog d = new AlertDialog.Builder(mContext)
+                .setTitle(r.getString(R.string.sms_control_title))
+                .setMessage(appName + " " + r.getString(R.string.sms_control_message))
+                .setPositiveButton(r.getString(R.string.sms_control_yes), mListener)
+                .setNegativeButton(r.getString(R.string.sms_control_no), null)
+                .create();
+
+        d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+        d.show();
+
+        mSTracker = tracker;
+        sendMessageDelayed ( obtainMessage(EVENT_ALERT_TIMEOUT, d),
+                DEFAULT_SMS_TIMOUEOUT);
+    }
+
+    protected String getAppNameByIntent(PendingIntent intent) {
+        Resources r = Resources.getSystem();
+        return (intent != null) ? intent.getTargetPackage()
+            : r.getString(R.string.sms_control_default_app_name);
+    }
+
+    /**
+     * Send the message along to the radio.
+     *
+     * @param tracker holds the SMS message to send
+     */
+    protected abstract void sendSms(SmsTracker tracker);
+
+    /**
+     * Send the multi-part SMS based on multipart Sms tracker
+     * 
+     * @param tracker holds the multipart Sms tracker ready to be sent
+     */
+    protected abstract void sendMultipartSms (SmsTracker tracker);
+
+    /**
+     * Activate or deactivate cell broadcast SMS.
+     *
+     * @param activate
+     *            0 = activate, 1 = deactivate
+     * @param response
+     *            Callback message is empty on completion
+     */
+    protected abstract void activateCellBroadcastSms(int activate, Message response);
+
+    /**
+     * Query the current configuration of cell broadcast SMS.
+     *
+     * @param response
+     *            Callback message contains the configuration from the modem on completion
+     *            @see #setCellBroadcastConfig
+     */
+    protected abstract void getCellBroadcastSmsConfig(Message response);
+
+    /**
+     * Configure cell broadcast SMS.
+     *
+     * @param configValuesArray
+     *          The first element defines the number of triples that follow.
+     *          A triple is made up of the service category, the language identifier
+     *          and a boolean that specifies whether the category is set active.
+     * @param response
+     *            Callback message is empty on completion
+     */
+    protected abstract void setCellBroadcastConfig(int[] configValuesArray, Message response);
+
+    /**
+     * Send an acknowledge message.
+     * @param success indicates that last message was successfully received.
+     * @param response callback message sent when operation completes.
+     */
+    protected abstract void acknowledgeLastIncomingSms(boolean success, Message response);
+
+    /**
+     * Check if a SmsTracker holds multi-part Sms
+     * 
+     * @param tracker a SmsTracker could hold a multi-part Sms
+     * @return true for tracker holds Multi-parts Sms
+     */
+    private boolean isMultipartTracker (SmsTracker tracker) {
+        HashMap map = tracker.mData;
+        return ( map.get("parts") != null);
+    }
+
+    /**
+     * Keeps track of an SMS that has been sent to the RIL, until it it has
+     * successfully been sent, or we're done trying.
+     *
+     */
+    static protected class SmsTracker {
+        // fields need to be public for derived SmsDispatchers
+        public HashMap mData;
+        public int mRetryCount;
+        public int mMessageRef;
+
+        public PendingIntent mSentIntent;
+        public PendingIntent mDeliveryIntent;
+
+        SmsTracker(HashMap data, PendingIntent sentIntent,
+                PendingIntent deliveryIntent) {
+            mData = data;
+            mSentIntent = sentIntent;
+            mDeliveryIntent = deliveryIntent;
+            mRetryCount = 0;
+        }
+    }
+    
+    protected SmsTracker SmsTrackerFactory(HashMap data, PendingIntent sentIntent,
+            PendingIntent deliveryIntent) {
+        return new SmsTracker(data, sentIntent, deliveryIntent);
+    }
+
+    private DialogInterface.OnClickListener mListener =
+        new DialogInterface.OnClickListener() {
+
+            public void onClick(DialogInterface dialog, int which) {
+                if (which == DialogInterface.BUTTON_POSITIVE) {
+                    Log.d(TAG, "click YES to send out sms");
+                    sendMessage(obtainMessage(EVENT_SEND_CONFIRMED_SMS));
+                }
+            }
+        };
+}
diff --git a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
new file mode 100644
index 0000000..a4bf0dd
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony;
+
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Registrant;
+import android.os.RegistrantList;
+import android.telephony.ServiceState;
+
+/**
+ * {@hide}
+ */
+public abstract class ServiceStateTracker extends Handler {
+    /**
+     *  The access technology currently in use:
+     *  0 = unknown
+     *  1 = GPRS only
+     *  2 = EDGE
+     *  3 = UMTS
+     */
+    protected static final int DATA_ACCESS_UNKNOWN = 0;
+    protected static final int DATA_ACCESS_GPRS = 1;
+    protected static final int DATA_ACCESS_EDGE = 2;
+    protected static final int DATA_ACCESS_UMTS = 3;
+    protected static final int DATA_ACCESS_CDMA_IS95A = 4;
+    protected static final int DATA_ACCESS_CDMA_IS95B = 5;
+    protected static final int DATA_ACCESS_CDMA_1xRTT = 6;
+    protected static final int DATA_ACCESS_CDMA_EvDo_0 = 7;
+    protected static final int DATA_ACCESS_CDMA_EvDo_A = 8;
+    //***** Instance Variables
+
+    protected CommandsInterface cm;
+
+    public ServiceState ss;
+    protected ServiceState newSS;
+
+    // Used as a unique identifier to track requests associated with a poll
+    // and ignore stale responses.The value is a count-down of expected responses
+    // in this pollingContext
+    protected int[] pollingContext;
+    protected boolean mDesiredPowerState;
+
+    protected boolean dontPollSignalStrength = false; // Default is to poll strength
+    // If we're getting unsolicited signal strength updates from the radio,
+    // set value to true and don't bother polling any more
+
+    protected RegistrantList networkAttachedRegistrants = new RegistrantList();
+    protected RegistrantList roamingOnRegistrants = new RegistrantList();
+    protected RegistrantList roamingOffRegistrants = new RegistrantList();
+
+    //***** Constants
+
+    protected  static final boolean DBG = true;
+
+    // signal strength poll rate
+    protected static final int POLL_PERIOD_MILLIS = 20 * 1000;
+
+    // waiting period before recheck gprs and voice registration
+    public static final int DEFAULT_GPRS_CHECK_PERIOD_MILLIS = 60 * 1000;
+
+    public static final int MAX_NUM_DATA_STATE_READS = 15;
+    public static final int DATA_STATE_POLL_SLEEP_MS = 100;
+
+    //*****GSM events
+    protected static final int EVENT_RADIO_STATE_CHANGED               = 1;
+    protected static final int EVENT_NETWORK_STATE_CHANGED             = 2;
+    protected static final int EVENT_GET_SIGNAL_STRENGTH               = 3;
+    protected static final int EVENT_POLL_STATE_REGISTRATION           = 4;
+    protected static final int EVENT_POLL_STATE_GPRS                   = 5;
+    protected static final int EVENT_POLL_STATE_OPERATOR               = 6;
+    protected static final int EVENT_POLL_SIGNAL_STRENGTH              = 10;
+    protected static final int EVENT_NITZ_TIME                         = 11;
+    protected static final int EVENT_SIGNAL_STRENGTH_UPDATE            = 12;
+    protected static final int EVENT_RADIO_AVAILABLE                   = 13;
+    protected static final int EVENT_POLL_STATE_NETWORK_SELECTION_MODE = 14;
+    protected static final int EVENT_GET_LOC_DONE                      = 15;
+    protected static final int EVENT_SIM_RECORDS_LOADED                = 16;
+    protected static final int EVENT_SIM_READY                         = 17;
+    protected static final int EVENT_LOCATION_UPDATES_ENABLED          = 18;
+    protected static final int EVENT_GET_PREFERRED_NETWORK_TYPE        = 19;
+    protected static final int EVENT_SET_PREFERRED_NETWORK_TYPE        = 20;
+    protected static final int EVENT_RESET_PREFERRED_NETWORK_TYPE      = 21;
+    protected static final int EVENT_CHECK_REPORT_GPRS                 = 22;
+    protected static final int EVENT_RESTRICTED_STATE_CHANGED          = 23;
+    
+    //*****CDMA events:
+    protected static final int EVENT_POLL_STATE_REGISTRATION_CDMA      = 24;
+    protected static final int EVENT_POLL_STATE_OPERATOR_CDMA          = 25;
+    protected static final int EVENT_RUIM_READY                        = 26;
+    protected static final int EVENT_RUIM_RECORDS_LOADED               = 27;
+    protected static final int EVENT_POLL_STATE_NETWORK_SELECTION_MODE_CDMA = 28;
+    protected static final int EVENT_POLL_SIGNAL_STRENGTH_CDMA         = 29;
+    protected static final int EVENT_GET_SIGNAL_STRENGTH_CDMA          = 30;
+    protected static final int EVENT_NETWORK_STATE_CHANGED_CDMA        = 31;
+    protected static final int EVENT_GET_LOC_DONE_CDMA                 = 32;
+    protected static final int EVENT_SIGNAL_STRENGTH_UPDATE_CDMA       = 33;
+    protected static final int EVENT_NV_LOADED                         = 34;
+
+    // Event Log Tags
+    protected static final int EVENT_LOG_CGREG_FAIL = 50107;
+    protected static final int EVENT_DATA_STATE_RADIO_OFF = 50108;
+
+    //***** Time Zones
+    protected static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
+
+    // List of ISO codes for countries that can have an offset of GMT+0
+    // when not in daylight savings time.  This ignores some small places
+    // such as the Canary Islands (Spain) and Danmarkshavn (Denmark).
+    // The list must be sorted by code.
+    protected static final String[] GMT_COUNTRY_CODES = {
+        "bf", // Burkina Faso
+        "ci", // Cote d'Ivoire
+        "eh", // Western Sahara
+        "fo", // Faroe Islands, Denmark
+        "gh", // Ghana
+        "gm", // Gambia
+        "gn", // Guinea
+        "gw", // Guinea Bissau
+        "ie", // Ireland
+        "lr", // Liberia
+        "is", // Iceland
+        "ma", // Morocco
+        "ml", // Mali
+        "mr", // Mauritania
+        "pt", // Portugal
+        "sl", // Sierra Leone
+        "sn", // Senegal
+        "st", // Sao Tome and Principe
+        "tg", // Togo
+        "uk", // U.K
+    };
+
+
+    //***** Constructors
+    public ServiceStateTracker() {
+
+    }
+
+
+    /**
+     * Registration point for combined roaming on
+     * combined roaming is true when roaming is true and ONS differs SPN
+     *
+     * @param h handler to notify
+     * @param what what code of message when delivered
+     * @param obj placed in Message.obj
+     */
+    public  void registerForRoamingOn(Handler h, int what, Object obj) {
+        Registrant r = new Registrant(h, what, obj);
+        roamingOnRegistrants.add(r);
+
+        if (ss.getRoaming()) {
+            r.notifyRegistrant();
+        }
+    }
+
+    public  void unregisterForRoamingOn(Handler h) {
+        roamingOnRegistrants.remove(h);
+    }
+
+    /**
+     * Registration point for combined roaming off
+     * combined roaming is true when roaming is true and ONS differs SPN
+     *
+     * @param h handler to notify
+     * @param what what code of message when delivered
+     * @param obj placed in Message.obj
+     */
+    public  void registerForRoamingOff(Handler h, int what, Object obj) {
+        Registrant r = new Registrant(h, what, obj);
+        roamingOffRegistrants.add(r);
+
+        if (!ss.getRoaming()) {
+            r.notifyRegistrant();
+        }
+    }
+
+    public  void unregisterForRoamingOff(Handler h) {
+        roamingOffRegistrants.remove(h);
+    }
+
+    /**
+     * Reregister network through toggle perferred network type
+     * This is a work aorund to deregister and register network since there is
+     * no ril api to set COPS=2 (deregister) only.
+     *
+     * @param onComplete is dispatched when this is complete.  it will be
+     * an AsyncResult, and onComplete.obj.exception will be non-null
+     * on failure.
+     */
+    public void reRegisterNetwork(Message onComplete) {
+        cm.getPreferredNetworkType(
+                obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE, onComplete));
+    }
+
+
+    //***** Called from Phone
+    public void
+    setRadioPower(boolean power) {
+        mDesiredPowerState = power;
+
+        setPowerStateToDesired();
+    }
+
+
+    public void enableLocationUpdates() {
+        cm.setLocationUpdates(true, obtainMessage(EVENT_LOCATION_UPDATES_ENABLED));
+    }
+
+    public void disableLocationUpdates() {
+        cm.setLocationUpdates(false, null);
+    }
+
+    //***** Overridden from Handler
+    public abstract void handleMessage(Message msg);
+
+    //***** Protected abstract Methods
+    protected abstract void handlePollStateResult(int what, AsyncResult ar);
+    protected abstract void updateSpnDisplay();
+    protected abstract void setPowerStateToDesired();
+
+    /** Cancel a pending (if any) pollState() operation */
+    protected void cancelPollState() {
+        // This will effectively cancel the rest of the poll requests
+        pollingContext = new int[1];
+    }
+}
+
diff --git a/telephony/java/com/android/internal/telephony/SmsAddress.java b/telephony/java/com/android/internal/telephony/SmsAddress.java
new file mode 100644
index 0000000..b3892cb
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/SmsAddress.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 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.
+ * 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.internal.telephony;
+
+public abstract class SmsAddress {
+    // From TS 23.040 9.1.2.5 and TS 24.008 table 10.5.118
+    // and C.S0005-D table 2.7.1.3.2.4-2
+    public static final int TON_UNKNOWN = 0;
+    public static final int TON_INTERNATIONAL = 1;
+    public static final int TON_NATIONAL = 2;
+    public static final int TON_NETWORK = 3;
+    public static final int TON_SUBSCRIBER = 4;
+    public static final int TON_ALPHANUMERIC = 5;
+    public static final int TON_ABBREVIATED = 6;
+
+    public int ton;
+    public String address;
+    public byte[] origBytes;
+
+    /**
+     * Returns the address of the SMS message in String form or null if unavailable
+     */
+    public String getAddressString() {
+        return address;
+    }
+
+    /**
+     * Returns true if this is an alphanumeric address
+     */
+    public boolean isAlphanumeric() {
+        return ton == TON_ALPHANUMERIC;
+    }
+
+    /**
+     * Returns true if this is a network address
+     */
+    public boolean isNetworkSpecific() {
+        return ton == TON_NETWORK;
+    }
+
+    public boolean couldBeEmailGateway() {
+        // Some carriers seems to send email gateway messages in this form:
+        // from: an UNKNOWN TON, 3 or 4 digits long, beginning with a 5
+        // PID: 0x00, Data coding scheme 0x03
+        // So we just attempt to treat any message from an address length <= 4
+        // as an email gateway
+
+        return address.length() <= 4;
+    }
+
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsHeader.java b/telephony/java/com/android/internal/telephony/SmsHeader.java
similarity index 78%
rename from telephony/java/com/android/internal/telephony/gsm/SmsHeader.java
rename to telephony/java/com/android/internal/telephony/SmsHeader.java
index 22366ec..64b884e 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsHeader.java
+++ b/telephony/java/com/android/internal/telephony/SmsHeader.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 import com.android.internal.util.HexDump;
 
@@ -24,8 +24,7 @@
  * This class represents a SMS user data header.
  *
  */
-public class SmsHeader
-{
+public class SmsHeader {
     /** See TS 23.040 9.2.3.24 for description of this element ID. */
     public static final int CONCATENATED_8_BIT_REFERENCE = 0x00;
     /** See TS 23.040 9.2.3.24 for description of this element ID. */
@@ -42,6 +41,7 @@
 
     private byte[] m_data;
     private ArrayList<Element> m_elements = new ArrayList<Element>();
+    public int nbrOfHeaders;
 
     /**
      * Creates an SmsHeader object from raw user data header bytes.
@@ -49,36 +49,33 @@
      * @param data is user data header bytes
      * @return an SmsHeader object
      */
-    public static SmsHeader parse(byte[] data)
-    {
+    public static SmsHeader parse(byte[] data) {
         SmsHeader header = new SmsHeader();
         header.m_data = data;
 
         int index = 0;
-        while (index < data.length)
-        {
+        header.nbrOfHeaders = 0;
+        while (index < data.length) {
             int id = data[index++] & 0xff;
             int length = data[index++] & 0xff;
             byte[] elementData = new byte[length];
             System.arraycopy(data, index, elementData, 0, length);
             header.add(new Element(id, elementData));
             index += length;
+            header.nbrOfHeaders++;
         }
 
         return header;
     }
 
-    public SmsHeader()
-    {
-    }
+    public SmsHeader() { }
 
     /**
      * Returns the list of SmsHeader Elements that make up the header.
      *
      * @return the list of SmsHeader Elements.
      */
-    public ArrayList<Element> getElements()
-    {
+    public ArrayList<Element> getElements() {
         return m_elements;
     }
 
@@ -87,14 +84,12 @@
      *
      * @param element to add.
      */
-    public void add(Element element)
-    {
+    public void add(Element element) {
         m_elements.add(element);
     }
 
     @Override
-    public String toString()
-    {
+    public String toString() {
         StringBuilder builder = new StringBuilder();
 
         builder.append("UDH LENGTH: " + m_data.length + " octets");
@@ -104,40 +99,56 @@
 
         for (Element e : getElements()) {
             builder.append("  0x" + HexDump.toHexString((byte)e.getID()) + " - ");
-            switch (e.getID())
-            {
-                case CONCATENATED_8_BIT_REFERENCE:
-                {
+            switch (e.getID()) {
+                case CONCATENATED_8_BIT_REFERENCE: {
                     builder.append("Concatenated Short Message 8bit ref\n");
                     byte[] data = e.getData();
                     builder.append("    " + data.length + " (0x");
-                    builder.append(HexDump.toHexString((byte)data.length)+") Bytes - Information Element\n");
+                    builder.append(HexDump.toHexString((byte)data.length)
+                            + ") Bytes - Information Element\n");
                     builder.append("      " + data[0] + " : SM reference number\n");
                     builder.append("      " + data[1] + " : number of messages\n");
                     builder.append("      " + data[2] + " : this SM sequence number\n");
                     break;
                 }
 
-                case CONCATENATED_16_BIT_REFERENCE:
-                {
+                case CONCATENATED_16_BIT_REFERENCE: {
                     builder.append("Concatenated Short Message 16bit ref\n");
                     byte[] data = e.getData();
                     builder.append("    " + data.length + " (0x");
-                    builder.append(HexDump.toHexString((byte)data.length)+") Bytes - Information Element\n");
-                    builder.append("      " + (data[0] & 0xff) * 256 + (data[1] & 0xff) +
-                                   " : SM reference number\n");
+                    builder.append(HexDump.toHexString((byte)data.length)
+                            + ") Bytes - Information Element\n");
+                    builder.append("      " + (data[0] & 0xff) * 256 + (data[1] & 0xff)
+                            + " : SM reference number\n");
                     builder.append("      " + data[2] + " : number of messages\n");
                     builder.append("      " + data[3] + " : this SM sequence number\n");
                     break;
                 }
 
-                case APPLICATION_PORT_ADDRESSING_16_BIT:
+                case APPLICATION_PORT_ADDRESSING_8_BIT:
                 {
+                    builder.append("Application port addressing 8bit\n");
+                    byte[] data = e.getData();
+
+                    builder.append("    " + data.length + " (0x");
+                    builder.append(HexDump.toHexString(
+                            (byte)data.length) + ") Bytes - Information Element\n");
+
+                    int source = (data[0] & 0xff);
+                    builder.append("      " + source + " : DESTINATION port\n");
+
+                    int dest = (data[1] & 0xff);
+                    builder.append("      " + dest + " : SOURCE port\n");
+                    break;
+                }
+
+                case APPLICATION_PORT_ADDRESSING_16_BIT: {
                     builder.append("Application port addressing 16bit\n");
                     byte[] data = e.getData();
 
                     builder.append("    " + data.length + " (0x");
-                    builder.append(HexDump.toHexString((byte)data.length)+") Bytes - Information Element\n");
+                    builder.append(HexDump.toHexString((byte)data.length)
+                            + ") Bytes - Information Element\n");
 
                     int source = (data[0] & 0xff) << 8;
                     source |= (data[1] & 0xff);
@@ -149,8 +160,7 @@
                     break;
                 }
 
-                default:
-                {
+                default: {
                     builder.append("Unknown element\n");
                     break;
                 }
@@ -202,13 +212,11 @@
      * See TS 23.040 9.2.3.24.
      *
      */
-    public static class Element
-    {
+    public static class Element {
         private byte[] m_data;
         private int m_id;
 
-        public Element(int id, byte[] data)
-        {
+        public Element(int id, byte[] data) {
             m_id = id;
             m_data = data;
         }
@@ -218,8 +226,7 @@
          *
          * @return the IE identifier.
          */
-        public int getID()
-        {
+        public int getID() {
             return m_id;
         }
 
@@ -228,8 +235,7 @@
          *
          * @return element data.
          */
-        public byte[] getData()
-        {
+        public byte[] getData() {
             return m_data;
         }
     }
diff --git a/telephony/java/com/android/internal/telephony/SmsMessageBase.java b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
new file mode 100644
index 0000000..7c32451
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
@@ -0,0 +1,388 @@
+/*
+ * Copyright (C) 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.
+ * 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.internal.telephony;
+
+import android.util.Log;
+import com.android.internal.telephony.SmsHeader;
+import java.util.Arrays;
+
+import static android.telephony.SmsMessage.ENCODING_7BIT;
+import static android.telephony.SmsMessage.ENCODING_16BIT;
+import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES;
+import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES_WITH_HEADER;
+import static android.telephony.SmsMessage.MAX_USER_DATA_SEPTETS;
+import static android.telephony.SmsMessage.MAX_USER_DATA_SEPTETS_WITH_HEADER;
+import static android.telephony.SmsMessage.MessageClass;
+import static com.android.internal.telephony.SmsAddress.TON_ABBREVIATED;
+import static com.android.internal.telephony.SmsAddress.TON_ALPHANUMERIC;
+import static com.android.internal.telephony.SmsAddress.TON_INTERNATIONAL;
+import static com.android.internal.telephony.SmsAddress.TON_NATIONAL;
+import static com.android.internal.telephony.SmsAddress.TON_NETWORK;
+import static com.android.internal.telephony.SmsAddress.TON_SUBSCRIBER;
+import static com.android.internal.telephony.SmsAddress.TON_UNKNOWN;
+
+/**
+ * Base class declaring the specific methods and members for SmsMessage.
+ * {@hide}
+ */
+public abstract class SmsMessageBase {
+    private static final String LOG_TAG = "SMS";
+
+    /** {@hide} The address of the SMSC. May be null */
+    protected String scAddress;
+
+    /** {@hide} The address of the sender */
+    protected SmsAddress originatingAddress;
+
+    /** {@hide} The message body as a string. May be null if the message isn't text */
+    protected String messageBody;
+
+    /** {@hide} */
+    protected String pseudoSubject;
+
+    /** {@hide} Non-null if this is an email gateway message */
+    protected String emailFrom;
+
+    /** {@hide} Non-null if this is an email gateway message */
+    protected String emailBody;
+
+    /** {@hide} */
+    protected boolean isEmail;
+
+    /** {@hide} */
+    protected long scTimeMillis;
+
+    /** {@hide} The raw PDU of the message */
+    protected byte[] mPdu;
+
+    /** {@hide} The raw bytes for the user data section of the message */
+    protected byte[] userData;
+
+    /** {@hide} */
+    protected SmsHeader userDataHeader;
+
+    // "Message Waiting Indication Group"
+    // 23.038 Section 4
+    /** {@hide} */
+    protected boolean isMwi;
+
+    /** {@hide} */
+    protected boolean mwiSense;
+
+    /** {@hide} */
+    protected boolean mwiDontStore;
+
+    /**
+     * Indicates status for messages stored on the ICC.
+     */
+    protected int statusOnIcc = -1;
+
+    /**
+     * Record index of message in the EF.
+     */
+    protected int indexOnIcc = -1;
+
+    /** TP-Message-Reference - Message Reference of sent message. @hide */
+    public int messageRef;
+
+    public static abstract class SubmitPduBase  {
+        public byte[] encodedScAddress; // Null if not applicable.
+        public byte[] encodedMessage;
+
+        public String toString() {
+            return "SubmitPdu: encodedScAddress = "
+                    + Arrays.toString(encodedScAddress)
+                    + ", encodedMessage = "
+                    + Arrays.toString(encodedMessage);
+        }
+    }
+
+    /**
+     * Returns the address of the SMS service center that relayed this message
+     * or null if there is none.
+     */
+    public String getServiceCenterAddress() {
+        return scAddress;
+    }
+
+    /**
+     * Returns the originating address (sender) of this SMS message in String
+     * form or null if unavailable
+     */
+    public String getOriginatingAddress() {
+        if (originatingAddress == null) {
+            return null;
+        }
+
+        return originatingAddress.getAddressString();
+    }
+
+    /**
+     * Returns the originating address, or email from address if this message
+     * was from an email gateway. Returns null if originating address
+     * unavailable.
+     */
+    public String getDisplayOriginatingAddress() {
+        if (isEmail) {
+            return emailFrom;
+        } else {
+            return getOriginatingAddress();
+        }
+    }
+
+    /**
+     * Returns the message body as a String, if it exists and is text based.
+     * @return message body is there is one, otherwise null
+     */
+    public String getMessageBody() {
+        return messageBody;
+    }
+
+    /**
+     * Returns the class of this message.
+     */
+    public abstract MessageClass getMessageClass();
+
+    /**
+     * Returns the message body, or email message body if this message was from
+     * an email gateway. Returns null if message body unavailable.
+     */
+    public String getDisplayMessageBody() {
+        if (isEmail) {
+            return emailBody;
+        } else {
+            return getMessageBody();
+        }
+    }
+
+    /**
+     * Unofficial convention of a subject line enclosed in parens empty string
+     * if not present
+     */
+    public String getPseudoSubject() {
+        return pseudoSubject == null ? "" : pseudoSubject;
+    }
+
+    /**
+     * Returns the service centre timestamp in currentTimeMillis() format
+     */
+    public long getTimestampMillis() {
+        return scTimeMillis;
+    }
+
+    /**
+     * Returns true if message is an email.
+     *
+     * @return true if this message came through an email gateway and email
+     *         sender / subject / parsed body are available
+     */
+    public boolean isEmail() {
+        return isEmail;
+    }
+
+    /**
+     * @return if isEmail() is true, body of the email sent through the gateway.
+     *         null otherwise
+     */
+    public String getEmailBody() {
+        return emailBody;
+    }
+
+    /**
+     * @return if isEmail() is true, email from address of email sent through
+     *         the gateway. null otherwise
+     */
+    public String getEmailFrom() {
+        return emailFrom;
+    }
+
+    /**
+     * Get protocol identifier.
+     */
+    public abstract int getProtocolIdentifier();
+
+    /**
+     * See TS 23.040 9.2.3.9 returns true if this is a "replace short message"
+     * SMS
+     */
+    public abstract boolean isReplace();
+
+    /**
+     * Returns true for CPHS MWI toggle message.
+     *
+     * @return true if this is a CPHS MWI toggle message See CPHS 4.2 section
+     *         B.4.2
+     */
+    public abstract boolean isCphsMwiMessage();
+
+    /**
+     * returns true if this message is a CPHS voicemail / message waiting
+     * indicator (MWI) clear message
+     */
+    public abstract boolean isMWIClearMessage();
+
+    /**
+     * returns true if this message is a CPHS voicemail / message waiting
+     * indicator (MWI) set message
+     */
+    public abstract boolean isMWISetMessage();
+
+    /**
+     * returns true if this message is a "Message Waiting Indication Group:
+     * Discard Message" notification and should not be stored.
+     */
+    public abstract boolean isMwiDontStore();
+
+    /**
+     * returns the user data section minus the user data header if one was
+     * present.
+     */
+    public byte[] getUserData() {
+        return userData;
+    }
+
+    /**
+     * Returns an object representing the user data header
+     *
+     * @return an object representing the user data header
+     *
+     * {@hide}
+     */
+    public SmsHeader getUserDataHeader() {
+        return userDataHeader;
+    }
+
+    /**
+     * Returns the raw PDU for the message.
+     *
+     * @return the raw PDU for the message.
+     */
+    public byte[] getPdu() {
+        return mPdu;
+    }
+
+    /**
+     * For an SMS-STATUS-REPORT message, this returns the status field from
+     * the status report.  This field indicates the status of a previously
+     * submitted SMS, if requested.  See TS 23.040, 9.2.3.15 TP-Status for a
+     * description of values.
+     *
+     * @return 0 indicates the previously sent message was received.
+     *         See TS 23.040, 9.9.2.3.15 for a description of other possible
+     *         values.
+     */
+    public abstract int getStatus();
+
+    /**
+     * Return true iff the message is a SMS-STATUS-REPORT message.
+     */
+    public abstract boolean isStatusReportMessage();
+
+    /**
+     * Returns true iff the <code>TP-Reply-Path</code> bit is set in
+     * this message.
+     */
+    public abstract boolean isReplyPathPresent();
+
+    /**
+     * Returns the status of the message on the ICC (read, unread, sent, unsent).
+     *
+     * @return the status of the message on the ICC.  These are:
+     *         SmsManager.STATUS_ON_ICC_FREE
+     *         SmsManager.STATUS_ON_ICC_READ
+     *         SmsManager.STATUS_ON_ICC_UNREAD
+     *         SmsManager.STATUS_ON_ICC_SEND
+     *         SmsManager.STATUS_ON_ICC_UNSENT
+     */
+    public int getStatusOnIcc() {
+        return statusOnIcc;
+    }
+
+    /**
+     * Returns the record index of the message on the ICC (1-based index).
+     * @return the record index of the message on the ICC, or -1 if this
+     *         SmsMessage was not created from a ICC SMS EF record.
+     */
+    public int getIndexOnIcc() {
+        return indexOnIcc;
+    }
+
+    protected void parseMessageBody() {
+        if (originatingAddress.couldBeEmailGateway()) {
+            extractEmailAddressFromMessageBody();
+        }
+    }
+
+    /**
+     * Try to parse this message as an email gateway message -> Neither
+     * of the standard ways are currently supported: There are two ways
+     * specified in TS 23.040 Section 3.8 (not supported via this mechanism) -
+     * SMS message "may have its TP-PID set for internet electronic mail - MT
+     * SMS format: [<from-address><space>]<message> - "Depending on the
+     * nature of the gateway, the destination/origination address is either
+     * derived from the content of the SMS TP-OA or TP-DA field, or the
+     * TP-OA/TP-DA field contains a generic gateway address and the to/from
+     * address is added at the beginning as shown above." - multiple addreses
+     * separated by commas, no spaces - subject field delimited by '()' or '##'
+     * and '#' Section 9.2.3.24.11
+     */
+    protected void extractEmailAddressFromMessageBody() {
+
+        /*
+         * a little guesswork here. I haven't found doc for this.
+         * the format could be either
+         *
+         * 1. [x@y][ ]/[subject][ ]/[body]
+         * -or-
+         * 2. [x@y][ ]/[body]
+         */
+        int slash = 0, slash2 = 0, atSymbol = 0;
+
+        try {
+            slash = messageBody.indexOf(" /");
+            if (slash == -1) {
+                return;
+            }
+
+            atSymbol = messageBody.indexOf('@');
+            if (atSymbol == -1 || atSymbol > slash) {
+                return;
+            }
+
+            emailFrom = messageBody.substring(0, slash);
+
+            slash2 = messageBody.indexOf(" /", slash + 2);
+
+            if (slash2 == -1) {
+                pseudoSubject = null;
+                emailBody = messageBody.substring(slash + 2);
+            } else {
+                pseudoSubject = messageBody.substring(slash + 2, slash2);
+                emailBody = messageBody.substring(slash2 + 2);
+            }
+
+            isEmail = true;
+        } catch (Exception ex) {
+            Log.w(LOG_TAG,
+                    "extractEmailAddressFromMessageBody: exception slash="
+                    + slash + ", atSymbol=" + atSymbol + ", slash2="
+                    + slash2, ex);
+        }
+    }
+
+}
+
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsRawData.aidl b/telephony/java/com/android/internal/telephony/SmsRawData.aidl
similarity index 93%
rename from telephony/java/com/android/internal/telephony/gsm/SmsRawData.aidl
rename to telephony/java/com/android/internal/telephony/SmsRawData.aidl
index 6f1a46d..b0b3e4f 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsRawData.aidl
+++ b/telephony/java/com/android/internal/telephony/SmsRawData.aidl
@@ -14,6 +14,6 @@
 ** limitations under the License.
 */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 parcelable SmsRawData;
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsRawData.java b/telephony/java/com/android/internal/telephony/SmsRawData.java
similarity index 96%
rename from telephony/java/com/android/internal/telephony/gsm/SmsRawData.java
rename to telephony/java/com/android/internal/telephony/SmsRawData.java
index a029d5c..891d942 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsRawData.java
+++ b/telephony/java/com/android/internal/telephony/SmsRawData.java
@@ -15,10 +15,10 @@
 */
 
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
-import android.os.Parcelable;
 import android.os.Parcel;
+import android.os.Parcelable;
 
 /**
  *  A parcelable holder class of byte[] for ISms aidl implementation
@@ -50,7 +50,7 @@
     public byte[] getBytes() {
         return data;
     }
-    
+
     public int describeContents() {
         return 0;
     }
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsResponse.java b/telephony/java/com/android/internal/telephony/SmsResponse.java
similarity index 88%
rename from telephony/java/com/android/internal/telephony/gsm/SmsResponse.java
rename to telephony/java/com/android/internal/telephony/SmsResponse.java
index c005b5f..3c4df56 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsResponse.java
+++ b/telephony/java/com/android/internal/telephony/SmsResponse.java
@@ -14,20 +14,20 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 /**
  * Object returned by the RIL upon successful completion of sendSMS.
  * Contains message reference and ackPdu.
  *
  */
-class SmsResponse {
+public class SmsResponse {
     /** Message reference of the just-sent SMS. */
     int messageRef;
     /** ackPdu for the just-sent SMS. */
     String ackPdu;
 
-    SmsResponse(int messageRef, String ackPdu) {
+    public SmsResponse(int messageRef, String ackPdu) {
         this.messageRef = messageRef;
         this.ackPdu = ackPdu;
     }
diff --git a/telephony/java/com/android/internal/telephony/gsm/TelephonyEventLog.java b/telephony/java/com/android/internal/telephony/TelephonyEventLog.java
similarity index 96%
rename from telephony/java/com/android/internal/telephony/gsm/TelephonyEventLog.java
rename to telephony/java/com/android/internal/telephony/TelephonyEventLog.java
index 1e583f0..1ef3c6c 100644
--- a/telephony/java/com/android/internal/telephony/gsm/TelephonyEventLog.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyEventLog.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 /* This class contains the details related to Telephony Event Logging */
 public final class TelephonyEventLog {
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index 9219e7a..c342233 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -35,6 +35,24 @@
      */
     public static final String ACTION_SERVICE_STATE_CHANGED = "android.intent.action.SERVICE_STATE";
 
+    /**
+     * <p>Broadcast Action: The radio technology has changed. The intent will have the following
+     * extra values:</p>
+     * <ul>
+     *   <li><em>phoneName</em> - A string version of the new phone name.</li>
+     * </ul>
+     *
+     * <p class="note">
+     * You can <em>not</em> receive this through components declared
+     * in manifests, only by explicitly registering for it with
+     * {@link android.content.Context#registerReceiver(android.content.BroadcastReceiver,
+     * android.content.IntentFilter) Context.registerReceiver()}.
+     *
+     * <p class="note">
+     * Requires no permission.
+     */
+    public static final String ACTION_RADIO_TECHNOLOGY_CHANGED 
+            = "android.intent.action.RADIO_TECHNOLOGY";
 
     /**
      * Broadcast Action: The phone's signal strength has changed. The intent will have the
@@ -47,7 +65,7 @@
      *          <ul><li>0 means "-113 dBm or less".</li><li>31 means "-51 dBm or greater".</li></ul>
      *   </li>
      * </ul>
-     * 
+     *
      * <p class="note">
      * You can <em>not</em> receive this through components declared
      * in manifests, only by exlicitly registering for it with
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index 6aa90f1..396b42d 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -26,8 +26,11 @@
 {
     //****** Baseband and Radio Interface version
 
-    /** 
-     * Baseband version 
+    //TODO T: property strings do not have to be gsm specific
+    //        change gsm.*operator.*" properties to "operator.*" properties
+
+    /**
+     * Baseband version
      * Availability: property is available any time radio is on
      */
     static final String PROPERTY_BASEBAND_VERSION = "gsm.version.baseband";
@@ -47,6 +50,12 @@
      */
     static final String PROPERTY_OPERATOR_NUMERIC = "gsm.operator.numeric";
 
+    /** 'true' if the device is on a manually selected network
+     *
+     *  Availability: when registered to a network
+     */
+    static final String PROPERTY_OPERATOR_ISMANUAL = "operator.ismanual";
+
     /** 'true' if the device is considered roaming on this network for GSM
      *  purposes.
      *  Availability: when registered to a network
@@ -60,7 +69,7 @@
     static final String PROPERTY_OPERATOR_ISO_COUNTRY = "gsm.operator.iso-country";
 
     //****** SIM Card
-    /** 
+    /**
      * One of <code>"UNKNOWN"</code> <code>"ABSENT"</code> <code>"PIN_REQUIRED"</code>
      * <code>"PUK_REQUIRED"</code> <code>"NETWORK_LOCKED"</code> or <code>"READY"</code>
      */
@@ -70,15 +79,15 @@
      *  provider of the SIM. 5 or 6 decimal digits.
      *  Availablity: SIM state must be "READY"
      */
-    static String PROPERTY_SIM_OPERATOR_NUMERIC = "gsm.sim.operator.numeric";
+    static String PROPERTY_ICC_OPERATOR_NUMERIC = "gsm.sim.operator.numeric";
 
-    /** PROPERTY_SIM_OPERATOR_ALPHA is also known as the SPN, or Service Provider Name. 
+    /** PROPERTY_ICC_OPERATOR_ALPHA is also known as the SPN, or Service Provider Name.
      *  Availablity: SIM state must be "READY"
      */
-    static String PROPERTY_SIM_OPERATOR_ALPHA = "gsm.sim.operator.alpha";
+    static String PROPERTY_ICC_OPERATOR_ALPHA = "gsm.sim.operator.alpha";
 
     /** ISO country code equivalent for the SIM provider's country code*/
-    static String PROPERTY_SIM_OPERATOR_ISO_COUNTRY = "gsm.sim.operator.iso-country";
+    static String PROPERTY_ICC_OPERATOR_ISO_COUNTRY = "gsm.sim.operator.iso-country";
 
     /**
      * Indicates the available radio technology.  Values include: <code>"unknown"</code>,
diff --git a/telephony/java/com/android/internal/telephony/WapPushOverSms.java b/telephony/java/com/android/internal/telephony/WapPushOverSms.java
index 2b70162..98899c9 100644
--- a/telephony/java/com/android/internal/telephony/WapPushOverSms.java
+++ b/telephony/java/com/android/internal/telephony/WapPushOverSms.java
@@ -22,7 +22,6 @@
 import android.provider.Telephony.Sms.Intents;
 import android.util.Config;
 import android.util.Log;
-import com.android.internal.telephony.gsm.SimUtils;
 
 
 /**
@@ -44,6 +43,7 @@
     private final int WAKE_LOCK_TIMEOUT = 5000;
 
     public WapPushOverSms(Phone phone) {
+
         mContext = phone.getContext();
         createWakelock();
     }
@@ -56,7 +56,7 @@
      */
     public void dispatchWapPdu(byte[] pdu) {
 
-        if (Config.LOGD) Log.d(LOG_TAG, "Rx: " + SimUtils.bytesToHexString(pdu));
+        if (Config.LOGD) Log.d(LOG_TAG, "Rx: " + IccUtils.bytesToHexString(pdu));
 
         int index = 0;
         int transactionId = pdu[index++] & 0xFF;
@@ -225,3 +225,4 @@
         mContext.sendBroadcast(intent, permission);
     }
 }
+
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
new file mode 100644
index 0000000..ef2f548
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -0,0 +1,916 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony.cdma;
+
+import android.content.Context;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Registrant;
+import android.os.RegistrantList;
+import android.os.SystemProperties;
+import android.provider.Settings;
+import android.telephony.CellLocation;
+import android.telephony.PhoneNumberUtils;
+import android.telephony.ServiceState;
+import android.text.TextUtils;
+import android.util.Log;
+
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_BASEBAND_VERSION;
+
+import com.android.internal.telephony.CallStateException;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.Connection;
+import com.android.internal.telephony.DataConnection;
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.IccFileHandler;
+import com.android.internal.telephony.IccPhoneBookInterfaceManager;
+import com.android.internal.telephony.IccSmsInterfaceManager;
+import com.android.internal.telephony.MmiCode;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneBase;
+import com.android.internal.telephony.PhoneNotifier;
+import com.android.internal.telephony.PhoneProxy;
+import com.android.internal.telephony.PhoneSubInfo;
+import com.android.internal.telephony.RILConstants;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * {@hide}
+ */
+public class CDMAPhone extends PhoneBase {
+    static final String LOG_TAG = "CDMA";
+    private static final boolean LOCAL_DEBUG = true;
+
+    //***** Instance Variables
+    CdmaCallTracker mCT;
+    CdmaSMSDispatcher mSMS;
+    CdmaServiceStateTracker mSST;
+    CdmaDataConnectionTracker mDataConnection;
+    RuimFileHandler mRuimFileHandler;
+    RuimRecords mRuimRecords;
+    RuimCard mRuimCard;
+    MyHandler h;
+    ArrayList <FeatureCode> mPendingMMIs = new ArrayList<FeatureCode>();
+    RuimPhoneBookInterfaceManager mRuimPhoneBookInterfaceManager;
+    RuimSmsInterfaceManager mRuimSmsInterfaceManager;
+    PhoneSubInfo mSubInfo;
+
+    protected RegistrantList mNvLoadedRegistrants = new RegistrantList();
+    private String mEsn;
+    private String mMeid;
+
+    Registrant mPostDialHandler;
+
+
+    //***** Constructors
+    public CDMAPhone(Context context, CommandsInterface ci, PhoneNotifier notifier) {
+        this(context,ci,notifier, false);
+    }
+
+    public CDMAPhone(Context context, CommandsInterface ci, PhoneNotifier notifier,
+            boolean unitTestMode) {
+        super(notifier, context, unitTestMode);
+
+        h = new MyHandler();
+        mCM = ci;
+
+        mCM.setPhoneType(RILConstants.CDMA_PHONE);
+        mCT = new CdmaCallTracker(this);
+        mSST = new CdmaServiceStateTracker (this);
+        mSMS = new CdmaSMSDispatcher(this);
+        mIccFileHandler = new RuimFileHandler(this);
+        mRuimRecords = new RuimRecords(this);
+        mDataConnection = new CdmaDataConnectionTracker (this);
+        mRuimCard = new RuimCard(this);
+        mRuimPhoneBookInterfaceManager = new RuimPhoneBookInterfaceManager(this);
+        mRuimSmsInterfaceManager = new RuimSmsInterfaceManager(this);
+        mSubInfo = new PhoneSubInfo(this);
+
+        mCM.registerForAvailable(h, EVENT_RADIO_AVAILABLE, null);
+        mRuimRecords.registerForRecordsLoaded(h, EVENT_RUIM_RECORDS_LOADED, null);
+        mCM.registerForOffOrNotAvailable(h, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
+        mCM.registerForOn(h, EVENT_RADIO_ON, null);
+        mCM.setOnSuppServiceNotification(h, EVENT_SSN, null);
+        mCM.setOnCallRing(h, EVENT_CALL_RING, null);
+        mSST.registerForNetworkAttach(h, EVENT_REGISTERED_TO_NETWORK, null);
+        mCM.registerForNVReady(h, EVENT_NV_READY, null);
+
+        //Change the system setting
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                Settings.Secure.CURRENT_ACTIVE_PHONE, RILConstants.CDMA_PHONE);
+    }
+
+    public void dispose() {
+        synchronized(PhoneProxy.lockForRadioTechnologyChange) {
+
+            //Unregister from all former registered events
+            mRuimRecords.unregisterForRecordsLoaded(h); //EVENT_RUIM_RECORDS_LOADED
+            mCM.unregisterForAvailable(h); //EVENT_RADIO_AVAILABLE
+            mCM.unregisterForOffOrNotAvailable(h); //EVENT_RADIO_OFF_OR_NOT_AVAILABLE
+            mCM.unregisterForOn(h); //EVENT_RADIO_ON
+            mCM.unregisterForNVReady(h); //EVENT_NV_READY
+            mSST.unregisterForNetworkAttach(h); //EVENT_REGISTERED_TO_NETWORK
+            mCM.unSetOnSuppServiceNotification(h);
+            mCM.unSetOnCallRing(h);
+
+            //Force all referenced classes to unregister their former registered events
+            mCT.dispose();
+            mDataConnection.dispose();
+            mSST.dispose();
+            mSMS.dispose();
+            mIccFileHandler.dispose(); // instance of RuimFileHandler
+            mRuimRecords.dispose();
+            mRuimCard.dispose();
+            mRuimPhoneBookInterfaceManager.dispose();
+            mRuimSmsInterfaceManager.dispose();
+            mSubInfo.dispose();
+        }
+    }
+
+    public void removeReferences() {
+            this.mRuimPhoneBookInterfaceManager = null;
+            this.mRuimSmsInterfaceManager = null;
+            this.mSMS = null;
+            this.mSubInfo = null;
+            this.mRuimRecords = null;
+            this.mIccFileHandler = null;
+            this.mRuimCard = null;
+            this.mDataConnection = null;
+            this.mCT = null;
+            this.mSST = null;
+    }
+
+    protected void finalize() {
+        if(LOCAL_DEBUG) Log.d(LOG_TAG, "CDMAPhone finalized");
+    }
+
+
+    //***** Overridden from Phone
+    public ServiceState getServiceState() {
+        return mSST.ss;
+    }
+
+    public Phone.State
+    getState() {
+        return mCT.state;
+    }
+
+    public String
+    getPhoneName() {
+        return "CDMA";
+    }
+
+    public boolean canTransfer() {
+        Log.e(LOG_TAG, "canTransfer: not possible in CDMA");
+        return false;
+    }
+
+    public CdmaCall
+    getRingingCall() {
+        return mCT.ringingCall;
+    }
+
+    public void setMute(boolean muted) {
+        mCT.setMute(muted);
+    }
+
+    public boolean getMute() {
+        return mCT.getMute();
+    }
+
+    public void conference() throws CallStateException {
+        // three way calls in CDMA will be handled by feature codes
+        Log.e(LOG_TAG, "conference: not possible in CDMA");
+    }
+
+    public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) {
+        this.mCM.setPreferredVoicePrivacy(enable, onComplete);
+    }
+
+    public void getEnhancedVoicePrivacy(Message onComplete) {
+        this.mCM.getPreferredVoicePrivacy(onComplete);
+    }
+
+    public void clearDisconnected() {
+        mCT.clearDisconnected();
+    }
+
+    public DataActivityState getDataActivityState() {
+        DataActivityState ret = DataActivityState.NONE;
+
+        if (mSST.getCurrentCdmaDataConnectionState() != ServiceState.RADIO_TECHNOLOGY_UNKNOWN) {
+
+            switch (mDataConnection.getActivity()) {
+                case DATAIN:
+                    ret = DataActivityState.DATAIN;
+                break;
+
+                case DATAOUT:
+                    ret = DataActivityState.DATAOUT;
+                break;
+
+                case DATAINANDOUT:
+                    ret = DataActivityState.DATAINANDOUT;
+                break;
+            }
+        }
+        return ret;
+    }
+
+    /*package*/ void
+    notifySignalStrength() {
+        mNotifier.notifySignalStrength(this);
+    }
+
+    public Connection
+    dial (String dialString) throws CallStateException {
+        // Need to make sure dialString gets parsed properly
+        String newDialString = PhoneNumberUtils.stripSeparators(dialString);
+
+        FeatureCode fc = FeatureCode.newFromDialString(newDialString, this);
+        if (LOCAL_DEBUG) Log.d(LOG_TAG,
+                "dialing w/ fc '" + fc + "'...");
+        // check for feature code
+        if (fc == null) {
+            // check if call in progress
+            if (!mCT.foregroundCall.isIdle()) {
+                FeatureCode digits = new FeatureCode(this);
+                // use dial number as poundString
+                digits.poundString = newDialString;
+                mPendingMMIs.add(fc);
+                mMmiRegistrants.notifyRegistrants(new AsyncResult(null, fc, null));
+                digits.processCode();
+                return null;
+            } else {
+                return mCT.dial(newDialString);
+            }
+        } else {
+            mPendingMMIs.add(fc);
+            mMmiRegistrants.notifyRegistrants(new AsyncResult(null, fc, null));
+            fc.processCode();
+
+            // FIXME should this return null or something else?
+            return null;
+        }
+    }
+
+    public int getSignalStrengthASU() {
+        return mSST.rssi == 99 ? -1 : mSST.rssi;
+    }
+
+    public boolean
+    getMessageWaitingIndicator() {
+        Log.e(LOG_TAG, "method getMessageWaitingIndicator is NOT supported in CDMA!");
+        return false;
+    }
+
+    public List<? extends MmiCode>
+    getPendingMmiCodes() {
+        Log.e(LOG_TAG, "method getPendingMmiCodes is NOT supported in CDMA!");
+        return null;
+    }
+
+    public void registerForSuppServiceNotification(
+            Handler h, int what, Object obj) {
+        Log.e(LOG_TAG, "method registerForSuppServiceNotification is NOT supported in CDMA!");
+    }
+
+    public CdmaCall getBackgroundCall() {
+        return mCT.backgroundCall;
+    }
+
+    public String getGateway(String apnType) {
+        return mDataConnection.getGateway();
+    }
+
+    public boolean handleInCallMmiCommands(String dialString) {
+        Log.e(LOG_TAG, "method handleInCallMmiCommands is NOT supported in CDMA!");
+        return false;
+    }
+
+    public int enableApnType(String type) {
+        // This request is mainly used to enable MMS APN
+        // In CDMA there is no need to enable/disable a different APN for MMS
+        Log.d(LOG_TAG, "Request to enableApnType("+type+")");
+        if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
+            return Phone.APN_ALREADY_ACTIVE;
+        } else {
+            return Phone.APN_REQUEST_FAILED;
+        }
+    }
+
+    public int disableApnType(String type) {
+        // This request is mainly used to disable MMS APN
+        // In CDMA there is no need to enable/disable a different APN for MMS
+        Log.d(LOG_TAG, "Request to disableApnType("+type+")");
+        if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
+            return Phone.APN_REQUEST_STARTED;
+        } else {
+            return Phone.APN_REQUEST_FAILED;
+        }
+    }
+
+    public String getActiveApn() {
+        Log.d(LOG_TAG, "Request to getActiveApn()");
+        return null;
+    }
+
+    public void
+    setNetworkSelectionModeAutomatic(Message response) {
+        Log.e(LOG_TAG, "method setNetworkSelectionModeAutomatic is NOT supported in CDMA!");
+    }
+
+    public void unregisterForSuppServiceNotification(Handler h) {
+        Log.e(LOG_TAG, "method unregisterForSuppServiceNotification is NOT supported in CDMA!");
+    }
+
+    public void
+    acceptCall() throws CallStateException {
+        mCT.acceptCall();
+    }
+
+    public void
+    rejectCall() throws CallStateException {
+        mCT.rejectCall();
+    }
+
+    public void
+    switchHoldingAndActive() throws CallStateException {
+        mCT.switchWaitingOrHoldingAndActive();
+    }
+
+    public String getLine1Number() {
+        return mRuimRecords.getMdnNumber();
+    }
+
+    public void getCallWaiting(Message onComplete) {
+        mCM.queryCallWaiting(CommandsInterface.SERVICE_CLASS_VOICE, onComplete);
+    }
+
+    public void
+    setRadioPower(boolean power) {
+        mSST.setRadioPower(power);
+    }
+
+    public String getEsn() {
+        return mEsn;
+    }
+
+    public String getMeid() {
+        return mMeid;
+    }
+
+    //returns MEID in CDMA
+    public String getDeviceId() {
+        return getMeid();
+    }
+
+    public String getDeviceSvn() {
+        Log.d(LOG_TAG, "getDeviceSvn(): return 0");
+        return "0";
+    }
+
+    public String getSubscriberId() {
+        Log.e(LOG_TAG, "method getSubscriberId for IMSI is NOT supported in CDMA!");
+        return null;
+    }
+
+    public boolean canConference() {
+        Log.e(LOG_TAG, "canConference: not possible in CDMA");
+        return false;
+    }
+
+    public String getInterfaceName(String apnType) {
+        return mDataConnection.getInterfaceName();
+    }
+
+    public CellLocation getCellLocation() {
+        return mSST.cellLoc;
+    }
+
+    public boolean disableDataConnectivity() {
+        return mDataConnection.setDataEnabled(false);
+    }
+
+    public CdmaCall getForegroundCall() {
+        return mCT.foregroundCall;
+    }
+
+    public void
+    selectNetworkManually(com.android.internal.telephony.gsm.NetworkInfo network,
+            Message response) {
+        Log.e(LOG_TAG, "selectNetworkManually: not possible in CDMA");
+    }
+
+    public void setOnPostDialCharacter(Handler h, int what, Object obj) {
+        Log.e(LOG_TAG, "setOnPostDialCharacter: not possible in CDMA");
+    }
+
+    public boolean handlePinMmi(String dialString) {
+        Log.e(LOG_TAG, "method handlePinMmi is NOT supported in CDMA!");
+        return false;
+    }
+
+    public boolean isDataConnectivityPossible() {
+        boolean noData = mDataConnection.getDataEnabled() &&
+                getDataConnectionState() == DataState.DISCONNECTED;
+        return !noData && getIccCard().getState() == IccCard.State.READY &&
+                getServiceState().getState() == ServiceState.STATE_IN_SERVICE &&
+                (mDataConnection.getDataOnRoamingEnabled() || !getServiceState().getRoaming());
+    }
+
+    public void setLine1Number(String alphaTag, String number, Message onComplete) {
+        Log.e(LOG_TAG, "setLine1Number: not possible in CDMA");
+    }
+
+    public String[] getDnsServers(String apnType) {
+        return mDataConnection.getDnsServers();
+    }
+
+    public IccCard getIccCard() {
+        return mRuimCard;
+    }
+
+    public String getIccSerialNumber() {
+        return mRuimRecords.iccid;
+    }
+
+    public void setCallWaiting(boolean enable, Message onComplete) {
+        Log.e(LOG_TAG, "method setCallWaiting is NOT supported in CDMA!");
+    }
+
+    public void updateServiceLocation(Message response) {
+        mSST.getLacAndCid(response);
+    }
+
+    public void setDataRoamingEnabled(boolean enable) {
+        mDataConnection.setDataOnRoamingEnabled(enable);
+    }
+
+    public String getIpAddress(String apnType) {
+        return mDataConnection.getIpAddress();
+    }
+
+    public void
+    getNeighboringCids(Message response) {
+        // WINK:TODO: implement after Cupcake merge
+        mCM.getNeighboringCids(response); // workaround.
+    }
+
+    public DataState getDataConnectionState() {
+        DataState ret = DataState.DISCONNECTED;
+
+        if ((SystemProperties.get("adb.connected", "").length() > 0)
+                && (SystemProperties.get("android.net.use-adb-networking", "")
+                        .length() > 0)) {
+            // We're connected to an ADB host and we have USB networking
+            // turned on. No matter what the radio state is,
+            // we report data connected
+
+            ret = DataState.CONNECTED;
+        } else if (mSST.getCurrentCdmaDataConnectionState()
+                == ServiceState.RADIO_TECHNOLOGY_UNKNOWN) {
+            // If we're out of service, open TCP sockets may still work
+            // but no data will flow
+            ret = DataState.DISCONNECTED;
+        } else {
+            switch (mDataConnection.getState()) {
+                case FAILED:
+                case IDLE:
+                    ret = DataState.DISCONNECTED;
+                break;
+
+                case CONNECTED:
+                case DISCONNECTING:
+                    if ( mCT.state != Phone.State.IDLE
+                            && !mSST.isConcurrentVoiceAndData()) {
+                        ret = DataState.SUSPENDED;
+                    } else {
+                        ret = DataState.CONNECTED;
+                    }
+                break;
+
+                case INITING:
+                case CONNECTING:
+                case SCANNING:
+                    ret = DataState.CONNECTING;
+                break;
+            }
+        }
+
+        return ret;
+    }
+
+    public void sendUssdResponse(String ussdMessge) {
+        Log.e(LOG_TAG, "sendUssdResponse: not possible in CDMA");
+    }
+
+    public void sendDtmf(char c) {
+        if (!PhoneNumberUtils.is12Key(c)) {
+            Log.e(LOG_TAG,
+                    "sendDtmf called with invalid character '" + c + "'");
+        } else {
+            if (mCT.state ==  Phone.State.OFFHOOK) {
+                mCM.sendDtmf(c, null);
+            }
+        }
+    }
+
+    public void startDtmf(char c) {
+        if (!PhoneNumberUtils.is12Key(c)) {
+            Log.e(LOG_TAG,
+                    "startDtmf called with invalid character '" + c + "'");
+        } else {
+            mCM.startDtmf(c, null);
+        }
+    }
+
+    public void stopDtmf() {
+        mCM.stopDtmf(null);
+    }
+
+    public void getAvailableNetworks(Message response) {
+        Log.e(LOG_TAG, "getAvailableNetworks: not possible in CDMA");
+    }
+
+    public String[] getActiveApnTypes() {
+        String[] result;
+        Log.d(LOG_TAG, "Request to getActiveApn()");
+        result = new String[1];
+        result[0] = Phone.APN_TYPE_DEFAULT;
+        return result;
+    }
+
+    public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, Message onComplete) {
+        Log.e(LOG_TAG, "getAvailableNetworks: not possible in CDMA");
+    }
+
+    public void enableLocationUpdates() {
+        mSST.enableLocationUpdates();
+    }
+
+    /**
+     * @deprecated
+     */
+    public void getPdpContextList(Message response) {
+        getDataCallList(response);
+    }
+
+    public void getDataCallList(Message response) {
+        mCM.getDataCallList(response);
+    }
+
+    public boolean getDataRoamingEnabled() {
+        return mDataConnection.getDataOnRoamingEnabled();
+    }
+
+    public List<DataConnection> getCurrentDataConnectionList () {
+        return mDataConnection.getAllDataConnections();
+    }
+
+    public void setVoiceMailNumber(String alphaTag,
+                                   String voiceMailNumber,
+                                   Message onComplete) {
+        //mSIMRecords.setVoiceMailNumber(alphaTag, voiceMailNumber, onComplete);
+        //TODO: Where do we have to store this value has to be clarified with QC
+    }
+
+    public String getVoiceMailNumber() {
+        //TODO: Where can we get this value has to be clarified with QC
+        //return mSIMRecords.getVoiceMailNumber();
+//      throw new RuntimeException();
+        return "12345";
+    }
+
+    public String getVoiceMailAlphaTag() {
+        // TODO: Where can we get this value has to be clarified with QC.
+        String ret = "";//TODO: Remove = "", if we know where to get this value.
+
+        //ret = mSIMRecords.getVoiceMailAlphaTag();
+
+        if (ret == null || ret.length() == 0) {
+            return mContext.getText(
+                com.android.internal.R.string.defaultVoiceMailAlphaTag).toString();
+        }
+
+        return ret;
+    }
+
+    public boolean enableDataConnectivity() {
+        return mDataConnection.setDataEnabled(true);
+    }
+
+    public void disableLocationUpdates() {
+        mSST.disableLocationUpdates();
+    }
+
+    public boolean getIccRecordsLoaded() {
+        return mRuimRecords.getRecordsLoaded();
+    }
+
+    public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) {
+        Log.e(LOG_TAG, "getCallForwardingOption: not possible in CDMA");
+    }
+
+    public void setCallForwardingOption(int commandInterfaceCFAction,
+            int commandInterfaceCFReason,
+            String dialingNumber,
+            int timerSeconds,
+            Message onComplete) {
+        Log.e(LOG_TAG, "setCallForwardingOption: not possible in CDMA");
+    }
+
+    public void
+    getOutgoingCallerIdDisplay(Message onComplete) {
+        Log.e(LOG_TAG, "getOutgoingCallerIdDisplay: not possible in CDMA");
+    }
+
+    public boolean
+    getCallForwardingIndicator() {
+        Log.e(LOG_TAG, "getCallForwardingIndicator: not possible in CDMA");
+        return false;
+    }
+
+    public void explicitCallTransfer() {
+        Log.e(LOG_TAG, "explicitCallTransfer: not possible in CDMA");
+    }
+
+    public String getLine1AlphaTag() {
+        Log.e(LOG_TAG, "getLine1AlphaTag: not possible in CDMA");
+        return null;
+    }
+
+    /**
+     * Notify any interested party of a Phone state change.
+     */
+    /*package*/ void notifyPhoneStateChanged() {
+        mNotifier.notifyPhoneState(this);
+    }
+
+    /**
+     * Notifies registrants (ie, activities in the Phone app) about
+     * changes to call state (including Phone and Connection changes).
+     */
+    /*package*/ void notifyCallStateChanged() {
+        /* we'd love it if this was package-scoped*/
+        super.notifyCallStateChangedP();
+    }
+
+     void notifyServiceStateChanged(ServiceState ss) {
+         super.notifyServiceStateChangedP(ss);
+     }
+
+     void notifyLocationChanged() {
+         mNotifier.notifyCellLocation(this);
+     }
+
+    /*package*/ void notifyNewRingingConnection(Connection c) {
+        /* we'd love it if this was package-scoped*/
+        super.notifyNewRingingConnectionP(c);
+    }
+
+    /**
+     * Notifiy registrants of a RING event.
+     */
+    void notifyIncomingRing() {
+        AsyncResult ar = new AsyncResult(null, this, null);
+        mIncomingRingRegistrants.notifyRegistrants(ar);
+    }
+
+    /*package*/ void notifyDisconnect(Connection cn) {
+        mDisconnectRegistrants.notifyResult(cn);
+    }
+
+    void notifyUnknownConnection() {
+        mUnknownConnectionRegistrants.notifyResult(this);
+    }
+
+    /*package*/ void
+    updateMessageWaitingIndicator(boolean mwi) {
+        // this also calls notifyMessageWaitingIndicator()
+        mRuimRecords.setVoiceMessageWaiting(1, mwi ? -1 : 0);
+    }
+
+
+    /**
+     * Removes the given FC from the pending list and notifies
+     * registrants that it is complete.
+     * @param fc FC that is done
+     */
+    /*package*/ void onMMIDone(FeatureCode fc) {
+        /* Only notify complete if it's on the pending list.
+         * Otherwise, it's already been handled (eg, previously canceled).
+         * The exception is cancellation of an incoming USSD-REQUEST, which is
+         * not on the list.
+         */
+        if (mPendingMMIs.remove(fc)) {
+            mMmiCompleteRegistrants.notifyRegistrants(
+                    new AsyncResult(null, fc, null));
+        }
+    }
+
+    //***** Inner Classes
+    class MyHandler extends Handler {
+        MyHandler() {
+        }
+
+        MyHandler(Looper l) {
+            super(l);
+        }
+
+        public void handleMessage(Message msg) {
+            AsyncResult ar;
+            Message     onComplete;
+
+            switch(msg.what) {
+                case EVENT_RADIO_AVAILABLE: {
+                    mCM.getBasebandVersion(obtainMessage(EVENT_GET_BASEBAND_VERSION_DONE));
+
+                    mCM.getDeviceIdentity(obtainMessage(EVENT_GET_DEVICE_IDENTITY_DONE));
+                }
+                break;
+
+                case EVENT_GET_BASEBAND_VERSION_DONE:{
+                    ar = (AsyncResult)msg.obj;
+
+                    if (ar.exception != null) {
+                        break;
+                    }
+
+                    if (LOCAL_DEBUG) Log.d(LOG_TAG, "Baseband version: " + ar.result);
+                    setSystemProperty(PROPERTY_BASEBAND_VERSION, (String)ar.result);
+                }
+                break;
+
+                case EVENT_GET_DEVICE_IDENTITY_DONE:{
+                    ar = (AsyncResult)msg.obj;
+
+                    if (ar.exception != null) {
+                        break;
+                    }
+                    String[] respId = (String[])ar.result;
+                    mEsn  =  respId[2];
+                    mMeid =  respId[3];
+                }
+                break;
+
+                case EVENT_RUIM_RECORDS_LOADED:{
+                    Log.d(LOG_TAG, "Event EVENT_RUIM_RECORDS_LOADED Received");
+                }
+                break;
+
+                case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:{
+                    Log.d(LOG_TAG, "Event EVENT_RADIO_OFF_OR_NOT_AVAILABLE Received");
+                }
+                break;
+
+                case EVENT_RADIO_ON:{
+                    Log.d(LOG_TAG, "Event EVENT_RADIO_ON Received");
+                }
+                break;
+
+                case EVENT_SSN:{
+                    Log.d(LOG_TAG, "Event EVENT_SSN Received");
+                }
+                break;
+
+                case EVENT_CALL_RING:{
+                    Log.d(LOG_TAG, "Event EVENT_CALL_RING Received");
+                }
+                break;
+
+                case EVENT_REGISTERED_TO_NETWORK:{
+                    Log.d(LOG_TAG, "Event EVENT_REGISTERED_TO_NETWORK Received");
+                }
+                break;
+
+                case EVENT_NV_READY:{
+                    Log.d(LOG_TAG, "Event EVENT_NV_READY Received");
+                    //Inform the Service State Tracker
+                    mNvLoadedRegistrants.notifyRegistrants();
+                }
+                break;
+
+                default:{
+                    throw new RuntimeException("unexpected event not handled");
+                }
+            }
+        }
+    }
+
+     /**
+      * Retrieves the PhoneSubInfo of the CDMAPhone
+      */
+     public PhoneSubInfo getPhoneSubInfo(){
+        return mSubInfo;
+     }
+
+     /**
+      * Retrieves the IccSmsInterfaceManager of the CDMAPhone
+      */
+     public IccSmsInterfaceManager getIccSmsInterfaceManager(){
+         return mRuimSmsInterfaceManager;
+     }
+
+     /**
+      * Retrieves the IccPhoneBookInterfaceManager of the CDMAPhone
+      */
+     public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager(){
+         return mRuimPhoneBookInterfaceManager;
+     }
+
+    public void registerForNvLoaded(Handler h, int what, Object obj) {
+        Registrant r = new Registrant (h, what, obj);
+        mNvLoadedRegistrants.add(r);
+    }
+
+    public void unregisterForNvLoaded(Handler h) {
+        mNvLoadedRegistrants.remove(h);
+    }
+
+     // override for allowing access from other classes of this package
+     /**
+      * {@inheritDoc}
+      */
+     public final void setSystemProperty(String property, String value) {
+         super.setSystemProperty(property, value);
+     }
+
+     /**
+      * {@inheritDoc}
+      */
+     public Handler getHandler(){
+         return h;
+     }
+
+     /**
+      * {@inheritDoc}
+      */
+     public IccFileHandler getIccFileHandler(){
+         return this.mIccFileHandler;
+     }
+
+     /**
+      * Set the TTY mode of the CDMAPhone
+      */
+     public void setTTYModeEnabled(boolean enable, Message onComplete) {
+         this.mCM.setTTYModeEnabled(enable, onComplete);
+}
+
+     /**
+      * Queries the TTY mode of the CDMAPhone
+      */
+     public void queryTTYModeEnabled(Message onComplete) {
+         this.mCM.queryTTYModeEnabled(onComplete);
+     }
+
+     /**
+      * Activate or deactivate cell broadcast SMS.
+      *
+      * @param activate
+      *            0 = activate, 1 = deactivate
+      * @param response
+      *            Callback message is empty on completion
+      */
+     public void activateCellBroadcastSms(int activate, Message response) {
+         mSMS.activateCellBroadcastSms(activate, response);
+     }
+
+     /**
+      * Query the current configuration of cdma cell broadcast SMS.
+      *
+      * @param response
+      *            Callback message is empty on completion
+      */
+     public void getCellBroadcastSmsConfig(Message response){
+         mSMS.getCellBroadcastSmsConfig(response);
+     }
+
+     /**
+      * Configure cdma cell broadcast SMS.
+      *
+      * @param response
+      *            Callback message is empty on completion
+      */
+     public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response){
+         mSMS.setCellBroadcastConfig(configValuesArray, response);
+     }
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CallFailCause.java b/telephony/java/com/android/internal/telephony/cdma/CallFailCause.java
new file mode 100644
index 0000000..ea557b2
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/CallFailCause.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony.cdma;
+
+/**
+ * Call fail causes from TS 24.008 .
+ * These are mostly the cause codes we need to distinguish for the UI.
+ * See 22.001 Annex F.4 for mapping of cause codes to local tones.
+ *
+ * {@hide}
+ *
+ */
+public interface CallFailCause {
+    static final int NORMAL_CLEARING     = 16;
+    // Busy Tone
+    static final int USER_BUSY           = 17;
+
+//    // No Tone
+//    static final int NUMBER_CHANGED      = 22;
+//    static final int STATUS_ENQUIRY      = 30;
+    static final int NORMAL_UNSPECIFIED  = 31;
+//
+//    // Congestion Tone
+//    static final int NO_CIRCUIT_AVAIL    = 34;
+//    static final int TEMPORARY_FAILURE   = 41;
+//    static final int SWITCHING_CONGESTION    = 42;
+//    static final int CHANNEL_NOT_AVAIL   = 44;
+//    static final int QOS_NOT_AVAIL       = 49;
+//    static final int BEARER_NOT_AVAIL    = 58;
+//
+//    // others
+//    static final int ACM_LIMIT_EXCEEDED = 68;
+//    static final int CALL_BARRED        = 240;
+//    static final int FDN_BLOCKED        = 241;
+    static final int ERROR_UNSPECIFIED = 0xffff;
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMCall.java b/telephony/java/com/android/internal/telephony/cdma/CdmaCall.java
similarity index 73%
copy from telephony/java/com/android/internal/telephony/gsm/GSMCall.java
copy to telephony/java/com/android/internal/telephony/cdma/CdmaCall.java
index 4feaf21..34514d9 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GSMCall.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaCall.java
@@ -14,27 +14,31 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
-import com.android.internal.telephony.*;
+package com.android.internal.telephony.cdma;
+
 import java.util.ArrayList;
 import java.util.List;
 
+import com.android.internal.telephony.Call;
+import com.android.internal.telephony.CallStateException;
+import com.android.internal.telephony.Connection;
+import com.android.internal.telephony.DriverCall;
+import com.android.internal.telephony.Phone;
+
 /**
  * {@hide}
  */
-class GSMCall extends Call
-{
+public final class CdmaCall extends Call {
     /*************************** Instance Variables **************************/
 
     /*package*/ ArrayList<Connection> connections = new ArrayList<Connection>();
     /*package*/ State state = State.IDLE;
-    /*package*/ CallTracker owner;
+    /*package*/ CdmaCallTracker owner;
 
     /***************************** Class Methods *****************************/
 
     static State
-    stateFromDCState (DriverCall.State dcState)
-    {
+    stateFromDCState (DriverCall.State dcState) {
         switch (dcState) {
             case ACTIVE:        return State.ACTIVE;
             case HOLDING:       return State.HOLDING;
@@ -45,40 +49,36 @@
             default:            throw new RuntimeException ("illegal call state:" + dcState);
         }
     }
-    
+
 
     /****************************** Constructors *****************************/
     /*package*/
-    GSMCall (CallTracker owner)
-    {
+    CdmaCall (CdmaCallTracker owner) {
         this.owner = owner;
     }
 
-    /************************** Overridden from Call *************************/
+    public void dispose() {
+    }
 
+    /************************** Overridden from Call *************************/
     public List<Connection>
-    getConnections()
-    {
+    getConnections() {
         // FIXME should return Collections.unmodifiableList();
         return connections;
     }
 
-    public State 
-    getState()
-    {
+    public State
+    getState() {
         return state;
     }
 
-    public Phone 
-    getPhone()
-    {
-        //TODO
+    public Phone
+    getPhone() {
+        //TODO, see GsmCall
         return null;
     }
 
-    public boolean
-    isMultiparty()
-    {
+    public boolean isMultiparty() {
         return connections.size() > 1;
     }
 
@@ -86,66 +86,60 @@
      *  background call exists, the background call will be resumed
      *  because an AT+CHLD=1 will be sent
      */
-    public void 
-    hangup() throws CallStateException
-    {
+    public void
+    hangup() throws CallStateException {
         owner.hangup(this);
     }
 
     public String
-    toString()
-    {
+    toString() {
         return state.toString();
     }
 
-    //***** Called from GSMConnection
+    //***** Called from CdmaConnection
 
     /*package*/ void
-    attach(GSMConnection conn, DriverCall dc)
-    {
+    attach(Connection conn, DriverCall dc) {
         connections.add(conn);
 
         state = stateFromDCState (dc.state);
     }
 
     /*package*/ void
-    attachFake(GSMConnection conn, State state)
-    {
+    attachFake(Connection conn, State state) {
         connections.add(conn);
 
         this.state = state;
     }
 
     /**
-     * Called by GSMConnection when it has disconnected
+     * Called by CdmaConnection when it has disconnected
      */
     void
-    connectionDisconnected(GSMConnection conn)
-    {
+    connectionDisconnected(CdmaConnection conn) {
         if (state != State.DISCONNECTED) {
             /* If only disconnected connections remain, we are disconnected*/
 
             boolean hasOnlyDisconnectedConnections = true;
-            
+
             for (int i = 0, s = connections.size()  ; i < s; i ++) {
-                if (connections.get(i).getState() 
+                if (connections.get(i).getState()
                     != State.DISCONNECTED
                 ) {
                     hasOnlyDisconnectedConnections = false;
                     break;
-                }            
+                }
             }
 
             if (hasOnlyDisconnectedConnections) {
-                state = State.DISCONNECTED;            
+                state = State.DISCONNECTED;
             }
-        }    
+        }
     }
 
 
     /*package*/ void
-    detach(GSMConnection conn)
-    {
+    detach(CdmaConnection conn) {
         connections.remove(conn);
 
         if (connections.size() == 0) {
@@ -154,13 +148,12 @@
     }
 
     /*package*/ boolean
-    update (GSMConnection conn, DriverCall dc)
-    {
+    update (CdmaConnection conn, DriverCall dc) {
         State newState;
         boolean changed = false;
-        
+
         newState = stateFromDCState(dc.state);
-        
+
         if (newState != state) {
             state = newState;
             changed = true;
@@ -174,48 +167,43 @@
      * connections to be added via "conference"
      */
     /*package*/ boolean
-    isFull()
-    {
-        return connections.size() == CallTracker.MAX_CONNECTIONS_PER_CALL;
+    isFull() {
+        return connections.size() == CdmaCallTracker.MAX_CONNECTIONS_PER_CALL;
     }
 
-    //***** Called from CallTracker
+    //***** Called from CdmaCallTracker
 
 
-    /** 
+    /**
      * Called when this Call is being hung up locally (eg, user pressed "end")
      * Note that at this point, the hangup request has been dispatched to the radio
      * but no response has yet been received so update() has not yet been called
      */
     void
-    onHangupLocal()
-    {
+    onHangupLocal() {
         for (int i = 0, s = connections.size()
                 ; i < s; i++
         ) {
-            GSMConnection cn = (GSMConnection)connections.get(i);
+            CdmaConnection cn = (CdmaConnection)connections.get(i);
 
             cn.onHangupLocal();
         }
     }
-    
+
     /**
      * Called when it's time to clean up disconnected Connection objects
      */
-    void
-    clearDisconnected()
-    {
+   void clearDisconnected() {
         for (int i = connections.size() - 1 ; i >= 0 ; i--) {
-            GSMConnection cn = (GSMConnection)connections.get(i);
-            
+        CdmaConnection cn = (CdmaConnection)connections.get(i);
+
             if (cn.getState() == State.DISCONNECTED) {
                 connections.remove(i);
             }
-        }    
+        }
 
         if (connections.size() == 0) {
             state = State.IDLE;
         }
     }
 }
-
diff --git a/telephony/java/com/android/internal/telephony/gsm/CallTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
similarity index 69%
copy from telephony/java/com/android/internal/telephony/gsm/CallTracker.java
copy to telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
index 2d716bb..a1d362f 100644
--- a/telephony/java/com/android/internal/telephony/gsm/CallTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
@@ -14,30 +14,24 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony.cdma;
 
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE;
-import static com.android.internal.telephony.gsm.ServiceStateTracker.DATA_ACCESS_EDGE;
-import static com.android.internal.telephony.gsm.ServiceStateTracker.DATA_ACCESS_GPRS;
-import static com.android.internal.telephony.gsm.ServiceStateTracker.DATA_ACCESS_UMTS;
-import static com.android.internal.telephony.gsm.ServiceStateTracker.DATA_ACCESS_UNKNOWN;
 import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.Message;
 import android.os.Registrant;
 import android.os.RegistrantList;
-import android.os.SystemProperties;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.ServiceState;
-import android.telephony.TelephonyManager;
-import android.telephony.gsm.GsmCellLocation;
-import android.util.EventLog;
 import android.util.Log;
 
-import com.android.internal.telephony.Call;
 import com.android.internal.telephony.CallStateException;
+import com.android.internal.telephony.CallTracker;
+import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.Connection;
+import com.android.internal.telephony.DriverCall;
 import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneProxy;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -45,95 +39,108 @@
 /**
  * {@hide}
  */
-public final class CallTracker extends Handler
-{
-    static final String LOG_TAG = "GSM";
+public final class CdmaCallTracker extends CallTracker {
+    static final String LOG_TAG = "CDMA";
+
     private static final boolean REPEAT_POLLING = false;
 
     private static final boolean DBG_POLL = false;
 
     //***** Constants
 
-    static final int POLL_DELAY_MSEC = 250;
-    static final int MAX_CONNECTIONS = 7;   // only 7 connections allowed in GSM
-    static final int MAX_CONNECTIONS_PER_CALL = 5; // only 5 connections allowed per call
+    static final int MAX_CONNECTIONS = 1;   // only 1 connection allowed in CDMA
+    static final int MAX_CONNECTIONS_PER_CALL = 1; // only 1 connection allowed per call
 
     //***** Instance Variables
 
-    GSMConnection connections[] = new GSMConnection[MAX_CONNECTIONS];
+    CdmaConnection connections[] = new CdmaConnection[MAX_CONNECTIONS];
     RegistrantList voiceCallEndedRegistrants = new RegistrantList();
     RegistrantList voiceCallStartedRegistrants = new RegistrantList();
 
 
     // connections dropped durin last poll
-    ArrayList<GSMConnection> droppedDuringPoll
-        = new ArrayList<GSMConnection>(MAX_CONNECTIONS);
+    ArrayList<CdmaConnection> droppedDuringPoll
+        = new ArrayList<CdmaConnection>(MAX_CONNECTIONS);
 
-    GSMCall ringingCall = new GSMCall(this);
-            // A call that is ringing or (call) waiting
-    GSMCall foregroundCall = new GSMCall(this);
-    GSMCall backgroundCall = new GSMCall(this);
+    CdmaCall ringingCall = new CdmaCall(this);
+    // A call that is ringing or (call) waiting
+    CdmaCall foregroundCall = new CdmaCall(this);
+    CdmaCall backgroundCall = new CdmaCall(this);
 
-    GSMConnection pendingMO;
+    CdmaConnection pendingMO;
     boolean hangupPendingMO;
 
-    GSMPhone phone;
-    CommandsInterface cm;
+    CDMAPhone phone;
+
     boolean desiredMute = false;    // false = mute off
 
     Phone.State state = Phone.State.IDLE;
 
-    int pendingOperations;
-    boolean needsPoll;
-    Message lastRelevantPoll;
+
+//    boolean needsPoll;
+
 
 
     //***** Events
 
-    static final int EVENT_POLL_CALLS_RESULT    = 1;
-    static final int EVENT_CALL_STATE_CHANGE    = 2;
-    static final int EVENT_REPOLL_AFTER_DELAY   = 3;
-    static final int EVENT_OPERATION_COMPLETE     = 4;
-    static final int EVENT_GET_LAST_CALL_FAIL_CAUSE = 5;
-
-    static final int EVENT_SWITCH_RESULT        = 8;
-    static final int EVENT_RADIO_AVAILABLE       = 9;
-    static final int EVENT_RADIO_NOT_AVAILABLE       = 10;
-    static final int EVENT_CONFERENCE_RESULT    = 11;
-    static final int EVENT_SEPARATE_RESULT      = 12;
-    static final int EVENT_ECT_RESULT           = 13;
-
     //***** Constructors
-
-    CallTracker (GSMPhone phone)
-    {
+    CdmaCallTracker(CDMAPhone phone) {
         this.phone = phone;
         cm = phone.mCM;
-
         cm.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null);
-
         cm.registerForOn(this, EVENT_RADIO_AVAILABLE, null);
         cm.registerForNotAvailable(this, EVENT_RADIO_NOT_AVAILABLE, null);
     }
 
+    public void dispose() {
+        cm.unregisterForCallStateChanged(this);
+        cm.unregisterForOn(this);
+        cm.unregisterForNotAvailable(this);
+
+        for(CdmaConnection c : connections) {
+            try {
+                if(c != null) hangup(c);
+            } catch (CallStateException ex) {
+                Log.e(LOG_TAG, "unexpected error on hangup during dispose");
+            }
+        }
+
+        try {
+            if(pendingMO != null) hangup(pendingMO);
+        } catch (CallStateException ex) {
+            Log.e(LOG_TAG, "unexpected error on hangup during dispose");
+        }
+
+        clearDisconnected();
+
+    }
+
+    protected void finalize() {
+        Log.d(LOG_TAG, "CdmaCallTracker finalized");
+    }
+
     //***** Instance Methods
 
     //***** Public Methods
-    public void registerForVoiceCallStarted(Handler h, int what, Object obj)
-    {
+    public void registerForVoiceCallStarted(Handler h, int what, Object obj) {
         Registrant r = new Registrant(h, what, obj);
         voiceCallStartedRegistrants.add(r);
     }
+    public void unregisterForVoiceCallStarted(Handler h) {
+        voiceCallStartedRegistrants.remove(h);
+    }
 
-    public void registerForVoiceCallEnded(Handler h, int what, Object obj)
-    {
+    public void registerForVoiceCallEnded(Handler h, int what, Object obj) {
         Registrant r = new Registrant(h, what, obj);
         voiceCallEndedRegistrants.add(r);
     }
 
+    public void unregisterForVoiceCallEnded(Handler h) {
+        voiceCallEndedRegistrants.remove(h);
+    }
+
     private void
-    fakeHoldForegroundBeforeDial()
-    {
+    fakeHoldForegroundBeforeDial() {
         List<Connection> connCopy;
 
         // We need to make a copy here, since fakeHoldBeforeDial()
@@ -141,7 +148,7 @@
         connCopy = (List<Connection>) foregroundCall.connections.clone();
 
         for (int i = 0, s = connCopy.size() ; i < s ; i++) {
-            GSMConnection conn = (GSMConnection)connCopy.get(i);
+            CdmaConnection conn = (CdmaConnection)connCopy.get(i);
 
             conn.fakeHoldBeforeDial();
         }
@@ -162,7 +169,7 @@
         // The new call must be assigned to the foreground call.
         // That call must be idle, so place anything that's
         // there on hold
-        if (foregroundCall.getState() == Call.State.ACTIVE) {
+        if (foregroundCall.getState() == CdmaCall.State.ACTIVE) {
             // this will probably be done by the radio anyway
             // but the dial might fail before this happens
             // and we need to make sure the foreground call is clear
@@ -176,12 +183,12 @@
             fakeHoldForegroundBeforeDial();
         }
 
-        if (foregroundCall.getState() != Call.State.IDLE) {
+        if (foregroundCall.getState() != CdmaCall.State.IDLE) {
             //we should have failed in !canDial() above before we get here
             throw new CallStateException("cannot dial in current state");
         }
 
-        pendingMO = new GSMConnection(phone.getContext(), dialString, this, foregroundCall);
+        pendingMO = new CdmaConnection(phone.getContext(), dialString, this, foregroundCall);
         hangupPendingMO = false;
 
         if (pendingMO.address == null || pendingMO.address.length() == 0
@@ -208,24 +215,22 @@
 
 
     Connection
-    dial (String dialString) throws CallStateException
-    {
+    dial (String dialString) throws CallStateException {
         return dial(dialString, CommandsInterface.CLIR_DEFAULT);
     }
 
     void
-    acceptCall () throws CallStateException
-    {
+    acceptCall () throws CallStateException {
         // FIXME if SWITCH fails, should retry with ANSWER
         // in case the active/holding call disappeared and this
         // is no longer call waiting
 
-        if (ringingCall.getState() == Call.State.INCOMING) {
+        if (ringingCall.getState() == CdmaCall.State.INCOMING) {
             Log.i("phone", "acceptCall: incoming...");
             // Always unmute when answering a new call
             setMute(false);
             cm.acceptCall(obtainCompleteMessage());
-        } else if (ringingCall.getState() == Call.State.WAITING) {
+        } else if (ringingCall.getState() == CdmaCall.State.WAITING) {
             setMute(false);
             switchWaitingOrHoldingAndActive();
         } else {
@@ -234,8 +239,7 @@
     }
 
     void
-    rejectCall () throws CallStateException
-    {
+    rejectCall () throws CallStateException {
         // AT+CHLD=0 means "release held or UDUB"
         // so if the phone isn't ringing, this could hang up held
         if (ringingCall.getState().isRinging()) {
@@ -248,29 +252,26 @@
     void
     switchWaitingOrHoldingAndActive() throws CallStateException {
         // Should we bother with this check?
-        if (ringingCall.getState() == Call.State.INCOMING) {
+        if (ringingCall.getState() == CdmaCall.State.INCOMING) {
             throw new CallStateException("cannot be in the incoming state");
         } else {
-            cm.switchWaitingOrHoldingAndActive(
-                    obtainCompleteMessage(EVENT_SWITCH_RESULT));
+            cm.sendCDMAFeatureCode("", obtainCompleteMessage(EVENT_SWITCH_RESULT));
         }
     }
 
     void
-    conference() throws CallStateException
-    {
-        cm.conference(obtainCompleteMessage(EVENT_CONFERENCE_RESULT));
+    conference() throws CallStateException {
+        // three way calls in CDMA will be handled by feature codes
+        Log.e(LOG_TAG, "conference: not possible in CDMA");
     }
 
     void
-    explicitCallTransfer() throws CallStateException
-    {
+    explicitCallTransfer() throws CallStateException {
         cm.explicitCallTransfer(obtainCompleteMessage(EVENT_ECT_RESULT));
     }
 
     void
-    clearDisconnected()
-    {
+    clearDisconnected() {
         internalClearDisconnected();
 
         updatePhoneState();
@@ -278,17 +279,15 @@
     }
 
     boolean
-    canConference()
-    {
-        return foregroundCall.getState() == Call.State.ACTIVE
-                && backgroundCall.getState() == Call.State.HOLDING
+    canConference() {
+        return foregroundCall.getState() == CdmaCall.State.ACTIVE
+                && backgroundCall.getState() == CdmaCall.State.HOLDING
                 && !backgroundCall.isFull()
                 && !foregroundCall.isFull();
     }
 
     boolean
-    canDial()
-    {
+    canDial() {
         boolean ret;
         int serviceState = phone.getServiceState().getState();
 
@@ -302,42 +301,26 @@
     }
 
     boolean
-    canTransfer()
-    {
-        return foregroundCall.getState() == Call.State.ACTIVE
-                && backgroundCall.getState() == Call.State.HOLDING;
+    canTransfer() {
+        Log.e(LOG_TAG, "canTransfer: not possible in CDMA");
+        return false;
     }
 
     //***** Private Instance Methods
 
     private void
-    internalClearDisconnected()
-    {
+    internalClearDisconnected() {
         ringingCall.clearDisconnected();
         foregroundCall.clearDisconnected();
         backgroundCall.clearDisconnected();
     }
 
     /**
-     * @return true if we're idle or there's a call to getCurrentCalls() pending
-     * but nothing else
-     */
-    private boolean
-    checkNoOperationsPending()
-    {
-        if (DBG_POLL) log("checkNoOperationsPending: pendingOperations=" +
-                pendingOperations);
-        return pendingOperations == 0;
-    }
-
-
-    /**
      * Obtain a message to use for signalling "invoke getCurrentCalls() when
      * this operation and all other pending operations are complete
      */
     private Message
-    obtainCompleteMessage()
-    {
+    obtainCompleteMessage() {
         return obtainCompleteMessage(EVENT_OPERATION_COMPLETE);
     }
 
@@ -346,8 +329,7 @@
      * this operation and all other pending operations are complete
      */
     private Message
-    obtainCompleteMessage(int what)
-    {
+    obtainCompleteMessage(int what) {
         pendingOperations++;
         lastRelevantPoll = null;
         needsPoll = true;
@@ -358,26 +340,8 @@
         return obtainMessage(what);
     }
 
-    /**
-     * Obtain a complete message that indicates that this operation
-     * does not require polling of getCurrentCalls(). However, if other
-     * operations that do need getCurrentCalls() are pending or are
-     * scheduled while this operation is pending, the invocatoin
-     * of getCurrentCalls() will be postponed until this
-     * operation is also complete.
-     */
-    private Message
-    obtainNoPollCompleteMessage(int what)
-    {
-        pendingOperations++;
-        lastRelevantPoll = null;
-        return obtainMessage(what);
-    }
-
-
     private void
-    operationComplete()
-    {
+    operationComplete() {
         pendingOperations--;
 
         if (DBG_POLL) log("operationComplete: pendingOperations=" +
@@ -388,42 +352,15 @@
             cm.getCurrentCalls(lastRelevantPoll);
         } else if (pendingOperations < 0) {
             // this should never happen
-            Log.e(LOG_TAG,"CallTracker.pendingOperations < 0");
+            Log.e(LOG_TAG,"CdmaCallTracker.pendingOperations < 0");
             pendingOperations = 0;
         }
     }
 
-    private void
-    pollCallsWhenSafe()
-    {
-        needsPoll = true;
 
-        if (checkNoOperationsPending()) {
-            lastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);
-            cm.getCurrentCalls(lastRelevantPoll);
-        }
-    }
 
     private void
-    pollCallsAfterDelay()
-    {
-        Message msg = obtainMessage();
-
-        msg.what = EVENT_REPOLL_AFTER_DELAY;
-        sendMessageDelayed(msg, POLL_DELAY_MSEC);
-    }
-
-    private boolean
-    isCommandExceptionRadioNotAvailable(Throwable e)
-    {
-        return e != null && e instanceof CommandException
-                && ((CommandException)e).getCommandError()
-                        == CommandException.Error.RADIO_NOT_AVAILABLE;
-    }
-
-    private void
-    updatePhoneState()
-    {
+    updatePhoneState() {
         Phone.State oldState = state;
 
         if (ringingCall.isRinging()) {
@@ -448,9 +385,10 @@
         }
     }
 
-    private void
-    handlePollCalls(AsyncResult ar)
-    {
+    // ***** Overwritten from CallTracker
+
+    protected void
+    handlePollCalls(AsyncResult ar) {
         List polledCalls;
 
         if (ar.exception == null) {
@@ -474,7 +412,7 @@
 
         for (int i = 0, curDC = 0, dcSize = polledCalls.size()
                 ; i < connections.length; i++) {
-            GSMConnection conn = connections[i];
+            CdmaConnection conn = connections[i];
             DriverCall dc = null;
 
             // polledCall list is sparse
@@ -519,7 +457,7 @@
                         return;
                     }
                 } else {
-                    connections[i] = new GSMConnection(phone.getContext(), dc, this, i);
+                    connections[i] = new CdmaConnection(phone.getContext(), dc, this, i);
 
                     // it's a ringing call
                     if (connections[i].getCall() == ringingCall) {
@@ -549,14 +487,14 @@
                 // tracking.
                 droppedDuringPoll.add(conn);
                 // Dropped connections are removed from the CallTracker
-                // list but kept in the GSMCall list
+                // list but kept in the Call list
                 connections[i] = null;
             } else if (conn != null && dc != null && !conn.compareTo(dc)) {
                 // Connection in CLCC response does not match what
                 // we were tracking. Assume dropped call and new call
 
                 droppedDuringPoll.add(conn);
-                connections[i] = new GSMConnection (phone.getContext(), dc, this, i);
+                connections[i] = new CdmaConnection (phone.getContext(), dc, this, i);
 
                 if (connections[i].getCall() == ringingCall) {
                     newRinging = connections[i];
@@ -608,7 +546,7 @@
         // cases from the "dropped during poll" list
         // These cases need no "last call fail" reason
         for (int i = droppedDuringPoll.size() - 1; i >= 0 ; i--) {
-            GSMConnection conn = droppedDuringPoll.get(i);
+            CdmaConnection conn = droppedDuringPoll.get(i);
 
             if (conn.isIncoming() && conn.getConnectTime() == 0) {
                 // Missed or rejected call
@@ -629,8 +567,7 @@
                 // Local hangup
                 droppedDuringPoll.remove(i);
                 conn.onDisconnect(Connection.DisconnectCause.LOCAL);
-            } else if (conn.cause ==
-                    Connection.DisconnectCause.INVALID_NUMBER) {
+            } else if (conn.cause == Connection.DisconnectCause.INVALID_NUMBER) {
                 droppedDuringPoll.remove(i);
                 conn.onDisconnect(Connection.DisconnectCause.INVALID_NUMBER);
             }
@@ -668,59 +605,12 @@
         //dumpState();
     }
 
-    private void
-    handleRadioAvailable()
-    {
-        pollCallsWhenSafe();
-    }
-
-    private void
-    handleRadioNotAvailable()
-    {
-        // handlePollCalls will clear out its
-        // call list when it gets the CommandException
-        // error result from this
-        pollCallsWhenSafe();
-    }
-
-    private void
-    dumpState()
-    {
-        List l;
-
-        Log.i(LOG_TAG,"Phone State:" + state);
-
-        Log.i(LOG_TAG,"Ringing call: " + ringingCall.toString());
-
-        l = ringingCall.getConnections();
-        for (int i = 0, s = l.size(); i < s; i++) {
-            Log.i(LOG_TAG,l.get(i).toString());
-        }
-
-        Log.i(LOG_TAG,"Foreground call: " + foregroundCall.toString());
-
-        l = foregroundCall.getConnections();
-        for (int i = 0, s = l.size(); i < s; i++) {
-            Log.i(LOG_TAG,l.get(i).toString());
-        }
-
-        Log.i(LOG_TAG,"Background call: " + backgroundCall.toString());
-
-        l = backgroundCall.getConnections();
-        for (int i = 0, s = l.size(); i < s; i++) {
-            Log.i(LOG_TAG,l.get(i).toString());
-        }
-
-    }
-
-    //***** Called from GSMConnection
-
+    //***** Called from CdmaConnection
     /*package*/ void
-    hangup (GSMConnection conn) throws CallStateException
-    {
+    hangup (CdmaConnection conn) throws CallStateException {
         if (conn.owner != this) {
-            throw new CallStateException ("Connection " + conn
-                                    + "does not belong to CallTracker " + this);
+            throw new CallStateException ("CdmaConnection " + conn
+                                    + "does not belong to CdmaCallTracker " + this);
         }
 
         if (conn == pendingMO) {
@@ -731,11 +621,11 @@
             hangupPendingMO = true;
         } else {
             try {
-                cm.hangupConnection (conn.getGSMIndex(), obtainCompleteMessage());
+                cm.hangupConnection (conn.getCDMAIndex(), obtainCompleteMessage());
             } catch (CallStateException ex) {
                 // Ignore "connection not found"
                 // Call may have hung up already
-                Log.w(LOG_TAG,"CallTracker WARN: hangup() on absent connection "
+                Log.w(LOG_TAG,"CdmaCallTracker WARN: hangup() on absent connection "
                                 + conn);
             }
         }
@@ -744,44 +634,40 @@
     }
 
     /*package*/ void
-    separate (GSMConnection conn) throws CallStateException
-    {
+    separate (CdmaConnection conn) throws CallStateException {
         if (conn.owner != this) {
-            throw new CallStateException ("Connection " + conn
-                                    + "does not belong to CallTracker " + this);
+            throw new CallStateException ("CdmaConnection " + conn
+                                    + "does not belong to CdmaCallTracker " + this);
         }
         try {
-            cm.separateConnection (conn.getGSMIndex(),
+            cm.separateConnection (conn.getCDMAIndex(),
                 obtainCompleteMessage(EVENT_SEPARATE_RESULT));
         } catch (CallStateException ex) {
             // Ignore "connection not found"
             // Call may have hung up already
-            Log.w(LOG_TAG,"CallTracker WARN: separate() on absent connection "
+            Log.w(LOG_TAG,"CdmaCallTracker WARN: separate() on absent connection "
                           + conn);
         }
     }
 
-    //***** Called from GSMPhone
+    //***** Called from CDMAPhone
 
     /*package*/ void
-    setMute(boolean mute)
-    {
+    setMute(boolean mute) {
         desiredMute = mute;
         cm.setMute(desiredMute, null);
     }
 
     /*package*/ boolean
-    getMute()
-    {
+    getMute() {
         return desiredMute;
     }
 
 
-    //***** Called from GSMCall
+    //***** Called from CdmaCall
 
     /* package */ void
-    hangup (GSMCall call) throws CallStateException
-    {
+    hangup (CdmaCall call) throws CallStateException {
         if (call.getConnections().size() == 0) {
             throw new CallStateException("no connections in call");
         }
@@ -794,7 +680,7 @@
                 if (Phone.DEBUG_PHONE) {
                     log("(foregnd) hangup dialing or alerting...");
                 }
-                hangup((GSMConnection)(call.getConnections().get(0)));
+                hangup((CdmaConnection)(call.getConnections().get(0)));
             } else {
                 hangupForegroundResumeBackground();
             }
@@ -808,8 +694,8 @@
                 hangupWaitingOrBackground();
             }
         } else {
-            throw new RuntimeException ("Call " + call +
-                    "does not belong to CallTracker " + this);
+            throw new RuntimeException ("CdmaCall " + call +
+                    "does not belong to CdmaCallTracker " + this);
         }
 
         call.onHangupLocal();
@@ -827,12 +713,12 @@
         cm.hangupForegroundResumeBackground(obtainCompleteMessage());
     }
 
-    void hangupConnectionByIndex(GSMCall call, int index)
+    void hangupConnectionByIndex(CdmaCall call, int index)
             throws CallStateException {
         int count = call.connections.size();
         for (int i = 0; i < count; i++) {
-            GSMConnection cn = (GSMConnection)call.connections.get(i);
-            if (cn.getGSMIndex() == index) {
+            CdmaConnection cn = (CdmaConnection)call.connections.get(i);
+            if (cn.getCDMAIndex() == index) {
                 cm.hangupConnection(index, obtainCompleteMessage());
                 return;
             }
@@ -841,12 +727,12 @@
         throw new CallStateException("no gsm index found");
     }
 
-    void hangupAllConnections(GSMCall call) throws CallStateException{
+    void hangupAllConnections(CdmaCall call) throws CallStateException{
         try {
             int count = call.connections.size();
             for (int i = 0; i < count; i++) {
-                GSMConnection cn = (GSMConnection)call.connections.get(i);
-                cm.hangupConnection(cn.getGSMIndex(), obtainCompleteMessage());
+                CdmaConnection cn = (CdmaConnection)call.connections.get(i);
+                cm.hangupConnection(cn.getCDMAIndex(), obtainCompleteMessage());
             }
         } catch (CallStateException ex) {
             Log.e(LOG_TAG, "hangupConnectionByIndex caught " + ex);
@@ -854,12 +740,12 @@
     }
 
     /* package */
-    GSMConnection getConnectionByIndex(GSMCall call, int index)
+    CdmaConnection getConnectionByIndex(CdmaCall call, int index)
             throws CallStateException {
         int count = call.connections.size();
         for (int i = 0; i < count; i++) {
-            GSMConnection cn = (GSMConnection)call.connections.get(i);
-            if (cn.getGSMIndex() == index) {
+            CdmaConnection cn = (CdmaConnection)call.connections.get(i);
+            if (cn.getCDMAIndex() == index) {
                 return cn;
             }
         }
@@ -881,24 +767,32 @@
         return Phone.SuppService.UNKNOWN;
     }
 
+    private void handleRadioNotAvailable() {
+        // handlePollCalls will clear out its
+        // call list when it gets the CommandException
+        // error result from this
+        pollCallsWhenSafe();
+    }
+
     //****** Overridden from Handler
 
     public void
-    handleMessage (Message msg)
-    {
+    handleMessage (Message msg) {
         AsyncResult ar;
 
         switch (msg.what) {
-            case EVENT_POLL_CALLS_RESULT:
+            case EVENT_POLL_CALLS_RESULT:{
+                Log.d(LOG_TAG, "Event EVENT_POLL_CALLS_RESULT Received");
                 ar = (AsyncResult)msg.obj;
 
-                if (msg == lastRelevantPoll) {
-                    if (DBG_POLL) log(
+                if(msg == lastRelevantPoll) {
+                    if(DBG_POLL) log(
                             "handle EVENT_POLL_CALL_RESULT: set needsPoll=F");
                     needsPoll = false;
                     lastRelevantPoll = null;
                     handlePollCalls((AsyncResult)msg.obj);
                 }
+            }
             break;
 
             case EVENT_OPERATION_COMPLETE:
@@ -907,14 +801,8 @@
             break;
 
             case EVENT_SWITCH_RESULT:
-            case EVENT_CONFERENCE_RESULT:
-            case EVENT_SEPARATE_RESULT:
-            case EVENT_ECT_RESULT:
-                ar = (AsyncResult)msg.obj;
-                if (ar.exception != null) {
-                    phone.notifySuppServiceFailed(getFailedService(msg.what));
-                }
-                operationComplete();
+                  ar = (AsyncResult)msg.obj;
+                  operationComplete();
             break;
 
             case EVENT_GET_LAST_CALL_FAIL_CAUSE:
@@ -932,27 +820,11 @@
                 } else {
                     causeCode = ((int[])ar.result)[0];
                 }
-                // Log the causeCode if its not normal
-                if (causeCode == CallFailCause.NO_CIRCUIT_AVAIL ||
-                    causeCode == CallFailCause.TEMPORARY_FAILURE ||
-                    causeCode == CallFailCause.SWITCHING_CONGESTION ||
-                    causeCode == CallFailCause.CHANNEL_NOT_AVAIL ||
-                    causeCode == CallFailCause.QOS_NOT_AVAIL ||
-                    causeCode == CallFailCause.BEARER_NOT_AVAIL ||
-                    causeCode == CallFailCause.ERROR_UNSPECIFIED) {
-                    int cid = -1;
-                    GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
-                    if (loc != null) cid = loc.getCid();
-
-                    EventLog.List val = new EventLog.List(causeCode, cid,
-                        TelephonyManager.getDefault().getNetworkType());
-                    EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_CALL_DROP, val);
-                }
 
                 for (int i = 0, s =  droppedDuringPoll.size()
                         ; i < s ; i++
                 ) {
-                    GSMConnection conn = droppedDuringPoll.get(i);
+                    CdmaConnection conn = droppedDuringPoll.get(i);
 
                     conn.onRemoteDisconnect(causeCode);
                 }
@@ -963,7 +835,6 @@
                 droppedDuringPoll.clear();
             break;
 
-            case EVENT_REPOLL_AFTER_DELAY:
             case EVENT_CALL_STATE_CHANGE:
                 pollCallsWhenSafe();
             break;
@@ -975,10 +846,15 @@
             case EVENT_RADIO_NOT_AVAILABLE:
                 handleRadioNotAvailable();
             break;
+
+            default:{
+             throw new RuntimeException("unexpected event not handled");
+            }
         }
     }
 
-    private void log(String msg) {
-        Log.d(LOG_TAG, "[CallTracker] " + msg);
+    protected void log(String msg) {
+        Log.d(LOG_TAG, "[CdmaCallTracker] " + msg);
     }
+
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
similarity index 76%
copy from telephony/java/com/android/internal/telephony/gsm/GSMConnection.java
copy to telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
index 4777892..cdad4a7 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GSMConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
@@ -14,41 +14,42 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
-import com.android.internal.telephony.*;
+package com.android.internal.telephony.cdma;
 
+import com.android.internal.telephony.*;
 import android.content.Context;
+import android.os.AsyncResult;
 import android.os.Handler;
-import android.os.PowerManager;
-import android.os.Registrant;
 import android.os.Looper;
 import android.os.Message;
-import android.os.AsyncResult;
+import android.os.PowerManager;
+import android.os.Registrant;
 import android.os.SystemClock;
-import android.util.Log;
 import android.util.Config;
+import android.util.Log;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.ServiceState;
 
+
 /**
  * {@hide}
  */
-public class GSMConnection extends Connection {
-    static final String LOG_TAG = "GSM";
+public class CdmaConnection extends Connection {
+    static final String LOG_TAG = "CDMA";
 
     //***** Instance Variables
 
-    CallTracker owner;
-    GSMCall parent;
+    CdmaCallTracker owner;
+    CdmaCall parent;
 
-    String address;     // MAY BE NULL!!!
+
+    String address;             // MAY BE NULL!!!
     String dialString;          // outgoing calls only
-    String postDialString;      // outgoing calls only    
+    String postDialString;      // outgoing calls only
     boolean isIncoming;
-    boolean disconnected; 
+    boolean disconnected;
 
-    int index;          // index in CallTracker.connections[], -1 if unassigned
-                        // The GSM index is 1 + this
+    int index;          // index in CdmaCallTracker.connections[], -1 if unassigned
 
     /*
      * These time/timespan values are based on System.currentTimeMillis(),
@@ -65,7 +66,7 @@
      */
     long connectTimeReal;
     long duration;
-    long holdingStartTime;  // The time when the Connection last transitioned 
+    long holdingStartTime;  // The time when the Connection last transitioned
                             // into HOLDING
 
     int nextPostDialChar;       // index into postDialString
@@ -95,8 +96,8 @@
         MyHandler(Looper l) {super(l);}
 
         public void
-        handleMessage(Message msg)
-        {
+        handleMessage(Message msg) {
+
             switch (msg.what) {
                 case EVENT_NEXT_POST_DIAL:
                 case EVENT_DTMF_DONE:
@@ -114,8 +115,7 @@
 
     /** This is probably an MT call that we first saw in a CLCC response */
     /*package*/
-    GSMConnection (Context context, DriverCall dc, CallTracker ct, int index)
-    {
+    CdmaConnection (Context context, DriverCall dc, CdmaCallTracker ct, int index) {
         createWakeLock(context);
         acquireWakeLock();
 
@@ -136,11 +136,10 @@
 
     /** This is an MO call, created when dialing */
     /*package*/
-    GSMConnection (Context context, String dialString, CallTracker ct, GSMCall parent)
-    {
+    CdmaConnection (Context context, String dialString, CdmaCallTracker ct, CdmaCall parent) {
         createWakeLock(context);
         acquireWakeLock();
-
+		
         owner = ct;
         h = new MyHandler(owner.getLooper());
 
@@ -155,18 +154,19 @@
         createTime = System.currentTimeMillis();
 
         this.parent = parent;
-        parent.attachFake(this, Call.State.DIALING);
+        parent.attachFake(this, CdmaCall.State.DIALING);
     }
-    
+
+    public void dispose() {
+    }
+
     static boolean
-    equalsHandlesNulls (Object a, Object b)
-    {
+    equalsHandlesNulls (Object a, Object b) {
         return (a == null) ? (b == null) : a.equals (b);
     }
 
     /*package*/ boolean
-    compareTo(DriverCall c)
-    {
+    compareTo(DriverCall c) {
         // On mobile originated (MO) calls, the phone number may have changed
         // due to a SIM Toolkit call control modification.
         //
@@ -178,43 +178,35 @@
         // no control over when they begin, so we might as well
 
         String cAddress = PhoneNumberUtils.stringFromStringAndTOA(c.number, c.TOA);
-        return isIncoming == c.isMT && equalsHandlesNulls(address, cAddress); 
+        return isIncoming == c.isMT && equalsHandlesNulls(address, cAddress);
     }
 
     public String
-    toString()
-    {
+    toString() {
         return (isIncoming ? "incoming" : "outgoing");
     }
 
-    public String getAddress()
-    {
-        return address; 
+    public String getAddress() {
+        return address;
     }
 
-
-    public Call getCall()
-    {
+    public CdmaCall getCall() {
         return parent;
     }
 
-    public long getCreateTime()
-    {
+    public long getCreateTime() {
         return createTime;
     }
 
-    public long getConnectTime()
-    {
+    public long getConnectTime() {
         return connectTime;
     }
 
-    public long getDisconnectTime()
-    {
+    public long getDisconnectTime() {
         return disconnectTime;
     }
 
-    public long getDurationMillis()
-    {
+    public long getDurationMillis() {
         if (connectTimeReal == 0) {
             return 0;
         } else if (duration == 0) {
@@ -224,9 +216,8 @@
         }
     }
 
-    public long getHoldDurationMillis()
-    {
-        if (getState() != Call.State.HOLDING) {
+    public long getHoldDurationMillis() {
+        if (getState() != CdmaCall.State.HOLDING) {
             // If not holding, return 0
             return 0;
         } else {
@@ -234,52 +225,45 @@
         }
     }
 
-    public DisconnectCause getDisconnectCause()
-    {
+    public DisconnectCause getDisconnectCause() {
         return cause;
     }
 
-    public boolean isIncoming()
-    {
+    public boolean isIncoming() {
         return isIncoming;
     }
 
-    public Call.State getState()
-    {
+    public CdmaCall.State getState() {
         if (disconnected) {
-            return Call.State.DISCONNECTED;
-        } else {   
+            return CdmaCall.State.DISCONNECTED;
+        } else {
             return super.getState();
         }
     }
 
-    public void hangup() throws CallStateException
-    {
-        if (!disconnected) {        
+    public void hangup() throws CallStateException {
+        if (!disconnected) {
             owner.hangup(this);
         } else {
             throw new CallStateException ("disconnected");
         }
     }
 
-    public void separate() throws CallStateException
-    {
-        if (!disconnected) {        
+    public void separate() throws CallStateException {
+        if (!disconnected) {
             owner.separate(this);
         } else {
             throw new CallStateException ("disconnected");
         }
     }
 
-    public PostDialState getPostDialState()
-    {
+    public PostDialState getPostDialState() {
         return postDialState;
     }
 
-    public void proceedAfterWaitChar()
-    {
+    public void proceedAfterWaitChar() {
         if (postDialState != PostDialState.WAIT) {
-            Log.w(LOG_TAG, "Connection.proceedAfterWaitChar(): Expected " 
+            Log.w(LOG_TAG, "CdmaConnection.proceedAfterWaitChar(): Expected "
                 + "getPostDialState() to be WAIT but was " + postDialState);
             return;
         }
@@ -288,10 +272,10 @@
 
         processNextPostDialChar();
     }
-    
+
     public void proceedAfterWildChar(String str) {
         if (postDialState != PostDialState.WILD) {
-            Log.w(LOG_TAG, "Connection.proceedAfterWaitChar(): Expected " 
+            Log.w(LOG_TAG, "CdmaConnection.proceedAfterWaitChar(): Expected "
                 + "getPostDialState() to be WILD but was " + postDialState);
             return;
         }
@@ -328,81 +312,51 @@
             postDialString = buf.toString();
             nextPostDialChar = 0;
             if (Phone.DEBUG_PHONE) {
-                log("proceedAfterWildChar: new postDialString is " + 
+                log("proceedAfterWildChar: new postDialString is " +
                         postDialString);
             }
 
             processNextPostDialChar();
         }
     }
-    
-    public void cancelPostDial()
-    {
+
+    public void cancelPostDial() {
         setPostDialState(PostDialState.CANCELLED);
     }
 
-    /** 
+    /**
      * Called when this Connection is being hung up locally (eg, user pressed "end")
      * Note that at this point, the hangup request has been dispatched to the radio
-     * but no response has yet been received so update() has not yet been called 
+     * but no response has yet been received so update() has not yet been called
      */
     void
-    onHangupLocal()
-    {
+    onHangupLocal() {
         cause = DisconnectCause.LOCAL;
     }
 
     DisconnectCause
-    disconnectCauseFromCode(int causeCode)
-    {
+    disconnectCauseFromCode(int causeCode) {
         /**
          * See 22.001 Annex F.4 for mapping of cause codes
          * to local tones
          */
-    
+
         switch (causeCode) {
             case CallFailCause.USER_BUSY:
                 return DisconnectCause.BUSY;
-
-            case CallFailCause.NO_CIRCUIT_AVAIL:
-            case CallFailCause.TEMPORARY_FAILURE:
-            case CallFailCause.SWITCHING_CONGESTION:
-            case CallFailCause.CHANNEL_NOT_AVAIL:
-            case CallFailCause.QOS_NOT_AVAIL:
-            case CallFailCause.BEARER_NOT_AVAIL:
-                return DisconnectCause.CONGESTION;
-
-            case CallFailCause.ACM_LIMIT_EXCEEDED:
-                return DisconnectCause.LIMIT_EXCEEDED;
-
-            case CallFailCause.CALL_BARRED:
-                return DisconnectCause.CALL_BARRED;
-
-            case CallFailCause.FDN_BLOCKED:
-                return DisconnectCause.FDN_BLOCKED;
-
             case CallFailCause.ERROR_UNSPECIFIED:
-            case CallFailCause.NORMAL_CLEARING: 
+            case CallFailCause.NORMAL_CLEARING:
             default:
-                GSMPhone phone = owner.phone;
+                CDMAPhone phone = owner.phone;
                 int serviceState = phone.getServiceState().getState();
                 if (serviceState == ServiceState.STATE_POWER_OFF) {
                     return DisconnectCause.POWER_OFF;
                 } else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE
                         || serviceState == ServiceState.STATE_EMERGENCY_ONLY ) {
                     return DisconnectCause.OUT_OF_SERVICE;
-                } else if (phone.getSimCard().getState() != GsmSimCard.State.READY) {
-                    return DisconnectCause.SIM_ERROR;
-                } else if (causeCode == CallFailCause.ERROR_UNSPECIFIED) {
-                    if (phone.mSST.rs.isCsRestricted()) {
-                        return DisconnectCause.CS_RESTRICTED; 
-                    } else if (phone.mSST.rs.isCsEmergencyRestricted()) {
-                        return DisconnectCause.CS_RESTRICTED_EMERGENCY;
-                    } else if (phone.mSST.rs.isCsNormalRestricted()) {
-                        return DisconnectCause.CS_RESTRICTED_NORMAL;
-                    } else {
-                        return DisconnectCause.NORMAL;
-                    }
+                } else if (phone.mCM.getRadioState() != CommandsInterface.RadioState.NV_READY
+                        && phone.getIccCard().getState() != RuimCard.State.READY) {
+                    return DisconnectCause.ICC_ERROR;
                 } else {
                     return DisconnectCause.NORMAL;
                 }
@@ -410,31 +364,29 @@
     }
 
     /*package*/ void
-    onRemoteDisconnect(int causeCode)
-    {
+    onRemoteDisconnect(int causeCode) {
         onDisconnect(disconnectCauseFromCode(causeCode));
     }
 
     /** Called when the radio indicates the connection has been disconnected */
     /*package*/ void
-    onDisconnect(DisconnectCause cause)
-    {
+    onDisconnect(DisconnectCause cause) {
         this.cause = cause;
-        
-        if (!disconnected) {        
+
+        if (!disconnected) {
             index = -1;
-            
+
             disconnectTime = System.currentTimeMillis();
             duration = SystemClock.elapsedRealtime() - connectTimeReal;
             disconnected = true;
 
             if (Config.LOGD) Log.d(LOG_TAG,
-                    "[GSMConn] onDisconnect: cause=" + cause);
+                    "[CDMAConn] onDisconnect: cause=" + cause);
 
             owner.phone.notifyDisconnect(this);
 
             if (parent != null) {
-                parent.connectionDisconnected(this);            
+                parent.connectionDisconnected(this);
             }
         }
         releaseWakeLock();
@@ -443,10 +395,10 @@
     // Returns true if state has changed, false if nothing changed
     /*package*/ boolean
     update (DriverCall dc) {
-        GSMCall newParent;
+        CdmaCall newParent;
         boolean changed = false;
         boolean wasConnectingInOrOut = isConnectingInOrOut();
-        boolean wasHolding = (getState() == Call.State.HOLDING);
+        boolean wasHolding = (getState() == CdmaCall.State.HOLDING);
 
         newParent = parentFromDCState(dc.state);
 
@@ -484,7 +436,7 @@
             onConnectedInOrOut();
         }
 
-        if (changed && !wasHolding && (getState() == Call.State.HOLDING)) {
+        if (changed && !wasHolding && (getState() == CdmaCall.State.HOLDING)) {
             // We've transitioned into HOLDING
             onStartedHolding();
         }
@@ -499,24 +451,23 @@
      * HOLDING in the backgroundCall
      */
     void
-    fakeHoldBeforeDial()
-    {
+    fakeHoldBeforeDial() {
         if (parent != null) {
             parent.detach(this);
         }
 
         parent = owner.backgroundCall;
-        parent.attachFake(this, Call.State.HOLDING);
+        parent.attachFake(this, CdmaCall.State.HOLDING);
 
         onStartedHolding();
     }
 
     /*package*/ int
-    getGSMIndex() throws CallStateException {
+    getCDMAIndex() throws CallStateException {
         if (index >= 0) {
             return index + 1;
         } else {
-            throw new CallStateException ("GSM index not yet assigned");
+            throw new CallStateException ("CDMA connection index not assigned");
         }
     }
 
@@ -552,28 +503,27 @@
      * should be ignored
      */
     private boolean
-    processPostDialChar(char c)
-    {
+    processPostDialChar(char c) {
         if (PhoneNumberUtils.is12Key(c)) {
             owner.cm.sendDtmf(c, h.obtainMessage(EVENT_DTMF_DONE));
         } else if (c == PhoneNumberUtils.PAUSE) {
             // From TS 22.101:
 
-            // "The first occurrence of the "DTMF Control Digits Separator" 
-            //  shall be used by the ME to distinguish between the addressing 
+            // "The first occurrence of the "DTMF Control Digits Separator"
+            //  shall be used by the ME to distinguish between the addressing
             //  digits (i.e. the phone number) and the DTMF digits...."
 
             if (nextPostDialChar == 1) {
                 // The first occurrence.
                 // We don't need to pause here, but wait for just a bit anyway
-                h.sendMessageDelayed(h.obtainMessage(EVENT_PAUSE_DONE), 
+                h.sendMessageDelayed(h.obtainMessage(EVENT_PAUSE_DONE),
                                             PAUSE_DELAY_FIRST_MILLIS);
             } else {
                 // It continues...
-                // "Upon subsequent occurrences of the separator, the UE shall 
-                //  pause again for 3 seconds (\u00B1 20 %) before sending any 
+                // "Upon subsequent occurrences of the separator, the UE shall
+                //  pause again for 3 seconds (\u00B1 20 %) before sending any
                 //  further DTMF digits."
-                h.sendMessageDelayed(h.obtainMessage(EVENT_PAUSE_DONE), 
+                h.sendMessageDelayed(h.obtainMessage(EVENT_PAUSE_DONE),
                                             PAUSE_DELAY_MILLIS);
             }
         } else if (c == PhoneNumberUtils.WAIT) {
@@ -588,9 +538,8 @@
     }
 
     public String
-    getRemainingPostDialString()
-    {
-        if (postDialState == PostDialState.CANCELLED 
+    getRemainingPostDialString() {
+        if (postDialState == PostDialState.CANCELLED
             || postDialState == PostDialState.COMPLETE
             || postDialString == null
             || postDialString.length() <= nextPostDialChar
@@ -611,19 +560,18 @@
          * and or onConnectedInOrOut.
          */
         if (mPartialWakeLock.isHeld()) {
-            Log.e(LOG_TAG, "[GSMConn] UNEXPECTED; mPartialWakeLock is held when finalizing.");
+            Log.e(LOG_TAG, "[CdmaConn] UNEXPECTED; mPartialWakeLock is held when finalizing.");
         }
         releaseWakeLock();
     }
 
     private void
-    processNextPostDialChar()
-    {
+    processNextPostDialChar() {
         char c = 0;
         Registrant postDialHandler;
 
         if (postDialState == PostDialState.CANCELLED) {
-            //Log.v("GSM", "##### processNextPostDialChar: postDialState == CANCELLED, bail");
+            //Log.v("CDMA", "##### processNextPostDialChar: postDialState == CANCELLED, bail");
             return;
         }
 
@@ -646,7 +594,7 @@
                 // Will call processNextPostDialChar
                 h.obtainMessage(EVENT_NEXT_POST_DIAL).sendToTarget();
                 // Don't notify application
-                Log.e("GSM", "processNextPostDialChar: c=" + c + " isn't valid!");
+                Log.e("CDMA", "processNextPostDialChar: c=" + c + " isn't valid!");
                 return;
             }
         }
@@ -655,7 +603,8 @@
 
         Message notifyMessage;
 
-        if (postDialHandler != null && (notifyMessage = postDialHandler.messageForRegistrant()) != null) {
+        if (postDialHandler != null &&
+                (notifyMessage = postDialHandler.messageForRegistrant()) != null) {
             // The AsyncResult.result is the Connection object
             PostDialState state = postDialState;
             AsyncResult ar = AsyncResult.forMessage(notifyMessage);
@@ -665,17 +614,8 @@
             // arg1 is the character that was/is being processed
             notifyMessage.arg1 = c;
 
-            //Log.v("GSM", "##### processNextPostDialChar: send msg to postDialHandler, arg1=" + c);
             notifyMessage.sendToTarget();
         }
-        /*
-        else {
-            if (postDialHandler == null)
-                Log.v("GSM", "##### processNextPostDialChar: postDialHandler is NULL!");
-            else
-                Log.v("GSM", "##### processNextPostDialChar: postDialHandler.messageForRegistrant() returned NULL!");
-        }
-        */
     }
 
 
@@ -683,16 +623,14 @@
      *  and outgoing calls
      */
     private boolean
-    isConnectingInOrOut()
-    {
-        return parent == null || parent == owner.ringingCall 
-            || parent.state == Call.State.DIALING 
-            || parent.state == Call.State.ALERTING;
+    isConnectingInOrOut() {
+        return parent == null || parent == owner.ringingCall
+            || parent.state == CdmaCall.State.DIALING
+            || parent.state == CdmaCall.State.ALERTING;
     }
 
-    private GSMCall
-    parentFromDCState (DriverCall.State state)
-    {
+    private CdmaCall
+    parentFromDCState (DriverCall.State state) {
         switch (state) {
             case ACTIVE:
             case DIALING:
@@ -757,7 +695,7 @@
     }
     
     private void log(String msg) {
-        Log.d(LOG_TAG, "[GSMConn] " + msg);
+        Log.d(LOG_TAG, "[CDMAConn] " + msg);
     }
 
     @Override
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
new file mode 100644
index 0000000..2cbad78
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony.cdma;
+
+import android.os.*;
+import android.util.EventLog;
+import android.util.Log;
+
+import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.DataConnection;
+import com.android.internal.telephony.DataLink;
+import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.TelephonyEventLog;
+
+/**
+ * {@hide}
+ *
+ */
+public class CdmaDataConnection extends DataConnection {
+
+    private static final String LOG_TAG = "CDMA";
+    private static final boolean DBG = true;
+
+    /** Fail cause of last Data Call activate from RIL_LastDataCallActivateFailCause */
+    private final static int PS_NET_DOWN_REASON_OPERATOR_DETERMINED_BARRING         = 8;
+    private final static int PS_NET_DOWN_REASON_UNKNOWN_APN                         = 27;
+    private final static int PS_NET_DOWN_REASON_AUTH_FAILED                         = 29;
+    private final static int PS_NET_DOWN_REASON_OPTION_NOT_SUPPORTED                = 32;
+    private final static int PS_NET_DOWN_REASON_OPTION_UNSUBSCRIBED                 = 33;
+
+/** It is likely that the number of error codes listed below will be removed
+ * in the foreseeable future.  They have been added, but not agreed upon.
+ *
+ */
+    private final static int PS_NET_DOWN_REASON_NOT_SPECIFIED                       = 0;
+    private final static int PS_NET_DOWN_REASON_CLOSE_IN_PROGRESS                   = 1;
+    private final static int PS_NET_DOWN_REASON_NW_INITIATED_TERMINATION            = 2;
+    private final static int PS_NET_DOWN_REASON_APP_PREEMPTED                       = 3;
+    private final static int PS_NET_DOWN_REASON_LLC_SNDCP_FAILURE                   = 25;
+    private final static int PS_NET_DOWN_REASON_INSUFFICIENT_RESOURCES              = 26;
+    private final static int PS_NET_DOWN_REASON_UNKNOWN_PDP                         = 28;
+    private final static int PS_NET_DOWN_REASON_GGSN_REJECT                         = 30;
+    private final static int PS_NET_DOWN_REASON_ACTIVATION_REJECT                   = 31;
+    private final static int PS_NET_DOWN_REASON_OPTION_TEMP_OOO                     = 34;
+    private final static int PS_NET_DOWN_REASON_NSAPI_ALREADY_USED                  = 35;
+    private final static int PS_NET_DOWN_REASON_REGULAR_DEACTIVATION                = 36;
+    private final static int PS_NET_DOWN_REASON_QOS_NOT_ACCEPTED                    = 37;
+    private final static int PS_NET_DOWN_REASON_NETWORK_FAILURE                     = 38;
+    private final static int PS_NET_DOWN_REASON_UMTS_REATTACH_REQ                   = 39;
+    private final static int PS_NET_DOWN_REASON_TFT_SEMANTIC_ERROR                  = 41;
+    private final static int PS_NET_DOWN_REASON_TFT_SYNTAX_ERROR                    = 42;
+    private final static int PS_NET_DOWN_REASON_UNKNOWN_PDP_CONTEXT                 = 43;
+    private final static int PS_NET_DOWN_REASON_FILTER_SEMANTIC_ERROR               = 44;
+    private final static int PS_NET_DOWN_REASON_FILTER_SYNTAX_ERROR                 = 45;
+    private final static int PS_NET_DOWN_REASON_PDP_WITHOUT_ACTIVE_TFT              = 46;
+    private final static int PS_NET_DOWN_REASON_INVALID_TRANSACTION_ID              = 81;
+    private final static int PS_NET_DOWN_REASON_MESSAGE_INCORRECT_SEMANTIC          = 95;
+    private final static int PS_NET_DOWN_REASON_INVALID_MANDATORY_INFO              = 96;
+    private final static int PS_NET_DOWN_REASON_MESSAGE_TYPE_UNSUPPORTED            = 97;
+    private final static int PS_NET_DOWN_REASON_MSG_TYPE_NONCOMPATIBLE_STATE        = 98;
+    private final static int PS_NET_DOWN_REASON_UNKNOWN_INFO_ELEMENT                = 99;
+    private final static int PS_NET_DOWN_REASON_CONDITIONAL_IE_ERROR                = 100;
+    private final static int PS_NET_DOWN_REASON_MSG_AND_PROTOCOL_STATE_UNCOMPATIBLE = 101;
+    private final static int PS_NET_DOWN_REASON_PROTOCOL_ERROR                      = 111;
+    private final static int PS_NET_DOWN_REASON_APN_TYPE_CONFLICT                   = 112;
+    private final static int PS_NET_DOWN_REASON_UNKNOWN_CAUSE_CODE                  = 113;
+    private final static int PS_NET_DOWN_REASON_INTERNAL_MIN                        = 200;
+    private final static int PS_NET_DOWN_REASON_INTERNAL_ERROR                      = 201;
+    private final static int PS_NET_DOWN_REASON_INTERNAL_CALL_ENDED                 = 202;
+    private final static int PS_NET_DOWN_REASON_INTERNAL_UNKNOWN_CAUSE_CODE         = 203;
+    private final static int PS_NET_DOWN_REASON_INTERNAL_MAX                        = 204;
+    private final static int PS_NET_DOWN_REASON_CDMA_LOCK                           = 500;
+    private final static int PS_NET_DOWN_REASON_INTERCEPT                           = 501;
+    private final static int PS_NET_DOWN_REASON_REORDER                             = 502;
+    private final static int PS_NET_DOWN_REASON_REL_SO_REJ                          = 503;
+    private final static int PS_NET_DOWN_REASON_INCOM_CALL                          = 504;
+    private final static int PS_NET_DOWN_REASON_ALERT_STOP                          = 505;
+    private final static int PS_NET_DOWN_REASON_ACTIVATION                          = 506;
+    private final static int PS_NET_DOWN_REASON_MAX_ACCESS_PROBE                    = 507;
+    private final static int PS_NET_DOWN_REASON_CCS_NOT_SUPPORTED_BY_BS             = 508;
+    private final static int PS_NET_DOWN_REASON_NO_RESPONSE_FROM_BS                 = 509;
+    private final static int PS_NET_DOWN_REASON_REJECTED_BY_BS                      = 510;
+    private final static int PS_NET_DOWN_REASON_INCOMPATIBLE                        = 511;
+    private final static int PS_NET_DOWN_REASON_ALREADY_IN_TC                       = 512;
+    private final static int PS_NET_DOWN_REASON_USER_CALL_ORIG_DURING_GPS           = 513;
+    private final static int PS_NET_DOWN_REASON_USER_CALL_ORIG_DURING_SMS           = 514;
+    private final static int PS_NET_DOWN_REASON_NO_CDMA_SRV                         = 515;
+    private final static int PS_NET_DOWN_REASON_CONF_FAILED                         = 1000;
+    private final static int PS_NET_DOWN_REASON_INCOM_REJ                           = 1001;
+    private final static int PS_NET_DOWN_REASON_NO_GW_SRV                           = 1002;
+    private final static int PS_NET_DOWN_REASON_CD_GEN_OR_BUSY                      = 1500;
+    private final static int PS_NET_DOWN_REASON_CD_BILL_OR_AUTH                     = 1501;
+    private final static int PS_NET_DOWN_REASON_CHG_HDR                             = 1502;
+    private final static int PS_NET_DOWN_REASON_EXIT_HDR                            = 1503;
+    private final static int PS_NET_DOWN_REASON_HDR_NO_SESSION                      = 1504;
+    private final static int PS_NET_DOWN_REASON_HDR_ORIG_DURING_GPS_FIX             = 1505;
+    private final static int PS_NET_DOWN_REASON_HDR_CS_TIMEOUT                      = 1506;
+    private final static int PS_NET_DOWN_REASON_HDR_RELEASED_BY_CM                  = 1507;
+    private final static int PS_NET_DOWN_REASON_CLIENT_END                          = 2000;
+    private final static int PS_NET_DOWN_REASON_NO_SRV                              = 2001;
+    private final static int PS_NET_DOWN_REASON_FADE                                = 2002;
+    private final static int PS_NET_DOWN_REASON_REL_NORMAL                          = 2003;
+    private final static int PS_NET_DOWN_REASON_ACC_IN_PROG                         = 2004;
+    private final static int PS_NET_DOWN_REASON_ACC_FAIL                            = 2005;
+    private final static int PS_NET_DOWN_REASON_REDIR_OR_HANDOFF                    = 2006;
+
+    // ***** Instance Variables
+
+    // ***** Constructor
+    CdmaDataConnection(CDMAPhone phone) {
+        super(phone);
+
+        if (DBG) log("CdmaDataConnection <constructor>");
+    }
+
+    /**
+     * Setup a data connection
+     *
+     * @param onCompleted
+     *            notify success or not after down
+     */
+    void connect(Message onCompleted) {
+        if (DBG) log("CdmaDataConnection Connecting...");
+
+        state = State.ACTIVATING;
+        onConnectCompleted = onCompleted;
+        createTime = -1;
+        lastFailTime = -1;
+        lastFailCause = FailCause.NONE;
+        receivedDisconnectReq = false;
+        phone.mCM.setupDataCall(Integer.toString(RILConstants.CDMA_PHONE), null, null, null,
+                null, obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE));
+    }
+
+    protected void disconnect(Message msg) {
+        onDisconnect = msg;
+        if (state == State.ACTIVE) {
+            if (phone.mCM.getRadioState().isOn()) {
+                phone.mCM.deactivateDataCall(cid, obtainMessage(EVENT_DEACTIVATE_DONE, msg));
+            }
+        } else if (state == State.ACTIVATING) {
+            receivedDisconnectReq = true;
+        } else {
+            // state == INACTIVE.  Nothing to do, so notify immediately.
+            notifyDisconnect(msg);
+        }
+    }
+
+
+    public String toString() {
+        return "State=" + state + " create=" + createTime + " lastFail="
+                + lastFailTime + " lastFailCause=" + lastFailCause;
+    }
+
+
+    protected void notifyFail(FailCause cause, Message onCompleted) {
+        if (onCompleted == null) {
+            return;
+        }
+        state = State.INACTIVE;
+        lastFailCause = cause;
+        lastFailTime = System.currentTimeMillis();
+        onConnectCompleted = null;
+
+        if(DBG) {
+            log("Notify data connection fail at " + lastFailTime +
+                    " due to " + lastFailCause);
+        }
+
+        AsyncResult.forMessage(onCompleted, cause, new Exception());
+        onCompleted.sendToTarget();
+    }
+
+    protected void notifySuccess(Message onCompleted) {
+        if (onCompleted == null) {
+            return;
+        }
+
+        state = State.ACTIVE;
+        createTime = System.currentTimeMillis();
+        onConnectCompleted = null;
+        onCompleted.arg1 = cid;
+
+        if (DBG) log("Notify data connection success at " + createTime);
+
+        AsyncResult.forMessage(onCompleted);
+        onCompleted.sendToTarget();
+    }
+
+    protected void notifyDisconnect(Message msg) {
+        if (DBG) log("Notify data connection disconnect");
+
+        if (msg != null) {
+            AsyncResult.forMessage(msg);
+            msg.sendToTarget();
+        }
+        clearSettings();
+    }
+
+    protected void onLinkStateChanged(DataLink.LinkState linkState) {
+        switch (linkState) {
+            case LINK_UP:
+                notifySuccess(onConnectCompleted);
+                break;
+
+            case LINK_DOWN:
+            case LINK_EXITED:
+                phone.mCM.getLastDataCallFailCause(obtainMessage(EVENT_GET_LAST_FAIL_DONE));
+                break;
+        }
+    }
+
+    protected FailCause getFailCauseFromRequest(int rilCause) {
+        FailCause cause;
+
+        switch (rilCause) {
+            case PS_NET_DOWN_REASON_OPERATOR_DETERMINED_BARRING:
+                cause = FailCause.BARRED;
+                break;
+            case PS_NET_DOWN_REASON_AUTH_FAILED:
+                cause = FailCause.USER_AUTHENTICATION;
+                break;
+            case PS_NET_DOWN_REASON_OPTION_NOT_SUPPORTED:
+                cause = FailCause.SERVICE_OPTION_NOT_SUPPORTED;
+                break;
+            case PS_NET_DOWN_REASON_OPTION_UNSUBSCRIBED:
+                cause = FailCause.SERVICE_OPTION_NOT_SUBSCRIBED;
+                break;
+            default:
+                cause = FailCause.UNKNOWN;
+        }
+        return cause;
+    }
+
+    protected void log(String s) {
+        Log.d(LOG_TAG, "[CdmaDataConnection] " + s);
+    }
+
+    @Override
+    protected void onDeactivated(AsyncResult ar) {
+        notifyDisconnect((Message) ar.userObj);
+        if (DBG) log("CDMA Connection Deactivated");
+    }
+
+    @Override
+    protected void onSetupConnectionCompleted(AsyncResult ar) {
+        if (ar.exception != null) {
+            Log.e(LOG_TAG, "CdmaDataConnection Init failed " + ar.exception);
+
+            if (receivedDisconnectReq) {
+                // Don't bother reporting the error if there's already a
+                // pending disconnect request, since DataConnectionTracker
+                // has already updated its state.
+                notifyDisconnect(onDisconnect);
+            } else {
+                if (ar.exception instanceof CommandException
+                        && ((CommandException) (ar.exception)).getCommandError()
+                        == CommandException.Error.RADIO_NOT_AVAILABLE) {
+                    notifyFail(FailCause.RADIO_NOT_AVAILABLE, onConnectCompleted);
+                } else {
+                    phone.mCM.getLastDataCallFailCause(obtainMessage(EVENT_GET_LAST_FAIL_DONE));
+                }
+            }
+        } else {
+            if (receivedDisconnectReq) {
+                // Don't bother reporting success if there's already a
+                // pending disconnect request, since DataConnectionTracker
+                // has already updated its state.
+                disconnect(onDisconnect);
+            } else {
+                String[] response = ((String[]) ar.result);
+                cid = Integer.parseInt(response[0]);
+
+                if (response.length > 2) {
+                    interfaceName = response[1];
+                    ipAddress = response[2];
+                    String prefix = "net." + interfaceName + ".";
+                    gatewayAddress = SystemProperties.get(prefix + "gw");
+                    dnsServers[0] = SystemProperties.get(prefix + "dns1");
+                    dnsServers[1] = SystemProperties.get(prefix + "dns2");
+                    if (DBG) {
+                        log("interface=" + interfaceName + " ipAddress=" + ipAddress
+                            + " gateway=" + gatewayAddress + " DNS1=" + dnsServers[0]
+                            + " DNS2=" + dnsServers[1]);
+                    }
+
+                    if (NULL_IP.equals(dnsServers[0]) && NULL_IP.equals(dnsServers[1])
+                                        && !((CDMAPhone) phone).isDnsCheckDisabled()) {
+                        // Work around a race condition where QMI does not fill in DNS:
+                        // Deactivate PDP and let DataConnectionTracker retry.
+                        EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_BAD_DNS_ADDRESS,
+                                    dnsServers[0]);
+                        phone.mCM.deactivateDataCall(cid, obtainMessage(EVENT_FORCE_RETRY));
+                        return;
+                    }
+                }
+
+                onLinkStateChanged(DataLink.LinkState.LINK_UP);
+
+                if (DBG) log("CdmaDataConnection setup on cid = " + cid);
+            }
+        }
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
new file mode 100644
index 0000000..84febf3b
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -0,0 +1,929 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony.cdma;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.net.NetworkInfo;
+import android.net.wifi.WifiManager;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.INetStatService;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.preference.PreferenceManager;
+import android.provider.Checkin;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
+import android.telephony.ServiceState;
+import android.telephony.TelephonyManager;
+import android.util.EventLog;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.DataConnection;
+import com.android.internal.telephony.DataConnection.FailCause;
+import com.android.internal.telephony.DataConnectionTracker;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneProxy;
+import com.android.internal.telephony.TelephonyEventLog;
+
+import java.util.ArrayList;
+
+/**
+ * WINK:TODO: In GsmDataConnectionTracker there are
+ *            EventLog's used quite a few places maybe
+ *            more need to be added in this file?
+ *
+ * {@hide}
+ */
+public final class CdmaDataConnectionTracker extends DataConnectionTracker {
+    private static final String LOG_TAG = "CDMA";
+    private static final boolean DBG = true;
+
+    //***** Instance Variables
+
+    // Indicates baseband will not auto-attach
+    private boolean noAutoAttach = false;
+    long nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
+    private boolean mIsScreenOn = true;
+
+    //useful for debugging
+    boolean failNextConnect = false;
+
+    /**
+     * dataConnectionList holds all the Data connection
+     */
+    private ArrayList<DataConnection> dataConnectionList;
+
+    /** Currently active CdmaDataConnection */
+    private CdmaDataConnection mActiveDataConnection;
+
+    /** Defined cdma connection profiles */
+    private static int EXTERNAL_NETWORK_DEFAULT_ID = 0;
+    private static int EXTERNAL_NETWORK_NUM_TYPES  = 1;
+
+    private boolean[] dataEnabled = new boolean[EXTERNAL_NETWORK_NUM_TYPES];
+
+    //***** Constants
+
+    /**
+     * Pool size of CdmaDataConnection objects.
+     */
+    private static final int DATA_CONNECTION_POOL_SIZE = 1;
+
+    private static final int POLL_CONNECTION_MILLIS = 5 * 1000;
+    private static final String INTENT_RECONNECT_ALARM = "com.android.internal.telephony.cdma-reconnect";
+    private static final String INTENT_RECONNECT_ALARM_EXTRA_REASON = "reason";
+
+    // Possibly promoate to base class, the only difference is
+    // the INTENT_RECONNECT_ALARM action is a different string.
+    // Do consider technology changes if it is promoted.
+    BroadcastReceiver mIntentReceiver = new BroadcastReceiver ()
+    {
+        @Override
+        public void onReceive(Context context, Intent intent)
+        {
+            String action = intent.getAction();
+            if (action.equals(Intent.ACTION_SCREEN_ON)) {
+                mIsScreenOn = true;
+                stopNetStatPoll();
+                startNetStatPoll();
+            } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
+                mIsScreenOn = false;
+                stopNetStatPoll();
+                startNetStatPoll();
+            } else if (action.equals((INTENT_RECONNECT_ALARM))) {
+                Log.d(LOG_TAG, "Data reconnect alarm. Previous state was " + state);
+
+                String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
+                if (state == State.FAILED) {
+                    cleanUpConnection(false, reason);
+                }
+                trySetupData(reason);
+            } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
+                final android.net.NetworkInfo networkInfo = (NetworkInfo)
+                        intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
+                mIsWifiConnected = (networkInfo != null && networkInfo.isConnected());
+            } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
+                final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
+                        WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
+
+                if (!enabled) {
+                    // when wifi got disabeled, the NETWORK_STATE_CHANGED_ACTION
+                    // quit and wont report disconnected til next enalbing.
+                    mIsWifiConnected = false;
+                }
+            }
+        }
+    };
+
+
+    //***** Constructor
+
+    CdmaDataConnectionTracker(CDMAPhone p) {
+        super(p);
+
+        p.mCM.registerForAvailable (this, EVENT_RADIO_AVAILABLE, null);
+        p.mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
+        p.mRuimRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null);
+        p.mCM.registerForNVReady(this, EVENT_NV_READY, null);
+        p.mCM.registerForDataStateChanged (this, EVENT_DATA_STATE_CHANGED, null);
+        p.mCT.registerForVoiceCallEnded (this, EVENT_VOICE_CALL_ENDED, null);
+        p.mCT.registerForVoiceCallStarted (this, EVENT_VOICE_CALL_STARTED, null);
+        p.mSST.registerForCdmaDataConnectionAttached(this, EVENT_TRY_SETUP_DATA, null);
+        p.mSST.registerForCdmaDataConnectionDetached(this, EVENT_CDMA_DATA_DETACHED, null);
+        p.mSST.registerForRoamingOn(this, EVENT_ROAMING_ON, null);
+        p.mSST.registerForRoamingOff(this, EVENT_ROAMING_OFF, null);
+
+        this.netstat = INetStatService.Stub.asInterface(ServiceManager.getService("netstat"));
+
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(INTENT_RECONNECT_ALARM);
+        filter.addAction(Intent.ACTION_SCREEN_ON);
+        filter.addAction(Intent.ACTION_SCREEN_OFF);
+        filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
+
+        p.getContext().registerReceiver(mIntentReceiver, filter, null, p.h);
+
+        mDataConnectionTracker = this;
+
+        createAllDataConnectionList();
+
+        // This preference tells us 1) initial condition for "dataEnabled",
+        // and 2) whether the RIL will setup the baseband to auto-PS attach.
+        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(phone.getContext());
+
+        dataEnabled[EXTERNAL_NETWORK_DEFAULT_ID] =
+                !sp.getBoolean(CDMAPhone.DATA_DISABLED_ON_BOOT_KEY, false);
+        noAutoAttach = !dataEnabled[EXTERNAL_NETWORK_DEFAULT_ID];
+    }
+
+    public void dispose() {
+        //Unregister from all events
+        phone.mCM.unregisterForAvailable(this);
+        phone.mCM.unregisterForOffOrNotAvailable(this);
+        ((CDMAPhone) phone).mRuimRecords.unregisterForRecordsLoaded(this);
+        phone.mCM.unregisterForNVReady(this);
+        phone.mCM.unregisterForDataStateChanged(this);
+        ((CDMAPhone) phone).mCT.unregisterForVoiceCallEnded(this);
+        ((CDMAPhone) phone).mCT.unregisterForVoiceCallStarted(this);
+        ((CDMAPhone) phone).mSST.unregisterForCdmaDataConnectionAttached(this);
+        ((CDMAPhone) phone).mSST.unregisterForCdmaDataConnectionDetached(this);
+        ((CDMAPhone) phone).mSST.unregisterForRoamingOn(this);
+        ((CDMAPhone) phone).mSST.unregisterForRoamingOff(this);
+
+        phone.getContext().unregisterReceiver(this.mIntentReceiver);
+        destroyAllDataConnectionList();
+    }
+
+    protected void finalize() {
+        if(DBG) Log.d(LOG_TAG, "CdmaDataConnectionTracker finalized");
+    }
+
+    void setState(State s) {
+        if (DBG) log ("setState: " + s);
+        if (state != s) {
+            if (s == State.INITING) { // request Data connection context
+                Checkin.updateStats(phone.getContext().getContentResolver(),
+                        Checkin.Stats.Tag.PHONE_CDMA_DATA_ATTEMPTED, 1, 0.0);
+            }
+
+            if (s == State.CONNECTED) { // pppd is up
+                Checkin.updateStats(phone.getContext().getContentResolver(),
+                        Checkin.Stats.Tag.PHONE_CDMA_DATA_CONNECTED, 1, 0.0);
+            }
+        }
+
+        state = s;
+    }
+
+    public int enableApnType(String type) {
+        // This request is mainly used to enable MMS APN
+        // In CDMA there is no need to enable/disable a different APN for MMS
+        Log.d(LOG_TAG, "Request to enableApnType("+type+")");
+        if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
+            return Phone.APN_ALREADY_ACTIVE;
+        } else {
+            return Phone.APN_REQUEST_FAILED;
+        }
+    }
+
+    public int disableApnType(String type) {
+        // This request is mainly used to disable MMS APN
+        // In CDMA there is no need to enable/disable a different APN for MMS
+        Log.d(LOG_TAG, "Request to disableApnType("+type+")");
+        if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
+            return Phone.APN_REQUEST_STARTED;
+        } else {
+            return Phone.APN_REQUEST_FAILED;
+        }
+    }
+
+    private boolean isEnabled(int cdmaDataProfile) {
+        return dataEnabled[cdmaDataProfile];
+    }
+
+    private void setEnabled(int cdmaDataProfile, boolean enable) {
+        Log.d(LOG_TAG, "setEnabled("  + cdmaDataProfile + ", " + enable + ')');
+        dataEnabled[cdmaDataProfile] = enable;
+        Log.d(LOG_TAG, "dataEnabled[DEFAULT_PROFILE]=" + dataEnabled[EXTERNAL_NETWORK_DEFAULT_ID]);
+    }
+
+    /**
+     * Simply tear down data connections due to radio off 
+     * and don't setup again.
+     */
+    public void cleanConnectionBeforeRadioOff() {
+        cleanUpConnection(true, Phone.REASON_RADIO_TURNED_OFF);
+    }
+
+    /**
+     * The data connection is expected to be setup while device
+     *  1. has ruim card or non-volatile data store
+     *  2. registered to data connection service
+     *  3. user doesn't explicitly disable data service
+     *  4. wifi is not on
+     *
+     * @return false while no data connection if all above requirements are met.
+     */
+    public boolean isDataConnectionAsDesired() {
+        boolean roaming = phone.getServiceState().getRoaming();
+
+        if ( ((phone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY) || 
+		        ((CDMAPhone) phone).mRuimRecords.getRecordsLoaded()) &&
+                ((CDMAPhone) phone).mSST.getCurrentCdmaDataConnectionState() == 
+				ServiceState.STATE_IN_SERVICE &&
+                (!roaming || getDataOnRoamingEnabled()) &&
+                !mIsWifiConnected ) {
+            return (state == State.CONNECTED);
+        }
+        return true;
+    }
+
+    /**
+     * Prevent mobile data connections from being established,
+     * or once again allow mobile data connections. If the state
+     * toggles, then either tear down or set up data, as
+     * appropriate to match the new state.
+     * <p>This operation only affects the default connection
+     * @param enable indicates whether to enable ({@code true}) or disable ({@code false}) data
+     * @return {@code true} if the operation succeeded
+     */
+    public boolean setDataEnabled(boolean enable) {
+
+        boolean isEnabled = isEnabled(EXTERNAL_NETWORK_DEFAULT_ID);
+
+        Log.d(LOG_TAG, "setDataEnabled("+enable+") isEnabled=" + isEnabled);
+        if (!isEnabled && enable) {
+            setEnabled(EXTERNAL_NETWORK_DEFAULT_ID, true);
+            return trySetupData(Phone.REASON_DATA_ENABLED);
+        } else if (!enable) {
+            setEnabled(EXTERNAL_NETWORK_DEFAULT_ID, false);
+            return false;
+        } else // isEnabled && enable
+
+        return true;
+    }
+
+    /**
+     * Report the current state of data connectivity (enabled or disabled)
+     * @return {@code false} if data connectivity has been explicitly disabled,
+     * {@code true} otherwise.
+     */
+    public boolean getDataEnabled() {
+        return dataEnabled[EXTERNAL_NETWORK_DEFAULT_ID];
+    }
+
+    /**
+     * Report on whether data connectivity is enabled
+     * @return {@code false} if data connectivity has been explicitly disabled,
+     * {@code true} otherwise.
+     */
+    public boolean getAnyDataEnabled() {
+        for (int i=0; i < EXTERNAL_NETWORK_NUM_TYPES; i++) {
+            if (isEnabled(i)) return true;
+        }
+        return false;
+    }
+
+    private boolean isDataAllowed() {
+        boolean roaming = phone.getServiceState().getRoaming();
+        return getAnyDataEnabled() && (!roaming || getDataOnRoamingEnabled());
+    }
+
+    private boolean trySetupData(String reason) {
+        if (DBG) log("***trySetupData due to " + (reason == null ? "(unspecified)" : reason));
+
+        if (phone.getSimulatedRadioControl() != null) {
+            // Assume data is connected on the simulator
+            // FIXME  this can be improved
+            setState(State.CONNECTED);
+            phone.notifyDataConnection(reason);
+
+            Log.i(LOG_TAG, "(fix?) We're on the simulator; assuming data is connected");
+            return true;
+        }
+
+        int psState = ((CDMAPhone) phone).mSST.getCurrentCdmaDataConnectionState();
+        boolean roaming = phone.getServiceState().getRoaming();
+
+        if ((state == State.IDLE || state == State.SCANNING)
+                && (psState == ServiceState.RADIO_TECHNOLOGY_1xRTT ||
+                    psState == ServiceState.RADIO_TECHNOLOGY_EVDO_0 ||
+                    psState == ServiceState.RADIO_TECHNOLOGY_EVDO_A)
+                && ((phone.mCM.getRadioState() == CommandsInterface.RadioState.NV_READY) ||
+                        ((CDMAPhone) phone).mRuimRecords.getRecordsLoaded())
+                && (((CDMAPhone) phone).mSST.isConcurrentVoiceAndData() ||
+                     phone.getState() == Phone.State.IDLE )
+                && isDataAllowed()) {
+
+            return setupData(reason);
+
+        } else {
+            if (DBG) {
+                    log("trySetupData: Not ready for data: " +
+                    " dataState=" + state +
+                    " PS state=" + psState +
+                    " radio state=" + phone.mCM.getRadioState() +
+                    " ruim=" + ((CDMAPhone) phone).mRuimRecords.getRecordsLoaded() +
+                    " concurrentVoice&Data=" + ((CDMAPhone) phone).mSST.isConcurrentVoiceAndData() +
+                    " phoneState=" + phone.getState() +
+                    " dataEnabled=" + getAnyDataEnabled() +
+                    " roaming=" + roaming +
+                    " dataOnRoamingEnable=" + getDataOnRoamingEnabled());
+            }
+            return false;
+        }
+    }
+
+    /**
+     * If tearDown is true, this only tears down a CONNECTED session. Presently,
+     * there is no mechanism for abandoning an INITING/CONNECTING session,
+     * but would likely involve cancelling pending async requests or
+     * setting a flag or new state to ignore them when they came in
+     * @param tearDown true if the underlying DataConnection should be
+     * disconnected.
+     * @param reason reason for the clean up.
+     */
+    private void cleanUpConnection(boolean tearDown, String reason) {
+        if (DBG) log("Clean up connection due to " + reason);
+
+        // Clear the reconnect alarm, if set.
+        if (mReconnectIntent != null) {
+            AlarmManager am =
+                (AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE);
+            am.cancel(mReconnectIntent);
+            mReconnectIntent = null;
+        }
+
+        for (DataConnection connBase : dataConnectionList) {
+            CdmaDataConnection conn = (CdmaDataConnection) connBase;
+
+            if(conn != null) {
+                if (tearDown) {
+                    Message msg = obtainMessage(EVENT_DISCONNECT_DONE, reason);
+                    conn.disconnect(msg);
+                } else {
+                    conn.clearSettings();
+                }
+            }
+        }
+
+        stopNetStatPoll();
+
+        /*
+         * If we've been asked to tear down the connection,
+         * set the state to DISCONNECTING. However, there's
+         * a race that can occur if for some reason we were
+         * already in the IDLE state. In that case, the call
+         * to conn.disconnect() above will immediately post
+         * a message to the handler thread that the disconnect
+         * is done, and if the handler runs before the code
+         * below does, the handler will have set the state to
+         * IDLE before the code below runs. If we didn't check
+         * for that, future calls to trySetupData would fail,
+         * and we would never get out of the DISCONNECTING state.
+         */
+        if (!tearDown) {
+            setState(State.IDLE);
+            phone.notifyDataConnection(reason);
+        } else if (state != State.IDLE) {
+            setState(State.DISCONNECTING);
+        }
+    }
+
+    private CdmaDataConnection findFreeDataConnection() {
+        for (DataConnection connBase : dataConnectionList) {
+            CdmaDataConnection conn = (CdmaDataConnection) connBase;
+            if (conn.getState() == DataConnection.State.INACTIVE) {
+                return conn;
+            }
+        }
+        return null;
+    }
+
+    private boolean setupData(String reason) {
+
+        CdmaDataConnection conn = findFreeDataConnection();
+
+        if (conn == null) {
+            if (DBG) log("setupData: No free CdmaDataConnectionfound!");
+            return false;
+        }
+
+        mActiveDataConnection = conn;
+
+        Message msg = obtainMessage();
+        msg.what = EVENT_DATA_SETUP_COMPLETE;
+        msg.obj = reason;
+        conn.connect(msg);
+
+        setState(State.INITING);
+        phone.notifyDataConnection(reason);
+        return true;
+    }
+
+    private void notifyDefaultData(String reason) {
+        setState(State.CONNECTED);
+        phone.notifyDataConnection(reason);
+        startNetStatPoll();
+        // reset reconnect timer
+        nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
+    }
+
+    private void resetPollStats() {
+        txPkts = -1;
+        rxPkts = -1;
+        sentSinceLastRecv = 0;
+        netStatPollPeriod = POLL_NETSTAT_MILLIS;
+        mNoRecvPollCount = 0;
+    }
+
+    protected void startNetStatPoll() {
+        if (state == State.CONNECTED && netStatPollEnabled == false) {
+            Log.d(LOG_TAG, "[DataConnection] Start poll NetStat");
+            resetPollStats();
+            netStatPollEnabled = true;
+            mPollNetStat.run();
+        }
+    }
+
+    protected void stopNetStatPoll() {
+        netStatPollEnabled = false;
+        removeCallbacks(mPollNetStat);
+        Log.d(LOG_TAG, "[DataConnection] Stop poll NetStat");
+    }
+
+    protected void restartRadio() {
+        Log.d(LOG_TAG, "************TURN OFF RADIO**************");
+        cleanUpConnection(true, Phone.REASON_RADIO_TURNED_OFF);
+        phone.mCM.setRadioPower(false, null);
+        /* Note: no need to call setRadioPower(true).  Assuming the desired
+         * radio power state is still ON (as tracked by ServiceStateTracker),
+         * ServiceStateTracker will call setRadioPower when it receives the
+         * RADIO_STATE_CHANGED notification for the power off.  And if the
+         * desired power state has changed in the interim, we don't want to
+         * override it with an unconditional power on.
+         */
+    }
+    
+    private Runnable mPollNetStat = new Runnable() {
+
+        public void run() {
+            long sent, received;
+            long preTxPkts = -1, preRxPkts = -1;
+
+            Activity newActivity;
+
+            preTxPkts = txPkts;
+            preRxPkts = rxPkts;
+
+            // check if netstat is still valid to avoid NullPointerException after NTC
+            if (netstat != null) {
+                try {
+                    txPkts = netstat.getMobileTxPackets();
+                    rxPkts = netstat.getMobileRxPackets();
+                } catch (RemoteException e) {
+                    txPkts = 0;
+                    rxPkts = 0;
+                }
+
+                //Log.d(LOG_TAG, "rx " + String.valueOf(rxPkts) + " tx " + String.valueOf(txPkts));
+
+                if (netStatPollEnabled && (preTxPkts > 0 || preRxPkts > 0)) {
+                    sent = txPkts - preTxPkts;
+                    received = rxPkts - preRxPkts;
+
+                    if ( sent > 0 && received > 0 ) {
+                        sentSinceLastRecv = 0;
+                        newActivity = Activity.DATAINANDOUT;
+                    } else if (sent > 0 && received == 0) {
+                        if (phone.getState()  == Phone.State.IDLE) {
+                            sentSinceLastRecv += sent;
+                        } else {
+                            sentSinceLastRecv = 0;
+                        }
+                        newActivity = Activity.DATAOUT;
+                    } else if (sent == 0 && received > 0) {
+                        sentSinceLastRecv = 0;
+                        newActivity = Activity.DATAIN;
+                    } else if (sent == 0 && received == 0) {
+                        newActivity = Activity.NONE;
+                    } else {
+                        sentSinceLastRecv = 0;
+                        newActivity = Activity.NONE;
+                    }
+
+                    if (activity != newActivity) {
+                        activity = newActivity;
+                        phone.notifyDataActivity();
+                    }
+                }
+
+                if (sentSinceLastRecv >= NUMBER_SENT_PACKETS_OF_HANG) {
+                    // we already have NUMBER_SENT_PACKETS sent without ack
+                    if (mNoRecvPollCount < NO_RECV_POLL_LIMIT) {
+                        mNoRecvPollCount++;
+                        // Slow down the poll interval to let things happen
+                        netStatPollPeriod = POLL_NETSTAT_SLOW_MILLIS;
+                    } else {
+                        if (DBG) log("Sent " + String.valueOf(sentSinceLastRecv) +
+                                            " pkts since last received");
+                        // We've exceeded the threshold.  Restart the radio.
+                        netStatPollEnabled = false;
+                        stopNetStatPoll();
+                        restartRadio();
+                    }
+                } else {
+                    mNoRecvPollCount = 0;
+                    netStatPollPeriod = POLL_NETSTAT_MILLIS;
+                }
+
+                if (netStatPollEnabled) {
+                    mDataConnectionTracker.postDelayed(this, netStatPollPeriod);
+                }
+            }
+        }
+    };
+
+    /**
+     * Returns true if the last fail cause is something that
+     * seems like it deserves an error notification.
+     * Transient errors are ignored
+     */
+    private boolean
+    shouldPostNotification(FailCause cause) {
+        return (cause != FailCause.UNKNOWN);
+    }
+
+    /**
+     * Return true if data connection need to be setup after disconnected due to
+     * reason.
+     * 
+     * @param reason the reason why data is disconnected
+     * @return true if try setup data connection is need for this reason 
+     */
+    private boolean retryAfterDisconnected(String reason) {
+        boolean retry = true;
+        
+        if ( Phone.REASON_RADIO_TURNED_OFF.equals(reason) ||
+             Phone.REASON_DATA_DISABLED.equals(reason) ) { 
+            retry = false;
+        }
+        return retry;
+    }   
+
+    private void reconnectAfterFail(FailCause lastFailCauseCode, String reason) {
+        if (state == State.FAILED) {
+            Log.d(LOG_TAG, "Data Connection activate failed. Scheduling next attempt for "
+                    + (nextReconnectDelay / 1000) + "s");
+
+            AlarmManager am =
+                (AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE);
+            Intent intent = new Intent(INTENT_RECONNECT_ALARM);
+            intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, reason);
+            mReconnectIntent = PendingIntent.getBroadcast(
+                    phone.getContext(), 0, intent, 0);
+            am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+                    SystemClock.elapsedRealtime() + nextReconnectDelay,
+                    mReconnectIntent);
+
+            // double it for next time
+            nextReconnectDelay *= 2;
+            if (nextReconnectDelay > RECONNECT_DELAY_MAX_MILLIS) {
+                nextReconnectDelay = RECONNECT_DELAY_MAX_MILLIS;
+            }
+
+            if (!shouldPostNotification(lastFailCauseCode)) {
+                Log.d(LOG_TAG,"NOT Posting Data Connection Unavailable notification "
+                                + "-- likely transient error");
+            } else {
+                notifyNoData(lastFailCauseCode);
+            }
+        }
+    }
+
+    private void notifyNoData(FailCause lastFailCauseCode) {
+        setState(State.FAILED);
+    }
+
+    protected void onRecordsLoaded() {
+        if (state == State.FAILED) {
+            cleanUpConnection(false, null);
+        }
+        sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
+    }
+
+    protected void onNVReady() {
+        if (state == State.FAILED) {
+            cleanUpConnection(false, null);
+        }
+        sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
+    }
+
+    /**
+     * @override com.android.internal.telephony.DataConnectionTracker
+     */
+    protected void onTrySetupData() {
+        trySetupData(null);
+    }
+
+    /**
+     * @override com.android.internal.telephony.DataConnectionTracker
+     */
+    protected void onRoamingOff() {
+        trySetupData(Phone.REASON_ROAMING_OFF);
+    }
+
+    /**
+     * @override com.android.internal.telephony.DataConnectionTracker
+     */
+    protected void onRoamingOn() {
+        if (getDataOnRoamingEnabled()) {
+            trySetupData(Phone.REASON_ROAMING_ON);
+        } else {
+            if (DBG) log("Tear down data connection on roaming.");
+            cleanUpConnection(true, Phone.REASON_ROAMING_ON);
+        }
+    }
+
+    /**
+     * @override com.android.internal.telephony.DataConnectionTracker
+     */
+    protected void onRadioAvailable() {
+        if (phone.getSimulatedRadioControl() != null) {
+            // Assume data is connected on the simulator
+            // FIXME  this can be improved
+            setState(State.CONNECTED);
+            phone.notifyDataConnection(null);
+
+            Log.i(LOG_TAG, "We're on the simulator; assuming data is connected");
+        }
+
+        if (state != State.IDLE) {
+            cleanUpConnection(true, null);
+        }
+    }
+
+    /**
+     * @override com.android.internal.telephony.DataConnectionTracker
+     */
+    protected void onRadioOffOrNotAvailable() {
+        // Make sure our reconnect delay starts at the initial value
+        // next time the radio comes on
+        nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
+
+        if (phone.getSimulatedRadioControl() != null) {
+            // Assume data is connected on the simulator
+            // FIXME  this can be improved
+            Log.i(LOG_TAG, "We're on the simulator; assuming radio off is meaningless");
+        } else {
+            if (DBG) log("Radio is off and clean up all connection");
+            cleanUpConnection(false, Phone.REASON_RADIO_TURNED_OFF);
+        }
+    }
+
+    /**
+     * @override com.android.internal.telephony.DataConnectionTracker
+     */
+    protected void onDataSetupComplete(AsyncResult ar) {
+        String reason = null;
+        if (ar.userObj instanceof String) {
+            reason = (String) ar.userObj;
+        }
+
+        if (ar.exception == null) {
+            // everything is setup
+            notifyDefaultData(reason);
+        } else {
+            FailCause cause = (FailCause) (ar.result);
+            if(DBG) log("Data Connection setup failed " + cause);
+
+            // No try for permanent failure
+            if (cause.isPermanentFail()) {
+                notifyNoData(cause);
+            }
+
+            if (tryAgain(cause)) {
+                    trySetupData(reason);
+            } else {
+                startDelayedRetry(cause, reason);
+            }
+        }
+    }
+
+    /**
+     * @override com.android.internal.telephony.DataConnectionTracker
+     */
+    protected void onDisconnectDone(AsyncResult ar) {
+        if(DBG) log("EVENT_DISCONNECT_DONE");
+        String reason = null;
+        if (ar.userObj instanceof String) {
+            reason = (String) ar.userObj;
+        }
+        setState(State.IDLE);
+        phone.notifyDataConnection(reason);
+        if (retryAfterDisconnected(reason)) {
+          trySetupData(reason);
+      }
+    }
+
+    /**
+     * @override com.android.internal.telephony.DataConnectionTracker
+     */
+    protected void onVoiceCallStarted() {
+        if (state == State.CONNECTED && !((CDMAPhone) phone).mSST.isConcurrentVoiceAndData()) {
+            stopNetStatPoll();
+            phone.notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED);
+        }
+    }
+
+    /**
+     * @override com.android.internal.telephony.DataConnectionTracker
+     */
+    protected void onVoiceCallEnded() {
+        if (state == State.CONNECTED) {
+            if (!((CDMAPhone) phone).mSST.isConcurrentVoiceAndData()) {
+                startNetStatPoll();
+                phone.notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED);
+            } else {
+                // clean slate after call end.
+                resetPollStats();
+            }
+        } else {
+            // in case data setup was attempted when we were on a voice call
+            trySetupData(Phone.REASON_VOICE_CALL_ENDED);
+        }
+    }
+
+    private boolean tryAgain(FailCause cause) {
+        return (cause != FailCause.RADIO_NOT_AVAILABLE)
+            && (cause != FailCause.RADIO_OFF)
+            && (cause != FailCause.RADIO_ERROR_RETRY)
+            && (cause != FailCause.NO_SIGNAL)
+            && (cause != FailCause.SIM_LOCKED);
+    }
+
+    private void createAllDataConnectionList() {
+       dataConnectionList = new ArrayList<DataConnection>();
+        CdmaDataConnection dataConn;
+
+       for (int i = 0; i < DATA_CONNECTION_POOL_SIZE; i++) {
+            dataConn = new CdmaDataConnection(((CDMAPhone) phone));
+            dataConnectionList.add(dataConn);
+       }
+    }
+
+    private void destroyAllDataConnectionList() {
+        if(dataConnectionList != null) {
+            CdmaDataConnection pdp;
+            dataConnectionList.removeAll(dataConnectionList);
+        }
+    }
+
+    private void onCdmaDataAttached() {
+        if (state == State.CONNECTED) {
+            startNetStatPoll();
+            phone.notifyDataConnection(Phone.REASON_CDMA_DATA_DETACHED);
+        } else {
+            if (state == State.FAILED) {
+                cleanUpConnection(false, Phone.REASON_CDMA_DATA_DETACHED);
+                nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
+            }
+            trySetupData(Phone.REASON_CDMA_DATA_DETACHED);
+        }
+    }
+
+    protected void onDataStateChanged (AsyncResult ar) {
+        if (ar.exception != null) {
+            // This is probably "radio not available" or something
+            // of that sort. If so, the whole connection is going
+            // to come down soon anyway
+            return;
+        }
+
+        if (state == State.CONNECTED) {
+            Log.i(LOG_TAG, "Data connection has changed.");
+
+            int cid = -1;
+            EventLog.List val = new EventLog.List(cid,
+                    TelephonyManager.getDefault().getNetworkType());
+            EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_PDP_NETWORK_DROP, val);
+
+            cleanUpConnection(true, null);
+        }
+        Log.i(LOG_TAG, "Data connection has changed.");
+    }
+
+    String getInterfaceName() {
+        if (mActiveDataConnection != null) {
+            return mActiveDataConnection.getInterface();
+        }
+        return null;
+    }
+
+    protected String getIpAddress() {
+        if (mActiveDataConnection != null) {
+            return mActiveDataConnection.getIpAddress();
+        }
+        return null;
+    }
+
+    String getGateway() {
+        if (mActiveDataConnection != null) {
+            return mActiveDataConnection.getGatewayAddress();
+        }
+        return null;
+    }
+
+    protected String[] getDnsServers() {
+        if (mActiveDataConnection != null) {
+            return mActiveDataConnection.getDnsServers();
+        }
+        return null;
+    }
+
+    public ArrayList<DataConnection> getAllDataConnections() {
+        return dataConnectionList;
+    }
+
+    private void startDelayedRetry(FailCause cause, String reason) {
+        notifyNoData(cause);
+        reconnectAfterFail(cause, reason);
+    }
+
+    public void handleMessage (Message msg) {
+
+        switch (msg.what) {
+            case EVENT_RECORDS_LOADED:
+                onRecordsLoaded();
+                break;
+
+            case EVENT_NV_READY:
+                onNVReady();
+                break;
+
+            case EVENT_CDMA_DATA_DETACHED:
+                onCdmaDataAttached();
+                break;
+
+            case EVENT_DATA_STATE_CHANGED:
+                onDataStateChanged((AsyncResult) msg.obj);
+                break;
+
+            default:
+                // handle the message in the super class DataConnectionTracker
+                super.handleMessage(msg);
+                break;
+        }
+    }
+
+    protected void log(String s) {
+        Log.d(LOG_TAG, "[CdmaDataConnectionTracker] " + s);
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
new file mode 100644
index 0000000..42c0583
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
@@ -0,0 +1,394 @@
+/*
+ * Copyright (C) 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.
+ * 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.internal.telephony.cdma;
+
+
+import android.app.PendingIntent;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.os.AsyncResult;
+import android.os.Message;
+import android.util.Config;
+import android.util.Log;
+
+import com.android.internal.telephony.SmsHeader;
+import com.android.internal.telephony.SmsMessageBase;
+import com.android.internal.telephony.SMSDispatcher;
+//import com.android.internal.telephony.SMSDispatcher.SmsTracker;
+import com.android.internal.telephony.cdma.SmsMessage;
+import com.android.internal.telephony.cdma.sms.SmsEnvelope;
+import com.android.internal.util.HexDump;
+
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+
+final class CdmaSMSDispatcher extends SMSDispatcher {
+    private static final String TAG = "CDMA";
+
+    CdmaSMSDispatcher(CDMAPhone phone) {
+        super(phone);
+    }
+
+    /**
+     * Called when a status report is received.  This should correspond to
+     * a previously successful SEND.
+     * Is a special GSM function, should never be called in CDMA!!
+     *
+     * @param ar AsyncResult passed into the message handler.  ar.result should
+     *           be a String representing the status report PDU, as ASCII hex.
+     */
+    protected void handleStatusReport(AsyncResult ar) {
+        Log.d(TAG, "handleStatusReport is a special GSM function, should never be called in CDMA!");
+    }
+
+    /**
+     * Dispatches an incoming SMS messages.
+     *
+     * @param smsb the incoming message from the phone
+     */
+    protected void dispatchMessage(SmsMessageBase smsb) {
+
+        // If sms is null, means there was a parsing error.
+        // TODO: Should NAK this.
+        if (smsb == null) {
+            return;
+        }
+        SmsMessage sms = (SmsMessage) smsb;
+        int teleService;
+        boolean handled = false;
+
+        // Decode BD stream and set sms variables.
+        sms.parseSms();
+        teleService = sms.getTeleService();
+
+        // Teleservices W(E)MT and VMN are handled together:
+        if ((SmsEnvelope.TELESERVICE_WMT == teleService)
+                ||(SmsEnvelope.TELESERVICE_WEMT == teleService)
+                ||(SmsEnvelope.TELESERVICE_VMN == teleService)){
+            // From here on we need decoded BD.
+            // Special case the message waiting indicator messages
+            if (sms.isMWISetMessage()) {
+                ((CDMAPhone) mPhone).updateMessageWaitingIndicator(true);
+
+                if (sms.isMwiDontStore()) {
+                    handled = true;
+                }
+
+                if (Config.LOGD) {
+                    Log.d(TAG,
+                            "Received voice mail indicator set SMS shouldStore=" + !handled);
+                }
+            } else if (sms.isMWIClearMessage()) {
+                ((CDMAPhone) mPhone).updateMessageWaitingIndicator(false);
+
+                if (sms.isMwiDontStore()) {
+                    handled = true;
+                }
+
+                if (Config.LOGD) {
+                    Log.d(TAG,
+                            "Received voice mail indicator clear SMS shouldStore=" + !handled);
+                }
+            }
+        }
+
+        if (null == sms.getUserData()){
+            handled = true;
+            if (Config.LOGD) {
+                Log.d(TAG, "Received SMS without user data");
+            }
+        }
+
+        if (handled) return;
+
+        if (SmsEnvelope.TELESERVICE_WAP == teleService){
+            processCdmaWapPdu(sms.getUserData(), sms.messageRef, sms.getOriginatingAddress());
+            return;
+        }
+
+        // Parse the headers to see if this is partial, or port addressed
+        int referenceNumber = -1;
+        int count = 0;
+        int sequence = 0;
+        int destPort = -1;
+        // From here on we need BD distributed to SMS member variables.
+
+        SmsHeader header = sms.getUserDataHeader();
+        if (header != null) {
+            for (SmsHeader.Element element : header.getElements()) {
+                try {
+                    switch (element.getID()) {
+                        case SmsHeader.CONCATENATED_8_BIT_REFERENCE: {
+                            byte[] data = element.getData();
+                            
+                            referenceNumber = data[0] & 0xff;
+                            count = data[1] & 0xff;
+                            sequence = data[2] & 0xff;
+                            
+                            // Per TS 23.040, 9.2.3.24.1: If the count is zero, sequence
+                            // is zero, or sequence > count, ignore the entire element
+                            if (count == 0 || sequence == 0 || sequence > count) {
+                                referenceNumber = -1;
+                            }
+                            break;
+                        }
+                        
+                        case SmsHeader.CONCATENATED_16_BIT_REFERENCE: {
+                            byte[] data = element.getData();
+                            
+                            referenceNumber = (data[0] & 0xff) * 256 + (data[1] & 0xff);
+                            count = data[2] & 0xff;
+                            sequence = data[3] & 0xff;
+                            
+                            // Per TS 23.040, 9.2.3.24.8: If the count is zero, sequence
+                            // is zero, or sequence > count, ignore the entire element
+                            if (count == 0 || sequence == 0 || sequence > count) {
+                                referenceNumber = -1;
+                            }
+                            break;
+                        }
+                        
+                        case SmsHeader.APPLICATION_PORT_ADDRESSING_16_BIT: {
+                            byte[] data = element.getData();
+                            
+                            destPort = (data[0] & 0xff) << 8;
+                            destPort |= (data[1] & 0xff);
+                            
+                            break;
+                        }
+                    }
+                } catch (ArrayIndexOutOfBoundsException e) {
+                    Log.e(TAG, "Bad element in header", e);
+                    return;  // TODO: NACK the message or something, don't just discard.
+                }
+            }
+        }
+
+        if (referenceNumber == -1) {
+            // notify everyone of the message if it isn't partial
+            byte[][] pdus = new byte[1][];
+            pdus[0] = sms.getPdu();
+
+            if (destPort != -1) {// GSM-style WAP indication
+                if (destPort == SmsHeader.PORT_WAP_PUSH) {
+                    mWapPush.dispatchWapPdu(sms.getUserData());
+                }
+                // The message was sent to a port, so concoct a URI for it
+                dispatchPortAddressedPdus(pdus, destPort);
+            } else {
+                // It's a normal message, dispatch it
+                dispatchPdus(pdus);
+            }
+        } else {
+            // Process the message part
+            processMessagePart(sms, referenceNumber, sequence, count, destPort);
+        }
+    }
+
+    /**
+     * Processes inbound messages that are in the WAP-WDP PDU format. See
+     * wap-259-wdp-20010614-a section 6.5 for details on the WAP-WDP PDU format.
+     * WDP segments are gathered until a datagram completes and gets dispatched.
+     *
+     * @param pdu The WAP-WDP PDU segment
+     */
+    protected void processCdmaWapPdu(byte[] pdu, int referenceNumber, String address) {
+        int segment;
+        int totalSegments;
+        int index = 0;
+        int msgType;
+
+        int sourcePort;
+        int destinationPort;
+
+        msgType = pdu[index++];
+        if (msgType != 0){
+            Log.w(TAG, "Received a WAP SMS which is not WDP. Discard.");
+            return;
+        }
+        totalSegments = pdu[index++]; // >=1
+        segment = pdu[index++]; // >=0
+
+        //process WDP segment
+        sourcePort = (0xFF & pdu[index++]) << 8;
+        sourcePort |= 0xFF & pdu[index++];
+        destinationPort = (0xFF & pdu[index++]) << 8;
+        destinationPort |= 0xFF & pdu[index++];
+
+        // Lookup all other related parts
+        StringBuilder where = new StringBuilder("reference_number =");
+        where.append(referenceNumber);
+        where.append(" AND address = ?");
+        String[] whereArgs = new String[] {address};
+
+        Log.i(TAG, "Received WAP PDU. Type = " + msgType + ", originator = " + address
+                + ", src-port = " + sourcePort + ", dst-port = " + destinationPort
+                + ", ID = " + referenceNumber + ", segment# = " + segment + "/" + totalSegments);
+
+        byte[][] pdus = null;
+        Cursor cursor = null;
+        try {
+            cursor = mResolver.query(mRawUri, RAW_PROJECTION, where.toString(), whereArgs, null);
+            int cursorCount = cursor.getCount();
+            if (cursorCount != totalSegments - 1) {
+                // We don't have all the parts yet, store this one away
+                ContentValues values = new ContentValues();
+                values.put("date", new Long(0));
+                values.put("pdu", HexDump.toHexString(pdu, index, pdu.length - index));
+                values.put("address", address);
+                values.put("reference_number", referenceNumber);
+                values.put("count", totalSegments);
+                values.put("sequence", segment);
+                values.put("destination_port", destinationPort);
+
+                mResolver.insert(mRawUri, values);
+
+                return;
+            }
+
+            // All the parts are in place, deal with them
+            int pduColumn = cursor.getColumnIndex("pdu");
+            int sequenceColumn = cursor.getColumnIndex("sequence");
+
+            pdus = new byte[totalSegments][];
+            for (int i = 0; i < cursorCount; i++) {
+                cursor.moveToNext();
+                int cursorSequence = (int)cursor.getLong(sequenceColumn);
+                pdus[cursorSequence] = HexDump.hexStringToByteArray(
+                        cursor.getString(pduColumn));
+            }
+            // The last part will be added later
+
+            // Remove the parts from the database
+            mResolver.delete(mRawUri, where.toString(), whereArgs);
+        } catch (SQLException e) {
+            Log.e(TAG, "Can't access multipart SMS database", e);
+            return;  // TODO: NACK the message or something, don't just discard.
+        } finally {
+            if (cursor != null) cursor.close();
+        }
+
+        // Build up the data stream
+        ByteArrayOutputStream output = new ByteArrayOutputStream();
+        for (int i = 0; i < totalSegments-1; i++) {
+            // reassemble the (WSP-)pdu
+            output.write(pdus[i], 0, pdus[i].length);
+        }
+
+        // This one isn't in the DB, so add it
+        output.write(pdu, index, pdu.length - index);
+
+        byte[] datagram = output.toByteArray();
+        // Dispatch the PDU to applications
+        switch (destinationPort) {
+        case SmsHeader.PORT_WAP_PUSH:
+            // Handle the PUSH
+            mWapPush.dispatchWapPdu(datagram);
+            break;
+
+        default:{
+            pdus = new byte[1][];
+            pdus[0] = datagram;
+            // The messages were sent to any other WAP port
+            dispatchPortAddressedPdus(pdus, destinationPort);
+            break;
+        }
+        }
+    }
+
+    /** {@inheritDoc} */
+    protected void sendMultipartText(String destinationAddress, String scAddress,
+            ArrayList<String> parts, ArrayList<PendingIntent> sentIntents,
+            ArrayList<PendingIntent> deliveryIntents) {
+
+        int ref = ++sConcatenatedRef & 0xff;
+
+        for (int i = 0, count = parts.size(); i < count; i++) {
+            // build SmsHeader data
+            byte[] data = new byte[5];
+            data[0] = (byte) SmsHeader.CONCATENATED_8_BIT_REFERENCE;
+            data[1] = (byte) 3;   // 3 bytes follow
+            data[2] = (byte) ref;   // reference #, unique per message
+            data[3] = (byte) count; // total part count
+            data[4] = (byte) (i + 1);  // 1-based sequence
+
+            PendingIntent sentIntent = null;
+            PendingIntent deliveryIntent = null;
+
+            if (sentIntents != null && sentIntents.size() > i) {
+                sentIntent = sentIntents.get(i);
+            }
+            if (deliveryIntents != null && deliveryIntents.size() > i) {
+                deliveryIntent = deliveryIntents.get(i);
+            }
+
+            SmsMessage.SubmitPdu pdus = SmsMessage.getSubmitPdu(scAddress, destinationAddress,
+                    parts.get(i), deliveryIntent != null, data);
+
+            sendRawPdu(pdus.encodedScAddress, pdus.encodedMessage, sentIntent, deliveryIntent);
+        }
+    }
+
+    protected void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent,
+            PendingIntent deliveryIntent) {
+        super.sendRawPdu(smsc, pdu, sentIntent, deliveryIntent);
+    }
+
+    /** {@inheritDoc} */
+    protected void sendSms(SmsTracker tracker) {
+        HashMap map = tracker.mData;
+
+        byte smsc[] = (byte[]) map.get("smsc");
+        byte pdu[] = (byte[]) map.get("pdu");
+
+        Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);
+
+        mCm.sendCdmaSms(pdu, reply);
+    }
+
+     /** {@inheritDoc} */
+    protected void sendMultipartSms (SmsTracker tracker) {
+        Log.d(TAG, "TODO: CdmaSMSDispatcher.sendMultipartSms not implemented");
+    }
+
+    /** {@inheritDoc} */
+    protected void acknowledgeLastIncomingSms(boolean success, Message response){
+        // FIXME unit test leaves cm == null. this should change
+        if (mCm != null) {
+            mCm.acknowledgeLastIncomingCdmaSms(success, response);
+        }
+    }
+
+    /** {@inheritDoc} */
+    protected void activateCellBroadcastSms(int activate, Message response) {
+        mCm.activateCdmaBroadcastSms(activate, response);
+    }
+
+    /** {@inheritDoc} */
+    protected void getCellBroadcastSmsConfig(Message response) {
+        mCm.getCdmaBroadcastConfig(response);
+    }
+
+    /** {@inheritDoc} */
+    protected void setCellBroadcastConfig(int[] configValuesArray, Message response) {
+        mCm.setCdmaBroadcastConfig(configValuesArray, response);
+    }
+
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
new file mode 100644
index 0000000..ca40e76
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -0,0 +1,1016 @@
+/*
+ * Copyright (C) 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.
+ * 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.internal.telephony.cdma;
+
+import android.app.AlarmManager;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.database.ContentObserver;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Registrant;
+import android.os.RegistrantList;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.provider.Checkin;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
+import android.provider.Telephony.Intents;
+import android.telephony.ServiceState;
+import android.telephony.cdma.CdmaCellLocation;
+import android.text.TextUtils;
+import android.util.EventLog;
+import android.util.Log;
+import android.util.TimeUtils;
+
+import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.DataConnectionTracker;
+// pretty sure importing stuff from GSM is bad:
+import com.android.internal.telephony.gsm.MccTable;
+import com.android.internal.telephony.PhoneProxy;
+import com.android.internal.telephony.ServiceStateTracker;
+import com.android.internal.telephony.TelephonyEventLog;
+import com.android.internal.telephony.TelephonyIntents;
+
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ALPHA;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISMANUAL;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISROAMING;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_NUMERIC;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.TimeZone;
+
+/**
+ * {@hide}
+ */
+final class CdmaServiceStateTracker extends ServiceStateTracker {
+    //***** Instance Variables
+    CDMAPhone phone;
+    CdmaCellLocation cellLoc;
+    CdmaCellLocation newCellLoc;
+
+    int rssi = 99;  // signal strength 0-31, 99=unknown
+    // That's "received signal strength indication" fyi
+
+    /**
+     *  The access technology currently in use: DATA_ACCESS_
+     */
+    private int networkType = 0;
+    private int newNetworkType = 0;
+
+    private boolean mCdmaRoaming = false;
+
+    private int cdmaDataConnectionState = -1;//Initial we assume no data connection
+    private int newCdmaDataConnectionState = -1;//Initial we assume no data connection
+    private int mRegistrationState = -1;
+    private RegistrantList cdmaDataConnectionAttachedRegistrants = new RegistrantList();
+    private RegistrantList cdmaDataConnectionDetachedRegistrants = new RegistrantList();
+
+    private boolean mGotCountryCode = false;
+
+    // We can't register for SIM_RECORDS_LOADED immediately because the
+    // SIMRecords object may not be instantiated yet.
+    private boolean mNeedToRegForRuimLoaded;
+
+    // Keep track of SPN display rules, so we only broadcast intent if something changes.
+    private String curSpn = null;
+    private String curPlmn = null;
+    private int curSpnRule = 0;
+
+    //***** Constants
+    static final String LOG_TAG = "CDMA";
+    static final String TMUK = "23430";
+
+    private ContentResolver cr;
+
+    private ContentObserver mAutoTimeObserver = new ContentObserver(new Handler()) {
+        @Override
+        public void onChange(boolean selfChange) {
+            Log.i("CdmaServiceStateTracker", "Auto time state called ...");
+            //NOTE in CDMA NITZ is not used
+        }
+    };
+
+
+    //***** Constructors
+
+    public CdmaServiceStateTracker(CDMAPhone phone) {
+        super();
+
+        this.phone = phone;
+        cm = phone.mCM;
+        ss = new ServiceState();
+        newSS = new ServiceState();
+        cellLoc = new CdmaCellLocation();
+        newCellLoc = new CdmaCellLocation();
+
+        cm.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
+        cm.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null);
+
+        cm.registerForNetworkStateChanged(this, EVENT_NETWORK_STATE_CHANGED_CDMA, null);
+        cm.setOnSignalStrengthUpdate(this, EVENT_SIGNAL_STRENGTH_UPDATE, null);
+
+        cm.registerForRUIMReady(this, EVENT_RUIM_READY, null);
+
+        phone.registerForNvLoaded(this, EVENT_NV_LOADED,null);
+
+        // system setting property AIRPLANE_MODE_ON is set in Settings.
+        int airplaneMode = Settings.System.getInt(
+                phone.getContext().getContentResolver(),
+                Settings.System.AIRPLANE_MODE_ON, 0);
+        mDesiredPowerState = ! (airplaneMode > 0);
+
+        cr = phone.getContext().getContentResolver();
+        cr.registerContentObserver(
+                Settings.System.getUriFor(Settings.System.AUTO_TIME), true,
+                mAutoTimeObserver);
+        setRssiDefaultValues();
+
+        mNeedToRegForRuimLoaded = true;
+    }
+
+    public void dispose() {
+        //Unregister for all events
+        cm.unregisterForAvailable(this);
+        cm.unregisterForRadioStateChanged(this);
+        cm.unregisterForNetworkStateChanged(this);
+        cm.unregisterForRUIMReady(this);
+        phone.unregisterForNvLoaded(this);
+        phone.mRuimRecords.unregisterForRecordsLoaded(this);
+        cm.unSetOnSignalStrengthUpdate(this);
+        cr.unregisterContentObserver(this.mAutoTimeObserver);
+    }
+
+    protected void finalize() {
+        if(DBG) Log.d(LOG_TAG, "CdmaServiceStateTracker finalized");
+    }
+
+    void registerForNetworkAttach(Handler h, int what, Object obj) {
+        Registrant r = new Registrant(h, what, obj);
+        networkAttachedRegistrants.add(r);
+
+        if (ss.getState() == ServiceState.STATE_IN_SERVICE) {
+            r.notifyRegistrant();
+        }
+    }
+
+    void unregisterForNetworkAttach(Handler h) {
+        networkAttachedRegistrants.remove(h);
+    }
+
+    /**
+     * Registration point for transition into Data attached.
+     * @param h handler to notify
+     * @param what what code of message when delivered
+     * @param obj placed in Message.obj
+     */
+    /*protected*/ void
+    registerForCdmaDataConnectionAttached(Handler h, int what, Object obj) {
+        Registrant r = new Registrant(h, what, obj);
+        cdmaDataConnectionAttachedRegistrants.add(r);
+
+        if (cdmaDataConnectionState == ServiceState.RADIO_TECHNOLOGY_1xRTT
+           || cdmaDataConnectionState == ServiceState.RADIO_TECHNOLOGY_EVDO_0
+           || cdmaDataConnectionState == ServiceState.RADIO_TECHNOLOGY_EVDO_A) {
+            r.notifyRegistrant();
+        }
+    }
+    void unregisterForCdmaDataConnectionAttached(Handler h) {
+        cdmaDataConnectionAttachedRegistrants.remove(h);
+    }
+
+    /**
+     * Registration point for transition into Data detached.
+     * @param h handler to notify
+     * @param what what code of message when delivered
+     * @param obj placed in Message.obj
+     */
+    /*protected*/  void
+    registerForCdmaDataConnectionDetached(Handler h, int what, Object obj) {
+        Registrant r = new Registrant(h, what, obj);
+        cdmaDataConnectionDetachedRegistrants.add(r);
+
+        if (cdmaDataConnectionState != ServiceState.RADIO_TECHNOLOGY_1xRTT
+           && cdmaDataConnectionState != ServiceState.RADIO_TECHNOLOGY_EVDO_0
+           && cdmaDataConnectionState != ServiceState.RADIO_TECHNOLOGY_EVDO_A) {
+            r.notifyRegistrant();
+        }
+    }
+    void unregisterForCdmaDataConnectionDetached(Handler h) {
+        cdmaDataConnectionDetachedRegistrants.remove(h);
+    }
+
+    //***** Called from CDMAPhone
+    public void
+    getLacAndCid(Message onComplete) {
+        cm.getRegistrationState(obtainMessage(
+                EVENT_GET_LOC_DONE_CDMA, onComplete));
+    }
+
+
+    //***** Overridden from ServiceStateTracker
+    public void
+    handleMessage (Message msg) {
+        AsyncResult ar;
+        int[] ints;
+        String[] strings;
+
+        switch (msg.what) {
+        case EVENT_RADIO_AVAILABLE:
+            //this is unnecessary
+            //setPowerStateToDesired();
+            break;
+
+        case EVENT_RUIM_READY:
+            // The RUIM is now ready i.e if it was locked
+            // it has been unlocked. At this stage, the radio is already
+            // powered on.
+            if (mNeedToRegForRuimLoaded) {
+                phone.mRuimRecords.registerForRecordsLoaded(this,
+                        EVENT_RUIM_RECORDS_LOADED, null);
+                mNeedToRegForRuimLoaded = false;
+            }
+            // restore the previous network selection.
+            phone.restoreSavedNetworkSelection(null);
+            pollState();
+            // Signal strength polling stops when radio is off
+            queueNextSignalStrengthPoll();
+            break;
+
+        case EVENT_RADIO_STATE_CHANGED:
+            // This will do nothing in the radio not
+            // available case
+            setPowerStateToDesired();
+            pollState();
+            break;
+
+        case EVENT_NETWORK_STATE_CHANGED_CDMA:
+            pollState();
+            break;
+
+        case EVENT_GET_SIGNAL_STRENGTH:
+            // This callback is called when signal strength is polled
+            // all by itself
+
+            if (!(cm.getRadioState().isOn()) || (cm.getRadioState().isGsm())) {
+                // Polling will continue when radio turns back on
+                return;
+            }
+            ar = (AsyncResult) msg.obj;
+            onSignalStrengthResult(ar);
+            queueNextSignalStrengthPoll();
+
+            break;
+
+        case EVENT_GET_LOC_DONE_CDMA:
+            ar = (AsyncResult) msg.obj;
+
+            if (ar.exception == null) {
+                String states[] = (String[])ar.result;
+                int baseStationId = -1;
+                int baseStationLongitude = -1;
+                int baseStationLatitude = -1;
+
+                int baseStationData[] = {
+                        -1, // baseStationId
+                        -1, // baseStationLatitude
+                        -1  // baseStationLongitude
+                };
+
+                if (states.length == 3) {
+                    for(int i = 0; i < states.length; i++) {
+                        try {
+                            if (states[i] != null && states[i].length() > 0) {
+                                baseStationData[i] = Integer.parseInt(states[i], 16);
+                            }
+                        } catch (NumberFormatException ex) {
+                            Log.w(LOG_TAG, "error parsing cell location data: " + ex);
+                        }
+                    }
+                }
+
+                // only update if cell location really changed
+                if (cellLoc.getBaseStationId() != baseStationData[0]
+                        || cellLoc.getBaseStationLatitude() != baseStationData[1]
+                        || cellLoc.getBaseStationLongitude() != baseStationData[2]) {
+                    cellLoc.setCellLocationData(baseStationData[0],
+                                                baseStationData[1],
+                                                baseStationData[2]);
+                   phone.notifyLocationChanged();
+                }
+            }
+
+            if (ar.userObj != null) {
+                AsyncResult.forMessage(((Message) ar.userObj)).exception
+                = ar.exception;
+                ((Message) ar.userObj).sendToTarget();
+            }
+            break;
+
+        case EVENT_POLL_STATE_NETWORK_SELECTION_MODE_CDMA: //Fall through
+        case EVENT_POLL_STATE_REGISTRATION_CDMA: //Fall through
+        case EVENT_POLL_STATE_OPERATOR_CDMA:
+            ar = (AsyncResult) msg.obj;
+            handlePollStateResult(msg.what, ar);
+            break;
+
+        case EVENT_POLL_SIGNAL_STRENGTH:
+            // Just poll signal strength...not part of pollState()
+
+            cm.getSignalStrength(obtainMessage(EVENT_GET_SIGNAL_STRENGTH));
+            break;
+
+        case EVENT_SIGNAL_STRENGTH_UPDATE:
+            // This is a notification from
+            // CommandsInterface.setOnSignalStrengthUpdate
+
+            ar = (AsyncResult) msg.obj;
+
+            // The radio is telling us about signal strength changes
+            // we don't have to ask it
+            dontPollSignalStrength = true;
+
+            onSignalStrengthResult(ar);
+            break;
+
+        case EVENT_RUIM_RECORDS_LOADED:
+        case EVENT_NV_LOADED:
+            updateSpnDisplay();
+            break;
+
+        case EVENT_LOCATION_UPDATES_ENABLED:
+            ar = (AsyncResult) msg.obj;
+
+            if (ar.exception == null) {
+                getLacAndCid(null);
+            }
+            break;
+
+        default:
+            Log.e(LOG_TAG, "Unhandled message with number: " + msg.what);
+        break;
+        }
+    }
+
+    //***** Private Instance Methods
+
+    protected void setPowerStateToDesired()
+    {
+        // If we want it on and it's off, turn it on
+        if (mDesiredPowerState
+            && cm.getRadioState() == CommandsInterface.RadioState.RADIO_OFF) {
+            cm.setRadioPower(true, null);
+        } else if (!mDesiredPowerState && cm.getRadioState().isOn()) {
+            DataConnectionTracker dcTracker = phone.mDataConnection;
+            if (! dcTracker.isDataConnectionAsDesired()) {
+
+                EventLog.List val = new EventLog.List(
+                        dcTracker.getStateInString(),
+                        (dcTracker.getAnyDataEnabled() ? 1 : 0) );
+                EventLog.writeEvent(TelephonyEventLog.EVENT_DATA_STATE_RADIO_OFF, val);
+            }
+            dcTracker.cleanConnectionBeforeRadioOff();
+            
+            // poll data state up to 15 times, with a 100ms delay
+            // totaling 1.5 sec. Normal data disable action will finish in 100ms.
+            for (int i = 0; i < MAX_NUM_DATA_STATE_READS; i++) {
+                if (dcTracker.getState() != DataConnectionTracker.State.CONNECTED 
+                        && dcTracker.getState() != DataConnectionTracker.State.DISCONNECTING) {
+                    Log.d(LOG_TAG, "Data shutdown complete.");
+                    break;
+                }
+                SystemClock.sleep(DATA_STATE_POLL_SLEEP_MS);
+            }
+            // If it's on and available and we want it off..
+            cm.setRadioPower(false, null);
+        } // Otherwise, we're in the desired state
+    }
+
+    protected void updateSpnDisplay() {
+
+        // TODO Check this method again, because it is not sure at the moment how
+        // the RUIM handles the SIM stuff
+
+        //int rule = phone.mRuimRecords.getDisplayRule(ss.getOperatorNumeric());
+        String spn = null; //phone.mRuimRecords.getServiceProviderName();
+        String plmn = ss.getOperatorAlphaLong();
+
+        if (!TextUtils.equals(this.curPlmn, plmn)) {
+            //TODO  (rule & SIMRecords.SPN_RULE_SHOW_SPN) == SIMRecords.SPN_RULE_SHOW_SPN;
+            boolean showSpn = false;
+            //TODO  (rule & SIMRecords.SPN_RULE_SHOW_PLMN) == SIMRecords.SPN_RULE_SHOW_PLMN;
+            boolean showPlmn = true;
+            Intent intent = new Intent(Intents.SPN_STRINGS_UPDATED_ACTION);
+            intent.putExtra(Intents.EXTRA_SHOW_SPN, showSpn);
+            intent.putExtra(Intents.EXTRA_SPN, spn);
+            intent.putExtra(Intents.EXTRA_SHOW_PLMN, showPlmn);
+            intent.putExtra(Intents.EXTRA_PLMN, plmn);
+            phone.getContext().sendStickyBroadcast(intent);
+        }
+
+        //curSpnRule = rule;
+        //curSpn = spn;
+        this.curPlmn = plmn;
+    }
+
+    /**
+     * Handle the result of one of the pollState()-related requests
+     */
+
+    protected void
+    handlePollStateResult (int what, AsyncResult ar) {
+        int ints[];
+        String states[];
+
+        // Ignore stale requests from last poll
+        if (ar.userObj != pollingContext) return;
+
+        if (ar.exception != null) {
+            CommandException.Error err=null;
+
+            if (ar.exception instanceof CommandException) {
+                err = ((CommandException)(ar.exception)).getCommandError();
+            }
+
+            if (err == CommandException.Error.RADIO_NOT_AVAILABLE) {
+                // Radio has crashed or turned off
+                cancelPollState();
+                return;
+            }
+
+            if (!cm.getRadioState().isOn()) {
+                // Radio has crashed or turned off
+                cancelPollState();
+                return;
+            }
+
+            if (err != CommandException.Error.OP_NOT_ALLOWED_BEFORE_REG_NW &&
+                    err != CommandException.Error.OP_NOT_ALLOWED_BEFORE_REG_NW) {
+                Log.e(LOG_TAG,
+                        "RIL implementation has returned an error where it must succeed",
+                        ar.exception);
+            }
+        } else try {
+            switch (what) {
+            case EVENT_POLL_STATE_REGISTRATION_CDMA:
+                //offset, because we don't want the first 3 values in the int-array
+                final int offset = 3;
+                states = (String[])ar.result;
+
+                int responseValuesRegistrationState[] = {
+                        -1, //[0] radioTechnology
+                        -1, //[1] baseStationId
+                        -1, //[2] baseStationLatitude
+                        -1, //[3] baseStationLongitude
+                         0, //[4] cssIndicator; init with 0, because it is treated as a boolean
+                        -1, //[5] systemId
+                        -1  //[6] networkId
+                };
+
+                if (states.length > 0) {
+                    try {
+                        this.mRegistrationState = Integer.parseInt(states[0]);
+                        if (states.length == 10) {
+                            for(int i = 0; i < states.length - offset; i++) {
+                                if (states[i + offset] != null
+                                  && states[i + offset].length() > 0) {
+                                    try {
+                                        responseValuesRegistrationState[i] =
+                                           Integer.parseInt(states[i + offset], 16);
+                                    }
+                                    catch(NumberFormatException ex) {
+                                        Log.w(LOG_TAG, "Warning! There is an unexpected value"
+                                            + "returned as response from " 
+                                            + "RIL_REQUEST_REGISTRATION_STATE.");
+                                    }
+                                }
+                            }
+                        }
+                        else {
+                            Log.e(LOG_TAG, "Too less parameters returned from"
+                                + " RIL_REQUEST_REGISTRATION_STATE");
+                        }
+                    } catch (NumberFormatException ex) {
+                        Log.w(LOG_TAG, "error parsing RegistrationState: " + ex);
+                    }
+                }
+
+                mCdmaRoaming = regCodeIsRoaming(this.mRegistrationState);
+                this.newCdmaDataConnectionState =
+                    radioTechnologyToServiceState(responseValuesRegistrationState[0]);
+                newSS.setState (regCodeToServiceState(this.mRegistrationState));
+                newSS.setRadioTechnology(responseValuesRegistrationState[0]);
+                newSS.setCssIndicator(responseValuesRegistrationState[4]);
+                newSS.setSystemAndNetworkId(responseValuesRegistrationState[5],
+                    responseValuesRegistrationState[6]);
+
+                newNetworkType = responseValuesRegistrationState[0];
+
+                // values are -1 if not available
+                newCellLoc.setCellLocationData(responseValuesRegistrationState[1],
+                                               responseValuesRegistrationState[2],
+                                               responseValuesRegistrationState[3]);
+                break;
+
+            case EVENT_POLL_STATE_OPERATOR_CDMA:
+                String opNames[] = (String[])ar.result;
+
+                if (opNames != null && opNames.length >= 4) {
+                    newSS.setOperatorName (opNames[0], opNames[1], opNames[2]);
+                }
+                break;
+
+            case EVENT_POLL_STATE_NETWORK_SELECTION_MODE_CDMA:
+                ints = (int[])ar.result;
+                newSS.setIsManualSelection(ints[0] == 1);
+                break;
+            default:
+                Log.e(LOG_TAG, "RIL response handle in wrong phone!"
+                    + " Expected CDMA RIL request and get GSM RIL request.");
+            break;
+            }
+
+        } catch (RuntimeException ex) {
+            Log.e(LOG_TAG, "Exception while polling service state. "
+                    + "Probably malformed RIL response.", ex);
+        }
+
+        pollingContext[0]--;
+
+        if (pollingContext[0] == 0) {
+            newSS.setRoaming(isRoamingBetweenOperators(mCdmaRoaming, newSS));
+
+            switch(this.mRegistrationState) {
+            case ServiceState.REGISTRATION_STATE_HOME_NETWORK:
+                newSS.setExtendedCdmaRoaming(ServiceState.REGISTRATION_STATE_HOME_NETWORK);
+                break;
+            case ServiceState.REGISTRATION_STATE_ROAMING:
+                newSS.setExtendedCdmaRoaming(ServiceState.REGISTRATION_STATE_ROAMING);
+                break;
+            case ServiceState.REGISTRATION_STATE_ROAMING_AFFILIATE:
+                newSS.setExtendedCdmaRoaming(ServiceState.REGISTRATION_STATE_ROAMING_AFFILIATE);
+                break;
+            default:
+                Log.w(LOG_TAG, "Received a different registration state, "
+                    + "but don't changed the extended cdma roaming mode.");
+            }
+            pollStateDone();
+        }
+
+    }
+
+    private void setRssiDefaultValues() {
+        rssi = 99;
+    }
+
+    /**
+     * A complete "service state" from our perspective is
+     * composed of a handful of separate requests to the radio.
+     *
+     * We make all of these requests at once, but then abandon them
+     * and start over again if the radio notifies us that some
+     * event has changed
+     */
+
+    private void
+    pollState() {
+        pollingContext = new int[1];
+        pollingContext[0] = 0;
+
+        switch (cm.getRadioState()) {
+        case RADIO_UNAVAILABLE:
+            newSS.setStateOutOfService();
+            newCellLoc.setStateInvalid();
+            setRssiDefaultValues();
+            mGotCountryCode = false;
+
+            pollStateDone();
+            break;
+
+        case RADIO_OFF:
+            newSS.setStateOff();
+            newCellLoc.setStateInvalid();
+            setRssiDefaultValues();
+            mGotCountryCode = false;
+
+            pollStateDone();
+            break;
+
+        case SIM_NOT_READY:
+        case SIM_LOCKED_OR_ABSENT:
+        case SIM_READY:
+            log("Radio Technology Change ongoing, setting SS to off");
+            newSS.setStateOff();
+            newCellLoc.setStateInvalid();
+            setRssiDefaultValues();
+            mGotCountryCode = false;
+
+            pollStateDone();
+            break;
+
+        default:
+            // Issue all poll-related commands at once
+            // then count down the responses, which
+            // are allowed to arrive out-of-order
+
+            pollingContext[0]++;
+        //RIL_REQUEST_OPERATOR is necessary for CDMA
+        cm.getOperator(
+                obtainMessage(EVENT_POLL_STATE_OPERATOR_CDMA, pollingContext));
+
+        pollingContext[0]++;
+        //RIL_REQUEST_REGISTRATION_STATE is necessary for CDMA
+        cm.getRegistrationState(
+                obtainMessage(EVENT_POLL_STATE_REGISTRATION_CDMA, pollingContext));
+
+        pollingContext[0]++;
+        //RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE necessary for CDMA
+        cm.getNetworkSelectionMode(
+                obtainMessage(EVENT_POLL_STATE_NETWORK_SELECTION_MODE_CDMA, pollingContext));
+        break;
+        }
+    }
+
+    private static String networkTypeToString(int type) {
+        String ret = "unknown";
+
+        switch (type) {
+        case DATA_ACCESS_CDMA_IS95A:
+        case DATA_ACCESS_CDMA_IS95B:
+            ret = "CDMA";
+            break;
+        case DATA_ACCESS_CDMA_1xRTT:
+            ret = "CDMA - 1xRTT";
+            break;
+        case DATA_ACCESS_CDMA_EvDo_0:
+            ret = "CDMA - EvDo rev. 0";
+            break;
+        case DATA_ACCESS_CDMA_EvDo_A:
+            ret = "CDMA - EvDo rev. A";
+            break;
+        default:
+            if (DBG) {
+                Log.e(LOG_TAG, "Wrong network. Can not return a string.");
+            }
+        break;
+        }
+
+        return ret;
+    }
+
+    private void
+    pollStateDone() {
+        if (DBG) {
+            Log.d(LOG_TAG, "Poll ServiceState done: " +
+                    " oldSS=[" + ss );
+            Log.d(LOG_TAG, "Poll ServiceState done: " +
+                    " newSS=[" + newSS);
+        }
+
+        boolean hasRegistered =
+            ss.getState() != ServiceState.STATE_IN_SERVICE
+            && newSS.getState() == ServiceState.STATE_IN_SERVICE;
+
+        boolean hasDeregistered =
+            ss.getState() == ServiceState.STATE_IN_SERVICE
+            && newSS.getState() != ServiceState.STATE_IN_SERVICE;
+
+        boolean hasCdmaDataConnectionAttached =
+            (this.cdmaDataConnectionState != ServiceState.RADIO_TECHNOLOGY_1xRTT
+                    && this.cdmaDataConnectionState != ServiceState.RADIO_TECHNOLOGY_EVDO_0
+                    && this.cdmaDataConnectionState != ServiceState.RADIO_TECHNOLOGY_EVDO_A)
+                    && (this.newCdmaDataConnectionState == ServiceState.RADIO_TECHNOLOGY_1xRTT
+                    || this.newCdmaDataConnectionState == ServiceState.RADIO_TECHNOLOGY_EVDO_0
+                    || this.newCdmaDataConnectionState == ServiceState.RADIO_TECHNOLOGY_EVDO_A);
+
+        boolean hasCdmaDataConnectionDetached =
+            (this.cdmaDataConnectionState == ServiceState.RADIO_TECHNOLOGY_1xRTT
+                    || this.cdmaDataConnectionState == ServiceState.RADIO_TECHNOLOGY_EVDO_0
+                    || this.cdmaDataConnectionState == ServiceState.RADIO_TECHNOLOGY_EVDO_A)
+                    && (this.newCdmaDataConnectionState != ServiceState.RADIO_TECHNOLOGY_1xRTT
+                    && this.newCdmaDataConnectionState != ServiceState.RADIO_TECHNOLOGY_EVDO_0
+                    && this.newCdmaDataConnectionState != ServiceState.RADIO_TECHNOLOGY_EVDO_A);
+
+        boolean hasCdmaDataConnectionChanged =
+                       cdmaDataConnectionState != newCdmaDataConnectionState;
+
+        boolean hasNetworkTypeChanged = networkType != newNetworkType;
+
+        boolean hasChanged = !newSS.equals(ss);
+
+        boolean hasRoamingOn = !ss.getRoaming() && newSS.getRoaming();
+
+        boolean hasRoamingOff = ss.getRoaming() && !newSS.getRoaming();
+
+        boolean hasLocationChanged = !newCellLoc.equals(cellLoc);
+
+        ServiceState tss;
+        tss = ss;
+        ss = newSS;
+        newSS = tss;
+        // clean slate for next time
+        newSS.setStateOutOfService();
+
+        CdmaCellLocation tcl = cellLoc;
+        cellLoc = newCellLoc;
+        newCellLoc = tcl;
+
+        cdmaDataConnectionState = newCdmaDataConnectionState;
+        networkType = newNetworkType;
+
+        newSS.setStateOutOfService(); // clean slate for next time
+
+        if (hasNetworkTypeChanged) {
+            phone.setSystemProperty(PROPERTY_DATA_NETWORK_TYPE,
+                    networkTypeToString(networkType));
+        }
+
+        if (hasRegistered) {
+            Checkin.updateStats(phone.getContext().getContentResolver(),
+                    Checkin.Stats.Tag.PHONE_CDMA_REGISTERED, 1, 0.0);
+            networkAttachedRegistrants.notifyRegistrants();
+        }
+
+        if (hasChanged) {
+            String operatorNumeric;
+
+            phone.setSystemProperty(PROPERTY_OPERATOR_ALPHA,
+                    ss.getOperatorAlphaLong());
+
+            operatorNumeric = ss.getOperatorNumeric();
+            phone.setSystemProperty(PROPERTY_OPERATOR_NUMERIC, operatorNumeric);
+
+            if (operatorNumeric == null) {
+                phone.setSystemProperty(PROPERTY_OPERATOR_ISO_COUNTRY, "");
+            } else {
+                String iso = "";
+                try{
+                    iso = MccTable.countryCodeForMcc(Integer.parseInt(
+                            operatorNumeric.substring(0,3)));
+                } catch ( NumberFormatException ex){
+                    Log.w(LOG_TAG, "countryCodeForMcc error" + ex);
+                } catch ( StringIndexOutOfBoundsException ex) {
+                    Log.w(LOG_TAG, "countryCodeForMcc error" + ex);
+                }
+
+                phone.setSystemProperty(PROPERTY_OPERATOR_ISO_COUNTRY, iso);
+                mGotCountryCode = true;
+            }
+
+            phone.setSystemProperty(PROPERTY_OPERATOR_ISROAMING,
+                    ss.getRoaming() ? "true" : "false");
+            phone.setSystemProperty(PROPERTY_OPERATOR_ISMANUAL,
+                    ss.getIsManualSelection() ? "true" : "false");
+
+            updateSpnDisplay();
+            phone.notifyServiceStateChanged(ss);
+        }
+
+        if (hasCdmaDataConnectionAttached) {
+            cdmaDataConnectionAttachedRegistrants.notifyRegistrants();
+        }
+
+        if (hasCdmaDataConnectionDetached) {
+            cdmaDataConnectionDetachedRegistrants.notifyRegistrants();
+        }
+
+        if (hasCdmaDataConnectionChanged) {
+            phone.notifyDataConnection(null);
+        }
+
+        if (hasRoamingOn) {
+            roamingOnRegistrants.notifyRegistrants();
+        }
+
+        if (hasRoamingOff) {
+            roamingOffRegistrants.notifyRegistrants();
+        }
+
+        if (hasLocationChanged) {
+            phone.notifyLocationChanged();
+        }
+    }
+
+    /**
+     * Returns a TimeZone object based only on parameters from the NITZ string.
+     */
+    private TimeZone getNitzTimeZone(int offset, boolean dst, long when) {
+        TimeZone guess = findTimeZone(offset, dst, when);
+        if (guess == null) {
+            // Couldn't find a proper timezone.  Perhaps the DST data is wrong.
+            guess = findTimeZone(offset, !dst, when);
+        }
+        if (DBG) {
+            Log.d(LOG_TAG, "getNitzTimeZone returning "
+                    + (guess == null ? guess : guess.getID()));
+        }
+        return guess;
+    }
+
+    private TimeZone findTimeZone(int offset, boolean dst, long when) {
+        int rawOffset = offset;
+        if (dst) {
+            rawOffset -= 3600000;
+        }
+        String[] zones = TimeZone.getAvailableIDs(rawOffset);
+        TimeZone guess = null;
+        Date d = new Date(when);
+        for (String zone : zones) {
+            TimeZone tz = TimeZone.getTimeZone(zone);
+            if (tz.getOffset(when) == offset &&
+                    tz.inDaylightTime(d) == dst) {
+                guess = tz;
+                break;
+            }
+        }
+
+        return guess;
+    }
+
+    private void
+    queueNextSignalStrengthPoll() {
+        if (dontPollSignalStrength || (cm.getRadioState().isGsm())) {
+            // The radio is telling us about signal strength changes
+            // we don't have to ask it
+            return;
+        }
+
+        Message msg;
+
+        msg = obtainMessage();
+        msg.what = EVENT_POLL_SIGNAL_STRENGTH;
+
+        // TODO Done't poll signal strength if screen is off
+        sendMessageDelayed(msg, POLL_PERIOD_MILLIS);
+    }
+
+    /**
+     *  send signal-strength-changed notification if rssi changed
+     *  Called both for solicited and unsolicited signal stength updates
+     */
+    private void
+    onSignalStrengthResult(AsyncResult ar) {
+        int oldRSSI = rssi;
+
+        if (ar.exception != null) {
+            // 99 = unknown
+            // most likely radio is resetting/disconnected
+            rssi = 99;
+        } else {
+            int[] ints = (int[])ar.result;
+
+            // bug 658816 seems to be a case where the result is 0-length
+            if (ints.length != 0) {
+                rssi = ints[0];
+            } else {
+                Log.e(LOG_TAG, "Bogus signal strength response");
+                rssi = 99;
+            }
+        }
+
+        if (rssi != oldRSSI) {
+            try { // This takes care of delayed EVENT_POLL_SIGNAL_STRENGTH (scheduled after
+                  // POLL_PERIOD_MILLIS) during Radio Technology Change)
+                phone.notifySignalStrength();
+           } catch (NullPointerException ex) {
+                log("onSignalStrengthResult() Phone already destroyed: " + ex 
+                        + "Signal Stranth not notified");
+           }
+        }
+    }
+
+
+    private int radioTechnologyToServiceState(int code) {
+        int retVal = ServiceState.RADIO_TECHNOLOGY_UNKNOWN;
+        switch(code) {
+        case 0:
+        case 1:
+        case 2:
+        case 3:
+        case 4:
+        case 5:
+            break;
+        case 6:
+            retVal = ServiceState.RADIO_TECHNOLOGY_1xRTT;
+            break;
+        case 7:
+            retVal = ServiceState.RADIO_TECHNOLOGY_EVDO_0;
+            break;
+        case 8:
+            retVal = ServiceState.RADIO_TECHNOLOGY_EVDO_A;
+            break;
+        default:
+            Log.e(LOG_TAG, "Wrong radioTechnology code.");
+        break;
+        }
+        return(retVal);
+    }
+
+    /** code is registration state 0-5 from TS 27.007 7.2 */
+    private int
+    regCodeToServiceState(int code) {
+        switch (code) {
+        case 0: // Not searching and not registered
+            return ServiceState.STATE_OUT_OF_SERVICE;
+        case 1:
+            return ServiceState.STATE_IN_SERVICE;
+        case 2: // 2 is "searching", fall through
+        case 3: // 3 is "registration denied", fall through
+        case 4: // 4 is "unknown" no vaild in current baseband
+            return ServiceState.STATE_OUT_OF_SERVICE;
+        case 5:// fall through
+        case 6:
+            // Registered and: roaming (5) or roaming affiliates (6)
+            return ServiceState.STATE_IN_SERVICE;
+
+        default:
+            Log.w(LOG_TAG, "unexpected service state " + code);
+        return ServiceState.STATE_OUT_OF_SERVICE;
+        }
+    }
+
+    /**
+     * @return The current CDMA data connection state. ServiceState.RADIO_TECHNOLOGY_1xRTT or
+     * ServiceState.RADIO_TECHNOLOGY_EVDO is the same as "attached" and
+     * ServiceState.RADIO_TECHNOLOGY_UNKNOWN is the same as detached.
+     */
+    /*package*/ int getCurrentCdmaDataConnectionState() {
+        return cdmaDataConnectionState;
+    }
+
+    /**
+     * code is registration state 0-5 from TS 27.007 7.2
+     * returns true if registered roam, false otherwise
+     */
+    private boolean
+    regCodeIsRoaming (int code) {
+        // 5 is  "in service -- roam"
+        return 5 == code;
+    }
+
+    /**
+     * Set roaming state when cdmaRoaming is true and ons is different from spn
+     * @param cdmaRoaming TS 27.007 7.2 CREG registered roaming
+     * @param s ServiceState hold current ons
+     * @return true for roaming state set
+     */
+    private
+    boolean isRoamingBetweenOperators(boolean cdmaRoaming, ServiceState s) {
+        String spn = SystemProperties.get(PROPERTY_ICC_OPERATOR_ALPHA, "empty");
+
+        String onsl = s.getOperatorAlphaLong();
+        String onss = s.getOperatorAlphaShort();
+
+        boolean equalsOnsl = onsl != null && spn.equals(onsl);
+        boolean equalsOnss = onss != null && spn.equals(onss);
+
+        return cdmaRoaming && !(equalsOnsl || equalsOnss);
+    }
+
+    private boolean getAutoTime() {
+        try {
+            return Settings.System.getInt(phone.getContext().getContentResolver(),
+                    Settings.System.AUTO_TIME) > 0;
+        } catch (SettingNotFoundException snfe) {
+            return true;
+        }
+    }
+
+    /**
+     * @return true if phone is camping on a technology
+     * that could support voice and data simultaneously.
+     */
+    boolean isConcurrentVoiceAndData() {
+
+        // Note: it needs to be confirmed which CDMA network types
+        // can support voice and data calls concurrently.
+        // For the time-being, the return value will be false.
+        return false;
+    }
+
+    protected void log(String s) {
+        Log.d(LOG_TAG, "[CdmaServiceStateTracker] " + s);
+    }
+
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/FeatureCode.java b/telephony/java/com/android/internal/telephony/cdma/FeatureCode.java
new file mode 100644
index 0000000..65b7336
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/FeatureCode.java
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony.cdma;
+
+import android.content.Context;
+import android.os.*;
+import android.util.Log;
+
+import com.android.internal.telephony.*;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ *
+ * {@hide}
+ *
+ */
+public final class FeatureCode  extends Handler implements MmiCode {
+    static final String LOG_TAG = "CDMA";
+
+    //***** Constants
+
+    // Call Forwarding
+    static final String FC_CF_ACTIVATE            = "72";
+    static final String FC_CF_DEACTIVATE          = "73";
+    static final String FC_CF_FORWARD_TO_NUMBER   = "56";
+
+    // Call Forwarding Busy Line
+    static final String FC_CFBL_ACTIVATE          = "90";
+    static final String FC_CFBL_DEACTIVATE        = "91";
+    static final String FC_CFBL_FORWARD_TO_NUMBER = "40";
+
+    // Call Forwarding Don't Answer
+    static final String FC_CFDA_ACTIVATE          = "92";
+    static final String FC_CFDA_DEACTIVATE        = "93";
+    static final String FC_CFDA_FORWARD_TO_NUMBER = "42";
+
+    // Cancel Call Waiting
+    static final String FC_CCW                    = "70";
+
+    // Usage Sensitive Three-way Calling
+    static final String FC_3WC                    = "71";
+
+    // Do Not Disturb
+    static final String FC_DND_ACTIVATE           = "78";
+    static final String FC_DND_DEACTIVATE         = "79";
+
+    // Who Called Me?
+    static final String FC_WHO                    = "51";
+
+    // Rejection of Undesired Annoying Calls
+    static final String FC_RUAC_ACTIVATE          = "60";
+    static final String FC_RUAC_DEACTIVATE        = "80";
+
+    // Calling Number Delivery
+    // Calling Number Identification Presentation
+    static final String FC_CNIP                   = "65";
+    // Calling Number Identification Restriction
+    static final String FC_CNIR                   = "85";
+
+
+    //***** Event Constants
+
+    static final int EVENT_SET_COMPLETE         = 1;
+    static final int EVENT_CDMA_FLASH_COMPLETED = 2;
+
+
+    //***** Instance Variables
+
+    CDMAPhone phone;
+    Context context;
+
+    String action;              // '*' in CDMA
+    String sc;                  // Service Code
+    String poundString;         // Entire Flash string
+    String dialingNumber;
+
+    /** Set to true in processCode, not at newFromDialString time */
+
+    State state = State.PENDING;
+    CharSequence message;
+
+    //***** Class Variables
+
+
+    // Flash Code Pattern
+
+    static Pattern sPatternSuppService = Pattern.compile(
+        "((\\*)(\\d{2,3})(#?)([^*#]*)?)(.*)");
+/*       1  2    3       4   5         6
+
+         1 = Full string up to and including #
+         2 = action
+         3 = service code
+         4 = separator
+         5 = dialing number
+*/
+
+    static final int MATCH_GROUP_POUND_STRING   = 1;
+    static final int MATCH_GROUP_ACTION_STRING  = 2;
+    static final int MATCH_GROUP_SERVICE_CODE   = 3;
+    static final int MATCH_GROUP_DIALING_NUMBER = 5;
+
+
+    //***** Public Class methods
+
+    /**
+     * Some dial strings in CDMA are defined to do non-call setup
+     * things, such as set supplementary service settings (eg, call
+     * forwarding). These are generally referred to as "Feature Codes".
+     * We look to see if the dial string contains a valid Feature code (potentially
+     * with a dial string at the end as well) and return info here.
+     *
+     * If the dial string contains no Feature code, we return an instance with
+     * only "dialingNumber" set
+     *
+     * Please see also S.R0006-000-A v2.0 "Wireless Features Description"
+     */
+
+    static FeatureCode newFromDialString(String dialString, CDMAPhone phone) {
+        Matcher m;
+        FeatureCode ret = null;
+
+        m = sPatternSuppService.matcher(dialString);
+
+        // Is this formatted like a standard supplementary service code?
+        if (m.matches()) {
+            ret = new FeatureCode(phone);
+            ret.poundString = makeEmptyNull(m.group(MATCH_GROUP_POUND_STRING));
+            ret.action = makeEmptyNull(m.group(MATCH_GROUP_ACTION_STRING));
+            ret.sc = makeEmptyNull(m.group(MATCH_GROUP_SERVICE_CODE));
+            ret.dialingNumber = makeEmptyNull(m.group(MATCH_GROUP_DIALING_NUMBER));
+        }
+
+        return ret;
+    }
+
+    //***** Private Class methods
+
+    /** make empty strings be null.
+     *  Java regexp returns empty strings for empty groups
+     */
+    private static String makeEmptyNull (String s) {
+        if (s != null && s.length() == 0) return null;
+
+        return s;
+    }
+
+    /** returns true of the string is empty or null */
+    private static boolean isEmptyOrNull(CharSequence s) {
+        return s == null || (s.length() == 0);
+    }
+
+    static boolean isServiceCodeCallForwarding(String sc) {
+        return sc != null &&
+                (sc.equals(FC_CF_ACTIVATE)
+                || sc.equals(FC_CF_DEACTIVATE) || sc.equals(FC_CF_FORWARD_TO_NUMBER)
+                || sc.equals(FC_CFBL_ACTIVATE) || sc.equals(FC_CFBL_DEACTIVATE)
+                || sc.equals(FC_CFBL_FORWARD_TO_NUMBER) || sc.equals(FC_CFDA_ACTIVATE)
+                || sc.equals(FC_CFDA_DEACTIVATE) || sc.equals(FC_CFDA_FORWARD_TO_NUMBER));
+    }
+
+    static boolean isServiceCodeCallWaiting(String sc) {
+        return sc != null && sc.equals(FC_CCW);
+    }
+
+    static boolean isServiceCodeThreeWayCalling(String sc) {
+        return sc != null && sc.equals(FC_3WC);
+    }
+
+    static boolean isServiceCodeAnnoyingCalls(String sc) {
+        return sc != null &&
+                (sc.equals(FC_RUAC_ACTIVATE)
+                || sc.equals(FC_RUAC_DEACTIVATE));
+    }
+
+    static boolean isServiceCodeCallingNumberDelivery(String sc) {
+        return sc != null &&
+                (sc.equals(FC_CNIP)
+                || sc.equals(FC_CNIR));
+    }
+
+    static boolean isServiceCodeDoNotDisturb(String sc) {
+        return sc != null &&
+                (sc.equals(FC_DND_ACTIVATE)
+                || sc.equals(FC_DND_DEACTIVATE));
+    }
+
+
+    //***** Constructor
+
+    FeatureCode (CDMAPhone phone) {
+        super(phone.getHandler().getLooper());
+        this.phone = phone;
+        this.context = phone.getContext();
+    }
+
+
+    //***** MmiCode implementation
+
+    public State getState() {
+        return state;
+    }
+
+    public CharSequence getMessage() {
+        return message;
+    }
+
+    // inherited javadoc suffices
+    public void cancel() {
+        //Not used here
+    }
+
+    public boolean isCancelable() {
+        Log.e(LOG_TAG, "isCancelable: not used in CDMA");
+        return false;
+    }
+
+    public boolean isUssdRequest() {
+        Log.e(LOG_TAG, "isUssdRequest: not used in CDMA");
+        return false;
+    }
+
+    /** Process a Flash Code...anything that isn't a dialing number */
+    void processCode () {
+        Log.d(LOG_TAG, "send feature code...");
+        phone.mCM.sendCDMAFeatureCode(this.poundString,
+                obtainMessage(EVENT_CDMA_FLASH_COMPLETED));
+    }
+
+    /** Called from CDMAPhone.handleMessage; not a Handler subclass */
+    public void handleMessage (Message msg) {
+        AsyncResult ar;
+
+        switch (msg.what) {
+        case EVENT_SET_COMPLETE:
+            ar = (AsyncResult) (msg.obj);
+            onSetComplete(ar);
+            break;
+        case EVENT_CDMA_FLASH_COMPLETED:
+            ar = (AsyncResult) (msg.obj);
+
+            if (ar.exception != null) {
+                state = State.FAILED;
+                message = context.getText(com.android.internal.R.string.mmiError);
+            } else {
+                state = State.COMPLETE;
+                message = context.getText(com.android.internal.R.string.mmiComplete);
+            }
+            phone.onMMIDone(this);
+            break;
+        }
+    }
+
+
+    //***** Private instance methods
+
+    private CharSequence getScString() {
+        if (sc != null) {
+            if (isServiceCodeCallForwarding(sc)) {
+                return context.getText(com.android.internal.R.string.CfMmi);
+            } else if (isServiceCodeCallWaiting(sc)) {
+                return context.getText(com.android.internal.R.string.CwMmi);
+            } else if (sc.equals(FC_CNIP)) {
+                return context.getText(com.android.internal.R.string.CnipMmi);
+            } else if (sc.equals(FC_CNIR)) {
+                return context.getText(com.android.internal.R.string.CnirMmi);
+            } else if (isServiceCodeThreeWayCalling(sc)) {
+                return context.getText(com.android.internal.R.string.ThreeWCMmi);
+            } else if (isServiceCodeAnnoyingCalls(sc)) {
+                return context.getText(com.android.internal.R.string.RuacMmi);
+            } else if (isServiceCodeCallingNumberDelivery(sc)) {
+                return context.getText(com.android.internal.R.string.CndMmi);
+            } else if (isServiceCodeDoNotDisturb(sc)) {
+                return context.getText(com.android.internal.R.string.DndMmi);
+            }
+        }
+
+        return "";
+    }
+
+    private void onSetComplete(AsyncResult ar){
+        StringBuilder sb = new StringBuilder(getScString());
+        sb.append("\n");
+
+        if (ar.exception != null) {
+            state = State.FAILED;
+            sb.append(context.getText(com.android.internal.R.string.mmiError));
+        } else {
+            state = State.FAILED;
+            sb.append(context.getText(com.android.internal.R.string.mmiError));
+        }
+
+        message = sb;
+        phone.onMMIDone(this);
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSimCard.java b/telephony/java/com/android/internal/telephony/cdma/RuimCard.java
similarity index 65%
copy from telephony/java/com/android/internal/telephony/gsm/GsmSimCard.java
copy to telephony/java/com/android/internal/telephony/cdma/RuimCard.java
index a4cded9..9d9f479 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmSimCard.java
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimCard.java
@@ -14,85 +14,90 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony.cdma;
 
 import android.os.AsyncResult;
-import android.os.RemoteException;
 import android.os.Handler;
 import android.os.Message;
 import android.os.Registrant;
 import android.os.RegistrantList;
+import android.os.RemoteException;
 import android.util.Log;
-import com.android.internal.telephony.SimCard;
-import com.android.internal.telephony.TelephonyProperties;
+
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.IccCard;
 import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneProxy;
 import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.TelephonyProperties;
+
+import android.app.ActivityManagerNative;
 import android.content.Intent;
 import android.content.res.Configuration;
-import android.app.ActivityManagerNative;
 
 import static android.Manifest.permission.READ_PHONE_STATE;
 
 /**
+ * Note: this class shares common code with SimCard, consider a base class to minimize code
+ * duplication.
  * {@hide}
  */
-public final class GsmSimCard extends Handler implements SimCard {
-    static final String LOG_TAG="GSM";
-    
+public final class RuimCard extends Handler implements IccCard {
+    static final String LOG_TAG="CDMA";
+
     //***** Instance Variables
     private static final boolean DBG = true;
 
-    private GSMPhone phone;
-    private CommandsInterface.SimStatus status = null;
-    private boolean mSimPinLocked = true; // Default to locked
-    private boolean mSimFdnEnabled = false; // Default to disabled.
-                                            // Will be updated when SIM_READY.
+    private CDMAPhone phone;
+
+    private CommandsInterface.IccStatus status = null;
     private boolean mDesiredPinLocked;
     private boolean mDesiredFdnEnabled;
+    private boolean mRuimPinLocked = true; // default to locked
+    private boolean mRuimFdnEnabled = false; // Default to disabled.
+                                            // Will be updated when RUIM_READY.
+//    //***** Constants
 
-    //***** Constants
-
-    // FIXME I hope this doesn't conflict with the Dialer's notifications
-    static final int NOTIFICATION_ID_SIM_STATUS = 33456;
+//    // FIXME I hope this doesn't conflict with the Dialer's notifications
+//    Nobody is using this at the moment
+//    static final int NOTIFICATION_ID_ICC_STATUS = 33456;
 
     //***** Event Constants
 
-    static final int EVENT_SIM_LOCKED_OR_ABSENT = 1;
-    static final int EVENT_GET_SIM_STATUS_DONE = 2;
+    static final int EVENT_RUIM_LOCKED_OR_ABSENT = 1;
+    static final int EVENT_GET_RUIM_STATUS_DONE = 2;
     static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 3;
     static final int EVENT_PINPUK_DONE = 4;
     static final int EVENT_REPOLL_STATUS_DONE = 5;
-    static final int EVENT_SIM_READY = 6;
+    static final int EVENT_RUIM_READY = 6;
     static final int EVENT_QUERY_FACILITY_LOCK_DONE = 7;
     static final int EVENT_CHANGE_FACILITY_LOCK_DONE = 8;
-    static final int EVENT_CHANGE_SIM_PASSWORD_DONE = 9;
+    static final int EVENT_CHANGE_RUIM_PASSWORD_DONE = 9;
     static final int EVENT_QUERY_FACILITY_FDN_DONE = 10;
     static final int EVENT_CHANGE_FACILITY_FDN_DONE = 11;
 
 
     //***** Constructor
 
-    GsmSimCard(GSMPhone phone)
-    {
+    RuimCard(CDMAPhone phone) {
         this.phone = phone;
 
-        phone.mCM.registerForSIMLockedOrAbsent(
-                        this, EVENT_SIM_LOCKED_OR_ABSENT, null);
+        phone.mCM.registerForRUIMLockedOrAbsent(
+                        this, EVENT_RUIM_LOCKED_OR_ABSENT, null);
 
         phone.mCM.registerForOffOrNotAvailable(
                         this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
 
-        phone.mCM.registerForSIMReady(
-                        this, EVENT_SIM_READY, null);
+        phone.mCM.registerForRUIMReady(
+                        this, EVENT_RUIM_READY, null);
 
         updateStateProperty();
     }
-    
-    //***** SimCard implementation
+
+    //***** RuimCard implementation
 
     public State
-    getState()
-    {
+    getState() {
         if (status == null) {
             switch(phone.mCM.getRadioState()) {
                 /* This switch block must not return anything in
@@ -101,36 +106,49 @@
                  */
                 case RADIO_OFF:
                 case RADIO_UNAVAILABLE:
-                case SIM_NOT_READY:
+                case RUIM_NOT_READY:
                     return State.UNKNOWN;
-                case SIM_LOCKED_OR_ABSENT:
+                case RUIM_LOCKED_OR_ABSENT:
                     //this should be transient-only
                     return State.UNKNOWN;
-                case SIM_READY:
+                case RUIM_READY:
                     return State.READY;
+                case NV_READY:
+                case NV_NOT_READY:
+                    return State.ABSENT;
             }
         } else {
             switch (status) {
-                case SIM_ABSENT:            return State.ABSENT;
-                case SIM_NOT_READY:         return State.UNKNOWN;
-                case SIM_READY:             return State.READY;
-                case SIM_PIN:               return State.PIN_REQUIRED;
-                case SIM_PUK:               return State.PUK_REQUIRED;
-                case SIM_NETWORK_PERSONALIZATION: return State.NETWORK_LOCKED;
+                case ICC_ABSENT:            return State.ABSENT;
+                case ICC_NOT_READY:         return State.UNKNOWN;
+                case ICC_READY:             return State.READY;
+                case ICC_PIN:               return State.PIN_REQUIRED;
+                case ICC_PUK:               return State.PUK_REQUIRED;
+                case ICC_NETWORK_PERSONALIZATION: return State.NETWORK_LOCKED;
             }
         }
 
-        Log.e(LOG_TAG, "GsmSimCard.getState(): case should never be reached");
+        Log.e(LOG_TAG, "RuimCard.getState(): case should never be reached");
         return State.UNKNOWN;
     }
 
+    public void dispose() {
+        //Unregister for all events
+        phone.mCM.unregisterForRUIMLockedOrAbsent(this);
+        phone.mCM.unregisterForOffOrNotAvailable(this);
+        phone.mCM.unregisterForRUIMReady(this);
+    }
+
+    protected void finalize() {
+        if(DBG) Log.d(LOG_TAG, "RuimCard finalized");
+    }
+
     private RegistrantList absentRegistrants = new RegistrantList();
     private RegistrantList pinLockedRegistrants = new RegistrantList();
     private RegistrantList networkLockedRegistrants = new RegistrantList();
 
 
-    public void registerForAbsent(Handler h, int what, Object obj)
-    {
+    public void registerForAbsent(Handler h, int what, Object obj) {
         Registrant r = new Registrant (h, what, obj);
 
         absentRegistrants.add(r);
@@ -139,9 +157,9 @@
             r.notifyRegistrant();
         }
     }
-    
+
     public void unregisterForAbsent(Handler h) {
-    	absentRegistrants.remove(h);
+        absentRegistrants.remove(h);
     }
 
     public void registerForNetworkLocked(Handler h, int what, Object obj) {
@@ -155,11 +173,10 @@
     }
 
     public void unregisterForNetworkLocked(Handler h) {
-    	networkLockedRegistrants.remove(h);
+        networkLockedRegistrants.remove(h);
     }
-    
-    public void registerForLocked(Handler h, int what, Object obj)
-    {
+
+    public void registerForLocked(Handler h, int what, Object obj) {
         Registrant r = new Registrant (h, what, obj);
 
         pinLockedRegistrants.add(r);
@@ -169,50 +186,41 @@
         }
     }
 
-    public void unregisterForLocked(Handler h)
-    {
+    public void unregisterForLocked(Handler h) {
         pinLockedRegistrants.remove(h);
     }
 
-
-    public void supplyPin (String pin, Message onComplete)
-    {
-        phone.mCM.supplySimPin(pin, 
-                            obtainMessage(EVENT_PINPUK_DONE, onComplete));
+    public void supplyPin (String pin, Message onComplete) {
+        phone.mCM.supplyIccPin(pin, obtainMessage(EVENT_PINPUK_DONE, onComplete));
     }
 
-    public void supplyPuk (String puk, String newPin, Message onComplete)
-    {
-        phone.mCM.supplySimPuk(puk, newPin,
-                        obtainMessage(EVENT_PINPUK_DONE, onComplete));
+    public void supplyPuk (String puk, String newPin, Message onComplete) {
+        phone.mCM.supplyIccPuk(puk, newPin, obtainMessage(EVENT_PINPUK_DONE, onComplete));
     }
-    public void supplyPin2 (String pin2, Message onComplete)
-    {
-        phone.mCM.supplySimPin2(pin2, 
-                        obtainMessage(EVENT_PINPUK_DONE, onComplete));
+
+    public void supplyPin2 (String pin2, Message onComplete) {
+        phone.mCM.supplyIccPin2(pin2, obtainMessage(EVENT_PINPUK_DONE, onComplete));
     }
-    public void supplyPuk2 (String puk2, String newPin2, Message onComplete)
-    {
-        phone.mCM.supplySimPuk2(puk2, newPin2,
+
+    public void supplyPuk2 (String puk2, String newPin2, Message onComplete) {
+        phone.mCM.supplyIccPuk2(puk2, newPin2, obtainMessage(EVENT_PINPUK_DONE, onComplete));
+    }
+
+    public void supplyNetworkDepersonalization (String pin, Message onComplete) {
+        if(DBG) log("Network Despersonalization: " + pin);
+        phone.mCM.supplyNetworkDepersonalization(pin,
                 obtainMessage(EVENT_PINPUK_DONE, onComplete));
     }
 
-    public void supplyNetworkDepersonalization (String pin, Message onComplete)
-    {
-        if(DBG) log("Network Despersonalization: " + pin);
-        phone.mCM.supplyNetworkDepersonalization(pin,
-                        obtainMessage(EVENT_PINPUK_DONE, onComplete));
+    public boolean getIccLockEnabled() {
+       return mRuimPinLocked;
     }
 
-    public boolean getSimLockEnabled() {
-       return mSimPinLocked;
+    public boolean getIccFdnEnabled() {
+       return mRuimFdnEnabled;
     }
 
-    public boolean getSimFdnEnabled() {
-       return mSimFdnEnabled;
-    }
-
-    public void setSimLockEnabled (boolean enabled,
+    public void setIccLockEnabled (boolean enabled,
             String password, Message onComplete) {
         int serviceClassX;
         serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE +
@@ -226,7 +234,7 @@
                 obtainMessage(EVENT_CHANGE_FACILITY_LOCK_DONE, onComplete));
     }
 
-    public void setSimFdnEnabled (boolean enabled,
+    public void setIccFdnEnabled (boolean enabled,
             String password, Message onComplete) {
         int serviceClassX;
         serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE +
@@ -241,24 +249,22 @@
                 obtainMessage(EVENT_CHANGE_FACILITY_FDN_DONE, onComplete));
     }
 
-    public void changeSimLockPassword(String oldPassword, String newPassword,
+    public void changeIccLockPassword(String oldPassword, String newPassword,
             Message onComplete) {
         if(DBG) log("Change Pin1 old: " + oldPassword + " new: " + newPassword);
-        phone.mCM.changeSimPin(oldPassword, newPassword,
-                obtainMessage(EVENT_CHANGE_SIM_PASSWORD_DONE, onComplete));
-
+        phone.mCM.changeIccPin(oldPassword, newPassword,
+                obtainMessage(EVENT_CHANGE_RUIM_PASSWORD_DONE, onComplete));
     }
 
-    public void changeSimFdnPassword(String oldPassword, String newPassword,
+    public void changeIccFdnPassword(String oldPassword, String newPassword,
             Message onComplete) {
         if(DBG) log("Change Pin2 old: " + oldPassword + " new: " + newPassword);
-        phone.mCM.changeSimPin2(oldPassword, newPassword,
-                obtainMessage(EVENT_CHANGE_SIM_PASSWORD_DONE, onComplete));
-
+        phone.mCM.changeIccPin2(oldPassword, newPassword,
+                obtainMessage(EVENT_CHANGE_RUIM_PASSWORD_DONE, onComplete));
     }
 
-    public String getServiceProviderName () {
-        return phone.mSIMRecords.getServiceProviderName();
+    public String getServiceProviderName() {
+        return phone.mRuimRecords.getServiceProviderName();
     }
 
     //***** Handler implementation
@@ -273,13 +279,15 @@
 
         switch (msg.what) {
             case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
+                Log.d(LOG_TAG, "Event EVENT_RADIO_OFF_OR_NOT_AVAILABLE Received");
                 status = null;
                 updateStateProperty();
-                broadcastSimStateChangedIntent(SimCard.INTENT_VALUE_SIM_NOT_READY, null);
+                broadcastRuimStateChangedIntent(RuimCard.INTENT_VALUE_ICC_NOT_READY, null);
                 break;
-            case EVENT_SIM_READY:
+            case EVENT_RUIM_READY:
+                Log.d(LOG_TAG, "Event EVENT_RUIM_READY Received");
                 //TODO: put facility read in SIM_READY now, maybe in REG_NW
-                phone.mCM.getSimStatus(obtainMessage(EVENT_GET_SIM_STATUS_DONE));
+                phone.mCM.getIccStatus(obtainMessage(EVENT_GET_RUIM_STATUS_DONE));
                 phone.mCM.queryFacilityLock (
                         CommandsInterface.CB_FACILITY_BA_SIM, "", serviceClassX,
                         obtainMessage(EVENT_QUERY_FACILITY_LOCK_DONE));
@@ -287,18 +295,21 @@
                         CommandsInterface.CB_FACILITY_BA_FD, "", serviceClassX,
                         obtainMessage(EVENT_QUERY_FACILITY_FDN_DONE));
                 break;
-            case EVENT_SIM_LOCKED_OR_ABSENT:
-                phone.mCM.getSimStatus(obtainMessage(EVENT_GET_SIM_STATUS_DONE));
+            case EVENT_RUIM_LOCKED_OR_ABSENT:
+                Log.d(LOG_TAG, "Event EVENT_RUIM_LOCKED_OR_ABSENT Received");
+                phone.mCM.getIccStatus(obtainMessage(EVENT_GET_RUIM_STATUS_DONE));
                 phone.mCM.queryFacilityLock (
                         CommandsInterface.CB_FACILITY_BA_SIM, "", serviceClassX,
                         obtainMessage(EVENT_QUERY_FACILITY_LOCK_DONE));
                 break;
-            case EVENT_GET_SIM_STATUS_DONE:
+            case EVENT_GET_RUIM_STATUS_DONE:
+                Log.d(LOG_TAG, "Event EVENT_GET_RUIM_STATUS_DONE Received");
                 ar = (AsyncResult)msg.obj;
 
-                getSimStatusDone(ar);
+                getRuimStatusDone(ar);
                 break;
             case EVENT_PINPUK_DONE:
+                Log.d(LOG_TAG, "Event EVENT_PINPUK_DONE Received");
                 // a PIN/PUK/PIN2/PUK2/Network Personalization
                 // request has completed. ar.userObj is the response Message
                 // Repoll before returning
@@ -306,33 +317,37 @@
                 // TODO should abstract these exceptions
                 AsyncResult.forMessage(((Message)ar.userObj)).exception
                                                     = ar.exception;
-                phone.mCM.getSimStatus(
+                phone.mCM.getIccStatus(
                     obtainMessage(EVENT_REPOLL_STATUS_DONE, ar.userObj));
                 break;
             case EVENT_REPOLL_STATUS_DONE:
+                Log.d(LOG_TAG, "Event EVENT_REPOLL_STATUS_DONE Received");
                 // Finished repolling status after PIN operation
                 // ar.userObj is the response messaeg
                 // ar.userObj.obj is already an AsyncResult with an
                 // appropriate exception filled in if applicable
 
                 ar = (AsyncResult)msg.obj;
-                getSimStatusDone(ar);
+                getRuimStatusDone(ar);
                 ((Message)ar.userObj).sendToTarget();
                 break;
             case EVENT_QUERY_FACILITY_LOCK_DONE:
+                Log.d(LOG_TAG, "Event EVENT_QUERY_FACILITY_LOCK_DONE Received");
                 ar = (AsyncResult)msg.obj;
                 onQueryFacilityLock(ar);
                 break;
             case EVENT_QUERY_FACILITY_FDN_DONE:
+                Log.d(LOG_TAG, "Event EVENT_QUERY_FACILITY_FDN_DONE Received");
                 ar = (AsyncResult)msg.obj;
                 onQueryFdnEnabled(ar);
                 break;
             case EVENT_CHANGE_FACILITY_LOCK_DONE:
+                Log.d(LOG_TAG, "Event EVENT_CHANGE_FACILITY_LOCK_DONE Received");
                 ar = (AsyncResult)msg.obj;
                 if (ar.exception == null) {
-                    mSimPinLocked = mDesiredPinLocked;
+                    mRuimPinLocked = mDesiredPinLocked;
                     if (DBG) log( "EVENT_CHANGE_FACILITY_LOCK_DONE: " +
-                            "mSimPinLocked= " + mSimPinLocked);
+                            "mRuimPinLocked= " + mRuimPinLocked);
                 } else {
                     Log.e(LOG_TAG, "Error change facility lock with exception "
                         + ar.exception);
@@ -342,12 +357,13 @@
                 ((Message)ar.userObj).sendToTarget();
                 break;
             case EVENT_CHANGE_FACILITY_FDN_DONE:
+                Log.d(LOG_TAG, "Event EVENT_CHANGE_FACILITY_FDN_DONE Received");
                 ar = (AsyncResult)msg.obj;
 
                 if (ar.exception == null) {
-                    mSimFdnEnabled = mDesiredFdnEnabled;
+                    mRuimFdnEnabled = mDesiredFdnEnabled;
                     if (DBG) log("EVENT_CHANGE_FACILITY_FDN_DONE: " +
-                            "mSimFdnEnabled=" + mSimFdnEnabled);
+                            "mRuimFdnEnabled=" + mRuimFdnEnabled);
                 } else {
                     Log.e(LOG_TAG, "Error change facility fdn with exception "
                             + ar.exception);
@@ -356,7 +372,8 @@
                                                     = ar.exception;
                 ((Message)ar.userObj).sendToTarget();
                 break;
-            case EVENT_CHANGE_SIM_PASSWORD_DONE:
+            case EVENT_CHANGE_RUIM_PASSWORD_DONE:
+                Log.d(LOG_TAG, "Event EVENT_CHANGE_RUIM_PASSWORD_DONE Received");
                 ar = (AsyncResult)msg.obj;
                 if(ar.exception != null) {
                     Log.e(LOG_TAG, "Error in change sim password with exception"
@@ -367,15 +384,14 @@
                 ((Message)ar.userObj).sendToTarget();
                 break;
             default:
-                Log.e(LOG_TAG, "[GsmSimCard] Unknown Event " + msg.what);
+                Log.e(LOG_TAG, "[CdmaRuimCard] Unknown Event " + msg.what);
         }
     }
 
-
     //***** Private methods
 
     /**
-     * Interperate EVENT_QUERY_FACILITY_LOCK_DONE
+     * Interpret EVENT_QUERY_FACILITY_LOCK_DONE
      * @param ar is asyncResult of Query_Facility_Locked
      */
     private void onQueryFacilityLock(AsyncResult ar) {
@@ -386,15 +402,15 @@
 
         int[] ints = (int[])ar.result;
         if(ints.length != 0) {
-            mSimPinLocked = (0!=ints[0]);
-            if(DBG) log("Query facility lock : "  + mSimPinLocked);
+            mRuimPinLocked = (0!=ints[0]);
+            if(DBG) log("Query facility lock : "  + mRuimPinLocked);
         } else {
-            Log.e(LOG_TAG, "[GsmSimCard] Bogus facility lock response");
+            Log.e(LOG_TAG, "[CdmaRuimCard] Bogus facility lock response");
         }
     }
 
     /**
-     * Interperate EVENT_QUERY_FACILITY_LOCK_DONE
+     * Interpret EVENT_QUERY_FACILITY_LOCK_DONE
      * @param ar is asyncResult of Query_Facility_Locked
      */
     private void onQueryFdnEnabled(AsyncResult ar) {
@@ -405,15 +421,15 @@
 
         int[] ints = (int[])ar.result;
         if(ints.length != 0) {
-            mSimFdnEnabled = (0!=ints[0]);
-            if(DBG) log("Query facility lock : "  + mSimFdnEnabled);
+            mRuimFdnEnabled = (0!=ints[0]);
+            if(DBG) log("Query facility lock : "  + mRuimFdnEnabled);
         } else {
-            Log.e(LOG_TAG, "[GsmSimCard] Bogus facility lock response");
+            Log.e(LOG_TAG, "[CdmaRuimCard] Bogus facility lock response");
         }
     }
 
     private void
-    getSimStatusDone(AsyncResult ar) {
+    getRuimStatusDone(AsyncResult ar) {
         if (ar.exception != null) {
             Log.e(LOG_TAG,"Error getting SIM status. "
                     + "RIL_REQUEST_GET_SIM_STATUS should "
@@ -421,19 +437,19 @@
             return;
         }
 
-        CommandsInterface.SimStatus newStatus 
-            = (CommandsInterface.SimStatus)  ar.result;
+        CommandsInterface.IccStatus newStatus
+            = (CommandsInterface.IccStatus)  ar.result;
 
-        handleSimStatus(newStatus);
+        handleRuimStatus(newStatus);
     }
 
     private void
-    handleSimStatus(CommandsInterface.SimStatus newStatus) {
+    handleRuimStatus(CommandsInterface.IccStatus newStatus) {
         boolean transitionedIntoPinLocked;
         boolean transitionedIntoAbsent;
         boolean transitionedIntoNetworkLocked;
-        
-        SimCard.State oldState, newState;
+
+        RuimCard.State oldState, newState;
 
         oldState = getState();
         status = newStatus;
@@ -449,28 +465,28 @@
                 && newState == State.NETWORK_LOCKED);
 
         if (transitionedIntoPinLocked) {
-            if(DBG) log("Notify SIM pin or puk locked.");
+            if(DBG) log("Notify RUIM pin or puk locked.");
             pinLockedRegistrants.notifyRegistrants();
-            broadcastSimStateChangedIntent(SimCard.INTENT_VALUE_SIM_LOCKED, 
+            broadcastRuimStateChangedIntent(RuimCard.INTENT_VALUE_ICC_LOCKED,
                     (newState == State.PIN_REQUIRED) ?
                        INTENT_VALUE_LOCKED_ON_PIN : INTENT_VALUE_LOCKED_ON_PUK);
         } else if (transitionedIntoAbsent) {
-            if(DBG) log("Notify SIM missing.");
+            if(DBG) log("Notify RUIM missing.");
             absentRegistrants.notifyRegistrants();
-            broadcastSimStateChangedIntent(SimCard.INTENT_VALUE_SIM_ABSENT, null);
+            broadcastRuimStateChangedIntent(RuimCard.INTENT_VALUE_ICC_ABSENT, null);
         } else if (transitionedIntoNetworkLocked) {
-            if(DBG) log("Notify SIM network locked.");
+            if(DBG) log("Notify RUIM network locked.");
             networkLockedRegistrants.notifyRegistrants();
-            broadcastSimStateChangedIntent(SimCard.INTENT_VALUE_SIM_LOCKED,
+            broadcastRuimStateChangedIntent(RuimCard.INTENT_VALUE_ICC_LOCKED,
                   INTENT_VALUE_LOCKED_NETWORK);
         }
     }
 
-    public void broadcastSimStateChangedIntent(String value, String reason) {
+    public void broadcastRuimStateChangedIntent(String value, String reason) {
         Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
         intent.putExtra(Phone.PHONE_NAME_KEY, phone.getPhoneName());
-        intent.putExtra(SimCard.INTENT_KEY_SIM_STATE, value);
-        intent.putExtra(SimCard.INTENT_KEY_LOCKED_REASON, reason);
+        intent.putExtra(RuimCard.INTENT_KEY_ICC_STATE, value);
+        intent.putExtra(RuimCard.INTENT_KEY_LOCKED_REASON, reason);
         if(DBG) log("Broadcasting intent SIM_STATE_CHANGED_ACTION " +  value
                 + " reason " + reason);
         ActivityManagerNative.broadcastStickyIntent(intent, READ_PHONE_STATE);
@@ -500,7 +516,7 @@
     }
 
     private void log(String msg) {
-        Log.d(LOG_TAG, "[GsmSimCard] " + msg);
+        Log.d(LOG_TAG, "[RuimCard] " + msg);
     }
 }
 
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimFileHandler.java b/telephony/java/com/android/internal/telephony/cdma/RuimFileHandler.java
new file mode 100644
index 0000000..7d392f0
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimFileHandler.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 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.
+ * 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.internal.telephony.cdma;
+
+import android.os.*;
+import android.os.AsyncResult;
+import android.util.Log;
+
+import com.android.internal.telephony.IccConstants;
+import com.android.internal.telephony.IccException;
+import com.android.internal.telephony.IccFileHandler;
+import com.android.internal.telephony.IccFileTypeMismatch;
+import com.android.internal.telephony.IccIoResult;
+import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.PhoneProxy;
+
+import java.util.ArrayList;
+
+/**
+ * {@hide}
+ */
+public final class RuimFileHandler extends IccFileHandler {
+    static final String LOG_TAG = "CDMA";
+
+    //***** Instance Variables
+
+    //***** Constructor
+    RuimFileHandler(CDMAPhone phone) {
+        super(phone);
+    }
+
+    public void dispose() {
+    }
+
+    protected void finalize() {
+        Log.d(LOG_TAG, "RuimFileHandler finalized");
+    }
+
+    //***** Overridden from IccFileHandler
+
+    @Override
+    public void loadEFImgTransparent(int fileid, int highOffset, int lowOffset,
+            int length, Message onLoaded) {
+        Message response = obtainMessage(EVENT_READ_ICON_DONE, fileid, 0,
+                onLoaded);
+
+        phone.mCM.iccIO(COMMAND_GET_RESPONSE, fileid, "img", 0, 0,
+                GET_RESPONSE_EF_IMG_SIZE_BYTES, null, null, response);
+    }
+
+    @Override
+    public void handleMessage(Message msg) {
+
+        super.handleMessage(msg);
+    }
+
+    protected void logd(String msg) {
+        Log.d(LOG_TAG, "[RuimFileHandler] " + msg);
+    }
+
+    protected void loge(String msg) {
+        Log.e(LOG_TAG, "[RuimFileHandler] " + msg);
+    }
+
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimPhoneBookInterfaceManager.java b/telephony/java/com/android/internal/telephony/cdma/RuimPhoneBookInterfaceManager.java
new file mode 100644
index 0000000..78e89d5
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimPhoneBookInterfaceManager.java
@@ -0,0 +1,101 @@
+/*
+** Copyright 2007, 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.internal.telephony.cdma;
+
+import android.content.pm.PackageManager;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.ServiceManager;
+import android.telephony.PhoneNumberUtils;
+import android.util.Log;
+
+import com.android.internal.telephony.AdnRecord;
+import com.android.internal.telephony.AdnRecordCache;
+import com.android.internal.telephony.IccPhoneBookInterfaceManager;
+import com.android.internal.telephony.PhoneProxy;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * RuimPhoneBookInterfaceManager to provide an inter-process communication to
+ * access ADN-like SIM records.
+ */
+
+
+public class RuimPhoneBookInterfaceManager extends IccPhoneBookInterfaceManager {
+    static final String LOG_TAG = "CDMA";
+
+
+    Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            AsyncResult ar;
+
+            switch(msg.what) {
+                default:
+                    mBaseHandler.handleMessage(msg);
+                    break;
+            }
+        }
+    };
+
+    public RuimPhoneBookInterfaceManager(CDMAPhone phone) {
+        super(phone);
+        adnCache = phone.mRuimRecords.getAdnCache();
+        //NOTE service "simphonebook" added by IccSmsInterfaceManagerProxy
+    }
+
+    public void dispose() {
+        super.dispose();
+    }
+
+    protected void finalize() {
+        if(DBG) Log.d(LOG_TAG, "RuimPhoneBookInterfaceManager finalized");
+    }
+
+    public int[] getAdnRecordsSize(int efid) {
+        if (DBG) logd("getAdnRecordsSize: efid=" + efid);
+        synchronized(mLock) {
+            checkThread();
+            recordSize = new int[3];
+
+            //Using mBaseHandler, no difference in EVENT_GET_SIZE_DONE handling
+            Message response = mBaseHandler.obtainMessage(EVENT_GET_SIZE_DONE);
+
+            phone.getIccFileHandler().getEFLinearRecordSize(efid, response);
+            try {
+                mLock.wait();
+            } catch (InterruptedException e) {
+                logd("interrupted while trying to load from the RUIM");
+            }
+        }
+
+        return recordSize;
+    }
+
+    protected void logd(String msg) {
+        Log.d(LOG_TAG, "[RuimPbInterfaceManager] " + msg);
+    }
+
+    protected void loge(String msg) {
+        Log.e(LOG_TAG, "[RuimPbInterfaceManager] " + msg);
+    }
+}
+
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
new file mode 100644
index 0000000..7776f8b
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
@@ -0,0 +1,380 @@
+/*
+ * Copyright (C) 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.
+ * 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.internal.telephony.cdma;
+
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Registrant;
+import android.util.Log;
+
+import static com.android.internal.telephony.TelephonyProperties.*;
+import com.android.internal.telephony.AdnRecord;
+import com.android.internal.telephony.AdnRecordCache;
+import com.android.internal.telephony.AdnRecordLoader;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.cdma.RuimCard;
+import com.android.internal.telephony.gsm.MccTable;
+
+// can't be used since VoiceMailConstants is not public
+//import com.android.internal.telephony.gsm.VoiceMailConstants;
+import com.android.internal.telephony.IccException;
+import com.android.internal.telephony.IccRecords;
+import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.PhoneProxy;
+
+
+/**
+ * {@hide}
+ */
+public final class RuimRecords extends IccRecords {
+    static final String LOG_TAG = "CDMA";
+
+    private static final boolean DBG = true;
+
+    //***** Instance Variables
+    String imsi_m;
+    String mdn = null;  // My mobile number
+    String h_sid;
+    String h_nid;
+
+    // is not initialized
+
+    //***** Event Constants
+
+    private static final int EVENT_RUIM_READY = 1;
+    private static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 2;
+    private static final int EVENT_GET_DEVICE_IDENTITY_DONE = 4;
+    private static final int EVENT_GET_ICCID_DONE = 5;
+    private static final int EVENT_GET_CDMA_SUBSCRIPTION_DONE = 10;
+    private static final int EVENT_UPDATE_DONE = 14;
+    private static final int EVENT_GET_SST_DONE = 17;
+    private static final int EVENT_GET_ALL_SMS_DONE = 18;
+    private static final int EVENT_MARK_SMS_READ_DONE = 19;
+
+    private static final int EVENT_SMS_ON_RUIM = 21;
+    private static final int EVENT_GET_SMS_DONE = 22;
+
+    private static final int EVENT_RUIM_REFRESH = 31;
+
+    //***** Constructor
+
+    RuimRecords(CDMAPhone p) {
+        super(p);
+
+        adnCache = new AdnRecordCache(phone);
+
+        recordsRequested = false;  // No load request is made till SIM ready
+
+        // recordsToLoad is set to 0 because no requests are made yet
+        recordsToLoad = 0;
+
+
+        p.mCM.registerForRUIMReady(this, EVENT_RUIM_READY, null);
+        p.mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
+        // NOTE the EVENT_SMS_ON_RUIM is not registered
+        p.mCM.setOnIccRefresh(this, EVENT_RUIM_REFRESH, null);
+
+        // Start off by setting empty state
+        onRadioOffOrNotAvailable();
+
+    }
+
+    public void dispose() {
+        //Unregister for all events
+        phone.mCM.unregisterForRUIMReady(this);
+        phone.mCM.unregisterForOffOrNotAvailable( this);
+        phone.mCM.unSetOnIccRefresh(this);
+    }
+
+    protected void finalize() {
+        if(DBG) Log.d(LOG_TAG, "RuimRecords finalized");
+    }
+
+    protected void onRadioOffOrNotAvailable() {
+        countVoiceMessages = 0;
+        mncLength = 0;
+        iccid = null;
+
+        adnCache.reset();
+
+        phone.setSystemProperty(PROPERTY_ICC_OPERATOR_NUMERIC, null);
+        phone.setSystemProperty(PROPERTY_ICC_OPERATOR_ISO_COUNTRY, null);
+
+        // recordsRequested is set to false indicating that the SIM
+        // read requests made so far are not valid. This is set to
+        // true only when fresh set of read requests are made.
+        recordsRequested = false;
+    }
+
+    //***** Public Methods
+
+    /** Returns null if RUIM is not yet ready */
+    public String getIMSI_M() {
+        return imsi_m;
+    }
+
+    public String getMdnNumber() {
+        return mdn;
+    }
+
+    public void setVoiceMailNumber(String alphaTag, String voiceNumber, Message onComplete){
+        // In CDMA this is Operator/OEM dependent
+        AsyncResult.forMessage((onComplete)).exception =
+                new IccException("setVoiceMailNumber not implemented");
+        onComplete.sendToTarget();
+        Log.e(LOG_TAG, "method setVoiceMailNumber is not implemented");
+    }
+
+    /**
+     * Called by CCAT Service when REFRESH is received.
+     * @param fileChanged indicates whether any files changed
+     * @param fileList if non-null, a list of EF files that changed
+     */
+    public void onRefresh(boolean fileChanged, int[] fileList) {
+        if (fileChanged) {
+            // A future optimization would be to inspect fileList and
+            // only reload those files that we care about.  For now,
+            // just re-fetch all RUIM records that we cache.
+            fetchRuimRecords();
+        }
+    }
+
+    /** Returns the 5 or 6 digit MCC/MNC of the operator that
+     *  provided the RUIM card. Returns null of RUIM is not yet ready
+     */
+    String getRUIMOperatorNumeric() {
+        if (imsi_m == null) {
+            return null;
+        }
+
+        if (mncLength != 0) {
+            // Length = length of MCC + length of MNC
+            // TODO: change spec name
+            // length of mcc = 3 (3GPP2 C.S0005 - Section 2.3)
+            return imsi_m.substring(0, 3 + mncLength);
+        }
+
+        // Guess the MNC length based on the MCC if we don't
+        // have a valid value in ef[ad]
+
+        int mcc;
+
+        mcc = Integer.parseInt(imsi_m.substring(0,3));
+
+        return imsi_m.substring(0, 3 + MccTable.smallestDigitsMccForMnc(mcc));
+    }
+
+    //***** Overridden from Handler
+    public void handleMessage(Message msg) {
+        AsyncResult ar;
+
+        byte data[];
+
+        boolean isRecordLoadResponse = false;
+
+        try { switch (msg.what) {
+            case EVENT_RUIM_READY:
+                onRuimReady();
+            break;
+
+            case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
+                onRadioOffOrNotAvailable();
+            break;
+
+            case EVENT_GET_DEVICE_IDENTITY_DONE:
+                Log.d(LOG_TAG, "Event EVENT_GET_DEVICE_IDENTITY_DONE Received");
+            break;
+
+            /* IO events */
+
+            case EVENT_GET_CDMA_SUBSCRIPTION_DONE:
+                ar = (AsyncResult)msg.obj;
+                String localTemp[] = (String[])ar.result;
+                if (ar.exception != null) {
+                    break;
+                }
+
+                mdn    = localTemp[0];
+                h_sid  = localTemp[1];
+                h_nid  = localTemp[2];
+
+                Log.d(LOG_TAG, "MDN: " + mdn);
+
+            break;
+
+            case EVENT_GET_ICCID_DONE:
+                isRecordLoadResponse = true;
+
+                ar = (AsyncResult)msg.obj;
+                data = (byte[])ar.result;
+
+                if (ar.exception != null) {
+                    break;
+                }
+
+                iccid = IccUtils.bcdToString(data, 0, data.length);
+
+                Log.d(LOG_TAG, "iccid: " + iccid);
+
+            break;
+
+            case EVENT_UPDATE_DONE:
+                ar = (AsyncResult)msg.obj;
+                if (ar.exception != null) {
+                    Log.i(LOG_TAG, "RuimRecords update failed", ar.exception);
+                }
+            break;
+
+            case EVENT_GET_ALL_SMS_DONE:
+            case EVENT_MARK_SMS_READ_DONE:
+            case EVENT_SMS_ON_RUIM:
+            case EVENT_GET_SMS_DONE:
+                Log.w(LOG_TAG, "Event not supported: " + msg.what);
+                break;
+
+            // TODO: probably EF_CST should be read instead
+            case EVENT_GET_SST_DONE:
+                Log.d(LOG_TAG, "Event EVENT_GET_SST_DONE Received");
+            break;
+
+            case EVENT_RUIM_REFRESH:
+                isRecordLoadResponse = false;
+                ar = (AsyncResult)msg.obj;
+                if (ar.exception == null) {
+                    handleRuimRefresh((int[])(ar.result));
+                }
+                break;
+
+        }}catch (RuntimeException exc) {
+            // I don't want these exceptions to be fatal
+            Log.w(LOG_TAG, "Exception parsing RUIM record", exc);
+        } finally {
+            // Count up record load responses even if they are fails
+            if (isRecordLoadResponse) {
+                onRecordLoaded();
+            }
+        }
+    }
+
+    protected void onRecordLoaded() {
+        // One record loaded successfully or failed, In either case
+        // we need to update the recordsToLoad count
+        recordsToLoad -= 1;
+
+        if (recordsToLoad == 0 && recordsRequested == true) {
+            onAllRecordsLoaded();
+        } else if (recordsToLoad < 0) {
+            Log.e(LOG_TAG, "RuimRecords: recordsToLoad <0, programmer error suspected");
+            recordsToLoad = 0;
+        }
+    }
+
+    protected void onAllRecordsLoaded() {
+        Log.d(LOG_TAG, "RuimRecords: record load complete");
+
+        // Further records that can be inserted are Operator/OEM dependent
+
+        recordsLoadedRegistrants.notifyRegistrants(
+            new AsyncResult(null, null, null));
+        ((CDMAPhone) phone).mRuimCard.broadcastRuimStateChangedIntent(
+                RuimCard.INTENT_VALUE_ICC_LOADED, null);
+    }
+
+
+    //***** Private Methods
+
+    private void onRuimReady() {
+        /* broadcast intent ICC_READY here so that we can make sure
+          READY is sent before IMSI ready
+        */
+
+        ((CDMAPhone) phone).mRuimCard.broadcastRuimStateChangedIntent(
+                RuimCard.INTENT_VALUE_ICC_READY, null);
+
+        fetchRuimRecords();
+
+        phone.mCM.getCDMASubscription(obtainMessage(EVENT_GET_CDMA_SUBSCRIPTION_DONE));
+
+    }
+
+    private void fetchRuimRecords() {
+        recordsRequested = true;
+
+        Log.v(LOG_TAG, "RuimRecords:fetchRuimRecords " + recordsToLoad);
+
+        phone.getIccFileHandler().loadEFTransparent(EF_ICCID,
+                obtainMessage(EVENT_GET_ICCID_DONE));
+        recordsToLoad++;
+
+        // Further records that can be inserted are Operator/OEM dependent
+    }
+
+    @Override
+    protected int getDisplayRule(String plmn) {
+        // TODO together with spn
+        return 0;
+    }
+
+    @Override
+    public void setVoiceMessageWaiting(int line, int countWaiting) {
+        Log.i(LOG_TAG, "RuimRecords: setVoiceMessageWaiting not supported.");
+    }
+
+    private void handleRuimRefresh(int[] result) {
+        if (result == null || result.length == 0) {
+	        if (DBG) log("handleRuimRefresh without input");
+            return;
+        }
+
+        switch ((result[0])) {
+            case CommandsInterface.SIM_REFRESH_FILE_UPDATED:
+ 		        if (DBG) log("handleRuimRefresh with SIM_REFRESH_FILE_UPDATED");
+                adnCache.reset();
+                fetchRuimRecords();
+                break;
+            case CommandsInterface.SIM_REFRESH_INIT:
+		        if (DBG) log("handleRuimRefresh with SIM_REFRESH_INIT");
+                // need to reload all files (that we care about)
+                fetchRuimRecords();
+                break;
+            case CommandsInterface.SIM_REFRESH_RESET:
+		        if (DBG) log("handleRuimRefresh with SIM_REFRESH_RESET");
+                phone.mCM.setRadioPower(false, null);
+                /* Note: no need to call setRadioPower(true).  Assuming the desired
+                * radio power state is still ON (as tracked by ServiceStateTracker),
+                * ServiceStateTracker will call setRadioPower when it receives the
+                * RADIO_STATE_CHANGED notification for the power off.  And if the
+                * desired power state has changed in the interim, we don't want to
+                * override it with an unconditional power on.
+                */
+                break;
+            default:
+                // unknown refresh operation
+		        if (DBG) log("handleRuimRefresh with unknown operation");
+                break;
+        }
+    }
+
+    protected void log(String s) {
+        Log.d(LOG_TAG, "[RuimRecords] " + s);
+    }
+
+}
+
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimSmsInterfaceManager.java b/telephony/java/com/android/internal/telephony/cdma/RuimSmsInterfaceManager.java
new file mode 100644
index 0000000..9439359
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimSmsInterfaceManager.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 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.
+ * 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.internal.telephony.cdma;
+
+import android.content.Context;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+import com.android.internal.telephony.IccConstants;
+import com.android.internal.telephony.IccSmsInterfaceManager;
+import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.PhoneProxy;
+import com.android.internal.telephony.SmsRawData;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static android.telephony.SmsManager.STATUS_ON_ICC_FREE;
+
+/**
+ * RuimSmsInterfaceManager to provide an inter-process communication to
+ * access Sms in Ruim.
+ */
+public class RuimSmsInterfaceManager extends IccSmsInterfaceManager {
+    static final String LOG_TAG = "CDMA";
+    static final boolean DBG = true;
+
+    private final Object mLock = new Object();
+    private boolean mSuccess;
+    private List<SmsRawData> mSms;
+
+    private static final int EVENT_LOAD_DONE = 1;
+    private static final int EVENT_UPDATE_DONE = 2;
+
+    Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            AsyncResult ar;
+
+            switch (msg.what) {
+                case EVENT_UPDATE_DONE:
+                    ar = (AsyncResult) msg.obj;
+                    synchronized (mLock) {
+                        mSuccess = (ar.exception == null);
+                        mLock.notifyAll();
+                    }
+                    break;
+                case EVENT_LOAD_DONE:
+                    ar = (AsyncResult)msg.obj;
+                    synchronized (mLock) {
+                        if (ar.exception == null) {
+                            mSms  = (List<SmsRawData>)
+                                    buildValidRawData((ArrayList<byte[]>) ar.result);
+                        } else {
+                            if(DBG) log("Cannot load Sms records");
+                            if (mSms != null)
+                                mSms.clear();
+                        }
+                        mLock.notifyAll();
+                    }
+                    break;
+            }
+        }
+    };
+
+    public RuimSmsInterfaceManager(CDMAPhone phone) {
+        super(phone);
+        mDispatcher = new CdmaSMSDispatcher(phone);
+    }
+
+    public void dispose() {
+    }
+
+    protected void finalize() {
+        if(DBG) Log.d(LOG_TAG, "RuimSmsInterfaceManager finalized");
+    }
+
+    /**
+     * Update the specified message on the RUIM.
+     *
+     * @param index record index of message to update
+     * @param status new message status (STATUS_ON_ICC_READ,
+     *                  STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT,
+     *                  STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE)
+     * @param pdu the raw PDU to store
+     * @return success or not
+     *
+     */
+    public boolean
+    updateMessageOnIccEf(int index, int status, byte[] pdu) {
+        if (DBG) log("updateMessageOnIccEf: index=" + index +
+                " status=" + status + " ==> " +
+                "("+ pdu + ")");
+        enforceReceiveAndSend("Updating message on RUIM");
+        synchronized(mLock) {
+            mSuccess = false;
+            Message response = mHandler.obtainMessage(EVENT_UPDATE_DONE);
+
+            if (status == STATUS_ON_ICC_FREE) {
+                // Special case FREE: call deleteSmsOnRuim instead of
+                // manipulating the RUIM record
+                mPhone.mCM.deleteSmsOnRuim(index, response);
+            } else {
+                byte[] record = makeSmsRecordData(status, pdu);
+                mPhone.getIccFileHandler().updateEFLinearFixed(
+                        IccConstants.EF_SMS, index, record, null, response);
+            }
+            try {
+                mLock.wait();
+            } catch (InterruptedException e) {
+                log("interrupted while trying to update by index");
+            }
+        }
+        return mSuccess;
+    }
+
+    /**
+     * Copy a raw SMS PDU to the RUIM.
+     *
+     * @param pdu the raw PDU to store
+     * @param status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD,
+     *               STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT)
+     * @return success or not
+     *
+     */
+    public boolean copyMessageToIccEf(int status, byte[] pdu, byte[] smsc) {
+        //NOTE smsc not used in RUIM
+        if (DBG) log("copyMessageToIccEf: status=" + status + " ==> " +
+                "pdu=("+ pdu + ")");
+        enforceReceiveAndSend("Copying message to RUIM");
+        synchronized(mLock) {
+            mSuccess = false;
+            Message response = mHandler.obtainMessage(EVENT_UPDATE_DONE);
+
+            mPhone.mCM.writeSmsToRuim(status, IccUtils.bytesToHexString(pdu),
+                    response);
+
+            try {
+                mLock.wait();
+            } catch (InterruptedException e) {
+                log("interrupted while trying to update by index");
+            }
+        }
+        return mSuccess;
+    }
+
+    /**
+     * Retrieves all messages currently stored on RUIM.
+     */
+    public List<SmsRawData> getAllMessagesFromIccEf() {
+        if (DBG) log("getAllMessagesFromEF");
+
+        Context context = mPhone.getContext();
+
+        context.enforceCallingPermission(
+                "android.permission.RECEIVE_SMS",
+                "Reading messages from RUIM");
+        synchronized(mLock) {
+            Message response = mHandler.obtainMessage(EVENT_LOAD_DONE);
+            mPhone.getIccFileHandler().loadEFLinearFixedAll(IccConstants.EF_SMS, response);
+
+            try {
+                mLock.wait();
+            } catch (InterruptedException e) {
+                log("interrupted while trying to load from the RUIM");
+            }
+        }
+        return mSms;
+    }
+
+    protected void log(String msg) {
+        Log.d(LOG_TAG, "[RuimSmsInterfaceManager] " + msg);
+    }
+}
+
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
new file mode 100644
index 0000000..e4b474a
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -0,0 +1,905 @@
+/*
+ * Copyright (C) 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.
+ * 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.internal.telephony.cdma;
+
+import android.os.Parcel;
+import android.text.format.Time;
+import android.util.Config;
+import android.util.Log;
+import com.android.internal.telephony.EncodeException;
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.SmsHeader;
+import com.android.internal.telephony.SmsMessageBase;
+import com.android.internal.telephony.cdma.sms.BearerData;
+import com.android.internal.telephony.cdma.sms.CdmaSmsAddress;
+import com.android.internal.telephony.cdma.sms.SmsDataCoding;
+import com.android.internal.telephony.cdma.sms.SmsEnvelope;
+import com.android.internal.telephony.cdma.sms.UserData;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.Random;
+
+import static android.telephony.SmsMessage.ENCODING_7BIT;
+import static android.telephony.SmsMessage.ENCODING_8BIT;
+import static android.telephony.SmsMessage.ENCODING_16BIT;
+import static android.telephony.SmsMessage.ENCODING_UNKNOWN;
+import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES;
+import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES_WITH_HEADER;
+import static android.telephony.SmsMessage.MAX_USER_DATA_SEPTETS;
+import static android.telephony.SmsMessage.MAX_USER_DATA_SEPTETS_WITH_HEADER;
+import static android.telephony.SmsMessage.MessageClass;
+import static com.android.internal.telephony.cdma.sms.BearerData.ERROR_NONE;
+import static com.android.internal.telephony.cdma.sms.BearerData.ERROR_TEMPORARY;
+import static com.android.internal.telephony.cdma.sms.BearerData.ERROR_PERMANENT;
+import static com.android.internal.telephony.cdma.sms.BearerData.MESSAGE_TYPE_DELIVER;
+import static com.android.internal.telephony.cdma.sms.BearerData.MESSAGE_TYPE_SUBMIT;
+import static com.android.internal.telephony.cdma.sms.BearerData.MESSAGE_TYPE_CANCELLATION;
+import static com.android.internal.telephony.cdma.sms.BearerData.MESSAGE_TYPE_DELIVERY_ACK;
+import static com.android.internal.telephony.cdma.sms.BearerData.MESSAGE_TYPE_USER_ACK;
+import static com.android.internal.telephony.cdma.sms.BearerData.MESSAGE_TYPE_READ_ACK;
+import static com.android.internal.telephony.cdma.sms.CdmaSmsAddress.SMS_ADDRESS_MAX;
+import static com.android.internal.telephony.cdma.sms.CdmaSmsAddress.SMS_SUBADDRESS_MAX;
+import static com.android.internal.telephony.cdma.sms.SmsEnvelope.SMS_BEARER_DATA_MAX;
+import static com.android.internal.telephony.cdma.sms.UserData.UD_ENCODING_7BIT_ASCII;
+import static com.android.internal.telephony.cdma.sms.UserData.UD_ENCODING_GSM_7BIT_ALPHABET;
+import static com.android.internal.telephony.cdma.sms.UserData.UD_ENCODING_IA5;
+import static com.android.internal.telephony.cdma.sms.UserData.UD_ENCODING_OCTET;
+import static com.android.internal.telephony.cdma.sms.UserData.UD_ENCODING_UNICODE_16;
+
+/**
+ * A Short Message Service message.
+ *
+ */
+public class SmsMessage extends SmsMessageBase {
+    static final String LOG_TAG = "CDMA";
+
+    /**
+     *  Status of a previously submitted SMS.
+     *  This field applies to SMS Delivery Acknowledge messages. 0 indicates success;
+     *  Here, the error class is defined by the bits from 9-8, the status code by the bits from 7-0.
+     *  See C.S0015-B, v2.0, 4.5.21 for a detailed description of possible values.
+     */
+    private int status;
+
+    /** The next message ID for the BearerData. Shall be a random value on first use.
+     * (See C.S0015-B, v2.0, 4.3.1.5)
+     */
+    private static int nextMessageId = 0;
+
+    /** Specifies if this is the first SMS message submit */
+    private static boolean firstSMS = true;
+
+    /** Specifies if a return of an acknowledgment is requested for send SMS */
+    private static final int RETURN_NO_ACK  = 0;
+    private static final int RETURN_ACK     = 1;
+
+    private SmsEnvelope mEnvelope;
+    private BearerData mBearerData;
+
+    public static class SubmitPdu extends SubmitPduBase {
+    }
+
+    /**
+     * Create an SmsMessage from a raw PDU.
+     * Note: In CDMA the PDU is just a byte representation of the received Sms.
+     */
+    public static SmsMessage createFromPdu(byte[] pdu) {
+        SmsMessage msg = new SmsMessage();
+
+        try {
+            msg.parsePdu(pdu);
+            return msg;
+        } catch (RuntimeException ex) {
+            Log.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
+            return null;
+        }
+    }
+
+    /**
+     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
+     */
+    public static SmsMessage newFromCMT(String[] lines) {
+        Log.w(LOG_TAG, "newFromCMT: is not supported in CDMA mode.");
+        return null;
+    }
+
+    /**
+     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
+     */
+    public static SmsMessage newFromCMTI(String line) {
+        Log.w(LOG_TAG, "newFromCMTI: is not supported in CDMA mode.");
+        return null;
+    }
+
+    /**
+     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
+     */
+    public static SmsMessage newFromCDS(String line) {
+        Log.w(LOG_TAG, "newFromCDS: is not supported in CDMA mode.");
+        return null;
+    }
+
+    /**
+     *  Create a "raw" CDMA SmsMessage from a Parcel that was forged in ril.cpp.
+     *  Note: Only primitive fields are set.
+     */
+    public static SmsMessage newFromParcel(Parcel p) {
+        // Note: Parcel.readByte actually reads one Int and masks to byte
+        SmsMessage msg = new SmsMessage();
+        SmsEnvelope env = new SmsEnvelope();
+        CdmaSmsAddress addr = new CdmaSmsAddress();
+        byte[] data;
+        byte count;
+        int countInt;
+
+        //currently not supported by the modem-lib: env.mMessageType
+        env.teleService = p.readInt(); //p_cur->uTeleserviceID
+
+        if (0 != p.readByte()) { //p_cur->bIsServicePresent
+            env.messageType = SmsEnvelope.MESSAGE_TYPE_BROADCAST;
+        }
+        else {
+            if (SmsEnvelope.TELESERVICE_NOT_SET == env.teleService) {
+                // assume type ACK
+                env.messageType = SmsEnvelope.MESSAGE_TYPE_ACKNOWLEDGE;
+            } else {
+                env.messageType = SmsEnvelope.MESSAGE_TYPE_POINT_TO_POINT;
+            }
+        }
+        env.serviceCategory = p.readInt(); //p_cur->uServicecategory
+
+        // address
+        addr.digitMode = (byte) (0xFF & p.readInt()); //p_cur->sAddress.digit_mode
+        addr.numberMode = (byte) (0xFF & p.readInt()); //p_cur->sAddress.number_mode
+        addr.ton = p.readInt(); //p_cur->sAddress.number_type
+        addr.numberPlan = (byte) (0xFF & p.readInt()); //p_cur->sAddress.number_plan
+        count = p.readByte(); //p_cur->sAddress.number_of_digits
+        addr.numberOfDigits = count;
+        data = new byte[count];
+        //p_cur->sAddress.digits[digitCount]
+        for (int index=0; index < count; index++) {
+            data[index] = p.readByte();
+        }
+        addr.origBytes = data;
+
+        // ignore subaddress
+        p.readInt(); //p_cur->sSubAddress.subaddressType
+        p.readByte(); //p_cur->sSubAddress.odd
+        count = p.readByte(); //p_cur->sSubAddress.number_of_digits
+        //p_cur->sSubAddress.digits[digitCount] :
+        for (int index=0; index < count; index++) {
+            p.readByte();
+        }
+
+        /* currently not supported by the modem-lib:
+            env.bearerReply
+            env.replySeqNo
+            env.errorClass
+            env.causeCode
+        */
+
+        // bearer data
+        countInt = p.readInt(); //p_cur->uBearerDataLen
+        if (countInt >0) {
+            data = new byte[countInt];
+             //p_cur->aBearerData[digitCount] :
+            for (int index=0; index < countInt; index++) {
+                data[index] = p.readByte();
+            }
+            env.bearerData = data;
+            // BD gets further decoded when accessed in SMSDispatcher
+        }
+
+        // link the the filled objects to the SMS
+        env.origAddress = addr;
+        msg.originatingAddress = addr;
+        msg.mEnvelope = env;
+
+        // create byte stream representation for transportation through the layers.
+        msg.createPdu();
+
+        return msg;
+    }
+
+    /**
+     * Create an SmsMessage from an SMS EF record.
+     *
+     * @param index Index of SMS record. This should be index in ArrayList
+     *              returned by RuimSmsInterfaceManager.getAllMessagesFromIcc + 1.
+     * @param data Record data.
+     * @return An SmsMessage representing the record.
+     *
+     * @hide
+     */
+    public static SmsMessage createFromEfRecord(int index, byte[] data) {
+        try {
+            SmsMessage msg = new SmsMessage();
+
+            msg.indexOnIcc = index;
+
+            // First byte is status: RECEIVED_READ, RECEIVED_UNREAD, STORED_SENT,
+            // or STORED_UNSENT
+            // See 3GPP2 C.S0023 3.4.27
+            if ((data[0] & 1) == 0) {
+                Log.w(LOG_TAG, "SMS parsing failed: Trying to parse a free record");
+                return null;
+            } else {
+                msg.statusOnIcc = data[0] & 0x07;
+            }
+
+            // Second byte is the MSG_LEN, length of the message
+            // See 3GPP2 C.S0023 3.4.27
+            int size = data[1];
+
+            // Note: Data may include trailing FF's.  That's OK; message
+            // should still parse correctly.
+            byte[] pdu = new byte[size];
+            System.arraycopy(data, 2, pdu, 0, size);
+            // the message has to be parsed before it can be displayed
+            // see gsm.SmsMessage
+            return msg;
+        } catch (RuntimeException ex) {
+            Log.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
+            return null;
+        }
+
+    }
+
+    /**
+     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
+     */
+    public static int getTPLayerLengthForPDU(String pdu) {
+        Log.w(LOG_TAG, "getTPLayerLengthForPDU: is not supported in CDMA mode.");
+        return 0;
+    }
+
+    /**
+     * Get an SMS-SUBMIT PDU for a destination address and a message
+     *
+     * @param scAddress             Service Centre address.  Null means use default.
+     * @param destinationAddress    Address of the recipient.
+     * @param message               String representation of the message payload.
+     * @param statusReportRequested Indicates whether a report is requested for this message.
+     * @param headerData            Array containing the data for the User Data Header, preceded
+     *                              by the Element Identifiers.
+     * @return a <code>SubmitPdu</code> containing the encoded SC
+     *         address, if applicable, and the encoded message.
+     *         Returns null on encode error.
+     * @hide
+     */
+    public static SubmitPdu getSubmitPdu(String scAddress,
+            String destinationAddress, String message,
+            boolean statusReportRequested, byte[] headerData) {
+
+        SmsMessage sms = new SmsMessage();
+        SubmitPdu ret = new SubmitPdu();
+        UserData uData = new UserData();
+        SmsHeader smsHeader;
+
+        // Perform null parameter checks.
+        if (message == null || destinationAddress == null) {
+            return null;
+        }
+
+        // ** Set UserData + SmsHeader **
+        try {
+            // First, try encoding it with the GSM alphabet
+            int septetCount = GsmAlphabet.countGsmSeptets(message, true);
+            // User Data (and length)
+
+            uData.userData = message.getBytes();
+
+            if (uData.userData.length > MAX_USER_DATA_SEPTETS) {
+                // Message too long
+                return null;
+            }
+
+            // desired TP-Data-Coding-Scheme
+            uData.userDataEncoding = UserData.UD_ENCODING_GSM_7BIT_ALPHABET;
+
+            // paddingBits not needed for UD_ENCODING_GSM_7BIT_ALPHABET
+
+            // sms header
+            if(headerData != null) {
+                smsHeader = SmsHeader.parse(headerData);
+                uData.userDataHeader = smsHeader;
+            } else {
+                // no user data header available!
+            }
+
+        } catch (EncodeException ex) {
+            byte[] textPart;
+            // Encoding to the 7-bit alphabet failed. Let's see if we can
+            // send it as a UCS-2 encoded message
+
+            try {
+                textPart = message.getBytes("utf-16be");
+            } catch (UnsupportedEncodingException uex) {
+                Log.e(LOG_TAG, "Implausible UnsupportedEncodingException ", uex);
+                return null;
+            }
+
+            uData.userData = textPart;
+
+            if (uData.userData.length > MAX_USER_DATA_BYTES) {
+                // Message too long
+                return null;
+            }
+
+            // TP-Data-Coding-Scheme
+            uData.userDataEncoding = UserData.UD_ENCODING_UNICODE_16;
+
+            // sms header
+            if(headerData != null) {
+                smsHeader = SmsHeader.parse(headerData);
+                uData.userDataHeader = smsHeader;
+            } else {
+                // no user data header available!
+            }
+        }
+
+        byte[] data = sms.getEnvelope(destinationAddress, statusReportRequested, uData,
+                (headerData != null), (null == headerData));
+
+        if (null == data) return null;
+
+        ret.encodedMessage = data;
+        ret.encodedScAddress = null;
+        return ret;
+    }
+
+
+    /**
+     * Get an SMS-SUBMIT PDU for a destination address and a message
+     *
+     * @param scAddress Service Centre address.  Null means use default.
+     * @return a <code>SubmitPdu</code> containing the encoded SC
+     *         address, if applicable, and the encoded message.
+     *         Returns null on encode error.
+     */
+    public static SubmitPdu getSubmitPdu(String scAddress,
+            String destinationAddress, String message,
+            boolean statusReportRequested) {
+        return getSubmitPdu(scAddress, destinationAddress, message, statusReportRequested, null);
+    }
+
+    /**
+     * Get an SMS-SUBMIT PDU for a data message to a destination address &amp; port
+     *
+     * @param scAddress Service Centre address. null == use default
+     * @param destinationAddress the address of the destination for the message
+     * @param destinationPort the port to deliver the message to at the
+     *        destination
+     * @param data the data for the message
+     * @return a <code>SubmitPdu</code> containing the encoded SC
+     *         address, if applicable, and the encoded message.
+     *         Returns null on encode error.
+     */
+    public static SubmitPdu getSubmitPdu(String scAddress,
+            String destinationAddress, short destinationPort, byte[] data,
+            boolean statusReportRequested) {
+
+        SmsMessage sms = new SmsMessage();
+        SubmitPdu ret = new SubmitPdu();
+        UserData uData = new UserData();
+        SmsHeader smsHeader = new SmsHeader();
+
+        if (data.length > (MAX_USER_DATA_BYTES - 7 /* UDH size */)) {
+            Log.e(LOG_TAG, "SMS data message may only contain "
+                    + (MAX_USER_DATA_BYTES - 7) + " bytes");
+            return null;
+        }
+
+        byte[] destPort = new byte[4];
+        destPort[0] = (byte) ((destinationPort >> 8) & 0xFF); // MSB of destination port
+        destPort[1] = (byte) (destinationPort & 0xFF); // LSB of destination port
+        destPort[2] = 0x00; // MSB of originating port
+        destPort[3] = 0x00; // LSB of originating port
+        smsHeader.add(
+                new SmsHeader.Element(SmsHeader.APPLICATION_PORT_ADDRESSING_16_BIT, destPort));
+
+        smsHeader.nbrOfHeaders = smsHeader.getElements().size();
+        uData.userDataHeader = smsHeader;
+
+        // TP-Data-Coding-Scheme
+        // No class, 8 bit data
+        uData.userDataEncoding = UserData.UD_ENCODING_OCTET;
+        uData.userData = data;
+
+        byte[] msgData = sms.getEnvelope(destinationAddress, statusReportRequested, uData,
+                true, true);
+
+        ret.encodedMessage = msgData;
+        ret.encodedScAddress = null;
+        return ret;
+    }
+
+    static class PduParser {
+
+        PduParser() {
+        }
+
+        /**
+         * Parses an SC timestamp and returns a currentTimeMillis()-style
+         * timestamp
+         */
+        static long getSCTimestampMillis(byte[] timestamp) {
+            // TP-Service-Centre-Time-Stamp
+            int year = IccUtils.beBcdByteToInt(timestamp[0]);
+            int month = IccUtils.beBcdByteToInt(timestamp[1]);
+            int day = IccUtils.beBcdByteToInt(timestamp[2]);
+            int hour = IccUtils.beBcdByteToInt(timestamp[3]);
+            int minute = IccUtils.beBcdByteToInt(timestamp[4]);
+            int second = IccUtils.beBcdByteToInt(timestamp[5]);
+
+            Time time = new Time(Time.TIMEZONE_UTC);
+
+            // C.S0015-B v2.0, 4.5.4: range is 1996-2095
+            time.year = year >= 96 ? year + 1900 : year + 2000;
+            time.month = month - 1;
+            time.monthDay = day;
+            time.hour = hour;
+            time.minute = minute;
+            time.second = second;
+
+            return time.toMillis(true);
+        }
+
+    }
+
+    /**
+     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
+     */
+    public int getProtocolIdentifier() {
+        Log.w(LOG_TAG, "getProtocolIdentifier: is not supported in CDMA mode.");
+        // (3GPP TS 23.040): "no interworking, but SME to SME protocol":
+        return 0;
+    }
+
+    /**
+     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
+     */
+    public boolean isReplace() {
+        Log.w(LOG_TAG, "isReplace: is not supported in CDMA mode.");
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
+     */
+    public boolean isCphsMwiMessage() {
+        Log.w(LOG_TAG, "isCphsMwiMessage: is not supported in CDMA mode.");
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isMWIClearMessage() {
+        if ((mBearerData != null) && (0 == mBearerData.numberOfMessages)) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isMWISetMessage() {
+        if ((mBearerData != null) && (mBearerData.numberOfMessages >0)) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isMwiDontStore() {
+        if ((mBearerData != null) && (mBearerData.numberOfMessages >0)
+                && (null == mBearerData.userData)) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Returns the status for a previously submitted message.
+     * For not interfering with status codes from GSM, this status code is
+     * shifted to the bits 31-16.
+     */
+    public int getStatus() {
+        return(status<<16);
+    }
+
+    /**
+     *  Note: This function is a GSM specific functionality which is not supported in CDMA mode.
+     */
+    public boolean isStatusReportMessage() {
+        Log.w(LOG_TAG, "isStatusReportMessage: is not supported in CDMA mode.");
+        return false;
+    }
+
+    /**
+     * Note: This function is a GSM specific functionality which is not supported in CDMA mode.
+     */
+    public boolean isReplyPathPresent() {
+        Log.w(LOG_TAG, "isReplyPathPresent: is not supported in CDMA mode.");
+        return false;
+    }
+
+    /**
+     * Returns the teleservice type of the message.
+     * @return the teleservice:
+     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_NOT_SET},
+     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_WMT},
+     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_WEMT},
+     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_VMN},
+     *  {@link com.android.internal.telephony.cdma.sms.SmsEnvelope#TELESERVICE_WAP}
+    */
+    public int getTeleService() {
+        return mEnvelope.teleService;
+    }
+
+    /**
+     * Decodes pdu to an empty SMS object.
+     * In the CDMA case the pdu is just an internal byte stream representation
+     * of the SMS Java-object.
+     * @see #createPdu()
+     */
+    private void parsePdu(byte[] pdu) {
+        ByteArrayInputStream bais = new ByteArrayInputStream(pdu);
+        DataInputStream dis = new DataInputStream(new BufferedInputStream(bais));
+        byte length;
+        SmsEnvelope env = new SmsEnvelope();
+        CdmaSmsAddress addr = new CdmaSmsAddress();
+
+        try {
+            env.messageType = dis.readInt();
+            env.teleService = dis.readInt();
+            env.serviceCategory = dis.readInt();
+
+            addr.digitMode = dis.readByte();
+            addr.numberMode = dis.readByte();
+            addr.ton = dis.readByte();
+            addr.numberPlan = dis.readByte();
+
+            length = dis.readByte();
+            addr.numberOfDigits = length;
+            addr.origBytes = new byte[length];
+            dis.read(addr.origBytes, 0, length); // digits
+
+            env.bearerReply = dis.readInt();
+            // CauseCode values:
+            env.replySeqNo = dis.readByte();
+            env.errorClass = dis.readByte();
+            env.causeCode = dis.readByte();
+
+            //encoded BearerData:
+            length = dis.readByte();
+            env.bearerData = new byte[length];
+            dis.read(env.bearerData, 0, length);
+            dis.close();
+        } catch (Exception ex) {
+            Log.e(LOG_TAG, "createFromPdu: conversion from byte array to object failed: " + ex);
+        }
+
+        // link the filled objects to this SMS
+        originatingAddress = addr;
+        env.origAddress = addr;
+        mEnvelope = env;
+
+        parseSms();
+    }
+
+    /**
+     * Parses a SMS message from its BearerData stream. (mobile-terminated only)
+     */
+    protected void parseSms() {
+        mBearerData = SmsDataCoding.decodeCdmaSms(mEnvelope.bearerData);
+        messageRef = mBearerData.messageID;
+
+        // TP-Message-Type-Indicator
+        // (See 3GPP2 C.S0015-B, v2, 4.5.1)
+        int messageType = mBearerData.messageType;
+
+        switch (messageType) {
+        case MESSAGE_TYPE_USER_ACK:
+        case MESSAGE_TYPE_READ_ACK:
+        case MESSAGE_TYPE_DELIVER:
+            // Deliver (mobile-terminated only)
+            parseSmsDeliver();
+            break;
+        case MESSAGE_TYPE_DELIVERY_ACK:
+            parseSmsDeliveryAck();
+            break;
+
+        default:
+            // the rest of these
+            throw new RuntimeException("Unsupported message type: " + messageType);
+        }
+    }
+
+    /**
+     * Parses a SMS-DELIVER message. (mobile-terminated only)
+     * See 3GPP2 C.S0015-B, v2, 4.4.1
+     */
+    private void parseSmsDeliver() {
+        if (originatingAddress != null) {
+            originatingAddress.address = new String(originatingAddress.origBytes);
+            if (Config.LOGV) Log.v(LOG_TAG, "SMS originating address: "
+                    + originatingAddress.address);
+        }
+
+        if (mBearerData.timeStamp != null) {
+                scTimeMillis = PduParser.getSCTimestampMillis(mBearerData.timeStamp);
+        }
+
+        if (Config.LOGD) Log.d(LOG_TAG, "SMS SC timestamp: " + scTimeMillis);
+
+        parseUserData(mBearerData.userData);
+    }
+
+    /**
+     * Parses a SMS-DELIVER message. (mobile-terminated only)
+     * See 3GPP2 C.S0015-B, v2, 4.4.1
+     */
+    private void parseSmsDeliveryAck() {
+        if (originatingAddress != null) {
+            originatingAddress.address = new String(originatingAddress.origBytes);
+            if (Config.LOGV) Log.v(LOG_TAG, "SMS originating address: "
+                    + originatingAddress.address);
+        }
+
+        if (mBearerData.timeStamp != null) {
+                scTimeMillis = PduParser.getSCTimestampMillis(mBearerData.timeStamp);
+        }
+
+        if (Config.LOGD) Log.d(LOG_TAG, "SMS SC timestamp: " + scTimeMillis);
+
+        if (mBearerData.errorClass != BearerData.ERROR_UNDEFINED) {
+            status = mBearerData.errorClass << 8;
+            status |= mBearerData.messageStatus;
+        }
+
+        parseUserData(mBearerData.userData);
+
+    }
+
+    /**
+     * Parses the User Data of an SMS.
+     */
+    private void parseUserData(UserData uData) {
+        int encodingType;
+
+        if (null == uData) {
+            return;
+        }
+
+        encodingType = uData.userDataEncoding;
+
+        // insert DCS-decoding here when type is supported by ril-library
+
+        userData = uData.userData;
+        userDataHeader = uData.userDataHeader;
+
+        switch (encodingType) {
+        case UD_ENCODING_GSM_7BIT_ALPHABET:
+        case UD_ENCODING_UNICODE_16:
+            // user data was already decoded by wmsts-library
+            messageBody = new String(userData);
+            break;
+
+        // data and unsupported encodings:
+        case UD_ENCODING_OCTET:
+        default:
+            messageBody = null;
+            break;
+        }
+
+        if (Config.LOGV) Log.v(LOG_TAG, "SMS message body (raw): '" + messageBody + "'");
+
+        if (messageBody != null) {
+            parseMessageBody();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public MessageClass getMessageClass() {
+        if (BearerData.DISPLAY_IMMEDIATE == mBearerData.displayMode ) {
+            return MessageClass.CLASS_0;
+        } else {
+            return MessageClass.UNKNOWN;
+        }
+    }
+
+    /**
+     * Creates BearerData and Envelope from parameters for a Submit SMS.
+     * @return byte stream for SubmitPdu.
+     */
+    private byte[] getEnvelope(String destinationAddress, boolean statusReportRequested,
+            UserData userData, boolean hasHeaders, boolean useNewId) {
+
+        BearerData mBearerData = new BearerData();
+        SmsEnvelope env = new SmsEnvelope();
+        CdmaSmsAddress mSmsAddress = new CdmaSmsAddress();
+
+        // ** set SmsAddress **
+        mSmsAddress.digitMode = CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR;
+        try {
+            mSmsAddress.origBytes = destinationAddress.getBytes("UTF-8");
+        } catch (Exception e) {
+            Log.e(LOG_TAG, "doGetSubmitPdu: conversion of destinationAddress from string to byte[]"
+                    + " failed: " + e.getMessage());
+            return null;
+        }
+        mSmsAddress.numberOfDigits = (byte)mSmsAddress.origBytes.length;
+        mSmsAddress.numberMode = CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK;
+        // see C.S0015-B, v2.0, 3.4.3.3
+        mSmsAddress.numberPlan = CdmaSmsAddress.NUMBERING_PLAN_ISDN_TELEPHONY;
+        mSmsAddress.ton = CdmaSmsAddress.TON_INTERNATIONAL_OR_IP;
+
+        // ** set BearerData **
+        mBearerData.userData = userData;
+        mBearerData.messageType = BearerData.MESSAGE_TYPE_SUBMIT;
+
+        if (useNewId) {
+            setNextMessageId();
+        }
+        mBearerData.messageID = nextMessageId;
+
+        // Set the reply options (See C.S0015-B, v2.0, 4.5.11)
+        if(statusReportRequested) {
+            mBearerData.deliveryAckReq = true;
+        } else {
+            mBearerData.deliveryAckReq = false;
+        }
+        // Currently settings applications do not support this
+        mBearerData.userAckReq = false;
+        mBearerData.readAckReq = false;
+        mBearerData.reportReq = false;
+
+        // Set the display mode (See C.S0015-B, v2.0, 4.5.16)
+        mBearerData.displayMode = BearerData.DISPLAY_DEFAULT;
+
+        // number of messages: not needed for encoding!
+
+        // indicate whether a user data header is available
+        mBearerData.hasUserDataHeader = hasHeaders;
+
+        // ** encode BearerData **
+        byte[] encodedBearerData = null;
+        try {
+            encodedBearerData = SmsDataCoding.encodeCdmaSms(mBearerData);
+        } catch (Exception e) {
+            Log.e(LOG_TAG, "doGetSubmitPdu: EncodeCdmaSMS function in JNI interface failed: "
+                    + e.getMessage());
+            return null;
+        }
+
+        // ** SmsEnvelope **
+        env.messageType = SmsEnvelope.MESSAGE_TYPE_POINT_TO_POINT;
+        env.teleService = SmsEnvelope.TELESERVICE_WEMT;
+        env.destAddress = mSmsAddress;
+        env.bearerReply = RETURN_ACK;
+        env.bearerData = encodedBearerData;
+        mEnvelope = env;
+
+        // get byte array output stream from SmsAddress object and SmsEnvelope member.
+        return serialize(mSmsAddress);
+    }
+
+    /**
+     * Set the nextMessageId to a random value between 0 and 65536
+     * See C.S0015-B, v2.0, 4.3.1.5
+     */
+    private void setNextMessageId() {
+        // Message ID, modulo 65536
+        if(firstSMS) {
+            Random generator = new Random();
+            nextMessageId = generator.nextInt(65536);
+            firstSMS = false;
+        } else {
+            nextMessageId = ++nextMessageId & 0xFFFF;
+        }
+    }
+
+    /**
+     * Creates ByteArrayOutputStream from CdmaSmsAddress and SmsEnvelope objects
+     *
+     * @param address CdmaSmsAddress object
+     * @return ByteArrayOutputStream
+     */
+    private byte[] serialize(CdmaSmsAddress destAddress) {
+        SmsEnvelope env = mEnvelope;
+        ByteArrayOutputStream baos = new ByteArrayOutputStream(100);
+        DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(baos));
+
+        try {
+            dos.writeInt(env.teleService);
+            dos.writeInt(0); //servicePresent
+            dos.writeInt(0); //serviceCategory
+            dos.write(destAddress.digitMode);
+            dos.write(destAddress.numberMode);
+            dos.write(destAddress.ton); // number_type
+            dos.write(destAddress.numberPlan);
+            dos.write(destAddress.numberOfDigits);
+            dos.write(destAddress.origBytes, 0, destAddress.origBytes.length); // digits
+            // Subaddress is not supported.
+            dos.write(0); //subaddressType
+            dos.write(0); //subaddr_odd
+            dos.write(0); //subaddr_nbr_of_digits
+            dos.write(env.bearerData.length);
+            dos.write(env.bearerData, 0, env.bearerData.length);
+            dos.close();
+            return baos.toByteArray();
+        } catch(IOException ex) {
+            Log.e(LOG_TAG, "serialize: conversion from object to data output stream failed: " + ex);
+            return null;
+        }
+    }
+
+    /**
+     * Creates byte array (pseudo pdu) from SMS object.
+     * Note: Do not call this method more than once per object!
+     */
+    private void createPdu() {
+        SmsEnvelope env = mEnvelope;
+        CdmaSmsAddress addr = env.origAddress;
+        ByteArrayOutputStream baos = new ByteArrayOutputStream(100);
+        DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(baos));
+
+        try {
+            dos.writeInt(env.messageType);
+            dos.writeInt(env.teleService);
+            dos.writeInt(env.serviceCategory);
+
+            dos.writeByte(addr.digitMode);
+            dos.writeByte(addr.numberMode);
+            dos.writeByte(addr.ton);
+            dos.writeByte(addr.numberPlan);
+            dos.writeByte(addr.numberOfDigits);
+            dos.write(addr.origBytes, 0, addr.origBytes.length); // digits
+
+            dos.writeInt(env.bearerReply);
+            // CauseCode values:
+            dos.writeByte(env.replySeqNo);
+            dos.writeByte(env.errorClass);
+            dos.writeByte(env.causeCode);
+            //encoded BearerData:
+            dos.writeByte(env.bearerData.length);
+            dos.write(env.bearerData, 0, env.bearerData.length);
+            dos.close();
+
+            mPdu = baos.toByteArray();
+        } catch (IOException ex) {
+            Log.e(LOG_TAG, "createPdu: conversion from object to byte array failed: " + ex);
+        }
+    }
+
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/TtyIntent.java b/telephony/java/com/android/internal/telephony/cdma/TtyIntent.java
new file mode 100644
index 0000000..f27f79c
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/TtyIntent.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony.cdma;
+
+public class TtyIntent {
+
+    private static final String TAG = "TtyIntent";
+
+
+    /** Event for TTY mode change */
+
+    /**
+     * Broadcast intent action indicating that the TTY has either been
+     * enabled or disabled. An intent extra provides this state as a boolean,
+     * where {@code true} means enabled.
+     * @see #TTY_ENABLED
+     *
+     * {@hide}
+     */
+    public static final String TTY_ENABLED_CHANGE_ACTION =
+        "com.android.internal.telephony.cdma.intent.action.TTY_ENABLED_CHANGE";
+
+    /**
+     * The lookup key for a boolean that indicates whether TTY mode is enabled or
+     * disabled. {@code true} means TTY mode is enabled. Retrieve it with
+     * {@link android.content.Intent#getBooleanExtra(String,boolean)}.
+     *
+     * {@hide}
+     */
+    public static final String TTY_ENABLED = "ttyEnabled";
+
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/package.html b/telephony/java/com/android/internal/telephony/cdma/package.html
new file mode 100644
index 0000000..cf1ad4a
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/package.html
@@ -0,0 +1,6 @@
+<HTML>
+<BODY>
+Provides classes to control or read data from CDMA phones. 
+@hide
+</BODY>
+</HTML>
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
new file mode 100644
index 0000000..fec9529
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 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.
+ * 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.internal.telephony.cdma.sms;
+
+public final class BearerData{
+
+    // For completeness the following fields are listed, though not used yet.
+    /**
+     * Supported priority modes for CDMA SMS messages
+     * (See 3GPP2 C.S0015-B, v2.0, table 4.5.9-1)
+     */
+    //public static final int PRIORITY_NORMAL        = 0x0;
+    //public static final int PRIORITY_INTERACTIVE   = 0x1;
+    //public static final int PRIORITY_URGENT        = 0x2;
+    //public static final int PRIORITY_EMERGENCY     = 0x3;
+
+    /**
+     * Supported privacy modes for CDMA SMS messages
+     * (See 3GPP2 C.S0015-B, v2.0, table 4.5.10-1)
+     */
+    //public static final int PRIVACY_NOT_RESTRICTED = 0x0;
+    //public static final int PRIVACY_RESTRICTED     = 0x1;
+    //public static final int PRIVACY_CONFIDENTIAL   = 0x2;
+    //public static final int PRIVACY_SECRET         = 0x3;
+
+    /**
+     * Supported alert modes for CDMA SMS messages
+     * (See 3GPP2 C.S0015-B, v2.0, table 4.5.13-1)
+     */
+    //public static final int ALERT_DEFAULT          = 0x0;
+    //public static final int ALERT_LOW_PRIO         = 0x1;
+    //public static final int ALERT_MEDIUM_PRIO      = 0x2;
+    //public static final int ALERT_HIGH_PRIO        = 0x3;
+
+    /**
+     * Supported display modes for CDMA SMS messages
+     * (See 3GPP2 C.S0015-B, v2.0, table 4.5.16-1)
+     */
+    public static final int DISPLAY_IMMEDIATE      = 0x0;
+    public static final int DISPLAY_DEFAULT        = 0x1;
+    public static final int DISPLAY_USER           = 0x2;
+
+    /**
+     * Supported message types for CDMA SMS messages
+     * (See 3GPP2 C.S0015-B, v2.0, table 4.5.1-1)
+     */
+    public static final int MESSAGE_TYPE_DELIVER        = 0x01;
+    public static final int MESSAGE_TYPE_SUBMIT         = 0x02;
+    public static final int MESSAGE_TYPE_CANCELLATION   = 0x03;
+    public static final int MESSAGE_TYPE_DELIVERY_ACK   = 0x04;
+    public static final int MESSAGE_TYPE_USER_ACK       = 0x05;
+    public static final int MESSAGE_TYPE_READ_ACK       = 0x06;
+    public static final int MESSAGE_TYPE_DELIVER_REPORT = 0x07;
+    public static final int MESSAGE_TYPE_SUBMIT_REPORT  = 0x08;
+
+    /**
+     * SMS Message Status Codes
+     * (See 3GPP2 C.S0015-B, v2.0, table 4.5.21-1)
+     */
+    /* no-error codes */
+    public static final int ERROR_NONE                   = 0x00;
+    public static final int STATUS_ACCEPTED              = 0x00;
+    public static final int STATUS_DEPOSITED_TO_INTERNET = 0x01;
+    public static final int STATUS_DELIVERED             = 0x02;
+    public static final int STATUS_CANCELLED             = 0x03;
+    /* temporary-error and permanent-error codes */
+    public static final int ERROR_TEMPORARY              = 0x02;
+    public static final int STATUS_NETWORK_CONGESTION    = 0x04;
+    public static final int STATUS_NETWORK_ERROR         = 0x05;
+    public static final int STATUS_UNKNOWN_ERROR         = 0x1F;
+    /* permanent-error codes */
+    public static final int ERROR_PERMANENT              = 0x03;
+    public static final int STATUS_CANCEL_FAILED         = 0x06;
+    public static final int STATUS_BLOCKED_DESTINATION   = 0x07;
+    public static final int STATUS_TEXT_TOO_LONG         = 0x08;
+    public static final int STATUS_DUPLICATE_MESSAGE     = 0x09;
+    public static final int STATUS_INVALID_DESTINATION   = 0x0A;
+    public static final int STATUS_MESSAGE_EXPIRED       = 0x0D;
+    /* undefined-status codes */
+    public static final int ERROR_UNDEFINED              = 0xFF;
+    public static final int STATUS_UNDEFINED             = 0xFF;
+
+    /** Bit-mask indicating used fields for SmsDataCoding */
+    public int mask;
+
+    /**
+     * 4-bit value indicating the message type in accordance to
+     *      table 4.5.1-1
+     * (See 3GPP2 C.S0015-B, v2, 4.5.1)
+     */
+    public byte messageType;
+
+    /**
+     * 16-bit value indicating the message ID, which increments modulo 65536.
+     * (Special rules apply for WAP-messages.)
+     * (See 3GPP2 C.S0015-B, v2, 4.5.1)
+     */
+    public int messageID;
+
+    /**
+     * 1-bit value that indicates whether a User Data Header is present.
+     * (See 3GPP2 C.S0015-B, v2, 4.5.1)
+     */
+    public boolean hasUserDataHeader;
+
+    /**
+     * provides the information for the user data
+     * (e.g. padding bits, user data, user data header, etc)
+     * (See 3GPP2 C.S.0015-B, v2, 4.5.2)
+     */
+    public UserData userData;
+
+    //public UserResponseCode userResponseCode;
+
+    /**
+     * 6-byte-field, see 3GPP2 C.S0015-B, v2, 4.5.4
+     * year, month, day, hours, minutes, seconds;
+     */
+    public byte[] timeStamp;
+
+    //public SmsTime validityPeriodAbsolute;
+    //public SmsRelTime validityPeriodRelative;
+    //public SmsTime deferredDeliveryTimeAbsolute;
+    //public SmsRelTime deferredDeliveryTimeRelative;
+    //public byte priority;
+    //public byte privacy;
+
+    /**
+     * Reply Option
+     * 1-bit values which indicate whether SMS acknowledgment is requested or not.
+     * (See 3GPP2 C.S0015-B, v2, 4.5.11)
+     */
+    public boolean userAckReq;
+    public boolean deliveryAckReq;
+    public boolean readAckReq;
+    public boolean reportReq;
+
+    /**
+     * The number of Messages element (8-bit value) is a decimal number in the 0 to 99 range
+     * representing the number of messages stored at the Voice Mail System. This element is
+     * used by the Voice Mail Notification service.
+     * (See 3GPP2 C.S0015-B, v2, 4.5.12)
+     */
+    public int numberOfMessages;
+
+    //public int alert;
+    //public int language;
+
+    /**
+     * 4-bit or 8-bit value that indicates the number to be dialed in reply to a
+     * received SMS message.
+     * (See 3GPP2 C.S0015-B, v2, 4.5.15)
+     */
+    public CdmaSmsAddress callbackNumber;
+
+    /**
+     * 2-bit value that is used to indicate to the mobile station when to display
+     * the received message.
+     * (See 3GPP2 C.S0015-B, v2, 4.5.16)
+     */
+    public byte displayMode = DISPLAY_DEFAULT;
+
+    /**
+     * First component of the Message status, that indicates if an error has occurred
+     * and whether the error is considered permanent or temporary.
+     * (See 3GPP2 C.S0015-B, v2, 4.5.21)
+     */
+    public int errorClass = ERROR_UNDEFINED;
+
+    /**
+     * Second component of the Message status, that indicates if an error has occurred
+     * and the cause of the error.
+     * (See 3GPP2 C.S0015-B, v2, 4.5.21)
+     */
+    public int messageStatus = STATUS_UNDEFINED;
+
+}
+
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/CdmaSmsAddress.java b/telephony/java/com/android/internal/telephony/cdma/sms/CdmaSmsAddress.java
new file mode 100644
index 0000000..1643cab
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/CdmaSmsAddress.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 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.
+ * 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.internal.telephony.cdma.sms;
+
+import com.android.internal.telephony.SmsAddress;
+
+public class CdmaSmsAddress extends SmsAddress {
+    /**
+     * digit mode indicators
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.3)
+     */
+    static public final int DIGIT_MODE_4BIT_DTMF              = 0x00;
+    static public final int DIGIT_MODE_8BIT_CHAR              = 0x01;
+
+    /**
+     * number mode indicators
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.3)
+     */
+    static public final int NUMBER_MODE_NOT_DATA_NETWORK      = 0x00;
+    static public final int NUMBER_MODE_DATA_NETWORK          = 0x01;
+
+    /**
+     *  number types for data networks
+     *  (See 3GPP2 C.S0015-B, v2, 3.4.3.3)
+     */
+    static public final int TON_UNKNOWN                   = 0x00;
+    static public final int TON_INTERNATIONAL_OR_IP       = 0x01;
+    static public final int TON_NATIONAL_OR_EMAIL         = 0x02;
+    static public final int TON_NETWORK                   = 0x03;
+    static public final int TON_SUBSCRIBER                = 0x04;
+    static public final int TON_ALPHANUMERIC              = 0x05;
+    static public final int TON_ABBREVIATED               = 0x06;
+    static public final int TON_RESERVED                  = 0x07;
+
+    /**
+     *  maximum lengths for fields as defined in ril_cdma_sms.h
+     */
+    static public final int SMS_ADDRESS_MAX          =  36;
+    static public final int SMS_SUBADDRESS_MAX       =  36;
+
+    /**
+     *  Supported numbering plan identification
+     *  (See C.S005-D, v1.0, table 2.7.1.3.2.4-3)
+     */
+    static public final int NUMBERING_PLAN_UNKNOWN           = 0x0;
+    static public final int NUMBERING_PLAN_ISDN_TELEPHONY    = 0x1;
+    //static protected final int NUMBERING_PLAN_DATA              = 0x3;
+    //static protected final int NUMBERING_PLAN_TELEX             = 0x4;
+    //static protected final int NUMBERING_PLAN_PRIVATE           = 0x9;
+
+    /**
+     * 1-bit value that indicates whether the address digits are 4-bit DTMF codes
+     * or 8-bit codes.
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.3)
+     */
+    public byte digitMode;
+
+    /**
+     * 1-bit value that indicates whether the address type is a data network address or not.
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.3)
+     */
+    public byte numberMode;
+
+    // use parent class member ton instead public byte numberType;
+
+    /**
+     * 0 or 4-bit value that indicates which numbering plan identification is set.
+     * (See 3GPP2, C.S0015-B, v2, 3.4.3.3 and C.S005-D, table2.7.1.3.2.4-3)
+     */
+    public byte numberPlan;
+
+    /**
+     * This field shall be set to the number of address digits
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.3)
+     */
+    public byte numberOfDigits;
+
+    // use parent class member orig_bytes instead of public byte[] digits;
+
+    // Constructor
+    public CdmaSmsAddress(){
+    }
+
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/SmsDataCoding.java b/telephony/java/com/android/internal/telephony/cdma/sms/SmsDataCoding.java
new file mode 100644
index 0000000..6ba7463
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/SmsDataCoding.java
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2007 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.internal.telephony.cdma.sms;
+
+import com.android.internal.telephony.SmsHeader;
+
+/*
+ * The SMSDataCoding class encodes and decodes CDMA SMS messages.
+ */
+public class SmsDataCoding {
+    private final static String TAG = "CDMA_SMS_JNI";
+
+    private final static int CDMA_SMS_WMS_MASK_BD_NULL             =   0x00000000;
+    private final static int CDMA_SMS_WMS_MASK_BD_MSG_ID           =   0x00000001;
+    private final static int CDMA_SMS_WMS_MASK_BD_USER_DATA        =   0x00000002;
+//    private final static int CDMA_SMS_WMS_MASK_BD_USER_RESP        =   0x00000004;
+    private final static int CDMA_SMS_WMS_MASK_BD_MC_TIME          =   0x00000008;
+//    private final static int CDMA_SMS_WMS_MASK_BD_VALID_ABS        =   0x00000010;
+//    private final static int CDMA_SMS_WMS_MASK_BD_VALID_REL        =   0x00000020;
+//    private final static int CDMA_SMS_WMS_MASK_BD_DEFER_ABS        =   0x00000040;
+//    private final static int CDMA_SMS_WMS_MASK_BD_DEFER_REL        =   0x00000080;
+//    private final static int CDMA_SMS_WMS_MASK_BD_PRIORITY         =   0x00000100;
+//    private final static int CDMA_SMS_WMS_MASK_BD_PRIVACY          =   0x00000200;
+//    private final static int CDMA_SMS_WMS_MASK_BD_REPLY_OPTION     =   0x00000400;
+    private final static int CDMA_SMS_WMS_MASK_BD_NUM_OF_MSGS      =   0x00000800;
+//    private final static int CDMA_SMS_WMS_MASK_BD_ALERT            =   0x00001000;
+//    private final static int CDMA_SMS_WMS_MASK_BD_LANGUAGE         =   0x00002000;
+    private final static int CDMA_SMS_WMS_MASK_BD_CALLBACK         =   0x00004000;
+    private final static int CDMA_SMS_WMS_MASK_BD_DISPLAY_MODE     =   0x00008000;
+//    private final static int CDMA_SMS_WMS_MASK_BD_SCPT_DATA        =   0x00010000;
+//    private final static int CDMA_SMS_WMS_MASK_BD_SCPT_RESULT      =   0x00020000;
+//    private final static int CDMA_SMS_WMS_MASK_BD_DEPOSIT_INDEX    =   0x00040000;
+//    private final static int CDMA_SMS_WMS_MASK_BD_DELIVERY_STATUS  =   0x00080000;
+//    private final static int CDMA_SMS_WMS_MASK_BD_IP_ADDRESS       =   0x10000000;
+//    private final static int CDMA_SMS_WMS_MASK_BD_RSN_NO_NOTIFY    =   0x20000000;
+//    private final static int CDMA_SMS_WMS_MASK_BD_OTHER            =   0x40000000;
+
+    /**
+     * Successful operation.
+     */
+    private static final int JNI_CDMA_SMS_SUCCESS = 0;
+
+    /**
+     * General failure.
+     */
+    private static final int JNI_CDMA_SMS_FAILURE = 1;
+
+    /**
+     * Data length is out of length.
+     */
+    private static final int JNI_CDMA_SMS_DATA_LEN_OUT_OF_RANGE = 2;
+
+    /**
+     * Class name unknown.
+     */
+    private static final int JNI_CDMA_SMS_CLASS_UNKNOWN = 3;
+
+    /**
+     * Field ID unknown.
+     */
+    private static final int JNI_CDMA_SMS_FIELD_ID_UNKNOWN = 4;
+
+    /**
+     * Memory allocation failed.
+     */
+    private static final int JNI_CDMA_SMS_OUT_OF_MEMORY = 5;
+
+    /**
+     * Encode SMS.
+     *
+     * @param bearerData    an instance of BearerData.
+     *
+     * @return the encoded SMS as byte[].
+     */
+    public static byte[] encodeCdmaSms(BearerData bearerData) {
+        byte[] encodedSms;
+
+        if( nativeCdmaSmsConstructClientBD() == JNI_CDMA_SMS_FAILURE){
+            return null;
+        }
+
+        // check bearer data and generate bit mask
+        generateBearerDataBitMask(bearerData);
+        encodedSms = startEncoding(bearerData);
+
+        if( nativeCdmaSmsDestructClientBD() == JNI_CDMA_SMS_FAILURE){
+            return null;
+        }
+        return encodedSms;
+    }
+
+    /**
+     * Decode SMS.
+     *
+     * @param SmsData    the encoded SMS.
+     *
+     * @return an instance of BearerData.
+     */
+    public static BearerData decodeCdmaSms(byte[] SmsData) {
+        BearerData bearerData;
+
+        if( nativeCdmaSmsConstructClientBD() == JNI_CDMA_SMS_FAILURE){
+            return null;
+        }
+
+        bearerData = startDecoding(SmsData);
+
+        if( nativeCdmaSmsDestructClientBD() == JNI_CDMA_SMS_FAILURE){
+            return null;
+        }
+        return bearerData;
+    }
+
+    private static void generateBearerDataBitMask(BearerData bearerData) {
+        // initial
+        bearerData.mask = CDMA_SMS_WMS_MASK_BD_NULL;
+
+        // check message type
+        if (bearerData.messageType != 0){
+            bearerData.mask |= CDMA_SMS_WMS_MASK_BD_MSG_ID;
+        }
+
+        // check mUserData
+        if (bearerData.userData != null){
+            bearerData.mask |= CDMA_SMS_WMS_MASK_BD_USER_DATA;
+        }
+
+        // check mTimeStamp
+        if (bearerData.timeStamp != null){
+            bearerData.mask |= CDMA_SMS_WMS_MASK_BD_MC_TIME;
+        }
+
+        // check mNumberOfMessages
+        if (bearerData.numberOfMessages > 0){
+            bearerData.mask |= CDMA_SMS_WMS_MASK_BD_NUM_OF_MSGS;
+        }
+
+        // check mCallbackNumber
+        if(bearerData.callbackNumber != null){
+            bearerData.mask |= CDMA_SMS_WMS_MASK_BD_CALLBACK;
+        }
+
+        // check DisplayMode
+        if(bearerData.displayMode == BearerData.DISPLAY_DEFAULT   ||
+           bearerData.displayMode == BearerData.DISPLAY_IMMEDIATE ||
+           bearerData.displayMode == BearerData.DISPLAY_USER){
+            bearerData.mask |= CDMA_SMS_WMS_MASK_BD_DISPLAY_MODE;
+        }
+    }
+
+    private static byte[] startEncoding(BearerData bearerData) {
+        int m_id;
+        byte[] m_data;
+        int dataLength;
+        byte[] encodedSms;
+        int nbrOfHeaders = 0;
+
+        if( nativeCdmaSmsSetBearerDataPrimitives(bearerData) == JNI_CDMA_SMS_FAILURE){
+            return null;
+        }
+
+        if ((bearerData.mask & CDMA_SMS_WMS_MASK_BD_USER_DATA) == CDMA_SMS_WMS_MASK_BD_USER_DATA){
+            if( nativeCdmaSmsSetUserData(bearerData.userData) == JNI_CDMA_SMS_FAILURE){
+                return null;
+            }
+
+            if (bearerData.userData.userDataHeader != null){
+                nbrOfHeaders = bearerData.userData.userDataHeader.nbrOfHeaders;
+            }
+
+            for (int i = 0; i < nbrOfHeaders; i++) {
+                m_id = bearerData.userData.userDataHeader.getElements().get(i).getID();
+                m_data = bearerData.userData.userDataHeader.getElements().get(i).getData();
+                dataLength = m_data.length;
+                if( nativeCdmaSmsSetUserDataHeader(m_id, m_data, dataLength, i)
+                        == JNI_CDMA_SMS_FAILURE){
+                    return null;
+                }
+            }
+        }
+
+        if ((bearerData.mask & CDMA_SMS_WMS_MASK_BD_CALLBACK) == CDMA_SMS_WMS_MASK_BD_CALLBACK) {
+            if( nativeCdmaSmsSetSmsAddress(bearerData.callbackNumber) == JNI_CDMA_SMS_FAILURE){
+                return null;
+            }
+        }
+
+        /* call native method to encode SMS */
+        encodedSms = nativeCdmaSmsEncodeSms();
+
+        return encodedSms;
+    }
+
+    private static BearerData startDecoding(byte[] SmsData) {
+        BearerData bData = new BearerData();
+        byte[] udhData;
+
+        /* call native method to decode SMS */
+        if( nativeCdmaSmsDecodeSms(SmsData) == JNI_CDMA_SMS_FAILURE){
+            return null;
+        }
+
+        if( nativeCdmaSmsGetBearerDataPrimitives(bData) == JNI_CDMA_SMS_FAILURE){
+            return null;
+        }
+
+        if ((bData.mask & CDMA_SMS_WMS_MASK_BD_USER_DATA) == CDMA_SMS_WMS_MASK_BD_USER_DATA) {
+            bData.userData = new UserData();
+            if( nativeCdmaSmsGetUserData(bData.userData) == JNI_CDMA_SMS_FAILURE){
+                return null;
+            }
+
+            udhData = nativeCdmaSmsGetUserDataHeader();
+            if (udhData != null) {
+                bData.userData.userDataHeader = SmsHeader.parse(udhData);
+            }
+        }
+
+        if ((bData.mask & CDMA_SMS_WMS_MASK_BD_CALLBACK) == CDMA_SMS_WMS_MASK_BD_CALLBACK) {
+            bData.callbackNumber = new CdmaSmsAddress();
+            if( nativeCdmaSmsGetSmsAddress(bData.callbackNumber) == JNI_CDMA_SMS_FAILURE){
+                return null;
+            }
+        }
+
+        return bData;
+    }
+
+    // native methods
+
+    /**
+     * native method: Allocate memory for clientBD structure
+     *
+     * @return #JNI_CDMA_SMS_SUCCESS if succeed.
+     *         #JNI_CDMA_SMS_FAILURE if fail.
+     */
+    private static native int nativeCdmaSmsConstructClientBD();
+
+    /**
+     * native method: Free memory used for clientBD structure
+     *
+     * @return #JNI_CDMA_SMS_SUCCESS if succeed.
+     *         #JNI_CDMA_SMS_FAILURE if fail.
+     */
+    private static native int nativeCdmaSmsDestructClientBD();
+
+    /**
+     * native method: fill clientBD structure with bearerData primitives
+     *
+     * @param bearerData    an instance of BearerData.
+     *
+     * @return #JNI_CDMA_SMS_SUCCESS if succeed.
+     *         #JNI_CDMA_SMS_FAILURE if fail.
+     */
+    private static native int nativeCdmaSmsSetBearerDataPrimitives(BearerData bearerData);
+
+    /**
+     * native method: fill bearerData primitives with clientBD variables
+     *
+     * @param bearerData    an instance of BearerData.
+     *
+     * @return #JNI_CDMA_SMS_SUCCESS if succeed.
+     *         #JNI_CDMA_SMS_FAILURE if fail.
+     */
+    private static native int nativeCdmaSmsGetBearerDataPrimitives(BearerData bearerData);
+
+    /**
+     * native method: fill clientBD.user_data with UserData primitives
+     *
+     * @param userData    an instance of UserData.
+     *
+     * @return #JNI_CDMA_SMS_SUCCESS if succeed.
+     *         #JNI_CDMA_SMS_FAILURE if fail.
+     */
+    private static native int nativeCdmaSmsSetUserData(UserData userData);
+
+    /**
+     * native method: fill UserData primitives with clientBD.user_data
+     *
+     * @param userData    an instance of UserData.
+     *
+     * @return #JNI_CDMA_SMS_SUCCESS if succeed.
+     *         #JNI_CDMA_SMS_FAILURE if fail.
+     */
+    private static native int nativeCdmaSmsGetUserData(UserData userData);
+
+    /**
+     * native method: fill clientBD.user_data.headers with UserDataHeader primitives
+     *
+     * @param ID         ID of element.
+     * @param data       element data.
+     * @param dataLength data length
+     * @param index      index of element
+     *
+     * @return #JNI_CDMA_SMS_SUCCESS if succeed.
+     *         #JNI_CDMA_SMS_FAILURE if fail.
+     */
+    private static native int nativeCdmaSmsSetUserDataHeader(
+            int ID, byte[] data, int dataLength, int index);
+
+    /**
+     * native method: fill UserDataHeader primitives with clientBD.user_data.headers
+     *
+     * @return   user data headers
+     */
+    private static native byte[] nativeCdmaSmsGetUserDataHeader();
+
+    /**
+     * native method: fill clientBD.callback with SmsAddress primitives
+     *
+     * @param smsAddr    an instance of SmsAddress.
+     *
+     * @return #JNI_CDMA_SMS_SUCCESS if succeed.
+     *         #JNI_CDMA_SMS_FAILURE if fail.
+     */
+    private static native int nativeCdmaSmsSetSmsAddress(CdmaSmsAddress smsAddr);
+
+    /**
+     * native method: fill SmsAddress primitives with clientBD.callback
+     *
+     * @param smsAddr    an instance of SmsAddress.
+     *
+     * @return #JNI_CDMA_SMS_SUCCESS if succeed.
+     *         #JNI_CDMA_SMS_FAILURE if fail.
+     */
+    private static native int nativeCdmaSmsGetSmsAddress(CdmaSmsAddress smsAddr);
+
+    /**
+     * native method: call encoding functions and get encoded SMS
+     *
+     * @return   the encoded SMS
+     */
+    private static native byte[] nativeCdmaSmsEncodeSms();
+
+    /**
+     * native method: call decode functions
+     *
+     * @param encodedSMS    encoded SMS.
+     *
+     * @return #JNI_CDMA_SMS_SUCCESS if succeed.
+     *         #JNI_CDMA_SMS_FAILURE if fail.
+     */
+    private static native int nativeCdmaSmsDecodeSms(byte[] encodedSMS);
+
+    /**
+     * Load the shared library to link the native methods.
+     */
+    static {
+        try {
+            System.loadLibrary("cdma_sms_jni");
+        }
+        catch (UnsatisfiedLinkError ule) {
+            System.err.println("WARNING: Could not load cdma_sms_jni.so");
+        }
+    }
+}
+
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java b/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java
new file mode 100644
index 0000000..f80e8c0
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/SmsEnvelope.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 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.
+ * 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.internal.telephony.cdma.sms;
+
+
+public final class SmsEnvelope{
+    /**
+     * Message Types
+     * (See 3GPP2 C.S0015-B 3.4.1)
+     */
+    static public final int MESSAGE_TYPE_POINT_TO_POINT   = 0x00;
+    static public final int MESSAGE_TYPE_BROADCAST        = 0x01;
+    static public final int MESSAGE_TYPE_ACKNOWLEDGE      = 0x02;
+
+    /**
+     * Supported Teleservices
+     * (See 3GPP2 N.S0005 and TIA-41)
+     */
+    static public final int TELESERVICE_NOT_SET           = 0x0000;
+    static public final int TELESERVICE_WMT               = 0x1002;
+    static public final int TELESERVICE_VMN               = 0x1003;
+    static public final int TELESERVICE_WAP               = 0x1004;
+    static public final int TELESERVICE_WEMT              = 0x1005;
+
+    // ServiceCategories for Cell Broadcast, see 3GPP2 C.R1001 table 9.3.1-1
+    //static public final int SERVICECATEGORY_EMERGENCY      = 0x0010;
+    //...
+
+    /**
+     *  maximum lengths for fields as defined in ril_cdma_sms.h
+     */
+    static public final int SMS_BEARER_DATA_MAX = 255;
+
+    /**
+     * Provides the type of a SMS message like point to point, broadcast or acknowledge
+     */
+    public int messageType;
+
+    /**
+     * The 16-bit Teleservice parameter identifies which upper layer service access point is sending
+     * or receiving the message.
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.1)
+     */
+    public int teleService = TELESERVICE_NOT_SET;
+
+    /**
+     * The 16-bit service category parameter identifies the type of service provided
+     * by the SMS message.
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.2)
+     */
+    public int serviceCategory;
+
+    /**
+     * The origination address identifies the originator of the SMS message.
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.4)
+     */
+    public CdmaSmsAddress origAddress;
+
+    /**
+     * The destination address identifies the target of the SMS message.
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.4)
+     */
+    public CdmaSmsAddress destAddress;
+
+    /**
+     * The 6-bit bearer reply parameter is used to request the return of a
+     * SMS Acknowledge Message.
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.5)
+     */
+    public int bearerReply;
+
+    /**
+     * Cause Code values:
+     * The cause code parameters are an indication whether an SMS error has occurred and if so,
+     * whether the condition is considered temporary or permanent.
+     * ReplySeqNo 6-bit value,
+     * ErrorClass 2-bit value,
+     * CauseCode 0-bit or 8-bit value
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.6)
+     */
+    public byte replySeqNo;
+    public byte errorClass;
+    public byte causeCode;
+
+    /**
+     * encoded bearer data
+     * (See 3GPP2 C.S0015-B, v2, 3.4.3.7)
+     */
+    public byte[] bearerData;
+
+    public SmsEnvelope() {
+        // nothing to see here
+    }
+
+}
+
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java b/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java
new file mode 100644
index 0000000..e761469
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 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.
+ * 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.internal.telephony.cdma.sms;
+
+import com.android.internal.telephony.SmsHeader;
+
+public class UserData{
+
+    /**
+     * Supported user data encoding types
+     * (See 3GPP2 C.R1001-F, v1.0, table 9.1-1)
+     */
+    public static final int UD_ENCODING_OCTET                      = 0x00;
+    //public static final int UD_ENCODING_EXTENDED_PROTOCOL          = 0x01;
+    public static final int UD_ENCODING_7BIT_ASCII                 = 0x02;
+    public static final int UD_ENCODING_IA5                        = 0x03;
+    public static final int UD_ENCODING_UNICODE_16                 = 0x04;
+    //public static final int UD_ENCODING_SHIFT_JIS                  = 0x05;
+    //public static final int UD_ENCODING_KOREAN                     = 0x06;
+    //public static final int UD_ENCODING_LATIN_HEBREW               = 0x07;
+    //public static final int UD_ENCODING_LATIN                      = 0x08;
+    public static final int UD_ENCODING_GSM_7BIT_ALPHABET          = 0x09;
+    //public static final int UD_ENCODING_GSM_DCS                    = 0x0A;
+
+    /**
+     * Contains the data header of the user data
+     */
+    public SmsHeader userDataHeader;
+
+    /**
+     * Contains the data encoding type for the SMS message
+     */
+    public int userDataEncoding;
+
+    // needed when encoding is IS91 or DCS (not supported yet):
+    //public int messageType;
+
+    /**
+     * Number of invalid bits in the last byte of data.
+     */
+    public int paddingBits;
+
+    /**
+     * Contains the user data of a SMS message
+     * (See 3GPP2 C.S0015-B, v2, 4.5.2)
+     */
+    public byte[] userData;
+
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/package.html b/telephony/java/com/android/internal/telephony/cdma/sms/package.html
new file mode 100644
index 0000000..48e1034
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/package.html
@@ -0,0 +1,6 @@
+<HTML>
+<BODY>
+Provides CDMA-specific features for text/data/PDU SMS messages 
+@hide
+</BODY>
+</HTML>
diff --git a/telephony/java/com/android/internal/telephony/gsm/AdnRecord.java b/telephony/java/com/android/internal/telephony/gsm/AdnRecord.java
deleted file mode 100644
index 30df699..0000000
--- a/telephony/java/com/android/internal/telephony/gsm/AdnRecord.java
+++ /dev/null
@@ -1,570 +0,0 @@
-/*
- * Copyright (C) 2006 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.internal.telephony.gsm;
-
-import com.android.internal.telephony.*;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.Message;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.AsyncResult;
-import android.util.Log;
-import android.telephony.PhoneNumberUtils;
-import java.util.ArrayList;
-
-class AdnRecordLoader extends Handler
-{
-    static final String LOG_TAG = "GSM";
-
-    //***** Instance Variables
-
-    GSMPhone phone;
-    int ef;
-    int extensionEF;
-    int pendingExtLoads;
-    Message userResponse;
-    String pin2;
-
-    // For "load one"
-    int recordNumber;
-
-    // for "load all"
-    ArrayList<AdnRecord> adns; // only valid after EVENT_ADN_LOAD_ALL_DONE
-
-    // Either an AdnRecord or a reference to adns depending
-    // if this is a load one or load all operation
-    Object result;
-
-    //***** Event Constants
-
-    static final int EVENT_ADN_LOAD_DONE = 1;
-    static final int EVENT_EXT_RECORD_LOAD_DONE = 2;
-    static final int EVENT_ADN_LOAD_ALL_DONE = 3;
-    static final int EVENT_EF_LINEAR_RECORD_SIZE_DONE = 4;
-    static final int EVENT_UPDATE_RECORD_DONE = 5;
-
-    //***** Constructor
-
-    AdnRecordLoader(GSMPhone phone)
-    {
-        // The telephony unit-test cases may create AdnRecords
-        // in secondary threads
-        super(phone.h.getLooper());
-
-        this.phone = phone;
-    }
-
-    /**
-     * Resulting AdnRecord is placed in response.obj.result
-     * or response.obj.exception is set
-     */
-    void
-    loadFromEF(int ef, int extensionEF, int recordNumber, 
-                Message response)
-    {
-        this.ef = ef;
-        this.extensionEF = extensionEF;
-        this.recordNumber = recordNumber;
-        this.userResponse = response;
-        
-        phone.mSIMFileHandler.loadEFLinearFixed(
-                    ef, recordNumber, 
-                    obtainMessage(EVENT_ADN_LOAD_DONE)); 
-
-    }
-
-
-    /**
-     * Resulting ArrayList&lt;adnRecord> is placed in response.obj.result
-     * or response.obj.exception is set
-     */
-    void
-    loadAllFromEF(int ef, int extensionEF, 
-                Message response)
-    {
-        this.ef = ef;
-        this.extensionEF = extensionEF;
-        this.userResponse = response;
-        
-        phone.mSIMFileHandler.loadEFLinearFixedAll(
-                    ef, 
-                    obtainMessage(EVENT_ADN_LOAD_ALL_DONE)); 
-
-    }
-
-    /**
-     * Write adn to a EF SIM record
-     * It will get the record size of EF record and compose hex adn array
-     * then write the hex array to EF record
-     *
-     * @param adn is set with alphaTag and phoneNubmer
-     * @param ef EF fileid
-     * @param extensionEF extension EF fileid
-     * @param recordNumber 1-based record index
-     * @param pin2 for CHV2 operations, must be null if pin2 is not needed
-     * @param response will be sent to its handler when completed
-     */
-    void
-    updateEF(AdnRecord adn, int ef, int extensionEF, int recordNumber,
-            String pin2, Message response)
-    {
-        this.ef = ef;
-        this.extensionEF = extensionEF;
-        this.recordNumber = recordNumber;
-        this.userResponse = response;
-        this.pin2 = pin2;
-
-        phone.mSIMFileHandler.getEFLinearRecordSize( ef,
-            obtainMessage(EVENT_EF_LINEAR_RECORD_SIZE_DONE, adn));
-    }
-
-    //***** Overridden from Handler
-
-    public void 
-    handleMessage(Message msg)
-    {
-        AsyncResult ar;
-        byte data[];
-        AdnRecord adn;
-
-        try {
-            switch (msg.what) {
-                case EVENT_EF_LINEAR_RECORD_SIZE_DONE:
-                    ar = (AsyncResult)(msg.obj);
-                    adn = (AdnRecord)(ar.userObj);
-
-                    if (ar.exception != null) {
-                        throw new RuntimeException("get EF record size failed",
-                                ar.exception);
-                    }
-
-                    int[] recordSize = (int[])ar.result;
-                    // recordSize is int[3] array
-                    // int[0]  is the record length
-                    // int[1]  is the total length of the EF file
-                    // int[2]  is the number of records in the EF file
-                    // So int[0] * int[2] = int[1]
-                   if (recordSize.length != 3 || recordNumber > recordSize[2]) {
-                        throw new RuntimeException("get wrong EF record size format",
-                                ar.exception);
-                    }
-
-                    data = adn.buildAdnString(recordSize[0]);
-
-                    if(data == null) {
-                        throw new RuntimeException("worong ADN format",
-                                ar.exception);
-                    }
-
-                    phone.mSIMFileHandler.updateEFLinearFixed(ef, recordNumber,
-                            data, pin2, obtainMessage(EVENT_UPDATE_RECORD_DONE));
-
-                    pendingExtLoads = 1;
-
-                    break;
-                case EVENT_UPDATE_RECORD_DONE:
-                    ar = (AsyncResult)(msg.obj);
-                    if (ar.exception != null) {
-                        throw new RuntimeException("update EF adn record failed",
-                                ar.exception);
-                    }
-                    pendingExtLoads = 0;
-                    result = null;
-                    break;
-                case EVENT_ADN_LOAD_DONE:
-                    ar = (AsyncResult)(msg.obj);
-                    data = (byte[])(ar.result);
-     
-                    if (ar.exception != null) {
-                        throw new RuntimeException("load failed", ar.exception);
-                    }
-
-                    if (false) {
-                        Log.d(LOG_TAG,"ADN EF: 0x" 
-                            + Integer.toHexString(ef)
-                            + ":" + recordNumber
-                            + "\n" + SimUtils.bytesToHexString(data));
-                    }
-                    
-                    adn = new AdnRecord(ef, recordNumber, data);
-                    result = adn;
-
-                    if (adn.hasExtendedRecord()) {
-                        // If we have a valid value in the ext record field,
-                        // we're not done yet: we need to read the corresponding
-                        // ext record and append it
-
-                        pendingExtLoads = 1;
-                        
-                        phone.mSIMFileHandler.loadEFLinearFixed(
-                            extensionEF, adn.extRecord, 
-                            obtainMessage(EVENT_EXT_RECORD_LOAD_DONE, adn)); 
-                    }
-                break;
-
-                case EVENT_EXT_RECORD_LOAD_DONE:
-                    ar = (AsyncResult)(msg.obj);
-                    data = (byte[])(ar.result);
-                    adn = (AdnRecord)(ar.userObj);
-     
-                    if (ar.exception != null) {
-                        throw new RuntimeException("load failed", ar.exception);
-                    }
-
-                    Log.d(LOG_TAG,"ADN extention EF: 0x" 
-                        + Integer.toHexString(extensionEF)
-                        + ":" + adn.extRecord
-                        + "\n" + SimUtils.bytesToHexString(data));
-
-                    adn.appendExtRecord(data);
-
-                    pendingExtLoads--;
-                    // result should have been set in 
-                    // EVENT_ADN_LOAD_DONE or EVENT_ADN_LOAD_ALL_DONE
-                break;            
-
-                case EVENT_ADN_LOAD_ALL_DONE:
-                    ar = (AsyncResult)(msg.obj);
-                    ArrayList<byte[]> datas = (ArrayList<byte[]>)(ar.result);
-     
-                    if (ar.exception != null) {
-                        throw new RuntimeException("load failed", ar.exception);
-                    }
-
-                    adns = new ArrayList<AdnRecord>(datas.size());
-                    result = adns;
-                    pendingExtLoads = 0;
-
-                    for(int i = 0, s = datas.size() ; i < s ; i++) {
-                        adn = new AdnRecord(ef, 1 + i, datas.get(i));
-                        adns.add(adn);
-
-                        if (adn.hasExtendedRecord()) {
-                            // If we have a valid value in the ext record field,
-                            // we're not done yet: we need to read the corresponding
-                            // ext record and append it
-
-                            pendingExtLoads++;
-                            
-                            phone.mSIMFileHandler.loadEFLinearFixed(
-                                extensionEF, adn.extRecord, 
-                                obtainMessage(EVENT_EXT_RECORD_LOAD_DONE, adn)); 
-                        }
-                    }
-                break;
-            }
-        } catch (RuntimeException exc) {            
-            if (userResponse != null) {
-                AsyncResult.forMessage(userResponse) 
-                                .exception = exc;
-                userResponse.sendToTarget();
-                // Loading is all or nothing--either every load succeeds
-                // or we fail the whole thing.
-                userResponse = null;
-            }
-            return;
-        }
-
-        if (userResponse != null && pendingExtLoads == 0) {
-            AsyncResult.forMessage(userResponse).result 
-                = result;
-
-            userResponse.sendToTarget();
-            userResponse = null;
-        }
-    }
-    
-
-}
-
-/**
- * 
- * Used to load or store ADNs (Abbreviated Dialing Numbers).
- *
- * {@hide}
- *
- */
-public class AdnRecord implements Parcelable
-{
-    static final String LOG_TAG = "GSM";
-    
-    //***** Instance Variables
-
-    String alphaTag = "";
-    String number = "";
-    int extRecord = 0xff;
-    int efid;                   // or 0 if none
-    int recordNumber;           // or 0 if none
-
-
-    //***** Constants
-
-    // In an ADN record, everything but the alpha identifier
-    // is in a footer that's 14 bytes
-    static final int FOOTER_SIZE_BYTES = 14;
-
-    // Maximum size of the un-extended number field
-    static final int MAX_NUMBER_SIZE_BYTES = 11;
-
-    static final int EXT_RECORD_LENGTH_BYTES = 13;
-    static final int EXT_RECORD_TYPE_ADDITIONAL_DATA = 2;
-    static final int EXT_RECORD_TYPE_MASK = 3;
-    static final int MAX_EXT_CALLED_PARTY_LENGTH = 0xa;
-
-    // ADN offset
-    static final int ADN_BCD_NUMBER_LENGTH = 0;
-    static final int ADN_TON_AND_NPI = 1;
-    static final int ADN_DAILING_NUMBER_START = 2;
-    static final int ADN_DAILING_NUMBER_END = 11;
-    static final int ADN_CAPABILITY_ID = 12;
-    static final int ADN_EXTENSION_ID = 13;
-
-    //***** Static Methods
-
-    public static final Parcelable.Creator<AdnRecord> CREATOR
-            = new Parcelable.Creator<AdnRecord>()
-    {
-        public AdnRecord createFromParcel(Parcel source)
-        {
-            int efid;
-            int recordNumber;
-            String alphaTag;
-            String number;
-
-            efid = source.readInt();
-            recordNumber = source.readInt();
-            alphaTag = source.readString();
-            number = source.readString();
-
-            return new AdnRecord(efid, recordNumber, alphaTag, number);
-        }
-
-        public AdnRecord[] newArray(int size)
-        {
-            return new AdnRecord[size];
-        }
-    };
-
-
-    //***** Constructor
-    public
-    AdnRecord (byte[] record)
-    {
-        this(0, 0, record);
-    }
-
-    public
-    AdnRecord (int efid, int recordNumber, byte[] record)
-    {
-        this.efid = efid;
-        this.recordNumber = recordNumber;
-        parseRecord(record);
-    }
-
-    public
-    AdnRecord (String alphaTag, String number)
-    {
-        this(0, 0, alphaTag, number);
-    }
-    
-    public
-    AdnRecord (int efid, int recordNumber, String alphaTag, String number)
-    {
-        this.efid = efid;
-        this.recordNumber = recordNumber;
-        this.alphaTag = alphaTag;
-        this.number = number;
-    }
-    
-    //***** Instance Methods
-
-    public String getAlphaTag()
-    {
-        return alphaTag;
-    }
-
-    public String getNumber()
-    {
-        return number;
-    }
-
-    public String toString()
-    {
-        return "ADN Record '" + alphaTag + "' '" + number + "'";
-    }
-
-    public boolean isEmpty()
-    {
-        return alphaTag.equals("") && number.equals("");
-    }
-
-    public boolean hasExtendedRecord()
-    {
-        return extRecord != 0 && extRecord != 0xff;
-    }
-
-    public boolean isEqual(AdnRecord adn) {
-        return ( alphaTag.equals(adn.getAlphaTag()) &&
-                number.equals(adn.getNumber()) );
-    }
-    //***** Parcelable Implementation
-
-    public int describeContents() {
-        return 0;
-    }
-
-    public void writeToParcel(Parcel dest, int flags)
-    {
-        dest.writeInt(efid);
-        dest.writeInt(recordNumber);
-        dest.writeString(alphaTag);
-        dest.writeString(number);
-    }
-
-    /**
-     * Build adn hex byte array based on record size
-     * The format of byte array is defined in 51.011 10.5.1
-     *
-     * @param recordSize is the size X of EF record
-     * @return hex byte[recordSize] to be written to EF record
-     *          return nulll for wrong format of dialing nubmer or tag
-     */
-    public byte[] buildAdnString(int recordSize) {
-        byte[] bcdNumber;
-        byte[] byteTag;
-        byte[] adnString = null;
-        int footerOffset = recordSize - FOOTER_SIZE_BYTES;
-
-        if (number == null || number.equals("") ||
-                alphaTag == null || alphaTag.equals("")) {
-
-            Log.w(LOG_TAG, "[buildAdnString] Empty alpha tag or number");
-            adnString = new byte[recordSize];
-            for (int i = 0; i < recordSize; i++) {
-                adnString[i] = (byte) 0xFF;
-            }
-        } else if (number.length()
-                > (ADN_DAILING_NUMBER_END - ADN_DAILING_NUMBER_START + 1) * 2) {
-            Log.w(LOG_TAG,
-                    "[buildAdnString] Max length of dailing number is 20");
-        } else if (alphaTag.length() > footerOffset) {
-            Log.w(LOG_TAG,
-                    "[buildAdnString] Max length of tag is " + footerOffset);
-        } else {
-
-            adnString = new byte[recordSize];
-            for (int i = 0; i < recordSize; i++) {
-                adnString[i] = (byte) 0xFF;
-            }
-
-            bcdNumber = PhoneNumberUtils.numberToCalledPartyBCD(number);
-
-            System.arraycopy(bcdNumber, 0, adnString,
-                    footerOffset + ADN_TON_AND_NPI, bcdNumber.length);
-
-            adnString[footerOffset + ADN_BCD_NUMBER_LENGTH]
-                    = (byte) (bcdNumber.length);
-            adnString[footerOffset + ADN_CAPABILITY_ID]
-                    = (byte) 0xFF; // Capacility Id
-            adnString[footerOffset + ADN_EXTENSION_ID]
-                    = (byte) 0xFF; // Extension Record Id
-
-            byteTag = GsmAlphabet.stringToGsm8BitPacked(alphaTag);
-            System.arraycopy(byteTag, 0, adnString, 0, byteTag.length);
-
-        }
-
-        return adnString;
-    }
-
-    /**
-     * See TS 51.011 10.5.10
-     */
-    public void
-    appendExtRecord (byte[] extRecord) {        
-        try {
-            if (extRecord.length != EXT_RECORD_LENGTH_BYTES) {
-                return;
-            }
-
-            if ((extRecord[0] & EXT_RECORD_TYPE_MASK)
-                    != EXT_RECORD_TYPE_ADDITIONAL_DATA
-            ) {
-                return;
-            }
-
-            if ((0xff & extRecord[1]) > MAX_EXT_CALLED_PARTY_LENGTH) {
-                // invalid or empty record
-                return;
-            }
-
-            number += PhoneNumberUtils.calledPartyBCDFragmentToString(
-                                        extRecord, 2, 0xff & extRecord[1]);
-
-            // We don't support ext record chaining.
-
-        } catch (RuntimeException ex) {
-
-
-
-            
-            Log.w(LOG_TAG, "Error parsing AdnRecord ext record", ex);
-        }
-    }
-
-    //***** Private Methods
-
-    /**
-     * alphaTag and number are set to null on invalid format
-     */
-    private void
-    parseRecord(byte[] record) {
-        try {
-            alphaTag = SimUtils.adnStringFieldToString(
-                            record, 0, record.length - FOOTER_SIZE_BYTES);
-
-            int footerOffset = record.length - FOOTER_SIZE_BYTES;
-
-            int numberLength = 0xff & record[footerOffset];
-
-            if (numberLength > MAX_NUMBER_SIZE_BYTES) {
-                // Invalid number length
-                number = "";
-                return;
-            }
-
-            // Please note 51.011 10.5.1:
-            //
-            // "If the Dialling Number/SSC String does not contain 
-            // a dialling number, e.g. a control string deactivating 
-            // a service, the TON/NPI byte shall be set to 'FF' by 
-            // the ME (see note 2)."
-
-            number = PhoneNumberUtils.calledPartyBCDToString(
-                            record, footerOffset + 1, numberLength);
-
-
-            extRecord = 0xff & record[record.length - 1];
-
-        } catch (RuntimeException ex) {
-            Log.w(LOG_TAG, "Error parsing AdnRecord", ex);
-            number = "";
-            alphaTag = "";
-        }        
-    }
-}
diff --git a/telephony/java/com/android/internal/telephony/gsm/BaseCommands.java b/telephony/java/com/android/internal/telephony/gsm/BaseCommands.java
deleted file mode 100644
index 8e14b43..0000000
--- a/telephony/java/com/android/internal/telephony/gsm/BaseCommands.java
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * Copyright (C) 2006 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.internal.telephony.gsm;
-
-import android.content.Context;
-import android.os.RegistrantList;
-import android.os.Registrant;
-import android.os.Handler;
-import android.os.AsyncResult;
-import android.os.SystemProperties;
-import android.provider.Checkin;
-import android.util.Config;
-import android.util.Log;
-
-/**
- * {@hide}
- */
-public abstract class BaseCommands implements CommandsInterface
-{
-    static final String LOG_TAG = "GSM";
-
-    //***** Instance Variables
-    protected Context mContext;
-    protected RadioState mState = RadioState.RADIO_UNAVAILABLE;
-    protected Object mStateMonitor = new Object();
-
-    protected RegistrantList mRadioStateChangedRegistrants = new RegistrantList();
-    protected RegistrantList mOnRegistrants = new RegistrantList();
-    protected RegistrantList mAvailRegistrants = new RegistrantList();
-    protected RegistrantList mOffOrNotAvailRegistrants = new RegistrantList();
-    protected RegistrantList mNotAvailRegistrants = new RegistrantList();
-    protected RegistrantList mSIMReadyRegistrants = new RegistrantList();
-    protected RegistrantList mSIMLockedRegistrants = new RegistrantList();
-    protected RegistrantList mCallStateRegistrants = new RegistrantList();
-    protected RegistrantList mNetworkStateRegistrants = new RegistrantList();
-    protected RegistrantList mPDPRegistrants = new RegistrantList();
-    protected Registrant mSMSRegistrant;
-    protected Registrant mNITZTimeRegistrant;
-    protected Registrant mSignalStrengthRegistrant;
-    protected Registrant mUSSDRegistrant;
-    protected Registrant mSmsOnSimRegistrant;
-    /** Registrant for handling SMS Status Reports */
-    protected Registrant mSmsStatusRegistrant;
-    /** Registrant for handling Supplementary Service Notifications */
-    protected Registrant mSsnRegistrant;
-    protected Registrant mStkSessionEndRegistrant;
-    protected Registrant mStkProCmdRegistrant;
-    protected Registrant mStkEventRegistrant;
-    protected Registrant mStkCallSetUpRegistrant;
-    /** Registrant for handling SIM SMS storage full messages */
-    protected Registrant mSimSmsFullRegistrant;
-    /** Registrant for handling SIM Refresh notifications */
-    protected Registrant mSimRefreshRegistrant;
-    /** Registrant for handling RING notifications */
-    protected Registrant mRingRegistrant;
-    /** Registrant for handling RESTRICTED STATE changed notification */
-    protected Registrant mRestrictedStateRegistrant;
-
-    public BaseCommands(Context context) {
-        mContext = context;  // May be null (if so we won't log statistics)
-    }
-
-    //***** CommandsInterface implementation
-
-    public RadioState 
-    getRadioState()
-    {
-        return mState;
-    }
-
-
-    public void 
-    registerForRadioStateChanged(Handler h, int what, Object obj)
-    {
-        Registrant r = new Registrant (h, what, obj);
-
-        synchronized (mStateMonitor) {
-            mRadioStateChangedRegistrants.add(r);
-            r.notifyRegistrant();
-        }
-    }
-
-    public void 
-    registerForOn(Handler h, int what, Object obj)
-    {
-        Registrant r = new Registrant (h, what, obj);
-
-        synchronized (mStateMonitor) {
-            mOnRegistrants.add(r);
-
-            if (mState.isOn()) {
-                r.notifyRegistrant(new AsyncResult(null, null, null));
-            }
-        }
-    }
-    
-
-    public void 
-    registerForAvailable(Handler h, int what, Object obj)
-    {
-        Registrant r = new Registrant (h, what, obj);
-
-        synchronized (mStateMonitor) {
-            mAvailRegistrants.add(r);
-
-            if (mState.isAvailable()) {
-                r.notifyRegistrant(new AsyncResult(null, null, null));
-            }
-        }
-    }
-
-    public void 
-    registerForNotAvailable(Handler h, int what, Object obj)
-    {
-        Registrant r = new Registrant (h, what, obj);
-
-        synchronized (mStateMonitor) {
-            mNotAvailRegistrants.add(r);
-
-            if (!mState.isAvailable()) {
-                r.notifyRegistrant(new AsyncResult(null, null, null));
-            }
-        }
-    }
-
-    public void 
-    registerForOffOrNotAvailable(Handler h, int what, Object obj)
-    {
-        Registrant r = new Registrant (h, what, obj);
-
-        synchronized (mStateMonitor) {
-            mOffOrNotAvailRegistrants.add(r);
-
-            if (mState == RadioState.RADIO_OFF || !mState.isAvailable()) {
-                r.notifyRegistrant(new AsyncResult(null, null, null));
-            }
-        }
-    }
-
-
-    /** Any transition into SIM_READY */
-    public void 
-    registerForSIMReady(Handler h, int what, Object obj)
-    {
-        Registrant r = new Registrant (h, what, obj);
-
-        synchronized (mStateMonitor) {
-            mSIMReadyRegistrants.add(r);
-
-            if (mState.isSIMReady()) {
-                r.notifyRegistrant(new AsyncResult(null, null, null));
-            }
-        }
-    }
-
-    public void 
-    registerForSIMLockedOrAbsent(Handler h, int what, Object obj)
-    {
-        Registrant r = new Registrant (h, what, obj);
-
-        synchronized (mStateMonitor) {
-            mSIMLockedRegistrants.add(r);
-
-            if (mState == RadioState.SIM_LOCKED_OR_ABSENT) {
-                r.notifyRegistrant(new AsyncResult(null, null, null));
-            }
-        }
-    }
-
-    public void 
-    registerForCallStateChanged(Handler h, int what, Object obj)
-    {
-        Registrant r = new Registrant (h, what, obj);
-
-        mCallStateRegistrants.add(r);
-    }
-
-    public void 
-    registerForNetworkStateChanged(Handler h, int what, Object obj)
-    {
-        Registrant r = new Registrant (h, what, obj);
-
-        mNetworkStateRegistrants.add(r);
-    }
-
-    public void
-    registerForPDPStateChanged(Handler h, int what, Object obj)
-    {
-        Registrant r = new Registrant (h, what, obj);
-
-        mPDPRegistrants.add(r);
-    }
-
-    public void 
-    setOnNewSMS(Handler h, int what, Object obj)
-    {
-        mSMSRegistrant = new Registrant (h, what, obj);
-    }
-
-    public void
-    setOnSmsOnSim(Handler h, int what, Object obj)
-    {
-        mSmsOnSimRegistrant = new Registrant (h, what, obj);
-    }
-    
-    public void setOnSmsStatus(Handler h, int what, Object obj) {
-        mSmsStatusRegistrant = new Registrant (h, what, obj);
-    }
-
-    public void
-    setOnSignalStrengthUpdate(Handler h, int what, Object obj)
-    {
-        mSignalStrengthRegistrant = new Registrant (h, what, obj);
-    }
-
-    public void 
-    setOnNITZTime(Handler h, int what, Object obj)
-    {
-        mNITZTimeRegistrant = new Registrant (h, what, obj);
-    }
-  
-    public void 
-    setOnUSSD(Handler h, int what, Object obj)
-    {
-        mUSSDRegistrant = new Registrant (h, what, obj);
-    }
-
-    public void
-    setOnSuppServiceNotification(Handler h, int what, Object obj)
-    {
-        mSsnRegistrant = new Registrant (h, what, obj);
-    }
-
-    public void
-    setOnStkSessionEnd(Handler h, int what, Object obj)
-    {
-        mStkSessionEndRegistrant = new Registrant (h, what, obj);
-    }
-
-    public void
-    setOnStkProactiveCmd(Handler h, int what, Object obj)
-    {
-        mStkProCmdRegistrant = new Registrant (h, what, obj);
-    }
-
-    public void
-    setOnStkEvent(Handler h, int what, Object obj)
-    {
-        mStkEventRegistrant = new Registrant (h, what, obj);
-    }
-
-    public void
-    setOnStkCallSetUp(Handler h, int what, Object obj)
-    {
-        mStkCallSetUpRegistrant = new Registrant (h, what, obj);
-    }
-
-    public void setOnSimSmsFull(Handler h, int what, Object obj) {
-        mSimSmsFullRegistrant = new Registrant (h, what, obj);
-    }
-
-    public void setOnSimRefresh(Handler h, int what, Object obj) {
-        mSimRefreshRegistrant = new Registrant (h, what, obj);
-    }
-    
-    public void setOnCallRing(Handler h, int what, Object obj) {
-        mRingRegistrant = new Registrant (h, what, obj);
-    }
-    
-    public void
-    setOnRestrictedStateChanged(Handler h, int what, Object obj)
-    {
-        mRestrictedStateRegistrant = new Registrant (h, what, obj);
-    }
-    
-    //***** Protected Methods
-    /**
-     * Store new RadioState and send notification based on the changes
-     *
-     * This function is called only by RIL.java when receiving unsolicited
-     * RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED
-     *
-     * RadioState has 5 values : RADIO_OFF, RADIO_UNAVAILABLE, SIM_NOT_READY,
-     * SIM_LOCKED_OR_ABSENT, and SIM_READY.
-     *
-     * @param newState new RadioState decoded from RIL_UNSOL_RADIO_STATE_CHANGED
-     */
-    protected void setRadioState(RadioState newState) {
-        RadioState oldState;
-        
-        synchronized (mStateMonitor) {
-            if (Config.LOGV) {
-                Log.v(LOG_TAG, "setRadioState old: " + mState
-                    + " new " + newState);
-            }
-        
-            oldState = mState;
-            mState = newState;
-            
-            if (oldState == mState) {
-                // no state transition
-                return;
-            }
-
-            if (mContext != null &&
-                newState == RadioState.RADIO_UNAVAILABLE &&
-                oldState != RadioState.RADIO_OFF) {
-                Checkin.updateStats(mContext.getContentResolver(),
-                        Checkin.Stats.Tag.PHONE_RADIO_RESETS, 1, 0.0);
-            }
-
-            mRadioStateChangedRegistrants.notifyRegistrants();
-
-            if (mState.isAvailable() && !oldState.isAvailable()) {
-                Log.d(LOG_TAG,"Notifying: radio available");
-                mAvailRegistrants.notifyRegistrants();
-                onRadioAvailable();
-            }
-
-            if (!mState.isAvailable() && oldState.isAvailable()) {
-                Log.d(LOG_TAG,"Notifying: radio not available");
-                mNotAvailRegistrants.notifyRegistrants();
-            }
-
-            if (mState.isSIMReady() && !oldState.isSIMReady()) {
-                Log.d(LOG_TAG,"Notifying: SIM ready");
-                mSIMReadyRegistrants.notifyRegistrants();
-            }
-
-            if (mState == RadioState.SIM_LOCKED_OR_ABSENT) {
-                Log.d(LOG_TAG,"Notifying: SIM locked or absent");
-                mSIMLockedRegistrants.notifyRegistrants();
-            } 
-
-            if (mState.isOn() && !oldState.isOn()) {
-                Log.d(LOG_TAG,"Notifying: Radio On");
-                mOnRegistrants.notifyRegistrants();
-            } 
-
-            if ((!mState.isOn() || !mState.isAvailable()) 
-                && !((!oldState.isOn() || !oldState.isAvailable()))
-            ) {
-                Log.d(LOG_TAG,"Notifying: radio off or not available");
-                mOffOrNotAvailRegistrants.notifyRegistrants();
-            }
-        }
-    }
-    
-    protected void
-    onRadioAvailable()
-    {
-    }
-}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
index f93c724..d1ae997 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -16,18 +16,6 @@
 
 package com.android.internal.telephony.gsm;
 
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_BASEBAND_VERSION;
-import static com.android.internal.telephony.gsm.CommandsInterface.CF_ACTION_DISABLE;
-import static com.android.internal.telephony.gsm.CommandsInterface.CF_ACTION_ENABLE;
-import static com.android.internal.telephony.gsm.CommandsInterface.CF_ACTION_ERASURE;
-import static com.android.internal.telephony.gsm.CommandsInterface.CF_ACTION_REGISTRATION;
-import static com.android.internal.telephony.gsm.CommandsInterface.CF_REASON_ALL;
-import static com.android.internal.telephony.gsm.CommandsInterface.CF_REASON_ALL_CONDITIONAL;
-import static com.android.internal.telephony.gsm.CommandsInterface.CF_REASON_BUSY;
-import static com.android.internal.telephony.gsm.CommandsInterface.CF_REASON_NOT_REACHABLE;
-import static com.android.internal.telephony.gsm.CommandsInterface.CF_REASON_NO_REPLY;
-import static com.android.internal.telephony.gsm.CommandsInterface.CF_REASON_UNCONDITIONAL;
-import static com.android.internal.telephony.gsm.CommandsInterface.SERVICE_CLASS_VOICE;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.SharedPreferences;
@@ -41,26 +29,47 @@
 import android.os.RegistrantList;
 import android.os.SystemProperties;
 import android.preference.PreferenceManager;
+import android.provider.Settings;
 import android.provider.Telephony;
 import android.telephony.CellLocation;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.ServiceState;
-import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.Log;
 
-import com.android.internal.telephony.Call;
+import static com.android.internal.telephony.CommandsInterface.CF_ACTION_DISABLE;
+import static com.android.internal.telephony.CommandsInterface.CF_ACTION_ENABLE;
+import static com.android.internal.telephony.CommandsInterface.CF_ACTION_ERASURE;
+import static com.android.internal.telephony.CommandsInterface.CF_ACTION_REGISTRATION;
+import static com.android.internal.telephony.CommandsInterface.CF_REASON_ALL;
+import static com.android.internal.telephony.CommandsInterface.CF_REASON_ALL_CONDITIONAL;
+import static com.android.internal.telephony.CommandsInterface.CF_REASON_NO_REPLY;
+import static com.android.internal.telephony.CommandsInterface.CF_REASON_NOT_REACHABLE;
+import static com.android.internal.telephony.CommandsInterface.CF_REASON_BUSY;
+import static com.android.internal.telephony.CommandsInterface.CF_REASON_UNCONDITIONAL;
+import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_VOICE;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_BASEBAND_VERSION;
+
+import com.android.internal.telephony.CallForwardInfo;
 import com.android.internal.telephony.CallStateException;
+import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.Connection;
+import com.android.internal.telephony.DataConnection;
+import com.android.internal.telephony.DataConnectionTracker;
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.IccFileHandler;
+import com.android.internal.telephony.IccPhoneBookInterfaceManager;
+import com.android.internal.telephony.IccSmsInterfaceManager;
 import com.android.internal.telephony.MmiCode;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneBase;
 import com.android.internal.telephony.PhoneNotifier;
+import com.android.internal.telephony.PhoneProxy;
 import com.android.internal.telephony.PhoneSubInfo;
-import com.android.internal.telephony.SimCard;
-import com.android.internal.telephony.gsm.SimException;
+import com.android.internal.telephony.RILConstants;
 import com.android.internal.telephony.gsm.stk.StkService;
 import com.android.internal.telephony.test.SimulatedRadioControl;
+import com.android.internal.telephony.IccVmNotSupportedException;
 
 import java.io.IOException;
 import java.net.InetSocketAddress;
@@ -77,40 +86,28 @@
     // from this file will go into the radio log rather than the main
     // log.  (Use "adb logcat -b radio" to see them.)
     static final String LOG_TAG = "GSM";
-    private static final boolean LOCAL_DEBUG = false;
+    private static final boolean LOCAL_DEBUG = true;
 
-    // Key used to read and write the saved network selection value
-    public static final String NETWORK_SELECTION_KEY = "network_selection_key";
-    // Key used to read/write "disable data connection on boot" pref (used for testing)
-    public static final String DATA_DISABLED_ON_BOOT_KEY = "disabled_on_boot_key";
     // Key used to read/write current ciphering state
     public static final String CIPHERING_KEY = "ciphering_key";
-    // Key used to read/write current CLIR setting
-    public static final String CLIR_KEY = "clir_key";
     // Key used to read/write voice mail number
     public static final String VM_NUMBER = "vm_number_key";
     // Key used to read/write the SIM IMSI used for storing the voice mail
     public static final String VM_SIM_IMSI = "vm_sim_imsi_key";
-    // Key used to read/write "disable DNS server check" pref (used for testing)
-    public static final String DNS_SERVER_CHECK_DISABLED_KEY = "dns_server_check_disabled_key";
 
     //***** Instance Variables
-
-    CallTracker mCT;
-    ServiceStateTracker mSST;
-    CommandsInterface mCM;
-    SMSDispatcher mSMS;
-    DataConnectionTracker mDataConnection;
-    SIMFileHandler mSIMFileHandler;
+    GsmCallTracker mCT;
+    GsmServiceStateTracker mSST;
+    GsmSMSDispatcher mSMS;
+    GsmDataConnectionTracker mDataConnection;
     SIMRecords mSIMRecords;
-    GsmSimCard mSimCard;
+    SimCard mSimCard;
     StkService mStkService;
     MyHandler h;
     ArrayList <GsmMmiCode> mPendingMMIs = new ArrayList<GsmMmiCode>();
     SimPhoneBookInterfaceManager mSimPhoneBookIntManager;
     SimSmsInterfaceManager mSimSmsIntManager;
     PhoneSubInfo mSubInfo;
-    boolean mDnsCheckDisabled = false;
 
 
     Registrant mPostDialHandler;
@@ -129,44 +126,17 @@
     private String mImeiSv;
     private String mVmNumber;
 
-    //***** Event Constants
-
-    static final int EVENT_RADIO_AVAILABLE          = 1;
-    /** Supplemnetary Service Notification received. */
-    static final int EVENT_SSN                      = 2;
-    static final int EVENT_SIM_RECORDS_LOADED       = 3;
-    static final int EVENT_MMI_DONE                 = 4;
-    static final int EVENT_RADIO_ON                 = 5;
-    static final int EVENT_GET_BASEBAND_VERSION_DONE = 6;
-    static final int EVENT_USSD                     = 7;
-    static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 8;
-    static final int EVENT_GET_IMEI_DONE            = 9;
-    static final int EVENT_GET_IMEISV_DONE          = 10;
-    static final int EVENT_GET_SIM_STATUS_DONE      = 11;
-    static final int EVENT_SET_CALL_FORWARD_DONE    = 12;
-    static final int EVENT_GET_CALL_FORWARD_DONE    = 13;
-    static final int EVENT_CALL_RING                = 14;
-    // Used to intercept the carriere selection calls so that 
-    // we can save the values.
-    static final int EVENT_SET_NETWORK_MANUAL_COMPLETE = 15;
-    static final int EVENT_SET_NETWORK_AUTOMATIC_COMPLETE = 16;
-    static final int EVENT_SET_CLIR_COMPLETE = 17;
-    static final int EVENT_REGISTERED_TO_NETWORK = 18;
-    static final int EVENT_SET_VM_NUMBER_DONE = 19;
 
     //***** Constructors
 
     public
-    GSMPhone (Context context, CommandsInterface ci, PhoneNotifier notifier)
-    {
+    GSMPhone (Context context, CommandsInterface ci, PhoneNotifier notifier) {
         this(context,ci,notifier, false);
     }
 
     public
-    GSMPhone (Context context, CommandsInterface ci, PhoneNotifier notifier, boolean unitTestMode)
-    {
+    GSMPhone (Context context, CommandsInterface ci, PhoneNotifier notifier, boolean unitTestMode) {
         super(notifier, context, unitTestMode);
-
         h = new MyHandler();
         mCM = ci;
 
@@ -174,34 +144,31 @@
             mSimulatedRadioControl = (SimulatedRadioControl) ci;
         }
 
-        mCT = new CallTracker(this);
-        mSST = new ServiceStateTracker (this);
-        mSMS = new SMSDispatcher(this);
-        mSIMFileHandler = new SIMFileHandler(this);
+        mCM.setPhoneType(RILConstants.GSM_PHONE);
+        mCT = new GsmCallTracker(this);
+        mSST = new GsmServiceStateTracker (this);
+        mSMS = new GsmSMSDispatcher(this);
+        mIccFileHandler = new SIMFileHandler(this);
         mSIMRecords = new SIMRecords(this);
-        mDataConnection = new DataConnectionTracker (this);
-        mSimCard = new GsmSimCard(this);
+        mDataConnection = new GsmDataConnectionTracker (this);
+        mSimCard = new SimCard(this);
         if (!unitTestMode) {
             mSimPhoneBookIntManager = new SimPhoneBookInterfaceManager(this);
             mSimSmsIntManager = new SimSmsInterfaceManager(this);
             mSubInfo = new PhoneSubInfo(this);
         }
         mStkService = StkService.getInstance(mCM, mSIMRecords, mContext,
-                mSIMFileHandler, mSimCard);
-                
+                (SIMFileHandler)mIccFileHandler, mSimCard);
+
         mCM.registerForAvailable(h, EVENT_RADIO_AVAILABLE, null);
         mSIMRecords.registerForRecordsLoaded(h, EVENT_SIM_RECORDS_LOADED, null);
-        mCM.registerForOffOrNotAvailable(h, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, 
-                                                    null);
+        mCM.registerForOffOrNotAvailable(h, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
         mCM.registerForOn(h, EVENT_RADIO_ON, null);
         mCM.setOnUSSD(h, EVENT_USSD, null);
         mCM.setOnSuppServiceNotification(h, EVENT_SSN, null);
         mCM.setOnCallRing(h, EVENT_CALL_RING, null);
         mSST.registerForNetworkAttach(h, EVENT_REGISTERED_TO_NETWORK, null);
 
-        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
-        mDnsCheckDisabled = sp.getBoolean(DNS_SERVER_CHECK_DISABLED_KEY, false);
-
         if (false) {
             try {
                 //debugSocket = new LocalServerSocket("com.android.internal.telephony.debug");
@@ -221,7 +188,7 @@
                                         mCM.resetRadio(null);
                                         sock.close();
                                     } catch (IOException ex) {
-                                        Log.w(LOG_TAG, 
+                                        Log.w(LOG_TAG,
                                             "Exception accepting socket", ex);
                                     }
                                 }
@@ -235,13 +202,64 @@
                 Log.w(LOG_TAG, "Failure to open com.android.internal.telephony.debug socket", ex);
             }
         }
+
+        //Change the system setting
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                Settings.Secure.CURRENT_ACTIVE_PHONE, RILConstants.GSM_PHONE);
     }
-    
+
+    public void dispose() {
+        synchronized(PhoneProxy.lockForRadioTechnologyChange) {
+            //Unregister from all former registered events
+            mCM.unregisterForAvailable(h); //EVENT_RADIO_AVAILABLE
+            mSIMRecords.unregisterForRecordsLoaded(h); //EVENT_SIM_RECORDS_LOADED
+            mCM.unregisterForOffOrNotAvailable(h); //EVENT_RADIO_OFF_OR_NOT_AVAILABLE
+            mCM.unregisterForOn(h); //EVENT_RADIO_ON
+            mSST.unregisterForNetworkAttach(h); //EVENT_REGISTERED_TO_NETWORK
+            mCM.unSetOnUSSD(h);
+            mCM.unSetOnSuppServiceNotification(h);
+            mCM.unSetOnCallRing(h);
+
+            mPendingMMIs.clear();
+
+            //Force all referenced classes to unregister their former registered events
+            mStkService.dispose();
+            mCT.dispose();
+            mDataConnection.dispose();
+            mSST.dispose();
+            mIccFileHandler.dispose(); // instance of SimFileHandler
+            mSIMRecords.dispose();
+            mSimCard.dispose();
+            mSimPhoneBookIntManager.dispose();
+            mSimSmsIntManager.dispose();
+            mSubInfo.dispose();
+        }
+    }
+
+    public void removeReferences() {
+            this.mSimulatedRadioControl = null;
+            this.mStkService = null;
+            this.mSimPhoneBookIntManager = null;
+            this.mSimSmsIntManager = null;
+            this.mSMS = null;
+            this.mSubInfo = null;
+            this.mSIMRecords = null;
+            this.mIccFileHandler = null;
+            this.mSimCard = null;
+            this.mDataConnection = null;
+            this.mCT = null;
+            this.mSST = null;
+    }
+
+    protected void finalize() {
+        if(LOCAL_DEBUG) Log.d(LOG_TAG, "GSMPhone finalized");
+    }
+
+
     //***** Overridden from Phone
 
-    public ServiceState 
-    getServiceState()
-    {
+    public ServiceState
+    getServiceState() {
         return mSST.ss;
     }
 
@@ -249,15 +267,13 @@
         return mSST.cellLoc;
     }
 
-    public Phone.State 
-    getState()
-    {
+    public Phone.State
+    getState() {
         return mCT.state;
     }
 
     public String
-    getPhoneName()
-    {
+    getPhoneName() {
         return "GSM";
     }
 
@@ -270,14 +286,12 @@
     }
 
     public int
-    getSignalStrengthASU()
-    {
+    getSignalStrengthASU() {
         return mSST.rssi == 99 ? -1 : mSST.rssi;
     }
 
     public boolean
-    getMessageWaitingIndicator()
-    {
+    getMessageWaitingIndicator() {
         return mSIMRecords.getVoiceMessageWaiting();
     }
 
@@ -287,8 +301,7 @@
     }
 
     public List<? extends MmiCode>
-    getPendingMmiCodes()
-    {
+    getPendingMmiCodes() {
         return mPendingMMIs;
     }
 
@@ -309,27 +322,27 @@
             // but no data will flow
             ret = DataState.DISCONNECTED;
         } else { /* mSST.gprsState == ServiceState.STATE_IN_SERVICE */
-            switch (mDataConnection.state) {
-            case FAILED:
-            case IDLE:
-                ret = DataState.DISCONNECTED;
-            break;
+            switch (mDataConnection.getState()) {
+                case FAILED:
+                case IDLE:
+                    ret = DataState.DISCONNECTED;
+                break;
 
-            case CONNECTED:
-            case DISCONNECTING:
-                if ( mCT.state != Phone.State.IDLE
-                        && !mSST.isConcurrentVoiceAndData()) {
-                    ret = DataState.SUSPENDED;
-                } else {
-                    ret = DataState.CONNECTED;
-                }
-            break;
+                case CONNECTED:
+                case DISCONNECTING:
+                    if ( mCT.state != Phone.State.IDLE
+                            && !mSST.isConcurrentVoiceAndData()) {
+                        ret = DataState.SUSPENDED;
+                    } else {
+                        ret = DataState.CONNECTED;
+                    }
+                break;
 
-            case INITING:
-            case CONNECTING:
-            case SCANNING:
-                ret = DataState.CONNECTING;
-            break;
+                case INITING:
+                case CONNECTING:
+                case SCANNING:
+                    ret = DataState.CONNECTING;
+                break;
             }
         }
 
@@ -340,19 +353,18 @@
         DataActivityState ret = DataActivityState.NONE;
 
         if (mSST.getCurrentGprsState() == ServiceState.STATE_IN_SERVICE) {
-            switch (mDataConnection.activity) {
+            switch (mDataConnection.getActivity()) {
+                case DATAIN:
+                    ret = DataActivityState.DATAIN;
+                break;
 
-            case DATAIN:
-                ret = DataActivityState.DATAIN;
-            break;
+                case DATAOUT:
+                    ret = DataActivityState.DATAOUT;
+                break;
 
-            case DATAOUT:
-                ret = DataActivityState.DATAOUT;
-            break;
-
-            case DATAINANDOUT:
-                ret = DataActivityState.DATAINANDOUT;
-            break;
+                case DATAINANDOUT:
+                    ret = DataActivityState.DATAINANDOUT;
+                break;
             }
         }
 
@@ -371,15 +383,13 @@
      * changes to call state (including Phone and Connection changes).
      */
     /*package*/ void
-    notifyCallStateChanged()
-    {
+    notifyCallStateChanged() {
         /* we'd love it if this was package-scoped*/
         super.notifyCallStateChangedP();
     }
 
     /*package*/ void
-    notifyNewRingingConnection(Connection c)
-    {
+    notifyNewRingingConnection(Connection c) {
         /* we'd love it if this was package-scoped*/
         super.notifyNewRingingConnectionP(c);
     }
@@ -387,28 +397,26 @@
     /**
      * Notifiy registrants of a RING event.
      */
-    void notifyIncomingRing() {    
+    void notifyIncomingRing() {
         AsyncResult ar = new AsyncResult(null, this, null);
         mIncomingRingRegistrants.notifyRegistrants(ar);
     }
-    
+
     /*package*/ void
-    notifyDisconnect(Connection cn)
-    {
+    notifyDisconnect(Connection cn) {
         mDisconnectRegistrants.notifyResult(cn);
     }
 
     void notifyUnknownConnection() {
         mUnknownConnectionRegistrants.notifyResult(this);
     }
-    
+
     void notifySuppServiceFailed(SuppService code) {
         mSuppServiceFailedRegistrants.notifyResult(code);
     }
 
     /*package*/ void
-    notifyServiceStateChanged(ServiceState ss)
-    {
+    notifyServiceStateChanged(ServiceState ss) {
         super.notifyServiceStateChangedP(ss);
     }
 
@@ -418,55 +426,38 @@
     }
 
     /*package*/ void
-    notifySignalStrength()
-    {
+    notifySignalStrength() {
         mNotifier.notifySignalStrength(this);
     }
 
     /*package*/ void
-    notifyDataConnection(String reason) {
-        mNotifier.notifyDataConnection(this, reason);
-    }
-
-    /*package*/ void
     notifyDataConnectionFailed(String reason) {
         mNotifier.notifyDataConnectionFailed(this, reason);
     }
 
     /*package*/ void
-    notifyDataActivity() {
-        mNotifier.notifyDataActivity(this);
-    }
-
-    /*package*/ void
-    updateMessageWaitingIndicator(boolean mwi)
-    {
+    updateMessageWaitingIndicator(boolean mwi) {
         // this also calls notifyMessageWaitingIndicator()
         mSIMRecords.setVoiceMessageWaiting(1, mwi ? -1 : 0);
     }
 
-    /*package*/ void
-    notifyMessageWaitingIndicator()
-    {
+    public void
+    notifyMessageWaitingIndicator() {
         mNotifier.notifyMessageWaitingChanged(this);
     }
 
-    /*package*/ void
+    public void
     notifyCallForwardingIndicator() {
         mNotifier.notifyCallForwardingChanged(this);
     }
 
+    // override for allowing access from other classes of this package
     /**
-     * Set a system property, unless we're in unit test mode
+     * {@inheritDoc}
      */
-
-    /*package*/ void
-    setSystemProperty(String property, String value)
-    {
-        if(getUnitTestMode()) {
-            return;
-        }
-        SystemProperties.set(property, value);
+    public final void
+    setSystemProperty(String property, String value) {
+        super.setSystemProperty(property, value);
     }
 
     public void registerForSuppServiceNotification(
@@ -480,71 +471,57 @@
         if (mSsnRegistrants.size() == 0) mCM.setSuppServiceNotifications(false, null);
     }
 
-    public void 
-    acceptCall() throws CallStateException
-    {
+    public void
+    acceptCall() throws CallStateException {
         mCT.acceptCall();
     }
 
-    public void 
-    rejectCall() throws CallStateException
-    {
+    public void
+    rejectCall() throws CallStateException {
         mCT.rejectCall();
     }
 
     public void
-    switchHoldingAndActive() throws CallStateException
-    {
+    switchHoldingAndActive() throws CallStateException {
         mCT.switchWaitingOrHoldingAndActive();
     }
 
-
-    public boolean canConference()
-    {
+    public boolean canConference() {
         return mCT.canConference();
     }
 
-    public boolean canDial()
-    {
+    public boolean canDial() {
         return mCT.canDial();
     }
 
-    public void conference() throws CallStateException
-    {
+    public void conference() throws CallStateException {
         mCT.conference();
     }
 
-    public void clearDisconnected()
-    {
-    
+    public void clearDisconnected() {
         mCT.clearDisconnected();
     }
 
-    public boolean canTransfer()
-    {
+    public boolean canTransfer() {
         return mCT.canTransfer();
     }
 
-    public void explicitCallTransfer() throws CallStateException
-    {
+    public void explicitCallTransfer() throws CallStateException {
         mCT.explicitCallTransfer();
     }
 
-    public Call
-    getForegroundCall()
-    {
+    public GsmCall
+    getForegroundCall() {
         return mCT.foregroundCall;
     }
 
-    public Call 
-    getBackgroundCall()
-    {
+    public GsmCall
+    getBackgroundCall() {
         return mCT.backgroundCall;
     }
 
-    public Call 
-    getRingingCall()
-    {
+    public GsmCall
+    getRingingCall() {
         return mCT.ringingCall;
     }
 
@@ -554,7 +531,7 @@
             return false;
         }
 
-        if (getRingingCall().getState() != Call.State.IDLE) {
+        if (getRingingCall().getState() != GsmCall.State.IDLE) {
             if (LOCAL_DEBUG) Log.d(LOG_TAG, "MmiCode 0: rejectCall");
             try {
                 mCT.rejectCall();
@@ -563,7 +540,7 @@
                     "reject failed", e);
                 notifySuppServiceFailed(Phone.SuppService.REJECT);
             }
-        } else if (getBackgroundCall().getState() != Call.State.IDLE) {
+        } else if (getBackgroundCall().getState() != GsmCall.State.IDLE) {
             if (LOCAL_DEBUG) Log.d(LOG_TAG,
                     "MmiCode 0: hangupWaitingOrBackground");
             mCT.hangupWaitingOrBackground();
@@ -580,21 +557,21 @@
             return false;
         }
 
-        GSMCall call = (GSMCall) getForegroundCall();
+        GsmCall call = (GsmCall) getForegroundCall();
 
         try {
             if (len > 1) {
                 char ch = dialString.charAt(1);
                 int callIndex = ch - '0';
 
-                if (callIndex >= 1 && callIndex <= CallTracker.MAX_CONNECTIONS) {
+                if (callIndex >= 1 && callIndex <= GsmCallTracker.MAX_CONNECTIONS) {
                     if (LOCAL_DEBUG) Log.d(LOG_TAG,
                             "MmiCode 1: hangupConnectionByIndex " +
                             callIndex);
                     mCT.hangupConnectionByIndex(call, callIndex);
                 }
             } else {
-                if (call.getState() != Call.State.IDLE) {
+                if (call.getState() != GsmCall.State.IDLE) {
                     if (LOCAL_DEBUG) Log.d(LOG_TAG,
                             "MmiCode 1: hangup foreground");
                     //mCT.hangupForegroundResumeBackground();
@@ -622,16 +599,16 @@
             return false;
         }
 
-        GSMCall call = (GSMCall) getForegroundCall();
+        GsmCall call = (GsmCall) getForegroundCall();
 
         if (len > 1) {
             try {
                 char ch = dialString.charAt(1);
                 int callIndex = ch - '0';
-                GSMConnection conn = mCT.getConnectionByIndex(call, callIndex);
-                
+                GsmConnection conn = mCT.getConnectionByIndex(call, callIndex);
+
                 // gsm index starts at 1, up to 5 connections in a call,
-                if (conn != null && callIndex >= 1 && callIndex <= CallTracker.MAX_CONNECTIONS) {
+                if (conn != null && callIndex >= 1 && callIndex <= GsmCallTracker.MAX_CONNECTIONS) {
                     if (LOCAL_DEBUG) Log.d(LOG_TAG, "MmiCode 2: separate call "+
                             callIndex);
                     mCT.separate(conn);
@@ -647,7 +624,7 @@
             }
         } else {
             try {
-                if (getRingingCall().getState() != Call.State.IDLE) {
+                if (getRingingCall().getState() != GsmCall.State.IDLE) {
                     if (LOCAL_DEBUG) Log.d(LOG_TAG,
                     "MmiCode 2: accept ringing call");
                     mCT.acceptCall();
@@ -756,9 +733,9 @@
     }
 
     boolean isInCall() {
-        Call.State foregroundCallState = getForegroundCall().getState();
-        Call.State backgroundCallState = getBackgroundCall().getState();
-        Call.State ringingCallState = getRingingCall().getState();
+        GsmCall.State foregroundCallState = getForegroundCall().getState();
+        GsmCall.State backgroundCallState = getBackgroundCall().getState();
+        GsmCall.State ringingCallState = getRingingCall().getState();
 
        return (foregroundCallState.isAlive() ||
                 backgroundCallState.isAlive() ||
@@ -797,15 +774,15 @@
 
     public boolean handlePinMmi(String dialString) {
         GsmMmiCode mmi = GsmMmiCode.newFromDialString(dialString, this);
-        
+
         if (mmi != null && mmi.isPinCommand()) {
             mPendingMMIs.add(mmi);
             mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
             mmi.processCode();
             return true;
         }
-        
-        return false;        
+
+        return false;
     }
 
     public void sendUssdResponse(String ussdMessge) {
@@ -814,11 +791,11 @@
         mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
         mmi.sendUssd(ussdMessge);
     }
-    
+
     public void
     sendDtmf(char c) {
         if (!PhoneNumberUtils.is12Key(c)) {
-            Log.e(LOG_TAG, 
+            Log.e(LOG_TAG,
                     "sendDtmf called with invalid character '" + c + "'");
         } else {
             if (mCT.state ==  Phone.State.OFFHOOK) {
@@ -887,7 +864,7 @@
                 com.android.internal.R.string.defaultVoiceMailAlphaTag).toString();
         }
 
-        return ret;        
+        return ret;
     }
 
     public String getDeviceId() {
@@ -898,11 +875,21 @@
         return mImeiSv;
     }
 
+    public String getEsn() {
+        Log.e(LOG_TAG, "[GSMPhone] getEsn() is a CDMA method");
+        return "0";
+    }
+
+    public String getMeid() {
+        Log.e(LOG_TAG, "[GSMPhone] getMeid() is a CDMA method");
+        return "0";
+    }
+
     public String getSubscriberId() {
         return mSIMRecords.imsi;
     }
 
-    public String getSimSerialNumber() {
+    public String getIccSerialNumber() {
         return mSIMRecords.iccid;
     }
 
@@ -939,37 +926,35 @@
     
     private boolean isValidCommandInterfaceCFReason (int commandInterfaceCFReason) {
         switch (commandInterfaceCFReason) {
-            case CF_REASON_UNCONDITIONAL:
-            case CF_REASON_BUSY:
-            case CF_REASON_NO_REPLY:
-            case CF_REASON_NOT_REACHABLE:
-            case CF_REASON_ALL:
-            case CF_REASON_ALL_CONDITIONAL:
-                return true;
-            default:
-                return false;
+        case CF_REASON_UNCONDITIONAL:
+        case CF_REASON_BUSY:
+        case CF_REASON_NO_REPLY:
+        case CF_REASON_NOT_REACHABLE:
+        case CF_REASON_ALL:
+        case CF_REASON_ALL_CONDITIONAL:
+            return true;
+        default:
+            return false;
         }
     }
 
     private boolean isValidCommandInterfaceCFAction (int commandInterfaceCFAction) {
         switch (commandInterfaceCFAction) {
-            case CF_ACTION_DISABLE:
-            case CF_ACTION_ENABLE:
-            case CF_ACTION_REGISTRATION:
-            case CF_ACTION_ERASURE:
-                return true;
-            default:
-                return false;
+        case CF_ACTION_DISABLE:
+        case CF_ACTION_ENABLE:
+        case CF_ACTION_REGISTRATION:
+        case CF_ACTION_ERASURE:
+            return true;
+        default:
+            return false;
         }
     }
-    
-    private boolean isCfEnable(int action) {
+
+    protected  boolean isCfEnable(int action) {
         return (action == CF_ACTION_ENABLE) || (action == CF_ACTION_REGISTRATION);
     }
-    
-    public void getCallForwardingOption(int commandInterfaceCFReason,
-                                        Message onComplete) {
-        
+
+    public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) {
         if (isValidCommandInterfaceCFReason(commandInterfaceCFReason)) {
             if (LOCAL_DEBUG) Log.d(LOG_TAG, "requesting call forwarding query.");
             Message resp;
@@ -983,14 +968,13 @@
     }
 
     public void setCallForwardingOption(int commandInterfaceCFAction,
-                                        int commandInterfaceCFReason,
-                                        String dialingNumber,
-                                        int timerSeconds,
-                                        Message onComplete) {
-            
-        if ((isValidCommandInterfaceCFAction(commandInterfaceCFAction)) && 
-            (isValidCommandInterfaceCFReason(commandInterfaceCFReason))) {
-            
+            int commandInterfaceCFReason,
+            String dialingNumber,
+            int timerSeconds,
+            Message onComplete) {
+        if (    (isValidCommandInterfaceCFAction(commandInterfaceCFAction)) &&
+                (isValidCommandInterfaceCFReason(commandInterfaceCFReason))) {
+
             Message resp;
             if (commandInterfaceCFReason == CF_REASON_UNCONDITIONAL) {
                 resp = h.obtainMessage(EVENT_SET_CALL_FORWARD_DONE,
@@ -1006,12 +990,12 @@
                     resp);
         }
     }
-    
+
     public void getOutgoingCallerIdDisplay(Message onComplete) {
         mCM.getCLIR(onComplete);
     }
-    
-    public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, 
+
+    public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode,
                                            Message onComplete) {
         mCM.setCLIR(commandInterfaceCLIRMode,
                 h.obtainMessage(EVENT_SET_CLIR_COMPLETE, commandInterfaceCLIRMode, 0, onComplete));
@@ -1020,162 +1004,111 @@
     public void getCallWaiting(Message onComplete) {
         mCM.queryCallWaiting(CommandsInterface.SERVICE_CLASS_VOICE, onComplete);
     }
-    
+
     public void setCallWaiting(boolean enable, Message onComplete) {
         mCM.setCallWaiting(enable, CommandsInterface.SERVICE_CLASS_VOICE, onComplete);
     }
-    
+
     public boolean
-    getSimRecordsLoaded() {
+    getIccRecordsLoaded() {
         return mSIMRecords.getRecordsLoaded();
     }
 
-    public SimCard
-    getSimCard() {
+    public IccCard getIccCard() {
         return mSimCard;
     }
 
-    public void 
+    public void
     getAvailableNetworks(Message response) {
         mCM.getAvailableNetworks(response);
     }
 
     /**
-     * Small container class used to hold information relevant to 
+     * Small container class used to hold information relevant to
      * the carrier selection process. operatorNumeric can be ""
-     * if we are looking for automatic selection. 
+     * if we are looking for automatic selection.
      */
     private static class NetworkSelectMessage {
         public Message message;
         public String operatorNumeric;
     }
-    
-    public void 
+
+    public void
     setNetworkSelectionModeAutomatic(Message response) {
         // wrap the response message in our own message along with
-        // an empty string (to indicate automatic selection) for the 
+        // an empty string (to indicate automatic selection) for the
         // operator's id.
         NetworkSelectMessage nsm = new NetworkSelectMessage();
         nsm.message = response;
         nsm.operatorNumeric = "";
-        
+
         // get the message
         Message msg = h.obtainMessage(EVENT_SET_NETWORK_AUTOMATIC_COMPLETE, nsm);
-        if (LOCAL_DEBUG) 
+        if (LOCAL_DEBUG)
             Log.d(LOG_TAG, "wrapping and sending message to connect automatically");
 
         mCM.setNetworkSelectionModeAutomatic(msg);
     }
 
-    public void 
+    public void
     selectNetworkManually(com.android.internal.telephony.gsm.NetworkInfo network,
-                          Message response) {
+            Message response) {
         // wrap the response message in our own message along with
         // the operator's id.
         NetworkSelectMessage nsm = new NetworkSelectMessage();
         nsm.message = response;
         nsm.operatorNumeric = network.operatorNumeric;
-        
+
         // get the message
         Message msg = h.obtainMessage(EVENT_SET_NETWORK_MANUAL_COMPLETE, nsm);
 
         mCM.setNetworkSelectionModeManual(network.operatorNumeric, msg);
     }
-    
-    /**
-     * Method to retrieve the saved operator id from the Shared Preferences
-     */
-    private String getSavedNetworkSelection() {
-        // open the shared preferences and search with our key. 
-        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
-        return sp.getString(NETWORK_SELECTION_KEY, "");
-    }
-
-    /**
-     * Method to restore the previously saved operator id, or reset to
-     * automatic selection, all depending upon the value in the shared
-     * preferences.
-     */
-    void restoreSavedNetworkSelection(Message response) {
-        // retrieve the operator id
-        String networkSelection = getSavedNetworkSelection();
-        
-        // set to auto if the id is empty, otherwise select the network.
-        if (TextUtils.isEmpty(networkSelection)) {
-            mCM.setNetworkSelectionModeAutomatic(response);
-        } else {
-            mCM.setNetworkSelectionModeManual(networkSelection, response);
-        }
-    }
-    
-    public void 
-    setPreferredNetworkType(int networkType, Message response) {
-        mCM.setPreferredNetworkType(networkType, response);
-    }
-
-    public void
-    getPreferredNetworkType(Message response) {
-        mCM.getPreferredNetworkType(response);
-    }
 
     public void
     getNeighboringCids(Message response) {
         mCM.getNeighboringCids(response);
     }
-    
-    public void setOnPostDialCharacter(Handler h, int what, Object obj)
-    {
+
+    public void setOnPostDialCharacter(Handler h, int what, Object obj) {
         mPostDialHandler = new Registrant(h, what, obj);
     }
 
-
-    public void setMute(boolean muted)
-    {
+    public void setMute(boolean muted) {
         mCT.setMute(muted);
     }
-    
-    public boolean getMute()
-    {
+
+    public boolean getMute() {
         return mCT.getMute();
     }
 
-
-    public void invokeOemRilRequestRaw(byte[] data, Message response)
-    {
-        mCM.invokeOemRilRequestRaw(data, response);
-    }
-
-    public void invokeOemRilRequestStrings(String[] strings, Message response)
-    {
-        mCM.invokeOemRilRequestStrings(strings, response);
-    }
-
+    /**
+     * @deprecated
+     */
     public void getPdpContextList(Message response) {
-        mCM.getPDPContextList(response);
+        getDataCallList(response);
     }
 
-    public List<PdpConnection> getCurrentPdpList () {
-        return mDataConnection.getAllPdps();
+    public void getDataCallList(Message response) {
+        mCM.getDataCallList(response);
     }
 
     /**
-     * Disables the DNS check (i.e., allows "0.0.0.0").
-     * Useful for lab testing environment.
-     * @param b true disables the check, false enables.
+     * @deprecated
      */
-    public void disableDnsCheck(boolean b) {
-        mDnsCheckDisabled = b;
-        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
-        SharedPreferences.Editor editor = sp.edit();
-        editor.putBoolean(DNS_SERVER_CHECK_DISABLED_KEY, b);        
-        editor.commit();
+    public List<PdpConnection> getCurrentPdpList() {
+        ArrayList<DataConnection> connections = new ArrayList<DataConnection>();
+        ArrayList<PdpConnection> pdp_list = new ArrayList<PdpConnection>();
+
+        for(int n = 0; n < connections.size(); n++) {
+            pdp_list.add((PdpConnection) connections.get(n));
+        }
+
+        return pdp_list;
     }
 
-    /**
-     * Returns true if the DNS check is currently disabled.
-     */
-    public boolean isDnsCheckDisabled() {
-        return mDnsCheckDisabled;
+    public List<DataConnection> getCurrentDataConnectionList () {
+        return mDataConnection.getAllDataConnections();
     }
 
     public void updateServiceLocation(Message response) {
@@ -1190,14 +1123,6 @@
         mSST.disableLocationUpdates();
     }
 
-    public void setBandMode(int bandMode, Message response) {
-        mCM.setBandMode(bandMode, response);
-    }
-
-    public void queryAvailableBandMode(Message response) {
-        mCM.queryAvailableBandMode(response);
-    }
-
     public boolean getDataRoamingEnabled() {
         return mDataConnection.getDataOnRoamingEnabled();
     }
@@ -1254,7 +1179,7 @@
         // check for "default"?
         boolean noData = mDataConnection.getDataEnabled() &&
             getDataConnectionState() == DataState.DISCONNECTED;
-        return !noData && getSimCard().getState() == SimCard.State.READY &&
+        return !noData && getIccCard().getState() == SimCard.State.READY &&
                 getServiceState().getState() == ServiceState.STATE_IN_SERVICE &&
             (mDataConnection.getDataOnRoamingEnabled() || !getServiceState().getRoaming());
     }
@@ -1265,9 +1190,8 @@
      * @param mmi MMI that is done
      */
     /*package*/ void
-    onMMIDone(GsmMmiCode mmi)
-    {
-        /* Only notify complete if it's on the pending list. 
+    onMMIDone(GsmMmiCode mmi) {
+        /* Only notify complete if it's on the pending list.
          * Otherwise, it's already been handled (eg, previously canceled).
          * The exception is cancellation of an incoming USSD-REQUEST, which is
          * not on the list.
@@ -1279,9 +1203,8 @@
     }
 
 
-    private void 
-    onNetworkInitiatedUssd(GsmMmiCode mmi)
-    {
+    private void
+    onNetworkInitiatedUssd(GsmMmiCode mmi) {
         mMmiCompleteRegistrants.notifyRegistrants(
             new AsyncResult(null, mmi, null));
     }
@@ -1289,18 +1212,17 @@
 
     /** ussdMode is one of CommandsInterface.USSD_MODE_* */
     private void
-    onIncomingUSSD (int ussdMode, String ussdMessage)
-    {
+    onIncomingUSSD (int ussdMode, String ussdMessage) {
         boolean isUssdError;
         boolean isUssdRequest;
-        
-        isUssdRequest 
+
+        isUssdRequest
             = (ussdMode == CommandsInterface.USSD_MODE_REQUEST);
 
-        isUssdError 
+        isUssdError
             = (ussdMode != CommandsInterface.USSD_MODE_NOTIFY
                 && ussdMode != CommandsInterface.USSD_MODE_REQUEST);
-    
+
         // See comments in GsmMmiCode.java
         // USSD requests aren't finished until one
         // of these two events happen
@@ -1327,7 +1249,7 @@
             // also, discard if there is no message to present
             if (!isUssdError && ussdMessage != null) {
                 GsmMmiCode mmi;
-                mmi = GsmMmiCode.newNetworkInitiatedUssd(ussdMessage, 
+                mmi = GsmMmiCode.newNetworkInitiatedUssd(ussdMessage,
                                                    isUssdRequest,
                                                    GSMPhone.this);
                 onNetworkInitiatedUssd(mmi);
@@ -1338,7 +1260,7 @@
     /**
      * Make sure the network knows our preferred setting.
      */
-    private void syncClirSetting() {
+    protected  void syncClirSetting() {
         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
         int clirSetting = sp.getInt(CLIR_KEY, -1);
         if (clirSetting >= 0) {
@@ -1348,20 +1270,16 @@
 
     //***** Inner Classes
 
-    class MyHandler extends Handler
-    {
-        MyHandler()
-        {
+    class MyHandler extends Handler {
+        MyHandler() {
         }
 
-        MyHandler(Looper l)
-        {
+        MyHandler(Looper l) {
             super(l);
         }
 
         public void
-        handleMessage (Message msg) 
-        {
+        handleMessage (Message msg) {
             AsyncResult ar;
             Message onComplete;
 
@@ -1422,11 +1340,10 @@
                     if (ar.exception != null) {
                         break;
                     }
-                    
+
                     mImeiSv = (String)ar.result;
                 break;
 
-
                 case EVENT_USSD:
                     ar = (AsyncResult)msg.obj;
 
@@ -1441,7 +1358,7 @@
                     }
                 break;
 
-                case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:                
+                case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
                     // Some MMI requests (eg USSD) are not completed
                     // within the course of a CommandsInterface request
                     // If the radio shuts off or resets while one of these
@@ -1450,10 +1367,10 @@
                     for (int i = 0, s = mPendingMMIs.size() ; i < s; i++) {
                         if (mPendingMMIs.get(i).isPendingUSSD()) {
                             mPendingMMIs.get(i).onUssdFinishedError();
-                        }                            
+                        }
                     }
                 break;
-                
+
                 case EVENT_SSN:
                     ar = (AsyncResult)msg.obj;
                     SuppServiceNotification not = (SuppServiceNotification) ar.result;
@@ -1474,7 +1391,7 @@
                     
                 case EVENT_SET_VM_NUMBER_DONE:
                     ar = (AsyncResult)msg.obj;
-                    if (SimVmNotSupportedException.class.isInstance(ar.exception)) {
+                    if (IccVmNotSupportedException.class.isInstance(ar.exception)) {
                         storeVoiceMailNumber(mVmNumber);
                         ar.exception = null;
                     }
@@ -1497,15 +1414,15 @@
                         onComplete.sendToTarget();
                     }
                     break;
-                    
+
                 case EVENT_CALL_RING:
                     ar = (AsyncResult)msg.obj;
                     if (ar.exception == null) {
                         notifyIncomingRing();
                     }
                     break;
-                    
-                // handle the select network completion callbacks.    
+
+                // handle the select network completion callbacks.
                 case EVENT_SET_NETWORK_MANUAL_COMPLETE:
                 case EVENT_SET_NETWORK_AUTOMATIC_COMPLETE:
                     handleSetSelectNetwork((AsyncResult) msg.obj);
@@ -1550,29 +1467,29 @@
      * Used to track the settings upon completion of the network change.
      */
     private void handleSetSelectNetwork(AsyncResult ar) {
-        // look for our wrapper within the asyncresult, skip the rest if it 
-        // is null. 
+        // look for our wrapper within the asyncresult, skip the rest if it
+        // is null.
         if (!(ar.userObj instanceof NetworkSelectMessage)) {
             if (LOCAL_DEBUG) Log.d(LOG_TAG, "unexpected result from user object.");
             return;
         }
-        
+
         NetworkSelectMessage nsm = (NetworkSelectMessage) ar.userObj;
-        
+
         // found the object, now we send off the message we had originally
-        // attached to the request. 
+        // attached to the request.
         if (nsm.message != null) {
             if (LOCAL_DEBUG) Log.d(LOG_TAG, "sending original message to recipient");
             AsyncResult.forMessage(nsm.message, ar.result, ar.exception);
             nsm.message.sendToTarget();
         }
-        
+
         // open the shared preferences editor, and write the value.
         // nsm.operatorNumeric is "" if we're in automatic.selection.
         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
         SharedPreferences.Editor editor = sp.edit();
         editor.putString(NETWORK_SELECTION_KEY, nsm.operatorNumeric);
-        
+
         // commit and log the result.
         if (! editor.commit()) {
             Log.e(LOG_TAG, "failed to commit network selection preference");
@@ -1584,17 +1501,16 @@
      * Saves CLIR setting so that we can re-apply it as necessary
      * (in case the RIL resets it across reboots).
      */
-    /* package */ void saveClirSetting(int commandInterfaceCLIRMode) {
+    public void saveClirSetting(int commandInterfaceCLIRMode) {
         // open the shared preferences editor, and write the value.
         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
         SharedPreferences.Editor editor = sp.edit();
         editor.putInt(CLIR_KEY, commandInterfaceCLIRMode);
-        
+
         // commit and log the result.
         if (! editor.commit()) {
             Log.e(LOG_TAG, "failed to commit CLIR preference");
         }
-
     }
 
     private void handleCfuQueryResult(CallForwardInfo[] infos) {
@@ -1618,7 +1534,7 @@
      * simulates various data connection states. This messes with
      * DataConnectionTracker's internal states, but doesn't actually change
      * the underlying radio connection states.
-     * 
+     *
      * @param state Phone.DataState enum.
      */
     public void simulateDataConnection(Phone.DataState state) {
@@ -1642,4 +1558,52 @@
         mDataConnection.setState(dcState);
         notifyDataConnection(null);
     }
+
+    /**
+     * Retrieves the PhoneSubInfo of the GSMPhone
+     */
+    public PhoneSubInfo getPhoneSubInfo(){
+        return mSubInfo;
+    }
+
+    /**
+     * Retrieves the IccSmsInterfaceManager of the GSMPhone
+     */
+    public IccSmsInterfaceManager getIccSmsInterfaceManager(){
+        return mSimSmsIntManager;
+    }
+
+    /**
+     * Retrieves the IccPhoneBookInterfaceManager of the GSMPhone
+     */
+    public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager(){
+        return mSimPhoneBookIntManager;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Handler getHandler(){
+        return h;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public IccFileHandler getIccFileHandler(){
+        return this.mIccFileHandler;
+    }
+
+    public void activateCellBroadcastSms(int activate, Message response) {
+        Log.e(LOG_TAG, "Error! This functionality is not implemented for GSM.");
+    }
+
+    public void getCellBroadcastSmsConfig(Message response) {
+        Log.e(LOG_TAG, "Error! This functionality is not implemented for GSM.");
+    }
+
+    public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response){
+        Log.e(LOG_TAG, "Error! This functionality is not implemented for GSM.");
+    }
+
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMCall.java b/telephony/java/com/android/internal/telephony/gsm/GsmCall.java
similarity index 75%
rename from telephony/java/com/android/internal/telephony/gsm/GSMCall.java
rename to telephony/java/com/android/internal/telephony/gsm/GsmCall.java
index 4feaf21..a92e52d 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GSMCall.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmCall.java
@@ -15,26 +15,30 @@
  */
 
 package com.android.internal.telephony.gsm;
-import com.android.internal.telephony.*;
+
+import com.android.internal.telephony.Call;
+import com.android.internal.telephony.CallStateException;
+import com.android.internal.telephony.Connection;
+import com.android.internal.telephony.DriverCall;
+import com.android.internal.telephony.Phone;
+
 import java.util.ArrayList;
 import java.util.List;
 
 /**
  * {@hide}
  */
-class GSMCall extends Call
-{
+class GsmCall extends Call {
     /*************************** Instance Variables **************************/
 
     /*package*/ ArrayList<Connection> connections = new ArrayList<Connection>();
-    /*package*/ State state = State.IDLE;
-    /*package*/ CallTracker owner;
+    /*package*/ GsmCallTracker owner;
+
 
     /***************************** Class Methods *****************************/
 
     static State
-    stateFromDCState (DriverCall.State dcState)
-    {
+    stateFromDCState (DriverCall.State dcState) {
         switch (dcState) {
             case ACTIVE:        return State.ACTIVE;
             case HOLDING:       return State.HOLDING;
@@ -45,40 +49,33 @@
             default:            throw new RuntimeException ("illegal call state:" + dcState);
         }
     }
-    
+
 
     /****************************** Constructors *****************************/
     /*package*/
-    GSMCall (CallTracker owner)
-    {
+    GsmCall (GsmCallTracker owner) {
         this.owner = owner;
     }
 
+    public void dispose() {
+    }
+
     /************************** Overridden from Call *************************/
 
     public List<Connection>
-    getConnections()
-    {
+    getConnections() {
         // FIXME should return Collections.unmodifiableList();
         return connections;
     }
 
-    public State 
-    getState()
-    {
-        return state;
-    }
-
-    public Phone 
-    getPhone()
-    {
+    public Phone
+    getPhone() {
         //TODO
         return null;
     }
 
     public boolean
-    isMultiparty()
-    {
+    isMultiparty() {
         return connections.size() > 1;
     }
 
@@ -86,66 +83,60 @@
      *  background call exists, the background call will be resumed
      *  because an AT+CHLD=1 will be sent
      */
-    public void 
-    hangup() throws CallStateException
-    {
+    public void
+    hangup() throws CallStateException {
         owner.hangup(this);
     }
 
     public String
-    toString()
-    {
+    toString() {
         return state.toString();
     }
 
-    //***** Called from GSMConnection
+    //***** Called from GsmConnection
 
     /*package*/ void
-    attach(GSMConnection conn, DriverCall dc)
-    {
+    attach(Connection conn, DriverCall dc) {
         connections.add(conn);
 
         state = stateFromDCState (dc.state);
     }
 
     /*package*/ void
-    attachFake(GSMConnection conn, State state)
-    {
+    attachFake(Connection conn, State state) {
         connections.add(conn);
 
         this.state = state;
     }
 
     /**
-     * Called by GSMConnection when it has disconnected
+     * Called by GsmConnection when it has disconnected
      */
     void
-    connectionDisconnected(GSMConnection conn)
-    {
+    connectionDisconnected(GsmConnection conn) {
         if (state != State.DISCONNECTED) {
             /* If only disconnected connections remain, we are disconnected*/
 
             boolean hasOnlyDisconnectedConnections = true;
-            
+
             for (int i = 0, s = connections.size()  ; i < s; i ++) {
-                if (connections.get(i).getState() 
+                if (connections.get(i).getState()
                     != State.DISCONNECTED
                 ) {
                     hasOnlyDisconnectedConnections = false;
                     break;
-                }            
+                }
             }
 
             if (hasOnlyDisconnectedConnections) {
-                state = State.DISCONNECTED;            
+                state = State.DISCONNECTED;
             }
-        }    
+        }
     }
 
 
     /*package*/ void
-    detach(GSMConnection conn)
-    {
+    detach(GsmConnection conn) {
         connections.remove(conn);
 
         if (connections.size() == 0) {
@@ -154,13 +145,12 @@
     }
 
     /*package*/ boolean
-    update (GSMConnection conn, DriverCall dc)
-    {
+    update (GsmConnection conn, DriverCall dc) {
         State newState;
         boolean changed = false;
-        
+
         newState = stateFromDCState(dc.state);
-        
+
         if (newState != state) {
             state = newState;
             changed = true;
@@ -174,44 +164,41 @@
      * connections to be added via "conference"
      */
     /*package*/ boolean
-    isFull()
-    {
-        return connections.size() == CallTracker.MAX_CONNECTIONS_PER_CALL;
+    isFull() {
+        return connections.size() == GsmCallTracker.MAX_CONNECTIONS_PER_CALL;
     }
 
-    //***** Called from CallTracker
+    //***** Called from GsmCallTracker
 
 
-    /** 
+    /**
      * Called when this Call is being hung up locally (eg, user pressed "end")
      * Note that at this point, the hangup request has been dispatched to the radio
      * but no response has yet been received so update() has not yet been called
      */
     void
-    onHangupLocal()
-    {
+    onHangupLocal() {
         for (int i = 0, s = connections.size()
                 ; i < s; i++
         ) {
-            GSMConnection cn = (GSMConnection)connections.get(i);
+            GsmConnection cn = (GsmConnection)connections.get(i);
 
             cn.onHangupLocal();
         }
     }
-    
+
     /**
      * Called when it's time to clean up disconnected Connection objects
      */
     void
-    clearDisconnected()
-    {
+    clearDisconnected() {
         for (int i = connections.size() - 1 ; i >= 0 ; i--) {
-            GSMConnection cn = (GSMConnection)connections.get(i);
-            
+            GsmConnection cn = (GsmConnection)connections.get(i);
+
             if (cn.getState() == State.DISCONNECTED) {
                 connections.remove(i);
             }
-        }    
+        }
 
         if (connections.size() == 0) {
             state = State.IDLE;
diff --git a/telephony/java/com/android/internal/telephony/gsm/CallTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmCallTracker.java
similarity index 79%
rename from telephony/java/com/android/internal/telephony/gsm/CallTracker.java
rename to telephony/java/com/android/internal/telephony/gsm/GsmCallTracker.java
index 2d716bb..5c5090f 100644
--- a/telephony/java/com/android/internal/telephony/gsm/CallTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmCallTracker.java
@@ -16,37 +16,34 @@
 
 package com.android.internal.telephony.gsm;
 
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE;
-import static com.android.internal.telephony.gsm.ServiceStateTracker.DATA_ACCESS_EDGE;
-import static com.android.internal.telephony.gsm.ServiceStateTracker.DATA_ACCESS_GPRS;
-import static com.android.internal.telephony.gsm.ServiceStateTracker.DATA_ACCESS_UMTS;
-import static com.android.internal.telephony.gsm.ServiceStateTracker.DATA_ACCESS_UNKNOWN;
-import android.os.AsyncResult;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Registrant;
-import android.os.RegistrantList;
-import android.os.SystemProperties;
+import android.os.*;
+import android.telephony.gsm.GsmCellLocation;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
-import android.telephony.gsm.GsmCellLocation;
 import android.util.EventLog;
 import android.util.Log;
 
-import com.android.internal.telephony.Call;
 import com.android.internal.telephony.CallStateException;
+import com.android.internal.telephony.CallTracker;
+import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.Connection;
+import com.android.internal.telephony.DriverCall;
+import com.android.internal.telephony.gsm.CallFailCause;
+import com.android.internal.telephony.gsm.GsmCall;
+import com.android.internal.telephony.gsm.GsmConnection;
+import com.android.internal.telephony.gsm.GSMPhone;
 import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.TelephonyEventLog;
+import com.android.internal.telephony.*;
 
-import java.util.ArrayList;
 import java.util.List;
+import java.util.ArrayList;
 
 /**
  * {@hide}
  */
-public final class CallTracker extends Handler
-{
+public final class GsmCallTracker extends CallTracker {
     static final String LOG_TAG = "GSM";
     private static final boolean REPEAT_POLLING = false;
 
@@ -54,59 +51,41 @@
 
     //***** Constants
 
-    static final int POLL_DELAY_MSEC = 250;
     static final int MAX_CONNECTIONS = 7;   // only 7 connections allowed in GSM
     static final int MAX_CONNECTIONS_PER_CALL = 5; // only 5 connections allowed per call
 
     //***** Instance Variables
-
-    GSMConnection connections[] = new GSMConnection[MAX_CONNECTIONS];
+    GsmConnection connections[] = new GsmConnection[MAX_CONNECTIONS];
     RegistrantList voiceCallEndedRegistrants = new RegistrantList();
     RegistrantList voiceCallStartedRegistrants = new RegistrantList();
 
 
     // connections dropped durin last poll
-    ArrayList<GSMConnection> droppedDuringPoll
-        = new ArrayList<GSMConnection>(MAX_CONNECTIONS);
+    ArrayList<GsmConnection> droppedDuringPoll
+        = new ArrayList<GsmConnection>(MAX_CONNECTIONS);
 
-    GSMCall ringingCall = new GSMCall(this);
+    GsmCall ringingCall = new GsmCall(this);
             // A call that is ringing or (call) waiting
-    GSMCall foregroundCall = new GSMCall(this);
-    GSMCall backgroundCall = new GSMCall(this);
+    GsmCall foregroundCall = new GsmCall(this);
+    GsmCall backgroundCall = new GsmCall(this);
 
-    GSMConnection pendingMO;
+    GsmConnection pendingMO;
     boolean hangupPendingMO;
 
     GSMPhone phone;
-    CommandsInterface cm;
+
     boolean desiredMute = false;    // false = mute off
 
     Phone.State state = Phone.State.IDLE;
 
-    int pendingOperations;
-    boolean needsPoll;
-    Message lastRelevantPoll;
 
 
     //***** Events
 
-    static final int EVENT_POLL_CALLS_RESULT    = 1;
-    static final int EVENT_CALL_STATE_CHANGE    = 2;
-    static final int EVENT_REPOLL_AFTER_DELAY   = 3;
-    static final int EVENT_OPERATION_COMPLETE     = 4;
-    static final int EVENT_GET_LAST_CALL_FAIL_CAUSE = 5;
-
-    static final int EVENT_SWITCH_RESULT        = 8;
-    static final int EVENT_RADIO_AVAILABLE       = 9;
-    static final int EVENT_RADIO_NOT_AVAILABLE       = 10;
-    static final int EVENT_CONFERENCE_RESULT    = 11;
-    static final int EVENT_SEPARATE_RESULT      = 12;
-    static final int EVENT_ECT_RESULT           = 13;
 
     //***** Constructors
 
-    CallTracker (GSMPhone phone)
-    {
+    GsmCallTracker (GSMPhone phone) {
         this.phone = phone;
         cm = phone.mCM;
 
@@ -116,24 +95,56 @@
         cm.registerForNotAvailable(this, EVENT_RADIO_NOT_AVAILABLE, null);
     }
 
+    public void dispose() {
+        //Unregister for all events
+        cm.unregisterForCallStateChanged(this);
+        cm.unregisterForOn(this);
+        cm.unregisterForNotAvailable(this);
+
+        for(GsmConnection c : connections) {
+            try {
+                if(c != null) hangup(c);
+            } catch (CallStateException ex) {
+                Log.e(LOG_TAG, "unexpected error on hangup during dispose");
+            }
+        }
+
+        try {
+            if(pendingMO != null) hangup(pendingMO);
+        } catch (CallStateException ex) {
+            Log.e(LOG_TAG, "unexpected error on hangup during dispose");
+        }
+
+        clearDisconnected();
+    }
+
+    protected void finalize() {
+        Log.d(LOG_TAG, "GsmCallTracker finalized");
+    }
+
     //***** Instance Methods
 
     //***** Public Methods
-    public void registerForVoiceCallStarted(Handler h, int what, Object obj)
-    {
+    public void registerForVoiceCallStarted(Handler h, int what, Object obj) {
         Registrant r = new Registrant(h, what, obj);
         voiceCallStartedRegistrants.add(r);
     }
 
-    public void registerForVoiceCallEnded(Handler h, int what, Object obj)
-    {
+    public void unregisterForVoiceCallStarted(Handler h) {
+        voiceCallStartedRegistrants.remove(h);
+    }
+
+    public void registerForVoiceCallEnded(Handler h, int what, Object obj) {
         Registrant r = new Registrant(h, what, obj);
         voiceCallEndedRegistrants.add(r);
     }
 
+    public void unregisterForVoiceCallEnded(Handler h) {
+        voiceCallEndedRegistrants.remove(h);
+    }
+
     private void
-    fakeHoldForegroundBeforeDial()
-    {
+    fakeHoldForegroundBeforeDial() {
         List<Connection> connCopy;
 
         // We need to make a copy here, since fakeHoldBeforeDial()
@@ -141,7 +152,7 @@
         connCopy = (List<Connection>) foregroundCall.connections.clone();
 
         for (int i = 0, s = connCopy.size() ; i < s ; i++) {
-            GSMConnection conn = (GSMConnection)connCopy.get(i);
+            GsmConnection conn = (GsmConnection)connCopy.get(i);
 
             conn.fakeHoldBeforeDial();
         }
@@ -162,7 +173,7 @@
         // The new call must be assigned to the foreground call.
         // That call must be idle, so place anything that's
         // there on hold
-        if (foregroundCall.getState() == Call.State.ACTIVE) {
+        if (foregroundCall.getState() == GsmCall.State.ACTIVE) {
             // this will probably be done by the radio anyway
             // but the dial might fail before this happens
             // and we need to make sure the foreground call is clear
@@ -176,12 +187,12 @@
             fakeHoldForegroundBeforeDial();
         }
 
-        if (foregroundCall.getState() != Call.State.IDLE) {
+        if (foregroundCall.getState() != GsmCall.State.IDLE) {
             //we should have failed in !canDial() above before we get here
             throw new CallStateException("cannot dial in current state");
         }
 
-        pendingMO = new GSMConnection(phone.getContext(), dialString, this, foregroundCall);
+        pendingMO = new GsmConnection(phone.getContext(), dialString, this, foregroundCall);
         hangupPendingMO = false;
 
         if (pendingMO.address == null || pendingMO.address.length() == 0
@@ -208,24 +219,22 @@
 
 
     Connection
-    dial (String dialString) throws CallStateException
-    {
+    dial (String dialString) throws CallStateException {
         return dial(dialString, CommandsInterface.CLIR_DEFAULT);
     }
 
     void
-    acceptCall () throws CallStateException
-    {
+    acceptCall () throws CallStateException {
         // FIXME if SWITCH fails, should retry with ANSWER
         // in case the active/holding call disappeared and this
         // is no longer call waiting
 
-        if (ringingCall.getState() == Call.State.INCOMING) {
+        if (ringingCall.getState() == GsmCall.State.INCOMING) {
             Log.i("phone", "acceptCall: incoming...");
             // Always unmute when answering a new call
             setMute(false);
             cm.acceptCall(obtainCompleteMessage());
-        } else if (ringingCall.getState() == Call.State.WAITING) {
+        } else if (ringingCall.getState() == GsmCall.State.WAITING) {
             setMute(false);
             switchWaitingOrHoldingAndActive();
         } else {
@@ -234,8 +243,7 @@
     }
 
     void
-    rejectCall () throws CallStateException
-    {
+    rejectCall () throws CallStateException {
         // AT+CHLD=0 means "release held or UDUB"
         // so if the phone isn't ringing, this could hang up held
         if (ringingCall.getState().isRinging()) {
@@ -248,7 +256,7 @@
     void
     switchWaitingOrHoldingAndActive() throws CallStateException {
         // Should we bother with this check?
-        if (ringingCall.getState() == Call.State.INCOMING) {
+        if (ringingCall.getState() == GsmCall.State.INCOMING) {
             throw new CallStateException("cannot be in the incoming state");
         } else {
             cm.switchWaitingOrHoldingAndActive(
@@ -257,20 +265,17 @@
     }
 
     void
-    conference() throws CallStateException
-    {
+    conference() throws CallStateException {
         cm.conference(obtainCompleteMessage(EVENT_CONFERENCE_RESULT));
     }
 
     void
-    explicitCallTransfer() throws CallStateException
-    {
+    explicitCallTransfer() throws CallStateException {
         cm.explicitCallTransfer(obtainCompleteMessage(EVENT_ECT_RESULT));
     }
 
     void
-    clearDisconnected()
-    {
+    clearDisconnected() {
         internalClearDisconnected();
 
         updatePhoneState();
@@ -278,17 +283,15 @@
     }
 
     boolean
-    canConference()
-    {
-        return foregroundCall.getState() == Call.State.ACTIVE
-                && backgroundCall.getState() == Call.State.HOLDING
+    canConference() {
+        return foregroundCall.getState() == GsmCall.State.ACTIVE
+                && backgroundCall.getState() == GsmCall.State.HOLDING
                 && !backgroundCall.isFull()
                 && !foregroundCall.isFull();
     }
 
     boolean
-    canDial()
-    {
+    canDial() {
         boolean ret;
         int serviceState = phone.getServiceState().getState();
 
@@ -302,42 +305,26 @@
     }
 
     boolean
-    canTransfer()
-    {
-        return foregroundCall.getState() == Call.State.ACTIVE
-                && backgroundCall.getState() == Call.State.HOLDING;
+    canTransfer() {
+        return foregroundCall.getState() == GsmCall.State.ACTIVE
+                && backgroundCall.getState() == GsmCall.State.HOLDING;
     }
 
     //***** Private Instance Methods
 
     private void
-    internalClearDisconnected()
-    {
+    internalClearDisconnected() {
         ringingCall.clearDisconnected();
         foregroundCall.clearDisconnected();
         backgroundCall.clearDisconnected();
     }
 
     /**
-     * @return true if we're idle or there's a call to getCurrentCalls() pending
-     * but nothing else
-     */
-    private boolean
-    checkNoOperationsPending()
-    {
-        if (DBG_POLL) log("checkNoOperationsPending: pendingOperations=" +
-                pendingOperations);
-        return pendingOperations == 0;
-    }
-
-
-    /**
      * Obtain a message to use for signalling "invoke getCurrentCalls() when
      * this operation and all other pending operations are complete
      */
     private Message
-    obtainCompleteMessage()
-    {
+    obtainCompleteMessage() {
         return obtainCompleteMessage(EVENT_OPERATION_COMPLETE);
     }
 
@@ -346,8 +333,7 @@
      * this operation and all other pending operations are complete
      */
     private Message
-    obtainCompleteMessage(int what)
-    {
+    obtainCompleteMessage(int what) {
         pendingOperations++;
         lastRelevantPoll = null;
         needsPoll = true;
@@ -358,26 +344,8 @@
         return obtainMessage(what);
     }
 
-    /**
-     * Obtain a complete message that indicates that this operation
-     * does not require polling of getCurrentCalls(). However, if other
-     * operations that do need getCurrentCalls() are pending or are
-     * scheduled while this operation is pending, the invocatoin
-     * of getCurrentCalls() will be postponed until this
-     * operation is also complete.
-     */
-    private Message
-    obtainNoPollCompleteMessage(int what)
-    {
-        pendingOperations++;
-        lastRelevantPoll = null;
-        return obtainMessage(what);
-    }
-
-
     private void
-    operationComplete()
-    {
+    operationComplete() {
         pendingOperations--;
 
         if (DBG_POLL) log("operationComplete: pendingOperations=" +
@@ -388,42 +356,13 @@
             cm.getCurrentCalls(lastRelevantPoll);
         } else if (pendingOperations < 0) {
             // this should never happen
-            Log.e(LOG_TAG,"CallTracker.pendingOperations < 0");
+            Log.e(LOG_TAG,"GsmCallTracker.pendingOperations < 0");
             pendingOperations = 0;
         }
     }
 
     private void
-    pollCallsWhenSafe()
-    {
-        needsPoll = true;
-
-        if (checkNoOperationsPending()) {
-            lastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);
-            cm.getCurrentCalls(lastRelevantPoll);
-        }
-    }
-
-    private void
-    pollCallsAfterDelay()
-    {
-        Message msg = obtainMessage();
-
-        msg.what = EVENT_REPOLL_AFTER_DELAY;
-        sendMessageDelayed(msg, POLL_DELAY_MSEC);
-    }
-
-    private boolean
-    isCommandExceptionRadioNotAvailable(Throwable e)
-    {
-        return e != null && e instanceof CommandException
-                && ((CommandException)e).getCommandError()
-                        == CommandException.Error.RADIO_NOT_AVAILABLE;
-    }
-
-    private void
-    updatePhoneState()
-    {
+    updatePhoneState() {
         Phone.State oldState = state;
 
         if (ringingCall.isRinging()) {
@@ -448,9 +387,8 @@
         }
     }
 
-    private void
-    handlePollCalls(AsyncResult ar)
-    {
+    protected void
+    handlePollCalls(AsyncResult ar) {
         List polledCalls;
 
         if (ar.exception == null) {
@@ -474,7 +412,7 @@
 
         for (int i = 0, curDC = 0, dcSize = polledCalls.size()
                 ; i < connections.length; i++) {
-            GSMConnection conn = connections[i];
+            GsmConnection conn = connections[i];
             DriverCall dc = null;
 
             // polledCall list is sparse
@@ -519,7 +457,7 @@
                         return;
                     }
                 } else {
-                    connections[i] = new GSMConnection(phone.getContext(), dc, this, i);
+                    connections[i] = new GsmConnection(phone.getContext(), dc, this, i);
 
                     // it's a ringing call
                     if (connections[i].getCall() == ringingCall) {
@@ -549,14 +487,14 @@
                 // tracking.
                 droppedDuringPoll.add(conn);
                 // Dropped connections are removed from the CallTracker
-                // list but kept in the GSMCall list
+                // list but kept in the GsmCall list
                 connections[i] = null;
             } else if (conn != null && dc != null && !conn.compareTo(dc)) {
                 // Connection in CLCC response does not match what
                 // we were tracking. Assume dropped call and new call
 
                 droppedDuringPoll.add(conn);
-                connections[i] = new GSMConnection (phone.getContext(), dc, this, i);
+                connections[i] = new GsmConnection (phone.getContext(), dc, this, i);
 
                 if (connections[i].getCall() == ringingCall) {
                     newRinging = connections[i];
@@ -608,7 +546,7 @@
         // cases from the "dropped during poll" list
         // These cases need no "last call fail" reason
         for (int i = droppedDuringPoll.size() - 1; i >= 0 ; i--) {
-            GSMConnection conn = droppedDuringPoll.get(i);
+            GsmConnection conn = droppedDuringPoll.get(i);
 
             if (conn.isIncoming() && conn.getConnectTime() == 0) {
                 // Missed or rejected call
@@ -630,7 +568,7 @@
                 droppedDuringPoll.remove(i);
                 conn.onDisconnect(Connection.DisconnectCause.LOCAL);
             } else if (conn.cause ==
-                    Connection.DisconnectCause.INVALID_NUMBER) {
+                Connection.DisconnectCause.INVALID_NUMBER) {
                 droppedDuringPoll.remove(i);
                 conn.onDisconnect(Connection.DisconnectCause.INVALID_NUMBER);
             }
@@ -669,14 +607,7 @@
     }
 
     private void
-    handleRadioAvailable()
-    {
-        pollCallsWhenSafe();
-    }
-
-    private void
-    handleRadioNotAvailable()
-    {
+    handleRadioNotAvailable() {
         // handlePollCalls will clear out its
         // call list when it gets the CommandException
         // error result from this
@@ -684,8 +615,7 @@
     }
 
     private void
-    dumpState()
-    {
+    dumpState() {
         List l;
 
         Log.i(LOG_TAG,"Phone State:" + state);
@@ -713,14 +643,13 @@
 
     }
 
-    //***** Called from GSMConnection
+    //***** Called from GsmConnection
 
     /*package*/ void
-    hangup (GSMConnection conn) throws CallStateException
-    {
+    hangup (GsmConnection conn) throws CallStateException {
         if (conn.owner != this) {
-            throw new CallStateException ("Connection " + conn
-                                    + "does not belong to CallTracker " + this);
+            throw new CallStateException ("GsmConnection " + conn
+                                    + "does not belong to GsmCallTracker " + this);
         }
 
         if (conn == pendingMO) {
@@ -735,7 +664,7 @@
             } catch (CallStateException ex) {
                 // Ignore "connection not found"
                 // Call may have hung up already
-                Log.w(LOG_TAG,"CallTracker WARN: hangup() on absent connection "
+                Log.w(LOG_TAG,"GsmCallTracker WARN: hangup() on absent connection "
                                 + conn);
             }
         }
@@ -744,11 +673,10 @@
     }
 
     /*package*/ void
-    separate (GSMConnection conn) throws CallStateException
-    {
+    separate (GsmConnection conn) throws CallStateException {
         if (conn.owner != this) {
-            throw new CallStateException ("Connection " + conn
-                                    + "does not belong to CallTracker " + this);
+            throw new CallStateException ("GsmConnection " + conn
+                                    + "does not belong to GsmCallTracker " + this);
         }
         try {
             cm.separateConnection (conn.getGSMIndex(),
@@ -756,7 +684,7 @@
         } catch (CallStateException ex) {
             // Ignore "connection not found"
             // Call may have hung up already
-            Log.w(LOG_TAG,"CallTracker WARN: separate() on absent connection "
+            Log.w(LOG_TAG,"GsmCallTracker WARN: separate() on absent connection "
                           + conn);
         }
     }
@@ -764,24 +692,21 @@
     //***** Called from GSMPhone
 
     /*package*/ void
-    setMute(boolean mute)
-    {
+    setMute(boolean mute) {
         desiredMute = mute;
         cm.setMute(desiredMute, null);
     }
 
     /*package*/ boolean
-    getMute()
-    {
+    getMute() {
         return desiredMute;
     }
 
 
-    //***** Called from GSMCall
+    //***** Called from GsmCall
 
     /* package */ void
-    hangup (GSMCall call) throws CallStateException
-    {
+    hangup (GsmCall call) throws CallStateException {
         if (call.getConnections().size() == 0) {
             throw new CallStateException("no connections in call");
         }
@@ -794,7 +719,7 @@
                 if (Phone.DEBUG_PHONE) {
                     log("(foregnd) hangup dialing or alerting...");
                 }
-                hangup((GSMConnection)(call.getConnections().get(0)));
+                hangup((GsmConnection)(call.getConnections().get(0)));
             } else {
                 hangupForegroundResumeBackground();
             }
@@ -808,8 +733,8 @@
                 hangupWaitingOrBackground();
             }
         } else {
-            throw new RuntimeException ("Call " + call +
-                    "does not belong to CallTracker " + this);
+            throw new RuntimeException ("GsmCall " + call +
+                    "does not belong to GsmCallTracker " + this);
         }
 
         call.onHangupLocal();
@@ -827,11 +752,11 @@
         cm.hangupForegroundResumeBackground(obtainCompleteMessage());
     }
 
-    void hangupConnectionByIndex(GSMCall call, int index)
+    void hangupConnectionByIndex(GsmCall call, int index)
             throws CallStateException {
         int count = call.connections.size();
         for (int i = 0; i < count; i++) {
-            GSMConnection cn = (GSMConnection)call.connections.get(i);
+            GsmConnection cn = (GsmConnection)call.connections.get(i);
             if (cn.getGSMIndex() == index) {
                 cm.hangupConnection(index, obtainCompleteMessage());
                 return;
@@ -841,11 +766,11 @@
         throw new CallStateException("no gsm index found");
     }
 
-    void hangupAllConnections(GSMCall call) throws CallStateException{
+    void hangupAllConnections(GsmCall call) throws CallStateException{
         try {
             int count = call.connections.size();
             for (int i = 0; i < count; i++) {
-                GSMConnection cn = (GSMConnection)call.connections.get(i);
+                GsmConnection cn = (GsmConnection)call.connections.get(i);
                 cm.hangupConnection(cn.getGSMIndex(), obtainCompleteMessage());
             }
         } catch (CallStateException ex) {
@@ -854,11 +779,11 @@
     }
 
     /* package */
-    GSMConnection getConnectionByIndex(GSMCall call, int index)
+    GsmConnection getConnectionByIndex(GsmCall call, int index)
             throws CallStateException {
         int count = call.connections.size();
         for (int i = 0; i < count; i++) {
-            GSMConnection cn = (GSMConnection)call.connections.get(i);
+            GsmConnection cn = (GsmConnection)call.connections.get(i);
             if (cn.getGSMIndex() == index) {
                 return cn;
             }
@@ -884,8 +809,7 @@
     //****** Overridden from Handler
 
     public void
-    handleMessage (Message msg)
-    {
+    handleMessage (Message msg) {
         AsyncResult ar;
 
         switch (msg.what) {
@@ -952,7 +876,7 @@
                 for (int i = 0, s =  droppedDuringPoll.size()
                         ; i < s ; i++
                 ) {
-                    GSMConnection conn = droppedDuringPoll.get(i);
+                    GsmConnection conn = droppedDuringPoll.get(i);
 
                     conn.onRemoteDisconnect(causeCode);
                 }
@@ -978,7 +902,7 @@
         }
     }
 
-    private void log(String msg) {
-        Log.d(LOG_TAG, "[CallTracker] " + msg);
+    protected void log(String msg) {
+        Log.d(LOG_TAG, "[GsmCallTracker] " + msg);
     }
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java
similarity index 85%
rename from telephony/java/com/android/internal/telephony/gsm/GSMConnection.java
rename to telephony/java/com/android/internal/telephony/gsm/GsmConnection.java
index 4777892..2b2f077 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GSMConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmConnection.java
@@ -15,39 +15,39 @@
  */
 
 package com.android.internal.telephony.gsm;
-import com.android.internal.telephony.*;
-
 import android.content.Context;
+import android.os.AsyncResult;
 import android.os.Handler;
-import android.os.PowerManager;
-import android.os.Registrant;
 import android.os.Looper;
 import android.os.Message;
-import android.os.AsyncResult;
+import android.os.PowerManager;
+import android.os.Registrant;
 import android.os.SystemClock;
-import android.util.Log;
 import android.util.Config;
+import android.util.Log;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.ServiceState;
 
+import com.android.internal.telephony.*;
+
 /**
  * {@hide}
  */
-public class GSMConnection extends Connection {
+public class GsmConnection extends Connection {
     static final String LOG_TAG = "GSM";
 
     //***** Instance Variables
 
-    CallTracker owner;
-    GSMCall parent;
+    GsmCallTracker owner;
+    GsmCall parent;
 
     String address;     // MAY BE NULL!!!
     String dialString;          // outgoing calls only
-    String postDialString;      // outgoing calls only    
+    String postDialString;      // outgoing calls only
     boolean isIncoming;
-    boolean disconnected; 
+    boolean disconnected;
 
-    int index;          // index in CallTracker.connections[], -1 if unassigned
+    int index;          // index in GsmCallTracker.connections[], -1 if unassigned
                         // The GSM index is 1 + this
 
     /*
@@ -65,7 +65,7 @@
      */
     long connectTimeReal;
     long duration;
-    long holdingStartTime;  // The time when the Connection last transitioned 
+    long holdingStartTime;  // The time when the Connection last transitioned
                             // into HOLDING
 
     int nextPostDialChar;       // index into postDialString
@@ -95,8 +95,8 @@
         MyHandler(Looper l) {super(l);}
 
         public void
-        handleMessage(Message msg)
-        {
+        handleMessage(Message msg) {
+
             switch (msg.what) {
                 case EVENT_NEXT_POST_DIAL:
                 case EVENT_DTMF_DONE:
@@ -114,11 +114,10 @@
 
     /** This is probably an MT call that we first saw in a CLCC response */
     /*package*/
-    GSMConnection (Context context, DriverCall dc, CallTracker ct, int index)
-    {
+    GsmConnection (Context context, DriverCall dc, GsmCallTracker ct, int index) {
         createWakeLock(context);
         acquireWakeLock();
-
+		
         owner = ct;
         h = new MyHandler(owner.getLooper());
 
@@ -136,11 +135,10 @@
 
     /** This is an MO call, created when dialing */
     /*package*/
-    GSMConnection (Context context, String dialString, CallTracker ct, GSMCall parent)
-    {
+    GsmConnection (Context context, String dialString, GsmCallTracker ct, GsmCall parent) {
         createWakeLock(context);
         acquireWakeLock();
-
+		
         owner = ct;
         h = new MyHandler(owner.getLooper());
 
@@ -155,18 +153,19 @@
         createTime = System.currentTimeMillis();
 
         this.parent = parent;
-        parent.attachFake(this, Call.State.DIALING);
+        parent.attachFake(this, GsmCall.State.DIALING);
     }
-    
+
+    public void dispose() {
+    }
+
     static boolean
-    equalsHandlesNulls (Object a, Object b)
-    {
+    equalsHandlesNulls (Object a, Object b) {
         return (a == null) ? (b == null) : a.equals (b);
     }
 
     /*package*/ boolean
-    compareTo(DriverCall c)
-    {
+    compareTo(DriverCall c) {
         // On mobile originated (MO) calls, the phone number may have changed
         // due to a SIM Toolkit call control modification.
         //
@@ -178,43 +177,35 @@
         // no control over when they begin, so we might as well
 
         String cAddress = PhoneNumberUtils.stringFromStringAndTOA(c.number, c.TOA);
-        return isIncoming == c.isMT && equalsHandlesNulls(address, cAddress); 
+        return isIncoming == c.isMT && equalsHandlesNulls(address, cAddress);
     }
 
     public String
-    toString()
-    {
+    toString() {
         return (isIncoming ? "incoming" : "outgoing");
     }
 
-    public String getAddress()
-    {
-        return address; 
+    public String getAddress() {
+        return address;
     }
 
-
-    public Call getCall()
-    {
+    public GsmCall getCall() {
         return parent;
     }
 
-    public long getCreateTime()
-    {
+    public long getCreateTime() {
         return createTime;
     }
 
-    public long getConnectTime()
-    {
+    public long getConnectTime() {
         return connectTime;
     }
 
-    public long getDisconnectTime()
-    {
+    public long getDisconnectTime() {
         return disconnectTime;
     }
 
-    public long getDurationMillis()
-    {
+    public long getDurationMillis() {
         if (connectTimeReal == 0) {
             return 0;
         } else if (duration == 0) {
@@ -224,9 +215,8 @@
         }
     }
 
-    public long getHoldDurationMillis()
-    {
-        if (getState() != Call.State.HOLDING) {
+    public long getHoldDurationMillis() {
+        if (getState() != GsmCall.State.HOLDING) {
             // If not holding, return 0
             return 0;
         } else {
@@ -234,52 +224,45 @@
         }
     }
 
-    public DisconnectCause getDisconnectCause()
-    {
+    public DisconnectCause getDisconnectCause() {
         return cause;
     }
 
-    public boolean isIncoming()
-    {
+    public boolean isIncoming() {
         return isIncoming;
     }
 
-    public Call.State getState()
-    {
+    public GsmCall.State getState() {
         if (disconnected) {
-            return Call.State.DISCONNECTED;
-        } else {   
+            return GsmCall.State.DISCONNECTED;
+        } else {
             return super.getState();
         }
     }
 
-    public void hangup() throws CallStateException
-    {
-        if (!disconnected) {        
+    public void hangup() throws CallStateException {
+        if (!disconnected) {
             owner.hangup(this);
         } else {
             throw new CallStateException ("disconnected");
         }
     }
 
-    public void separate() throws CallStateException
-    {
-        if (!disconnected) {        
+    public void separate() throws CallStateException {
+        if (!disconnected) {
             owner.separate(this);
         } else {
             throw new CallStateException ("disconnected");
         }
     }
 
-    public PostDialState getPostDialState()
-    {
+    public PostDialState getPostDialState() {
         return postDialState;
     }
 
-    public void proceedAfterWaitChar()
-    {
+    public void proceedAfterWaitChar() {
         if (postDialState != PostDialState.WAIT) {
-            Log.w(LOG_TAG, "Connection.proceedAfterWaitChar(): Expected " 
+            Log.w(LOG_TAG, "GsmConnection.proceedAfterWaitChar(): Expected "
                 + "getPostDialState() to be WAIT but was " + postDialState);
             return;
         }
@@ -288,10 +271,10 @@
 
         processNextPostDialChar();
     }
-    
+
     public void proceedAfterWildChar(String str) {
         if (postDialState != PostDialState.WILD) {
-            Log.w(LOG_TAG, "Connection.proceedAfterWaitChar(): Expected " 
+            Log.w(LOG_TAG, "GsmConnection.proceedAfterWaitChar(): Expected "
                 + "getPostDialState() to be WILD but was " + postDialState);
             return;
         }
@@ -328,38 +311,35 @@
             postDialString = buf.toString();
             nextPostDialChar = 0;
             if (Phone.DEBUG_PHONE) {
-                log("proceedAfterWildChar: new postDialString is " + 
+                log("proceedAfterWildChar: new postDialString is " +
                         postDialString);
             }
 
             processNextPostDialChar();
         }
     }
-    
-    public void cancelPostDial()
-    {
+
+    public void cancelPostDial() {
         setPostDialState(PostDialState.CANCELLED);
     }
 
-    /** 
+    /**
      * Called when this Connection is being hung up locally (eg, user pressed "end")
      * Note that at this point, the hangup request has been dispatched to the radio
-     * but no response has yet been received so update() has not yet been called 
+     * but no response has yet been received so update() has not yet been called
      */
     void
-    onHangupLocal()
-    {
+    onHangupLocal() {
         cause = DisconnectCause.LOCAL;
     }
 
     DisconnectCause
-    disconnectCauseFromCode(int causeCode)
-    {
+    disconnectCauseFromCode(int causeCode) {
         /**
          * See 22.001 Annex F.4 for mapping of cause codes
          * to local tones
          */
-    
+
         switch (causeCode) {
             case CallFailCause.USER_BUSY:
                 return DisconnectCause.BUSY;
@@ -382,7 +362,7 @@
                 return DisconnectCause.FDN_BLOCKED;
 
             case CallFailCause.ERROR_UNSPECIFIED:
-            case CallFailCause.NORMAL_CLEARING: 
+            case CallFailCause.NORMAL_CLEARING:
             default:
                 GSMPhone phone = owner.phone;
                 int serviceState = phone.getServiceState().getState();
@@ -391,8 +371,8 @@
                 } else if (serviceState == ServiceState.STATE_OUT_OF_SERVICE
                         || serviceState == ServiceState.STATE_EMERGENCY_ONLY ) {
                     return DisconnectCause.OUT_OF_SERVICE;
-                } else if (phone.getSimCard().getState() != GsmSimCard.State.READY) {
-                    return DisconnectCause.SIM_ERROR;
+                } else if (phone.getIccCard().getState() != SimCard.State.READY) {
+                    return DisconnectCause.ICC_ERROR;
                 } else if (causeCode == CallFailCause.ERROR_UNSPECIFIED) {
                     if (phone.mSST.rs.isCsRestricted()) {
                         return DisconnectCause.CS_RESTRICTED; 
@@ -410,20 +390,18 @@
     }
 
     /*package*/ void
-    onRemoteDisconnect(int causeCode)
-    {
+    onRemoteDisconnect(int causeCode) {
         onDisconnect(disconnectCauseFromCode(causeCode));
     }
 
     /** Called when the radio indicates the connection has been disconnected */
     /*package*/ void
-    onDisconnect(DisconnectCause cause)
-    {
+    onDisconnect(DisconnectCause cause) {
         this.cause = cause;
-        
-        if (!disconnected) {        
+
+        if (!disconnected) {
             index = -1;
-            
+
             disconnectTime = System.currentTimeMillis();
             duration = SystemClock.elapsedRealtime() - connectTimeReal;
             disconnected = true;
@@ -434,7 +412,7 @@
             owner.phone.notifyDisconnect(this);
 
             if (parent != null) {
-                parent.connectionDisconnected(this);            
+                parent.connectionDisconnected(this);
             }
         }
         releaseWakeLock();
@@ -443,10 +421,10 @@
     // Returns true if state has changed, false if nothing changed
     /*package*/ boolean
     update (DriverCall dc) {
-        GSMCall newParent;
+        GsmCall newParent;
         boolean changed = false;
         boolean wasConnectingInOrOut = isConnectingInOrOut();
-        boolean wasHolding = (getState() == Call.State.HOLDING);
+        boolean wasHolding = (getState() == GsmCall.State.HOLDING);
 
         newParent = parentFromDCState(dc.state);
 
@@ -484,7 +462,7 @@
             onConnectedInOrOut();
         }
 
-        if (changed && !wasHolding && (getState() == Call.State.HOLDING)) {
+        if (changed && !wasHolding && (getState() == GsmCall.State.HOLDING)) {
             // We've transitioned into HOLDING
             onStartedHolding();
         }
@@ -499,14 +477,13 @@
      * HOLDING in the backgroundCall
      */
     void
-    fakeHoldBeforeDial()
-    {
+    fakeHoldBeforeDial() {
         if (parent != null) {
             parent.detach(this);
         }
 
         parent = owner.backgroundCall;
-        parent.attachFake(this, Call.State.HOLDING);
+        parent.attachFake(this, GsmCall.State.HOLDING);
 
         onStartedHolding();
     }
@@ -552,28 +529,27 @@
      * should be ignored
      */
     private boolean
-    processPostDialChar(char c)
-    {
+    processPostDialChar(char c) {
         if (PhoneNumberUtils.is12Key(c)) {
             owner.cm.sendDtmf(c, h.obtainMessage(EVENT_DTMF_DONE));
         } else if (c == PhoneNumberUtils.PAUSE) {
             // From TS 22.101:
 
-            // "The first occurrence of the "DTMF Control Digits Separator" 
-            //  shall be used by the ME to distinguish between the addressing 
+            // "The first occurrence of the "DTMF Control Digits Separator"
+            //  shall be used by the ME to distinguish between the addressing
             //  digits (i.e. the phone number) and the DTMF digits...."
 
             if (nextPostDialChar == 1) {
                 // The first occurrence.
                 // We don't need to pause here, but wait for just a bit anyway
-                h.sendMessageDelayed(h.obtainMessage(EVENT_PAUSE_DONE), 
+                h.sendMessageDelayed(h.obtainMessage(EVENT_PAUSE_DONE),
                                             PAUSE_DELAY_FIRST_MILLIS);
             } else {
                 // It continues...
-                // "Upon subsequent occurrences of the separator, the UE shall 
-                //  pause again for 3 seconds (\u00B1 20 %) before sending any 
+                // "Upon subsequent occurrences of the separator, the UE shall
+                //  pause again for 3 seconds (\u00B1 20 %) before sending any
                 //  further DTMF digits."
-                h.sendMessageDelayed(h.obtainMessage(EVENT_PAUSE_DONE), 
+                h.sendMessageDelayed(h.obtainMessage(EVENT_PAUSE_DONE),
                                             PAUSE_DELAY_MILLIS);
             }
         } else if (c == PhoneNumberUtils.WAIT) {
@@ -588,9 +564,8 @@
     }
 
     public String
-    getRemainingPostDialString()
-    {
-        if (postDialState == PostDialState.CANCELLED 
+    getRemainingPostDialString() {
+        if (postDialState == PostDialState.CANCELLED
             || postDialState == PostDialState.COMPLETE
             || postDialString == null
             || postDialString.length() <= nextPostDialChar
@@ -617,8 +592,7 @@
     }
 
     private void
-    processNextPostDialChar()
-    {
+    processNextPostDialChar() {
         char c = 0;
         Registrant postDialHandler;
 
@@ -655,7 +629,8 @@
 
         Message notifyMessage;
 
-        if (postDialHandler != null && (notifyMessage = postDialHandler.messageForRegistrant()) != null) {
+        if (postDialHandler != null
+                && (notifyMessage = postDialHandler.messageForRegistrant()) != null) {
             // The AsyncResult.result is the Connection object
             PostDialState state = postDialState;
             AsyncResult ar = AsyncResult.forMessage(notifyMessage);
@@ -668,14 +643,6 @@
             //Log.v("GSM", "##### processNextPostDialChar: send msg to postDialHandler, arg1=" + c);
             notifyMessage.sendToTarget();
         }
-        /*
-        else {
-            if (postDialHandler == null)
-                Log.v("GSM", "##### processNextPostDialChar: postDialHandler is NULL!");
-            else
-                Log.v("GSM", "##### processNextPostDialChar: postDialHandler.messageForRegistrant() returned NULL!");
-        }
-        */
     }
 
 
@@ -683,16 +650,14 @@
      *  and outgoing calls
      */
     private boolean
-    isConnectingInOrOut()
-    {
-        return parent == null || parent == owner.ringingCall 
-            || parent.state == Call.State.DIALING 
-            || parent.state == Call.State.ALERTING;
+    isConnectingInOrOut() {
+        return parent == null || parent == owner.ringingCall
+            || parent.state == GsmCall.State.DIALING
+            || parent.state == GsmCall.State.ALERTING;
     }
 
-    private GSMCall
-    parentFromDCState (DriverCall.State state)
-    {
+    private GsmCall
+    parentFromDCState (DriverCall.State state) {
         switch (state) {
             case ACTIVE:
             case DIALING:
diff --git a/telephony/java/com/android/internal/telephony/gsm/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
similarity index 71%
rename from telephony/java/com/android/internal/telephony/gsm/DataConnectionTracker.java
rename to telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 02a6841..e2da7cb 100644
--- a/telephony/java/com/android/internal/telephony/gsm/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -50,8 +50,12 @@
 import android.util.EventLog;
 import android.util.Log;
 
+import com.android.internal.telephony.DataConnection;
+import com.android.internal.telephony.DataConnection.FailCause;
+import com.android.internal.telephony.DataConnectionTracker;
 import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.gsm.PdpConnection.PdpFailCause;
+import com.android.internal.telephony.PhoneProxy;
+import com.android.internal.telephony.TelephonyEventLog;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -59,45 +63,11 @@
 /**
  * {@hide}
  */
-final class DataConnectionTracker extends Handler
-{
+public final class GsmDataConnectionTracker extends DataConnectionTracker {
     private static final String LOG_TAG = "GSM";
     private static final boolean DBG = true;
 
     /**
-     * IDLE: ready to start data connection setup, default state
-     * INITING: state of issued setupDefaultPDP() but not finish yet
-     * CONNECTING: state of issued startPppd() but not finish yet
-     * SCANNING: data connection fails with one apn but other apns are available
-     *           ready to start data connection on other apns (before INITING)
-     * CONNECTED: IP connection is setup
-     * DISCONNECTING: PdpConnection.disconnect() has been called, but PDP
-     *                context is not yet deactivated
-     * FAILED: data connection fail for all apns settings
-     *
-     * getDataConnectionState() maps State to DataState
-     *      FAILED or IDLE : DISCONNECTED
-     *      INITING or CONNECTING or SCANNING: CONNECTING
-     *      CONNECTED : CONNECTED or DISCONNECTING
-     */
-    enum State {
-        IDLE,
-        INITING,
-        CONNECTING,
-        SCANNING,
-        CONNECTED,
-        DISCONNECTING,
-        FAILED
-    }
-
-    enum Activity {
-        NONE,
-        DATAIN,
-        DATAOUT,
-        DATAINANDOUT
-    }
-
-    /**
      * Handles changes to the APN db.
      */
     private class ApnChangeObserver extends ContentObserver {
@@ -113,20 +83,12 @@
 
     //***** Instance Variables
 
-    GSMPhone phone;
     INetStatService netstat;
-    State state = State.IDLE;
-    Activity activity = Activity.NONE;
-    boolean netStatPollEnabled = false;
     // Indicates baseband will not auto-attach
     private boolean noAutoAttach = false;
     long nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
-    Handler mDataConnectionTracker = null;
     private ContentResolver mResolver;
 
-    long txPkts, rxPkts, sentSinceLastRecv;
-    int netStatPollPeriod;
-    private int mNoRecvPollCount = 0;
     private boolean mPingTestActive = false;
     // Count of PDP reset attempts; reset when we see incoming,
     // call reRegisterNetwork, or pingTest succeeds.
@@ -156,10 +118,7 @@
     /**
      * pdpList holds all the PDP connection, i.e. IP Link in GPRS
      */
-    private ArrayList<PdpConnection> pdpList;
-
-    /** CID of active PDP */
-    int cidActive;
+    private ArrayList<DataConnection> pdpList;
 
     /** Currently requested APN type */
     private String mRequestedApnType = Phone.APN_TYPE_DEFAULT;
@@ -176,12 +135,6 @@
 
     private boolean[] dataEnabled = new boolean[APN_NUM_TYPES];
 
-    /** wifi connection status will be updated by sticky intent */
-    private boolean mIsWifiConnected = false;
-
-    /** Intent sent when the reconnect alarm fires. */
-    private PendingIntent mReconnectIntent = null;
-    
     /** Is packet service restricted by network */
     private boolean mIsPsRestricted = false;
 
@@ -195,69 +148,17 @@
     private static final int PDP_CONNECTION_POOL_SIZE = 1;
 
     private static final int POLL_PDP_MILLIS = 5 * 1000;
-    private static final int RECONNECT_DELAY_INITIAL_MILLIS = 5 * 1000;
-    /** Cap out with 1 hour retry interval. */
-    private static final int RECONNECT_DELAY_MAX_MILLIS = 60 * 60 * 1000;
 
-    /** Slow poll when attempting connection recovery. */
-    private static final int POLL_NETSTAT_SLOW_MILLIS = 5000;
-
-    /** Default ping deadline, in seconds. */
-    private static final int DEFAULT_PING_DEADLINE = 5;
-    /** Default max failure count before attempting to network re-registration. */
-    private static final int DEFAULT_MAX_PDP_RESET_FAIL = 3;
-
-    /**
-     * After detecting a potential connection problem, this is the max number
-     * of subsequent polls before attempting a radio reset.  At this point,
-     * poll interval is 5 seconds (POLL_NETSTAT_SLOW_MILLIS), so set this to
-     * poll for about 2 more minutes.
-     */
-    private static final int NO_RECV_POLL_LIMIT = 24;
-
-    // 1 sec. default polling interval when screen is on.
-    private static final int POLL_NETSTAT_MILLIS = 1000;
-    // 10 min. default polling interval when screen is off.
-    private static final int POLL_NETSTAT_SCREEN_OFF_MILLIS = 1000*60*10;
-    // 2 min for round trip time
-    private static final int POLL_LONGEST_RTT = 120 * 1000;
-    // 10 for packets without ack
-    private static final int NUMBER_SENT_PACKETS_OF_HANG = 10;
-    // how long to wait before switching back to default APN
-    private static final int RESTORE_DEFAULT_APN_DELAY = 1 * 60 * 1000;
-    // system property that can override the above value
-    private static final String APN_RESTORE_DELAY_PROP_NAME = "android.telephony.apn-restore";
-    // represents an invalid IP address
-    private static final String NULL_IP = "0.0.0.0";
-
+    //WINK:TODO: Teleca, is this really gsm specific, what about CDMA?
     private static final String INTENT_RECONNECT_ALARM = "com.android.internal.telephony.gprs-reconnect";
     private static final String INTENT_RECONNECT_ALARM_EXTRA_REASON = "reason";
 
-
-    //***** Event Codes
-    static final int EVENT_DATA_SETUP_COMPLETE = 1;
-    static final int EVENT_RADIO_AVAILABLE = 3;
-    static final int EVENT_RECORDS_LOADED = 4;
-    static final int EVENT_TRY_SETUP_DATA = 5;
-    static final int EVENT_PDP_STATE_CHANGED = 6;
-    static final int EVENT_POLL_PDP = 7;
-    static final int EVENT_GET_PDP_LIST_COMPLETE = 11;
-    static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 12;
-    static final int EVENT_VOICE_CALL_STARTED = 14;
-    static final int EVENT_VOICE_CALL_ENDED = 15;
-    static final int EVENT_GPRS_DETACHED = 19;
-    static final int EVENT_LINK_STATE_CHANGED = 20;
-    static final int EVENT_ROAMING_ON = 21;
-    static final int EVENT_ROAMING_OFF = 22;
-    static final int EVENT_ENABLE_NEW_APN = 23;
-    static final int EVENT_RESTORE_DEFAULT_APN = 24;
-    static final int EVENT_DISCONNECT_DONE = 25;
-    static final int EVENT_GPRS_ATTACHED = 26;
-    static final int EVENT_START_NETSTAT_POLL = 27;
-    static final int EVENT_START_RECOVERY = 28;
-    static final int EVENT_APN_CHANGED = 29;
-    static final int EVENT_PS_RESTRICT_ENABLED = 30;
-    static final int EVENT_PS_RESTRICT_DISABLED = 31;
+    //***** Tag IDs for EventLog
+    private static final int EVENT_LOG_RADIO_RESET_COUNTDOWN_TRIGGERED = 50101;
+    private static final int EVENT_LOG_RADIO_RESET = 50102;
+    private static final int EVENT_LOG_PDP_RESET = 50103;
+    private static final int EVENT_LOG_REREGISTER_NETWORK = 50104;
+    private static final int EVENT_LOG_RADIO_PDP_SETUP_FAIL = 50105;
 
     static final Uri PREFERAPN_URI = Uri.parse("content://telephony/carriers/preferapn");
     static final String APN_ID = "apn_id";
@@ -307,21 +208,21 @@
 
     //***** Constructor
 
-    DataConnectionTracker(GSMPhone phone)
-    {
-        this.phone = phone;
-        phone.mCM.registerForAvailable (this, EVENT_RADIO_AVAILABLE, null);
-        phone.mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
-        phone.mSIMRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null);
-        phone.mCM.registerForPDPStateChanged (this, EVENT_PDP_STATE_CHANGED, null);
-        phone.mCT.registerForVoiceCallEnded (this, EVENT_VOICE_CALL_ENDED, null);
-        phone.mCT.registerForVoiceCallStarted (this, EVENT_VOICE_CALL_STARTED, null);
-        phone.mSST.registerForGprsAttached(this, EVENT_GPRS_ATTACHED, null);
-        phone.mSST.registerForGprsDetached(this, EVENT_GPRS_DETACHED, null);
-        phone.mSST.registerForRoamingOn(this, EVENT_ROAMING_ON, null);
-        phone.mSST.registerForRoamingOff(this, EVENT_ROAMING_OFF, null);
-        phone.mSST.registerForPsRestrictedEnabled(this, EVENT_PS_RESTRICT_ENABLED, null);
-        phone.mSST.registerForPsRestrictedDisabled(this, EVENT_PS_RESTRICT_DISABLED, null);
+    GsmDataConnectionTracker(GSMPhone p) {
+        super(p);
+
+        p.mCM.registerForAvailable (this, EVENT_RADIO_AVAILABLE, null);
+        p.mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
+        p.mSIMRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null);
+        p.mCM.registerForDataStateChanged (this, EVENT_DATA_STATE_CHANGED, null);
+        p.mCT.registerForVoiceCallEnded (this, EVENT_VOICE_CALL_ENDED, null);
+        p.mCT.registerForVoiceCallStarted (this, EVENT_VOICE_CALL_STARTED, null);
+        p.mSST.registerForGprsAttached(this, EVENT_GPRS_ATTACHED, null);
+        p.mSST.registerForGprsDetached(this, EVENT_GPRS_DETACHED, null);
+        p.mSST.registerForRoamingOn(this, EVENT_ROAMING_ON, null);
+        p.mSST.registerForRoamingOff(this, EVENT_ROAMING_OFF, null);
+        p.mSST.registerForPsRestrictedEnabled(this, EVENT_PS_RESTRICT_ENABLED, null);
+        p.mSST.registerForPsRestrictedDisabled(this, EVENT_PS_RESTRICT_DISABLED, null);
 
         this.netstat = INetStatService.Stub.asInterface(ServiceManager.getService("netstat"));
 
@@ -332,14 +233,14 @@
         filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
         filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
 
-        phone.getContext().registerReceiver(mIntentReceiver, filter, null, phone.h);
+        p.getContext().registerReceiver(mIntentReceiver, filter, null, p.h);
 
 
         mDataConnectionTracker = this;
         mResolver = phone.getContext().getContentResolver();
 
         apnObserver = new ApnChangeObserver();
-        phone.getContext().getContentResolver().registerContentObserver(
+        p.getContext().getContentResolver().registerContentObserver(
                 Telephony.Carriers.CONTENT_URI, true, apnObserver);
 
         createAllPdpList();
@@ -351,6 +252,31 @@
         noAutoAttach = !dataEnabled[APN_DEFAULT_ID];
     }
 
+    public void dispose() {
+        //Unregister for all events
+        phone.mCM.unregisterForAvailable(this);
+        phone.mCM.unregisterForOffOrNotAvailable(this);
+        ((GSMPhone) phone).mSIMRecords.unregisterForRecordsLoaded(this);
+        phone.mCM.unregisterForDataStateChanged(this);
+        ((GSMPhone) phone).mCT.unregisterForVoiceCallEnded(this);
+        ((GSMPhone) phone).mCT.unregisterForVoiceCallStarted(this);
+        ((GSMPhone) phone).mSST.unregisterForGprsAttached(this);
+        ((GSMPhone) phone).mSST.unregisterForGprsDetached(this);
+        ((GSMPhone) phone).mSST.unregisterForRoamingOn(this);
+        ((GSMPhone) phone).mSST.unregisterForRoamingOff(this);
+        ((GSMPhone) phone).mSST.unregisterForPsRestrictedEnabled(this);
+        ((GSMPhone) phone).mSST.unregisterForPsRestrictedDisabled(this);
+        
+        phone.getContext().unregisterReceiver(this.mIntentReceiver);
+        phone.getContext().getContentResolver().unregisterContentObserver(this.apnObserver);
+
+        destroyAllPdpList();
+    }
+
+    protected void finalize() {
+        if(DBG) Log.d(LOG_TAG, "GsmDataConnectionTracker finalized");
+    }
+
     void setState(State s) {
         if (DBG) log ("setState: " + s);
         if (state != s) {
@@ -375,19 +301,6 @@
         }
     }
 
-    String getStateInString() {
-        switch (state) {
-            case IDLE:          return "IDLE";
-            case INITING:       return "INIT";
-            case CONNECTING:    return "CING";
-            case SCANNING:      return "SCAN";
-            case CONNECTED:     return "CNTD";
-            case DISCONNECTING: return "DING";
-            case FAILED:        return "FAIL";
-            default:            return "ERRO";
-        }
-    }
-
     String[] getActiveApnTypes() {
         String[] result;
         if (mActiveApn != null) {
@@ -399,7 +312,7 @@
         return result;
     }
 
-    String getActiveApnString() {
+    protected String getActiveApnString() {
         String result = null;
         if (mActiveApn != null) {
             result = mActiveApn.apn;
@@ -417,7 +330,7 @@
      * will be sent by the ConnectivityManager when a connection to
      * the APN has been established.
      */
-    int enableApnType(String type) {
+    protected int enableApnType(String type) {
         if (!TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
             return Phone.APN_REQUEST_FAILED;
         }
@@ -456,7 +369,7 @@
      * @param type the APN type. The only valid value currently is {@link Phone#APN_TYPE_MMS}.
      * @return
      */
-    int disableApnType(String type) {
+    protected int disableApnType(String type) {
         Log.d(LOG_TAG, "disableApnType("+type+")");
         if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
             removeMessages(EVENT_RESTORE_DEFAULT_APN);
@@ -489,16 +402,15 @@
      *  2. registered to gprs service
      *  3. user doesn't explicitly disable data service
      *  4. wifi is not on
-     *  5. packet service is not restricted
      *
      * @return false while no data connection if all above requirements are met.
      */
-    boolean isDataConnectionAsDesired() {
+    public boolean isDataConnectionAsDesired() {
         boolean roaming = phone.getServiceState().getRoaming();
 
-        if (phone.mSIMRecords.getRecordsLoaded() &&
-            phone.mSST.getCurrentGprsState() == ServiceState.STATE_IN_SERVICE &&
-            (!roaming || getDataOnRoamingEnabled()) &&
+        if (((GSMPhone) phone).mSIMRecords.getRecordsLoaded() &&
+                ((GSMPhone) phone).mSST.getCurrentGprsState() == ServiceState.STATE_IN_SERVICE &&
+                (!roaming || getDataOnRoamingEnabled()) &&
             !mIsWifiConnected && 
             !mIsPsRestricted ) {
             return (state == State.CONNECTED);
@@ -571,10 +483,12 @@
                 return true;
             }
             return false;
-        } else // isEnabled && enable
+        } else {
+            // isEnabled && enable
             return true;
+        }
     }
-
+    
     /**
      * Simply tear down data connections due to radio off 
      * and don't setup again.
@@ -582,7 +496,7 @@
     public void cleanConnectionBeforeRadioOff() {
         cleanUpConnection(true, Phone.REASON_RADIO_TURNED_OFF);
     }
-    
+
     /**
      * Report the current state of data connectivity (enabled or disabled) for
      * the default APN.
@@ -602,31 +516,11 @@
         return dataEnabled[APN_DEFAULT_ID] || dataEnabled[APN_MMS_ID];
     }
 
-    //The data roaming setting is now located in the shared preferences.
-    //  See if the requested preference value is the same as that stored in
-    //  the shared values.  If it is not, then update it.
-    public void setDataOnRoamingEnabled(boolean enabled) {
-        if (getDataOnRoamingEnabled() != enabled) {
-            Settings.Secure.putInt(phone.getContext().getContentResolver(),
-                Settings.Secure.DATA_ROAMING, enabled ? 1 : 0);
-        }
-        Message roamingMsg = phone.getServiceState().getRoaming() ?
-            obtainMessage(EVENT_ROAMING_ON) : obtainMessage(EVENT_ROAMING_OFF);
-        sendMessage(roamingMsg);
-    }
-
-    //Retrieve the data roaming setting from the shared preferences.
-    public boolean getDataOnRoamingEnabled() {
-        try {
-            return Settings.Secure.getInt(phone.getContext().getContentResolver(),
-                Settings.Secure.DATA_ROAMING) > 0;
-        } catch (SettingNotFoundException snfe) {
-            return false;
-        }
-    }
-
-    public ArrayList<PdpConnection> getAllPdps() {
-        ArrayList<PdpConnection> pdps = (ArrayList<PdpConnection>)pdpList.clone();
+    /**
+     * Formerly this method was ArrayList<PdpConnection> getAllPdps()
+     */
+    public ArrayList<DataConnection> getAllDataConnections() {
+        ArrayList<DataConnection> pdps = (ArrayList<DataConnection>)pdpList.clone();
         return pdps;
     }
 
@@ -640,8 +534,7 @@
      * Invoked when ServiceStateTracker observes a transition from GPRS
      * attach to detach.
      */
-    private void onGprsDetached()
-    {
+    protected void onGprsDetached() {
         /*
          * We presently believe it is unnecessary to tear down the PDP context
          * when GPRS detaches, but we should stop the network polling.
@@ -663,8 +556,7 @@
         }
     }
 
-    private boolean trySetupData(String reason)
-    {
+    private boolean trySetupData(String reason) {
         if (DBG) log("***trySetupData due to " + (reason == null ? "(unspecified)" : reason));
 
         Log.d(LOG_TAG, "[DSAC DEB] " + "trySetupData with mIsPsRestricted=" + mIsPsRestricted);
@@ -679,13 +571,14 @@
             return true;
         }
 
-        int gprsState = phone.mSST.getCurrentGprsState();
+        int gprsState = ((GSMPhone) phone).mSST.getCurrentGprsState();
         boolean roaming = phone.getServiceState().getRoaming();
 
         if ((state == State.IDLE || state == State.SCANNING)
                 && (gprsState == ServiceState.STATE_IN_SERVICE || noAutoAttach)
-                && phone.mSIMRecords.getRecordsLoaded()
-                && phone.getState() == Phone.State.IDLE
+                && ((GSMPhone) phone).mSIMRecords.getRecordsLoaded()
+                && ( ((GSMPhone) phone).mSST.isConcurrentVoiceAndData() ||
+                     phone.getState() == Phone.State.IDLE )
                 && isDataAllowed()
                 && !mIsPsRestricted ) {
 
@@ -693,7 +586,7 @@
                 waitingApns = buildWaitingApns();
                 if (waitingApns.isEmpty()) {
                     if (DBG) log("No APN found");
-                    notifyNoData(PdpConnection.PdpFailCause.BAD_APN);
+                    notifyNoData(PdpConnection.FailCause.BAD_APN);
                     return false;
                 } else {
                     log ("Create from allApns : " + apnListToString(allApns));
@@ -709,8 +602,8 @@
                 log("trySetupData: Not ready for data: " +
                     " dataState=" + state +
                     " gprsState=" + gprsState +
-                    " sim=" + phone.mSIMRecords.getRecordsLoaded() +
-                    " UMTS=" + phone.mSST.isConcurrentVoiceAndData() +
+                    " sim=" + ((GSMPhone) phone).mSIMRecords.getRecordsLoaded() +
+                    " UMTS=" + ((GSMPhone) phone).mSST.isConcurrentVoiceAndData() +
                     " phoneState=" + phone.getState() +
                     " dataEnabled=" + getAnyDataEnabled() +
                     " roaming=" + roaming +
@@ -740,7 +633,8 @@
             mReconnectIntent = null;
         }
 
-        for (PdpConnection pdp : pdpList) {
+        for (DataConnection conn : pdpList) {
+            PdpConnection pdp = (PdpConnection) conn;
             if (tearDown) {
                 Message msg = obtainMessage(EVENT_DISCONNECT_DONE, reason);
                 pdp.disconnect(msg);
@@ -762,7 +656,7 @@
          * IDLE before the code below runs. If we didn't check
          * for that, future calls to trySetupData would fail,
          * and we would never get out of the DISCONNECTING state.
-         */
+         */ 
         if (!tearDown) {
             setState(State.IDLE);
             phone.notifyDataConnection(reason);
@@ -814,8 +708,9 @@
     }
 
     private PdpConnection findFreePdp() {
-        for (PdpConnection pdp : pdpList) {
-            if (pdp.getState() == PdpConnection.PdpState.INACTIVE) {
+        for (DataConnection conn : pdpList) {
+            PdpConnection pdp = (PdpConnection) conn;
+            if (pdp.getState() == DataConnection.State.INACTIVE) {
                 return pdp;
             }
         }
@@ -854,7 +749,7 @@
         return null;
     }
 
-    String getIpAddress(String apnType) {
+    protected String getIpAddress(String apnType) {
         if (mActivePdp != null
                 && (apnType == null || mActiveApn.canHandleType(apnType))) {
             return mActivePdp.getIpAddress();
@@ -870,7 +765,7 @@
         return null;
     }
 
-    String[] getDnsServers(String apnType) {
+    protected String[] getDnsServers(String apnType) {
         if (mActivePdp != null
                 && (apnType == null || mActiveApn.canHandleType(apnType))) {
             return mActivePdp.getDnsServers();
@@ -879,8 +774,7 @@
     }
 
     private boolean
-    pdpStatesHasCID (ArrayList<PDPContextState> states, int cid)
-    {
+    pdpStatesHasCID (ArrayList<PDPContextState> states, int cid) {
         for (int i = 0, s = states.size() ; i < s ; i++) {
             if (states.get(i).cid == cid) return true;
         }
@@ -889,8 +783,7 @@
     }
 
     private boolean
-    pdpStatesHasActiveCID (ArrayList<PDPContextState> states, int cid)
-    {
+    pdpStatesHasActiveCID (ArrayList<PDPContextState> states, int cid) {
         for (int i = 0, s = states.size() ; i < s ; i++) {
             if (states.get(i).cid == cid) return states.get(i).active;
         }
@@ -907,7 +800,7 @@
         isConnected = (state != State.IDLE && state != State.FAILED);
 
         // The "current" may no longer be valid.  MMS depends on this to send properly.
-        phone.updateCurrentCarrierInProvider();
+        ((GSMPhone) phone).updateCurrentCarrierInProvider();
 
         // TODO: It'd be nice to only do this if the changed entrie(s)
         // match the current operator.
@@ -926,9 +819,7 @@
      * via an unsolicited response (which could have happened at any
      * previous state
      */
-    private void
-    onPdpStateChanged (AsyncResult ar, boolean explicitPoll)
-    {
+    protected void onPdpStateChanged (AsyncResult ar, boolean explicitPoll) {
         ArrayList<PDPContextState> pdpStates;
 
         pdpStates = (ArrayList<PDPContextState>)(ar.result);
@@ -1062,9 +953,7 @@
      * with certain RIL impl's/basebands
      *
      */
-    private void
-    startPeriodicPdpPoll()
-    {
+    private void startPeriodicPdpPoll() {
         removeMessages(EVENT_POLL_PDP);
 
         sendMessageDelayed(obtainMessage(EVENT_POLL_PDP), POLL_PDP_MILLIS);
@@ -1074,6 +963,7 @@
         txPkts = -1;
         rxPkts = -1;
         sentSinceLastRecv = 0;
+        netStatPollPeriod = POLL_NETSTAT_MILLIS;
         mNoRecvPollCount = 0;
     }
 
@@ -1089,16 +979,14 @@
             } else {
                 mPdpResetCount = 0;
                 EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_REREGISTER_NETWORK, sentSinceLastRecv);
-                phone.mSST.reRegisterNetwork(null);
+                ((GSMPhone) phone).mSST.reRegisterNetwork(null);
             }
             // TODO: Add increasingly drastic recovery steps, eg,
             // reset the radio, reset the device.
         }
     }
 
-    private void
-    startNetStatPoll()
-    {
+    protected void startNetStatPoll() {
         if (state == State.CONNECTED && mPingTestActive == false && netStatPollEnabled == false) {
             Log.d(LOG_TAG, "[DataConnection] Start poll NetStat");
             resetPollStats();
@@ -1107,17 +995,13 @@
         }
     }
 
-    private void
-    stopNetStatPoll()
-    {
+    protected void stopNetStatPoll() {
         netStatPollEnabled = false;
         removeCallbacks(mPollNetStat);
         Log.d(LOG_TAG, "[DataConnection] Stop poll NetStat");
     }
 
-    private void
-    restartRadio()
-    {
+    protected void restartRadio() {
         Log.d(LOG_TAG, "************TURN OFF RADIO**************");
         cleanUpConnection(true, Phone.REASON_RADIO_TURNED_OFF);
         phone.mCM.setRadioPower(false, null);
@@ -1133,7 +1017,7 @@
         SystemProperties.set("net.ppp.reset-by-timeout", String.valueOf(reset+1));
     }
 
-    Runnable mPollNetStat = new Runnable()
+    private Runnable mPollNetStat = new Runnable()
     {
 
         public void run() {
@@ -1164,7 +1048,7 @@
                     newActivity = Activity.DATAINANDOUT;
                     mPdpResetCount = 0;
                 } else if (sent > 0 && received == 0) {
-                    if (phone.mCT.state == Phone.State.IDLE) {
+                    if (phone.getState() == Phone.State.IDLE) {
                         sentSinceLastRecv += sent;
                     } else {
                         sentSinceLastRecv = 0;
@@ -1188,7 +1072,8 @@
             }
 
             int watchdogTrigger = Settings.Gservices.getInt(mResolver,
-                    Settings.Gservices.PDP_WATCHDOG_TRIGGER_PACKET_COUNT, NUMBER_SENT_PACKETS_OF_HANG);
+                    Settings.Gservices.PDP_WATCHDOG_TRIGGER_PACKET_COUNT, 
+                    NUMBER_SENT_PACKETS_OF_HANG);
 
             if (sentSinceLastRecv >= watchdogTrigger) {
                 // we already have NUMBER_SENT_PACKETS sent without ack
@@ -1204,13 +1089,14 @@
                     // It's possible the PDP context went down and we weren't notified.
                     // Start polling the context list in an attempt to recover.
                     if (DBG) log("no DATAIN in a while; polling PDP");
-                    phone.mCM.getPDPContextList(obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
+                    phone.mCM.getDataCallList(obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
 
                     mNoRecvPollCount++;
 
                     // Slow down the poll interval to let things happen
                     netStatPollPeriod = Settings.Gservices.getInt(mResolver,
-                            Settings.Gservices.PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS, POLL_NETSTAT_SLOW_MILLIS);
+                            Settings.Gservices.PDP_WATCHDOG_ERROR_POLL_INTERVAL_MS, 
+                            POLL_NETSTAT_SLOW_MILLIS);
                 } else {
                     if (DBG) log("Sent " + String.valueOf(sentSinceLastRecv) +
                                         " pkts since last received");
@@ -1242,7 +1128,7 @@
             }
         }
     };
-
+    
     private void runPingTest () {
         int status = -1;
         try {
@@ -1279,15 +1165,13 @@
      * seems like it deserves an error notification.
      * Transient errors are ignored
      */
-    private boolean
-    shouldPostNotification(PdpConnection.PdpFailCause  cause)
-    {
+    private boolean shouldPostNotification(PdpConnection.FailCause  cause) {
         boolean shouldPost = true;
         // TODO CHECK
         // if (dataLink != null) {
         //    shouldPost = dataLink.getLastLinkExitCode() != DataLink.EXIT_OPEN_FAILED;
         //}
-        return (shouldPost && cause != PdpConnection.PdpFailCause.UNKNOWN);
+        return (shouldPost && cause != PdpConnection.FailCause.UNKNOWN);
     }
 
     /**
@@ -1301,14 +1185,13 @@
         boolean retry = true;
         
         if ( Phone.REASON_RADIO_TURNED_OFF.equals(reason) ||
-             Phone.REASON_DATA_DISABLED.equals(reason)    ||
-             Phone.REASON_PS_RESTRICT_ENABLED.equals(reason)) { 
+             Phone.REASON_DATA_DISABLED.equals(reason) ) { 
             retry = false;
         }
         return retry;
-    }
-    
-    private void reconnectAfterFail(PdpFailCause lastFailCauseCode, String reason) {
+    }   
+
+    private void reconnectAfterFail(FailCause lastFailCauseCode, String reason) {
         if (state == State.FAILED) {
             Log.d(LOG_TAG, "PDP activate failed. Scheduling next attempt for "
                     + (nextReconnectDelay / 1000) + "s");
@@ -1338,314 +1221,215 @@
         }
     }
 
-    private void notifyNoData(PdpConnection.PdpFailCause lastFailCauseCode) {
+    private void notifyNoData(PdpConnection.FailCause lastFailCauseCode) {
         setState(State.FAILED);
     }
 
-
-    private void log(String s) {
-        Log.d(LOG_TAG, "[DataConnectionTracker] " + s);
+    protected void onRecordsLoaded() {
+        createAllApnList();
+        if (state == State.FAILED) {
+            cleanUpConnection(false, null);
+        }
+        sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
     }
 
-    //***** Overridden from Handler
-    public void
-    handleMessage (Message msg)
-    {
-        AsyncResult ar;
+    protected void onEnableNewApn() {
+        // TODO:  To support simultaneous PDP contexts, this should really only call
+        // cleanUpConnection if it needs to free up a PdpConnection.
+        cleanUpConnection(true, Phone.REASON_APN_SWITCHED);
+    }
+
+    protected void onTrySetupData() {
+        trySetupData(null);
+    }
+
+    protected void onRestoreDefaultApn() {
+        if (DBG) Log.d(LOG_TAG, "Restore default APN");
+        setEnabled(Phone.APN_TYPE_MMS, false);
+
+        if (!isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
+            cleanUpConnection(true, Phone.REASON_RESTORE_DEFAULT_APN);
+            mRequestedApnType = Phone.APN_TYPE_DEFAULT;
+        }
+    }
+
+    protected void onRoamingOff() {
+        trySetupData(Phone.REASON_ROAMING_OFF);
+    }
+
+    protected void onRoamingOn() {
+        if (getDataOnRoamingEnabled()) {
+            trySetupData(Phone.REASON_ROAMING_ON);
+        } else {
+            if (DBG) log("Tear down data connection on roaming.");
+            cleanUpConnection(true, Phone.REASON_ROAMING_ON);
+        }
+    }
+
+    protected void onRadioAvailable() {
+        if (phone.getSimulatedRadioControl() != null) {
+            // Assume data is connected on the simulator
+            // FIXME  this can be improved
+            setState(State.CONNECTED);
+            phone.notifyDataConnection(null);
+
+            Log.i(LOG_TAG, "We're on the simulator; assuming data is connected");
+        }
+
+        if (state != State.IDLE) {
+            cleanUpConnection(true, null);
+        }
+    }
+
+    protected void onRadioOffOrNotAvailable() {
+        // Make sure our reconnect delay starts at the initial value
+        // next time the radio comes on
+        nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
+
+        if (phone.getSimulatedRadioControl() != null) {
+            // Assume data is connected on the simulator
+            // FIXME  this can be improved
+            Log.i(LOG_TAG, "We're on the simulator; assuming radio off is meaningless");
+        } else {
+            if (DBG) log("Radio is off and clean up all connection");
+            // TODO: Should we reset mRequestedApnType to "default"?
+            cleanUpConnection(false, Phone.REASON_RADIO_TURNED_OFF);
+        }
+    }
+
+    protected void onDataSetupComplete(AsyncResult ar) {
         String reason = null;
+        if (ar.userObj instanceof String) {
+            reason = (String) ar.userObj;
+        }
 
-        switch (msg.what) {
-            case EVENT_RECORDS_LOADED:
-                createAllApnList();
-                if (state == State.FAILED) {
-                    cleanUpConnection(false, null);
-                }
-                sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA, Phone.REASON_SIM_LOADED));
-                break;
+        if (ar.exception == null) {
+            // everything is setup
 
-            case EVENT_ENABLE_NEW_APN:
-                // TODO:  To support simultaneous PDP contexts, this should really only call
-                // cleanUpConnection if it needs to free up a PdpConnection.
-                reason = Phone.REASON_APN_SWITCHED;
-                cleanUpConnection(true, reason);
-                break;
-
-            case EVENT_TRY_SETUP_DATA:
-                if (msg.obj instanceof String) {
-                    reason = (String)msg.obj;
-                }
-
-                trySetupData(reason);
-                break;
-
-            case EVENT_RESTORE_DEFAULT_APN:
-                if (DBG) Log.d(LOG_TAG, "Restore default APN");
-                setEnabled(Phone.APN_TYPE_MMS, false);
-                if (!isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
-                    cleanUpConnection(true, Phone.REASON_RESTORE_DEFAULT_APN);
-                    mRequestedApnType = Phone.APN_TYPE_DEFAULT;
-                }
-                break;
-
-            case EVENT_ROAMING_OFF:
-                trySetupData(Phone.REASON_ROAMING_OFF);
-                break;
-
-            case EVENT_GPRS_DETACHED:
-                onGprsDetached();
-                break;
-
-            case EVENT_GPRS_ATTACHED:
-                onGprsAttached();
-                break;
-
-            case EVENT_ROAMING_ON:
-                if (getDataOnRoamingEnabled()) {
-                    trySetupData(Phone.REASON_ROAMING_ON);
-                } else {
-                    if (DBG) log("Tear down data connection on roaming.");
-                    cleanUpConnection(true, Phone.REASON_ROAMING_ON);
-                }
-                break;
-
-            case EVENT_RADIO_AVAILABLE:
-                if (phone.getSimulatedRadioControl() != null) {
-                    // Assume data is connected on the simulator
-                    // FIXME  this can be improved
-                    setState(State.CONNECTED);
-                    phone.notifyDataConnection(null);
-
-
-                    Log.i(LOG_TAG, "We're on the simulator; assuming data is connected");
-                }
-
-                if (state != State.IDLE) {
-                    cleanUpConnection(true, null);
-                }
-            break;
-
-            case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
-                // Make sure our reconnect delay starts at the initial value
-                // next time the radio comes on
-                nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
-
-                if (phone.getSimulatedRadioControl() != null) {
-                    // Assume data is connected on the simulator
-                    // FIXME  this can be improved
-                    Log.i(LOG_TAG, "We're on the simulator; assuming radio off is meaningless");
-                } else {
-                    if (DBG) log("Radio is off and clean up all connection");
-                    // TODO: Should we reset mRequestedApnType to "default"?
-                    cleanUpConnection(false, Phone.REASON_RADIO_TURNED_OFF);
-                }
-            break;
-
-            case EVENT_DATA_SETUP_COMPLETE:
-                ar = (AsyncResult) msg.obj;
-                if (ar.userObj instanceof String) {
-                    reason = (String) ar.userObj;
-                }
-
-                if (ar.exception == null) {
-                    // everything is setup
-
-                    // arg1 contains CID for this PDP context
-                    cidActive = msg.arg1;
-                    /*
-                     * We may have switched away from the default PDP context
-                     * in order to enable a "special" APN (e.g., for MMS
-                     * traffic). Set a timer to switch back and/or disable the
-                     * special APN, so that a negligient application doesn't
-                     * permanently prevent data connectivity. What we are
-                     * protecting against here is not malicious apps, but
-                     * rather an app that inadvertantly fails to reset to the
-                     * default APN, or that dies before doing so.
-                     */
-                    if (dataEnabled[APN_MMS_ID]) {
-                        removeMessages(EVENT_RESTORE_DEFAULT_APN);
-                        sendMessageDelayed(
-                                obtainMessage(EVENT_RESTORE_DEFAULT_APN),
-                                getRestoreDefaultApnDelay());
-                    }
-                    if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
-                        SystemProperties.set("gsm.defaultpdpcontext.active", "true");
+            /*
+             * We may have switched away from the default PDP context
+             * in order to enable a "special" APN (e.g., for MMS
+             * traffic). Set a timer to switch back and/or disable the
+             * special APN, so that a negligient application doesn't
+             * permanently prevent data connectivity. What we are
+             * protecting against here is not malicious apps, but
+             * rather an app that inadvertantly fails to reset to the
+             * default APN, or that dies before doing so.
+             */
+            if (dataEnabled[APN_MMS_ID]) {
+                removeMessages(EVENT_RESTORE_DEFAULT_APN);
+                sendMessageDelayed(obtainMessage(EVENT_RESTORE_DEFAULT_APN),
+                        getRestoreDefaultApnDelay());
+            }
+            if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
+                SystemProperties.set("gsm.defaultpdpcontext.active", "true");
                         if (canSetPreferApn && preferredApn == null) {
                             Log.d(LOG_TAG, "PREFERED APN is null");
                             preferredApn = mActiveApn;
                             setPreferredApn(preferredApn.id);
                         }
-                    } else {
-                        SystemProperties.set("gsm.defaultpdpcontext.active", "false");
-                    }
-                    notifyDefaultData(reason);
+            } else {
+                SystemProperties.set("gsm.defaultpdpcontext.active", "false");
+            }
+            notifyDefaultData(reason);
 
-                    // TODO: For simultaneous PDP support, we need to build another
-                    // trigger another TRY_SETUP_DATA for the next APN type.  (Note
-                    // that the existing connection may service that type, in which
-                    // case we should try the next type, etc.
-                } else {
-                    PdpConnection.PdpFailCause cause;
-                    cause = (PdpConnection.PdpFailCause) (ar.result);
-                    if(DBG)
-                        log("PDP setup failed " + cause);
+            // TODO: For simultaneous PDP support, we need to build another
+            // trigger another TRY_SETUP_DATA for the next APN type.  (Note
+            // that the existing connection may service that type, in which
+            // case we should try the next type, etc.
+        } else {
+            PdpConnection.FailCause cause;
+            cause = (PdpConnection.FailCause) (ar.result);
+            if(DBG) log("PDP setup failed " + cause);
                     // Log this failure to the Event Logs.
-                    if (cause == PdpConnection.PdpFailCause.BAD_APN ||
-                        cause == PdpConnection.PdpFailCause.BAD_PAP_SECRET ||
-                        cause == PdpConnection.PdpFailCause.BARRED ||
-                        cause == PdpConnection.PdpFailCause.RADIO_ERROR_RETRY ||
-                        cause == PdpConnection.PdpFailCause.SUSPENED_TEMPORARY ||
-                        cause == PdpConnection.PdpFailCause.UNKNOWN ||
-                        cause == PdpConnection.PdpFailCause.USER_AUTHENTICATION) {
-                        int cid = -1;
-                        GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
-                        if (loc != null) cid = loc.getCid();
+            if (cause == PdpConnection.FailCause.BAD_APN || 
+                    cause == PdpConnection.FailCause.BAD_PAP_SECRET ||
+                    cause == PdpConnection.FailCause.BARRED ||
+                    cause == PdpConnection.FailCause.RADIO_ERROR_RETRY ||
+                    cause == PdpConnection.FailCause.SUSPENED_TEMPORARY ||
+                    cause == PdpConnection.FailCause.UNKNOWN ||
+                    cause == PdpConnection.FailCause.USER_AUTHENTICATION) {
+                int cid = -1;
+                GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
+                if (loc != null) cid = loc.getCid();
 
-                        EventLog.List val = new EventLog.List(
-                            cause.ordinal(), cid,
-                            TelephonyManager.getDefault().getNetworkType());
-                        EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_RADIO_PDP_SETUP_FAIL, val);
-                    }
-                    // No try for permanent failure
-                    if (cause.isPermanentFail()) {
-                        notifyNoData(cause);
-                    }
+                EventLog.List val = new EventLog.List(
+                        cause.ordinal(), cid, 
+                        TelephonyManager.getDefault().getNetworkType());
+                EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_RADIO_PDP_SETUP_FAIL, val);
+            }
 
-                    if (tryNextApn(cause)) {
-                        waitingApns.remove(0);
-                        if (waitingApns.isEmpty()) {
-                            // No more to try, start delayed retry
-                            startDelayedRetry(cause, reason);
-                        } else {
-                            // we still have more apns to try
-                            setState(State.SCANNING);
-                            // Wait a bit before trying the next APN, so that 
-                            // we're not tying up the RIL command channel
-                            sendMessageDelayed(obtainMessage(EVENT_TRY_SETUP_DATA, reason),
-                                    RECONNECT_DELAY_INITIAL_MILLIS);
-                        }
-                    } else {
-                        startDelayedRetry(cause, reason);
-                    }
-                }
-            break;
+            // No try for permanent failure
+            if (cause.isPermanentFail()) {
+                notifyNoData(cause);
+            }
 
-            case EVENT_DISCONNECT_DONE:
-                if(DBG) log("EVENT_DISCONNECT_DONE");
-                ar = (AsyncResult) msg.obj;
-                if (ar.userObj instanceof String) {
-                    reason = (String) ar.userObj;
-                }
-                setState(State.IDLE);
-                phone.notifyDataConnection(reason);
-                mActiveApn = null;
-                if ( retryAfterDisconnected(reason) ) {
+            if (tryNextApn(cause)) {
+                waitingApns.remove(0);
+                if (waitingApns.isEmpty()) {
+                    // No more to try, start delayed retry
+                    startDelayedRetry(cause, reason);
+                } else {
+                    // we still have more apns to try
+                    setState(State.SCANNING);
                     trySetupData(reason);
                 }
-                break;
-
-            case EVENT_PDP_STATE_CHANGED:
-                ar = (AsyncResult) msg.obj;
-
-                onPdpStateChanged(ar, false);
-            break;
-
-            case EVENT_GET_PDP_LIST_COMPLETE:
-                ar = (AsyncResult) msg.obj;
-
-                onPdpStateChanged(ar, true);
-            break;
-
-            case EVENT_POLL_PDP:
-                /* See comment in startPeriodicPdpPoll */
-                ar = (AsyncResult) msg.obj;
-
-                if (!(state == State.CONNECTED)) {
-                    // not connected; don't poll anymore
-                    break;
-                }
-
-                phone.mCM.getPDPContextList(this.obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
-
-                sendMessageDelayed(obtainMessage(EVENT_POLL_PDP),
-                                   POLL_PDP_MILLIS);
-            break;
-
-            case EVENT_VOICE_CALL_STARTED:
-                if (state == State.CONNECTED &&
-                        !phone.mSST.isConcurrentVoiceAndData()) {
-                    stopNetStatPoll();
-                    phone.notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED);
-                }
-            break;
-
-            case EVENT_VOICE_CALL_ENDED:
-                if (state == State.CONNECTED) {
-                    if (!phone.mSST.isConcurrentVoiceAndData()) {
-                        startNetStatPoll();
-                        phone.notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED);
-                    } else {
-                        // clean slate after call end.
-                        resetPollStats();
-                    }
-                } else {
-                    // in case data setup was attempted when we were on a voice call
-                    trySetupData(Phone.REASON_VOICE_CALL_ENDED);
-                }
-            break;
-
-            case EVENT_START_NETSTAT_POLL:
-                mPingTestActive = false;
-                startNetStatPoll();
-                break;
-
-            case EVENT_START_RECOVERY:
-                mPingTestActive = false;
-                doRecovery();
-                break;
-
-            case EVENT_APN_CHANGED:
-                onApnChanged();
-                break;
-            
-            case EVENT_PS_RESTRICT_ENABLED:
-                /**
-                 * We don't need to explicitly to tear down the PDP context
-                 * when PS restricted is enabled. The base band will deactive
-                 * PDP context and notify us with PDP_CONTEXT_CHANGED.
-                 * But we should stop the network polling and prevent reset PDP.
-                 */
-                Log.d(LOG_TAG, "[DSAC DEB] " + "EVENT_PS_RESTRICT_ENABLED " + mIsPsRestricted); 
-                stopNetStatPoll();
-                mIsPsRestricted = true; 
-                break;
-                
-            case EVENT_PS_RESTRICT_DISABLED:
-                /**
-                 * When PS restrict is removed, we need setup PDP connection if
-                 * PDP connection is down.
-                 */
-                Log.d(LOG_TAG, "[DSAC DEB] " + "EVENT_PS_RESTRICT_DISABLED " + mIsPsRestricted);
-                mIsPsRestricted  = false;
-                if (state == State.CONNECTED) {
-                    startNetStatPoll();
-                } else {
-                    if (state == State.FAILED) {
-                        cleanUpConnection(false, Phone.REASON_PS_RESTRICT_ENABLED);
-                        nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
-                    }
-                    trySetupData(Phone.REASON_PS_RESTRICT_ENABLED);
-                }
-                break;
-             
+            } else {
+                startDelayedRetry(cause, reason);
+            }
         }
     }
 
-    private boolean tryNextApn(PdpFailCause cause) {
-        return (cause != PdpFailCause.RADIO_NOT_AVIALABLE)
-            && (cause != PdpFailCause.RADIO_OFF)
-            && (cause != PdpFailCause.RADIO_ERROR_RETRY)
-            && (cause != PdpFailCause.NO_SIGNAL)
-            && (cause != PdpFailCause.SIM_LOCKED);
+    protected void onDisconnectDone(AsyncResult ar) {
+        String reason = null;
+        if(DBG) log("EVENT_DISCONNECT_DONE");
+        if (ar.userObj instanceof String) {
+           reason = (String) ar.userObj;
+        }
+        setState(State.IDLE);
+        phone.notifyDataConnection(reason);
+        mActiveApn = null;
+        if (retryAfterDisconnected(reason)) {
+            trySetupData(reason);
+        }
+    }
+
+    protected void onPollPdp() {
+        if (state == State.CONNECTED) {
+            // only poll when connected
+            phone.mCM.getPDPContextList(this.obtainMessage(EVENT_GET_PDP_LIST_COMPLETE));
+            sendMessageDelayed(obtainMessage(EVENT_POLL_PDP), POLL_PDP_MILLIS);
+        }
+    }
+
+    protected void onVoiceCallStarted() {
+        if (state == State.CONNECTED && !((GSMPhone) phone).mSST.isConcurrentVoiceAndData()) {
+            stopNetStatPoll();
+            phone.notifyDataConnection(Phone.REASON_VOICE_CALL_STARTED);
+        }
+    }
+
+    protected void onVoiceCallEnded() {
+        if (state == State.CONNECTED) {
+            if (!((GSMPhone) phone).mSST.isConcurrentVoiceAndData()) {
+                startNetStatPoll();
+                phone.notifyDataConnection(Phone.REASON_VOICE_CALL_ENDED);
+            } else {
+                // clean slate after call end.
+                resetPollStats();
+            }
+        } else {
+            // in case data setup was attempted when we were on a voice call
+            trySetupData(Phone.REASON_VOICE_CALL_ENDED);
+        }
+    }
+
+    private boolean tryNextApn(FailCause cause) {
+        return (cause != FailCause.RADIO_NOT_AVAILABLE)
+                && (cause != FailCause.RADIO_OFF)
+                && (cause != FailCause.RADIO_ERROR_RETRY)
+                && (cause != FailCause.NO_SIGNAL)
+                && (cause != FailCause.SIM_LOCKED);
     }
 
     private int getRestoreDefaultApnDelay() {
@@ -1668,7 +1452,7 @@
      */
     private void createAllApnList() {
         allApns = new ArrayList<ApnSetting>();
-        String operator = phone.mSIMRecords.getSIMOperatorNumeric();
+        String operator = ((GSMPhone) phone).mSIMRecords.getSIMOperatorNumeric();
 
         if (operator != null) {
             String selection = "numeric = '" + operator + "'";
@@ -1694,7 +1478,7 @@
         if (allApns.isEmpty()) {
             if (DBG) log("No APN found for carrier: " + operator);
             preferredApn = null;
-            notifyNoData(PdpConnection.PdpFailCause.BAD_APN);
+            notifyNoData(PdpConnection.FailCause.BAD_APN);
         } else {
             preferredApn = getPreferredApn();
             Log.d(LOG_TAG, "Get PreferredAPN");
@@ -1706,15 +1490,22 @@
     }
 
     private void createAllPdpList() {
-        pdpList = new ArrayList<PdpConnection>();
-        PdpConnection pdp;
+        pdpList = new ArrayList<DataConnection>();
+        DataConnection pdp;
 
         for (int i = 0; i < PDP_CONNECTION_POOL_SIZE; i++) {
-            pdp = new PdpConnection(phone);
+            pdp = new PdpConnection((GSMPhone) phone);
             pdpList.add(pdp);
          }
     }
 
+    private void destroyAllPdpList() {
+        if(pdpList != null) {
+            PdpConnection pdp;
+            pdpList.removeAll(pdpList);
+        }
+    }
+
     /**
      *
      * @return waitingApns list to be used to create PDP
@@ -1722,7 +1513,7 @@
      */
     private ArrayList<ApnSetting> buildWaitingApns() {
         ArrayList<ApnSetting> apnList = new ArrayList<ApnSetting>();
-        String operator = phone.mSIMRecords.getSIMOperatorNumeric();
+        String operator = ((GSMPhone )phone).mSIMRecords.getSIMOperatorNumeric();
 
         if (mRequestedApnType.equals(Phone.APN_TYPE_DEFAULT)) {
             if (canSetPreferApn && preferredApn != null) {
@@ -1775,7 +1566,7 @@
         return result.toString();
     }
 
-    private void startDelayedRetry(PdpConnection.PdpFailCause cause, String reason) {
+    private void startDelayedRetry(PdpConnection.FailCause cause, String reason) {
         notifyNoData(cause);
         if (mRequestedApnType != Phone.APN_TYPE_DEFAULT) {
             sendMessage(obtainMessage(EVENT_RESTORE_DEFAULT_APN));
@@ -1833,4 +1624,95 @@
 
         return null;
     }
+
+    public void handleMessage (Message msg) {
+
+        switch (msg.what) {
+            case EVENT_RECORDS_LOADED:
+                onRecordsLoaded();
+                break;
+
+            case EVENT_ENABLE_NEW_APN:
+                onEnableNewApn();
+                break;
+
+            case EVENT_RESTORE_DEFAULT_APN:
+                onRestoreDefaultApn();
+                break;
+
+            case EVENT_GPRS_DETACHED:
+                onGprsDetached();
+                break;
+
+            case EVENT_GPRS_ATTACHED:
+                onGprsAttached();
+                break;
+
+            case EVENT_DATA_STATE_CHANGED:
+                onPdpStateChanged((AsyncResult) msg.obj, false);
+                break;
+
+            case EVENT_GET_PDP_LIST_COMPLETE:
+                onPdpStateChanged((AsyncResult) msg.obj, true);
+                break;
+
+            case EVENT_POLL_PDP:
+                onPollPdp();
+                break;
+
+            case EVENT_START_NETSTAT_POLL:
+                mPingTestActive = false;
+                startNetStatPoll();
+                break;
+
+            case EVENT_START_RECOVERY:
+                mPingTestActive = false;
+                doRecovery();
+                break;
+
+            case EVENT_APN_CHANGED:
+                onApnChanged();
+                break;
+
+            case EVENT_PS_RESTRICT_ENABLED:
+                /**
+                 * We don't need to explicitly to tear down the PDP context
+                 * when PS restricted is enabled. The base band will deactive
+                 * PDP context and notify us with PDP_CONTEXT_CHANGED.
+                 * But we should stop the network polling and prevent reset PDP.
+                 */
+                Log.d(LOG_TAG, "[DSAC DEB] " + "EVENT_PS_RESTRICT_ENABLED " + mIsPsRestricted); 
+                stopNetStatPoll();
+                mIsPsRestricted = true; 
+                break;
+
+            case EVENT_PS_RESTRICT_DISABLED:
+                /**
+                 * When PS restrict is removed, we need setup PDP connection if
+                 * PDP connection is down.
+                 */
+                Log.d(LOG_TAG, "[DSAC DEB] " + "EVENT_PS_RESTRICT_DISABLED " + mIsPsRestricted);
+                mIsPsRestricted  = false;
+                if (state == State.CONNECTED) {
+                    startNetStatPoll();
+                } else {
+                    if (state == State.FAILED) {
+                        cleanUpConnection(false, Phone.REASON_PS_RESTRICT_ENABLED);
+                        nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
+                    }
+                    trySetupData(Phone.REASON_PS_RESTRICT_ENABLED);
+                }
+                break;
+
+            default:
+                // handle the message in the super class DataConnectionTracker
+                super.handleMessage(msg);
+                break;
+        }
+    }
+
+    protected void log(String s) {
+        Log.d(LOG_TAG, "[GsmDataConnectionTracker] " + s);
+    }
+
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java b/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java
index 04f8332..4db8fc6 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java
@@ -18,39 +18,40 @@
 
 import android.content.Context;
 import com.android.internal.telephony.*;
+
 import android.os.*;
-import android.os.AsyncResult;
-import android.util.Log;
-import java.util.regex.Pattern;
-import java.util.regex.Matcher;
+import android.telephony.PhoneNumberUtils;
 import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
-import android.telephony.PhoneNumberUtils;
-import static com.android.internal.telephony.gsm.CommandsInterface.*;
+import android.util.Log;
+
+import static com.android.internal.telephony.CommandsInterface.*;
+
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
 
 /**
  * The motto for this file is:
  *
- * "NOTE:	By using the # as a separator, most cases are expected to be unambiguous."
+ * "NOTE:    By using the # as a separator, most cases are expected to be unambiguous."
  *   -- TS 22.030 6.5.2
  *
  * {@hide}
  *
  */
-public final class GsmMmiCode  extends Handler implements MmiCode
-{
+public final class GsmMmiCode  extends Handler implements MmiCode {
     static final String LOG_TAG = "GSM";
 
     //***** Constants
-    
+
     // From TS 22.030 6.5.2
     static final String ACTION_ACTIVATE = "*";
     static final String ACTION_DEACTIVATE = "#";
     static final String ACTION_INTERROGATE = "*#";
     static final String ACTION_REGISTER = "**";
     static final String ACTION_ERASURE = "##";
-    
-    // Supp Service cocdes from TS 22.030 Annex B 
+
+    // Supp Service cocdes from TS 22.030 Annex B
 
     //Called line presentation
     static final String SC_CLIP    = "30";
@@ -102,25 +103,24 @@
 
     GSMPhone phone;
     Context context;
-    
+
     String action;              // One of ACTION_*
     String sc;                  // Service Code
     String sia, sib, sic;       // Service Info a,b,c
     String poundString;         // Entire MMI string up to and including #
     String dialingNumber;
     String pwd;                 // For password registration
-    
 
-    /** Set to true in processCode, not at newFromDialString time */ 
+    /** Set to true in processCode, not at newFromDialString time */
     private boolean isPendingUSSD;
 
     private boolean isUssdRequest;
 
-    State state = State.PENDING;    
+    State state = State.PENDING;
     CharSequence message;
-    
+
     //***** Class Variables
-    
+
 
     // See TS 22.030 6.5.2 "Structure of the MMI"
 
@@ -137,9 +137,9 @@
          10 = dialing number
 */
 
-    static final int MATCH_GROUP_POUND_STRING = 1; 
+    static final int MATCH_GROUP_POUND_STRING = 1;
 
-    static final int MATCH_GROUP_ACTION = 2; 
+    static final int MATCH_GROUP_ACTION = 2;
                         //(activation/interrogation/registration/erasure)
 
     static final int MATCH_GROUP_SERVICE_CODE = 3;
@@ -151,7 +151,7 @@
 
 
     //***** Public Class methods
-    
+
     /**
      * Some dial strings in GSM are defined to do non-call setup
      * things, such as modify or query supplementry service settings (eg, call
@@ -165,9 +165,8 @@
      * Please see flow chart in TS 22.030 6.5.3.2
      */
 
-    static GsmMmiCode 
-    newFromDialString(String dialString, GSMPhone phone)
-    {
+    static GsmMmiCode
+    newFromDialString(String dialString, GSMPhone phone) {
         Matcher m;
         GsmMmiCode ret = null;
 
@@ -187,7 +186,7 @@
 
         } else if (dialString.endsWith("#")) {
             // TS 22.030 sec 6.5.3.2
-            // "Entry of any characters defined in the 3GPP TS 23.038 [8] Default Alphabet 
+            // "Entry of any characters defined in the 3GPP TS 23.038 [8] Default Alphabet
             // (up to the maximum defined in 3GPP TS 24.080 [10]), followed by #SEND".
 
             ret = new GsmMmiCode(phone);
@@ -202,16 +201,15 @@
     }
 
     static GsmMmiCode
-    newNetworkInitiatedUssd (String ussdMessage, 
-                                boolean isUssdRequest, GSMPhone phone)
-    {
+    newNetworkInitiatedUssd (String ussdMessage,
+                                boolean isUssdRequest, GSMPhone phone) {
         GsmMmiCode ret;
 
         ret = new GsmMmiCode(phone);
 
         ret.message = ussdMessage;
         ret.isUssdRequest = isUssdRequest;
-        
+
         // If it's a request, set to PENDING so that it's cancelable.
         if (isUssdRequest) {
             ret.isPendingUSSD = true;
@@ -225,42 +223,39 @@
 
     static GsmMmiCode newFromUssdUserInput(String ussdMessge, GSMPhone phone) {
         GsmMmiCode ret = new GsmMmiCode(phone);
-        
+
         ret.message = ussdMessge;
         ret.state = State.PENDING;
         ret.isPendingUSSD = true;
-        
+
         return ret;
     }
 
     //***** Private Class methods
 
-    /** make empty strings be null. 
-     *  Regexp returns empty strings for empty groups 
+    /** make empty strings be null.
+     *  Regexp returns empty strings for empty groups
      */
     private static String
-    makeEmptyNull (String s)
-    {
+    makeEmptyNull (String s) {
         if (s != null && s.length() == 0) return null;
 
         return s;
     }
 
     /** returns true of the string is empty or null */
-    private static boolean 
-    isEmptyOrNull(CharSequence s)
-    {
+    private static boolean
+    isEmptyOrNull(CharSequence s) {
         return s == null || (s.length() == 0);
     }
 
 
     private static int
-    scToCallForwardReason(String sc)
-    {
-        if (sc == null) { 
+    scToCallForwardReason(String sc) {
+        if (sc == null) {
             throw new RuntimeException ("invalid call forward sc");
         }
-   
+
         if (sc.equals(SC_CF_All)) {
            return CommandsInterface.CF_REASON_ALL;
         } else if (sc.equals(SC_CFU)) {
@@ -279,8 +274,7 @@
     }
 
     private static int
-    siToServiceClass(String si)
-    {
+    siToServiceClass(String si) {
         if (si == null || si.length() == 0) {
                 return  SERVICE_CLASS_NONE;
         } else {
@@ -299,7 +293,7 @@
 /*
     Note for code 20:
      From TS 22.030 Annex C:
-                "All GPRS bearer services" are not included in "All tele and bearer services" 
+                "All GPRS bearer services" are not included in "All tele and bearer services"
                     and "All bearer services"."
 ....so SERVICE_CLASS_DATA, which (according to 27.007) includes GPRS
 */
@@ -319,8 +313,7 @@
     }
 
     private static int
-    siToTime (String si)
-    {
+    siToTime (String si) {
         if (si == null || si.length() == 0) {
             return 0;
         } else {
@@ -330,33 +323,30 @@
     }
 
     static boolean
-    isServiceCodeCallForwarding(String sc)
-    {
-        return sc != null && 
-                (sc.equals(SC_CFU) 
-                || sc.equals(SC_CFB) || sc.equals(SC_CFNRy) 
-                || sc.equals(SC_CFNR) || sc.equals(SC_CF_All) 
+    isServiceCodeCallForwarding(String sc) {
+        return sc != null &&
+                (sc.equals(SC_CFU)
+                || sc.equals(SC_CFB) || sc.equals(SC_CFNRy)
+                || sc.equals(SC_CFNR) || sc.equals(SC_CF_All)
                 || sc.equals(SC_CF_All_Conditional));
     }
 
     static boolean
-    isServiceCodeCallBarring(String sc)
-    {
+    isServiceCodeCallBarring(String sc) {
         return sc != null &&
-                (sc.equals(SC_BAOC) 
+                (sc.equals(SC_BAOC)
                 || sc.equals(SC_BAOIC)
                 || sc.equals(SC_BAOICxH)
                 || sc.equals(SC_BAIC)
                 || sc.equals(SC_BAICr)
                 || sc.equals(SC_BA_ALL)
                 || sc.equals(SC_BA_MO)
-                || sc.equals(SC_BA_MT));    
+                || sc.equals(SC_BA_MT));
     }
 
     static String
-    scToBarringFacility(String sc)
-    {
-        if (sc == null) { 
+    scToBarringFacility(String sc) {
+        if (sc == null) {
             throw new RuntimeException ("invalid call barring sc");
         }
 
@@ -383,11 +373,10 @@
 
     //***** Constructor
 
-    GsmMmiCode (GSMPhone phone)
-    {
+    GsmMmiCode (GSMPhone phone) {
         // The telephony unit-test cases may create GsmMmiCode's
         // in secondary threads
-        super(phone.h.getLooper());
+        super(phone.getHandler().getLooper());
         this.phone = phone;
         this.context = phone.getContext();
     }
@@ -395,21 +384,18 @@
     //***** MmiCode implementation
 
     public State
-    getState()
-    {
+    getState() {
         return state;
     }
 
     public CharSequence
-    getMessage()
-    {
+    getMessage() {
         return message;
     }
 
     // inherited javadoc suffices
     public void
-    cancel()
-    {
+    cancel() {
         // Complete or failed cannot be cancelled
         if (state == State.COMPLETE || state == State.FAILED) {
             return;
@@ -423,7 +409,7 @@
              * cancel it.
              */
             phone.mCM.cancelPendingUssd(obtainMessage(EVENT_USSD_CANCEL_COMPLETE, this));
-            
+
             /*
              * Don't call phone.onMMIDone here; wait for CANCEL_COMPLETE notice
              * from RIL.
@@ -436,7 +422,6 @@
             phone.onMMIDone (this);
         }
 
-
     }
 
     public boolean isCancelable() {
@@ -445,20 +430,17 @@
     }
 
     //***** Instance Methods
-    
 
     /** Does this dial string contain a structured or unstructured MMI code? */
     boolean
-    isMMI()
-    {
+    isMMI() {
         return poundString != null;
     }
 
     /* Is this a 1 or 2 digit "short code" as defined in TS 22.030 sec 6.5.3.2? */
     boolean
-    isShortCode()
-    {
-        return poundString == null 
+    isShortCode() {
+        return poundString == null
                     && dialingNumber != null && dialingNumber.length() <= 2;
 
     }
@@ -479,7 +461,7 @@
                           * for treating "0" and "00" as call setup strings.
                           */
                          || dialString.equals("0")
-                         || dialString.equals("00")))); 
+                         || dialString.equals("00"))));
     }
     /**
      * @return true if the Service Code is PIN/PIN2/PUK/PUK2-related
@@ -489,17 +471,16 @@
                               || sc.equals(SC_PUK) || sc.equals(SC_PUK2));
      }
 
-    /** 
+    /**
      * *See TS 22.030 Annex B
-     * In temporary mode, to suppress CLIR for a single call, enter: 
+     * In temporary mode, to suppress CLIR for a single call, enter:
      *      " * 31 # <called number> SEND "
-     *  In temporary mode, to invoke CLIR for a single call enter: 
+     *  In temporary mode, to invoke CLIR for a single call enter:
      *       " # 31 # <called number> SEND "
      */
-     
-    boolean 
-    isTemporaryModeCLIR()
-    {
+
+    boolean
+    isTemporaryModeCLIR() {
         return sc != null && sc.equals(SC_CLIR) && dialingNumber != null
                 && (isActivate() || isDeactivate());
     }
@@ -509,50 +490,43 @@
      * See also isTemporaryModeCLIR()
      */
     int
-    getCLIRMode()
-    {
+    getCLIRMode() {
         if (sc != null && sc.equals(SC_CLIR)) {
             if (isActivate()) {
                 return CommandsInterface.CLIR_SUPPRESSION;
             } else if (isDeactivate()) {
-                return CommandsInterface.CLIR_INVOCATION;            
+                return CommandsInterface.CLIR_INVOCATION;
             }
         }
-        
+
         return CommandsInterface.CLIR_DEFAULT;
     }
-    
-    boolean isActivate()
-    {
+
+    boolean isActivate() {
         return action != null && action.equals(ACTION_ACTIVATE);
     }
 
-    boolean isDeactivate()
-    {
+    boolean isDeactivate() {
         return action != null && action.equals(ACTION_DEACTIVATE);
     }
-    
-    boolean isInterrogate()
-    {
+
+    boolean isInterrogate() {
         return action != null && action.equals(ACTION_INTERROGATE);
     }
 
-    boolean isRegister()
-    {
+    boolean isRegister() {
         return action != null && action.equals(ACTION_REGISTER);
     }
 
-    boolean isErasure()
-    {
+    boolean isErasure() {
         return action != null && action.equals(ACTION_ERASURE);
     }
 
-    /** 
+    /**
      * Returns true if this is a USSD code that's been submitted to the
      * network...eg, after processCode() is called
      */
-    public boolean isPendingUSSD()
-    {
+    public boolean isPendingUSSD() {
         return isPendingUSSD;
     }
 
@@ -562,8 +536,7 @@
 
     /** Process a MMI code or short code...anything that isn't a dialing number */
     void
-    processCode ()
-    {
+    processCode () {
         try {
             if (isShortCode()) {
                 Log.d(LOG_TAG, "isShortCode");
@@ -573,7 +546,7 @@
                 // We should have no dialing numbers here
                 throw new RuntimeException ("Invalid or Unsupported MMI Code");
             } else if (sc != null && sc.equals(SC_CLIP)) {
-                Log.d(LOG_TAG, "is CLIP"); 
+                Log.d(LOG_TAG, "is CLIP");
                 if (isInterrogate()) {
                     phone.mCM.queryCLIP(
                             obtainMessage(EVENT_QUERY_COMPLETE, this));
@@ -581,7 +554,7 @@
                     throw new RuntimeException ("Invalid or Unsupported MMI Code");
                 }
             } else if (sc != null && sc.equals(SC_CLIR)) {
-                Log.d(LOG_TAG, "is CLIR"); 
+                Log.d(LOG_TAG, "is CLIR");
                 if (isActivate()) {
                     phone.mCM.setCLIR(CommandsInterface.CLIR_INVOCATION,
                         obtainMessage(EVENT_SET_COMPLETE, this));
@@ -688,13 +661,13 @@
                 // sia = basic service group
                 int serviceClass = siToServiceClass(sia);
 
-            	if (isActivate() || isDeactivate()) {
+                if (isActivate() || isDeactivate()) {
                     phone.mCM.setCallWaiting(isActivate(), serviceClass,
                             obtainMessage(EVENT_SET_COMPLETE, this));
-            	} else if (isInterrogate()) {
+                } else if (isInterrogate()) {
                     phone.mCM.queryCallWaiting(serviceClass,
                             obtainMessage(EVENT_QUERY_COMPLETE, this));
-            	} else {
+                } else {
                     throw new RuntimeException ("Invalid or Unsupported MMI Code");
                 }
             } else if (isPinCommand()) {
@@ -718,16 +691,16 @@
                     } else {
                         // pre-checks OK
                         if (sc.equals(SC_PIN)) {
-                            phone.mCM.changeSimPin(oldPinOrPuk, newPin,
+                            phone.mCM.changeIccPin(oldPinOrPuk, newPin,
                                     obtainMessage(EVENT_SET_COMPLETE, this));
                         } else if (sc.equals(SC_PIN2)) {
-                            phone.mCM.changeSimPin2(oldPinOrPuk, newPin,
+                            phone.mCM.changeIccPin2(oldPinOrPuk, newPin,
                                     obtainMessage(EVENT_SET_COMPLETE, this));
                         } else if (sc.equals(SC_PUK)) {
-                            phone.mCM.supplySimPuk(oldPinOrPuk, newPin,
+                            phone.mCM.supplyIccPuk(oldPinOrPuk, newPin,
                                     obtainMessage(EVENT_SET_COMPLETE, this));
                         } else if (sc.equals(SC_PUK2)) {
-                            phone.mCM.supplySimPuk2(oldPinOrPuk, newPin,
+                            phone.mCM.supplyIccPuk2(oldPinOrPuk, newPin,
                                     obtainMessage(EVENT_SET_COMPLETE, this));
                         }
                     }
@@ -743,7 +716,7 @@
             state = State.FAILED;
             message = context.getText(com.android.internal.R.string.mmiError);
             phone.onMMIDone(this);
-        }    
+        }
     }
 
     private void handlePasswordError(int res) {
@@ -755,8 +728,8 @@
         phone.onMMIDone(this);
     }
 
-    /** 
-     * Called from GSMPhone 
+    /**
+     * Called from GSMPhone
      *
      * An unsolicited USSD NOTIFY or REQUEST has come in matching
      * up with this pending USSD request
@@ -765,8 +738,7 @@
      *       active (ie, the network expects user input).
      */
     void
-    onUssdFinished(String ussdMessage, boolean isUssdRequest)
-    {
+    onUssdFinished(String ussdMessage, boolean isUssdRequest) {
         if (state == State.PENDING) {
             if (ussdMessage == null) {
                 message = context.getText(com.android.internal.R.string.mmiComplete);
@@ -783,15 +755,14 @@
         }
     }
 
-    /** 
-     * Called from GSMPhone 
+    /**
+     * Called from GSMPhone
      *
      * The radio has reset, and this is still pending
      */
 
     void
-    onUssdFinishedError()
-    {
+    onUssdFinishedError() {
         if (state == State.PENDING) {
             state = State.FAILED;
             message = context.getText(com.android.internal.R.string.mmiError);
@@ -808,15 +779,14 @@
         // response does not complete this MMI code...we wait for
         // an unsolicited USSD "Notify" or "Request".
         // The matching up of this is doene in GSMPhone.
-        
-        phone.mCM.sendUSSD(ussdMessage, 
+
+        phone.mCM.sendUSSD(ussdMessage,
             obtainMessage(EVENT_USSD_COMPLETE, this));
     }
 
     /** Called from GSMPhone.handleMessage; not a Handler subclass */
     public void
-    handleMessage (Message msg)
-    {
+    handleMessage (Message msg) {
         AsyncResult ar;
 
         switch (msg.what) {
@@ -865,13 +835,13 @@
                                             com.android.internal.R.string.mmiError);
 
                     phone.onMMIDone(this);
-                } 
+                }
 
                 // Note that unlike most everything else, the USSD complete
                 // response does not complete this MMI code...we wait for
                 // an unsolicited USSD "Notify" or "Request".
                 // The matching up of this is done in GSMPhone.
-                                
+
             break;
 
             case EVENT_USSD_CANCEL_COMPLETE:
@@ -976,8 +946,7 @@
     }
 
     private void
-    onGetClirComplete(AsyncResult ar)
-    {
+    onGetClirComplete(AsyncResult ar) {
         StringBuilder sb = new StringBuilder(getScString());
         sb.append("\n");
 
@@ -996,35 +965,35 @@
                                 com.android.internal.R.string.serviceNotProvisioned));
                     state = State.COMPLETE;
                 break;
-                    
+
                 case 1: // CLIR provisioned in permanent mode
                     sb.append(context.getText(
                                 com.android.internal.R.string.CLIRPermanent));
                     state = State.COMPLETE;
                 break;
 
-                case 2: // unknown (e.g. no network, etc.)	
+                case 2: // unknown (e.g. no network, etc.)
                     sb.append(context.getText(
                                 com.android.internal.R.string.mmiError));
                     state = State.FAILED;
                 break;
 
-                case 3: // CLIR temporary mode presentation restricted	
+                case 3: // CLIR temporary mode presentation restricted
 
                     // the 'n' parameter from TS 27.007 7.7
                     switch (clirArgs[0]) {
                         default:
                         case 0: // Default
                             sb.append(context.getText(
-                                            com.android.internal.R.string.CLIRDefaultOnNextCallOn));
+                                    com.android.internal.R.string.CLIRDefaultOnNextCallOn));
                         break;
                         case 1: // CLIR invocation
                             sb.append(context.getText(
-                                            com.android.internal.R.string.CLIRDefaultOnNextCallOn));
+                                    com.android.internal.R.string.CLIRDefaultOnNextCallOn));
                         break;
                         case 2: // CLIR suppression
                             sb.append(context.getText(
-                                            com.android.internal.R.string.CLIRDefaultOnNextCallOff));
+                                    com.android.internal.R.string.CLIRDefaultOnNextCallOff));
                         break;
                     }
                     state = State.COMPLETE;
@@ -1036,21 +1005,21 @@
                         default:
                         case 0: // Default
                             sb.append(context.getText(
-                                            com.android.internal.R.string.CLIRDefaultOffNextCallOff));
+                                    com.android.internal.R.string.CLIRDefaultOffNextCallOff));
                         break;
                         case 1: // CLIR invocation
                             sb.append(context.getText(
-                                            com.android.internal.R.string.CLIRDefaultOffNextCallOn));
+                                    com.android.internal.R.string.CLIRDefaultOffNextCallOn));
                         break;
                         case 2: // CLIR suppression
                             sb.append(context.getText(
-                                            com.android.internal.R.string.CLIRDefaultOffNextCallOff));
+                                    com.android.internal.R.string.CLIRDefaultOffNextCallOff));
                         break;
                     }
 
                     state = State.COMPLETE;
                 break;
-            }            
+            }
         }
 
         message = sb;
@@ -1059,23 +1028,29 @@
 
     /**
      * @param serviceClass 1 bit of the service class bit vectory
-     * @return String to be used for call forward query MMI response text. 
+     * @return String to be used for call forward query MMI response text.
      *        Returns null if unrecognized
      */
 
     private CharSequence
-    serviceClassToCFString (int serviceClass)
-    {
+    serviceClassToCFString (int serviceClass) {
         switch (serviceClass) {
-            case SERVICE_CLASS_VOICE:       return context.getText(com.android.internal.R.string.serviceClassVoice);
-            case SERVICE_CLASS_DATA:        return context.getText(com.android.internal.R.string.serviceClassData);
-            case SERVICE_CLASS_FAX:         return context.getText(com.android.internal.R.string.serviceClassFAX);
-            case SERVICE_CLASS_SMS:         return context.getText(com.android.internal.R.string.serviceClassSMS);
-            case SERVICE_CLASS_DATA_SYNC:   return context.getText(com.android.internal.R.string.serviceClassDataSync);
-            case SERVICE_CLASS_DATA_ASYNC:  return context.getText(com.android.internal.R.string.serviceClassDataAsync);
-            case SERVICE_CLASS_PACKET:      return context.getText(com.android.internal.R.string.serviceClassPacket);
-            case SERVICE_CLASS_PAD:         return context.getText(com.android.internal.R.string.serviceClassPAD);
-
+            case SERVICE_CLASS_VOICE:
+                return context.getText(com.android.internal.R.string.serviceClassVoice);
+            case SERVICE_CLASS_DATA:
+                return context.getText(com.android.internal.R.string.serviceClassData);
+            case SERVICE_CLASS_FAX:
+                return context.getText(com.android.internal.R.string.serviceClassFAX);
+            case SERVICE_CLASS_SMS:
+                return context.getText(com.android.internal.R.string.serviceClassSMS);
+            case SERVICE_CLASS_DATA_SYNC:
+                return context.getText(com.android.internal.R.string.serviceClassDataSync);
+            case SERVICE_CLASS_DATA_ASYNC:
+                return context.getText(com.android.internal.R.string.serviceClassDataAsync);
+            case SERVICE_CLASS_PACKET:
+                return context.getText(com.android.internal.R.string.serviceClassPacket);
+            case SERVICE_CLASS_PAD:
+                return context.getText(com.android.internal.R.string.serviceClassPAD);
             default:
                 return null;
         }
@@ -1084,8 +1059,7 @@
 
     /** one CallForwardInfo + serviceClassMask -> one line of text */
     private CharSequence
-    makeCFQueryResultMessage(CallForwardInfo info, int serviceClassMask)
-    {
+    makeCFQueryResultMessage(CallForwardInfo info, int serviceClassMask) {
         CharSequence template;
         String sources[] = {"{0}", "{1}", "{2}"};
         CharSequence destinations[] = new CharSequence[3];
@@ -1094,7 +1068,7 @@
         // CF_REASON_NO_REPLY also has a time value associated with
         // it. All others don't.
 
-        needTimeTemplate = 
+        needTimeTemplate =
             (info.reason == CommandsInterface.CF_REASON_NO_REPLY);
 
         if (info.status == 1) {
@@ -1122,8 +1096,8 @@
         }
 
         // In the template (from strings.xmls)
-        // 		{0} is one of "bearerServiceCode*" 
-        //		{1} is dialing number  
+        //         {0} is one of "bearerServiceCode*"
+        //        {1} is dialing number
         //      {2} is time in seconds
 
         destinations[0] = serviceClassToCFString(info.serviceClass & serviceClassMask);
@@ -1142,8 +1116,7 @@
 
 
     private void
-    onQueryCfComplete(AsyncResult ar)
-    {
+    onQueryCfComplete(AsyncResult ar) {
         StringBuilder sb = new StringBuilder(getScString());
         sb.append("\n");
 
@@ -1152,7 +1125,7 @@
             sb.append(context.getText(com.android.internal.R.string.mmiError));
         } else {
             CallForwardInfo infos[];
-            
+
             infos = (CallForwardInfo[]) ar.result;
 
             if (infos.length == 0) {
@@ -1166,18 +1139,18 @@
                 SpannableStringBuilder tb = new SpannableStringBuilder();
 
                 // Each bit in the service class gets its own result line
-                // The service classes may be split up over multiple 
+                // The service classes may be split up over multiple
                 // CallForwardInfos. So, for each service classs, find out
                 // which CallForwardInfo represents it and then build
                 // the response text based on that
 
-                for (int serviceClassMask = 1 
+                for (int serviceClassMask = 1
                             ; serviceClassMask <= SERVICE_CLASS_MAX
-                            ; serviceClassMask <<= 1 
+                            ; serviceClassMask <<= 1
                 ) {
                     for (int i = 0, s = infos.length; i < s ; i++) {
                         if ((serviceClassMask & infos[i].serviceClass) != 0) {
-                            tb.append(makeCFQueryResultMessage(infos[i], 
+                            tb.append(makeCFQueryResultMessage(infos[i],
                                             serviceClassMask));
                             tb.append("\n");
                         }
@@ -1191,12 +1164,11 @@
 
         message = sb;
         phone.onMMIDone(this);
-    
+
     }
 
     private void
-    onQueryComplete(AsyncResult ar)
-    {
+    onQueryComplete(AsyncResult ar) {
         StringBuilder sb = new StringBuilder(getScString());
         sb.append("\n");
 
@@ -1230,15 +1202,15 @@
         message = sb;
         phone.onMMIDone(this);
     }
-    
-    private CharSequence
-    createQueryCallWaitingResultMessage(int serviceClass)
-    {
-        StringBuilder sb = new StringBuilder(context.getText(com.android.internal.R.string.serviceEnabledFor));
 
-        for (int classMask = 1 
+    private CharSequence
+    createQueryCallWaitingResultMessage(int serviceClass) {
+        StringBuilder sb =
+                new StringBuilder(context.getText(com.android.internal.R.string.serviceEnabledFor));
+
+        for (int classMask = 1
                     ; classMask <= SERVICE_CLASS_MAX
-                    ; classMask <<= 1 
+                    ; classMask <<= 1
         ) {
             if ((classMask & serviceClass) != 0) {
                 sb.append("\n");
@@ -1267,8 +1239,8 @@
     /***
      * TODO: It would be nice to have a method here that can take in a dialstring and
      * figure out if there is an MMI code embedded within it.  This code would replace
-     * some of the string parsing functionality in the Phone App's 
-     * SpecialCharSequenceMgr class.   
+     * some of the string parsing functionality in the Phone App's
+     * SpecialCharSequenceMgr class.
      */
 
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
new file mode 100644
index 0000000..3e73caf
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
@@ -0,0 +1,379 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony.gsm;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.app.PendingIntent.CanceledException;
+import android.content.Intent;
+import android.os.AsyncResult;
+import android.os.Message;
+import android.telephony.ServiceState;
+import android.util.Config;
+import android.util.Log;
+
+import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.gsm.SmsMessage;
+import com.android.internal.telephony.SMSDispatcher;
+import com.android.internal.telephony.SmsHeader;
+import com.android.internal.telephony.SmsMessageBase;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+
+final class GsmSMSDispatcher extends SMSDispatcher {
+    private static final String TAG = "GSM";
+
+    GsmSMSDispatcher(GSMPhone phone) {
+        super(phone);
+    }
+
+    /**
+     * Called when a status report is received.  This should correspond to
+     * a previously successful SEND.
+     *
+     * @param ar AsyncResult passed into the message handler.  ar.result should
+     *           be a String representing the status report PDU, as ASCII hex.
+     */
+    protected void handleStatusReport(AsyncResult ar) {
+        String pduString = (String) ar.result;
+        SmsMessage sms = SmsMessage.newFromCDS(pduString);
+
+        if (sms != null) {
+            int messageRef = sms.messageRef;
+            for (int i = 0, count = deliveryPendingList.size(); i < count; i++) {
+                SmsTracker tracker = deliveryPendingList.get(i);
+                if (tracker.mMessageRef == messageRef) {
+                    // Found it.  Remove from list and broadcast.
+                    deliveryPendingList.remove(i);
+                    PendingIntent intent = tracker.mDeliveryIntent;
+                    Intent fillIn = new Intent();
+                    fillIn.putExtra("pdu", IccUtils.hexStringToBytes(pduString));
+                    try {
+                        intent.send(mContext, Activity.RESULT_OK, fillIn);
+                    } catch (CanceledException ex) {}
+
+                    // Only expect to see one tracker matching this messageref
+                    break;
+                }
+            }
+        }
+
+        if (mCm != null) {
+            mCm.acknowledgeLastIncomingSMS(true, null);
+        }
+    }
+
+
+    /**
+     * Dispatches an incoming SMS messages.
+     *
+     * @param sms the incoming message from the phone
+     */
+    protected void dispatchMessage(SmsMessageBase smsb) {
+
+        // If sms is null, means there was a parsing error.
+        // TODO: Should NAK this.
+        if (smsb == null) {
+            return;
+        }
+        SmsMessage sms = (SmsMessage) smsb;
+        boolean handled = false;
+
+        // Special case the message waiting indicator messages
+        if (sms.isMWISetMessage()) {
+            ((GSMPhone) mPhone).updateMessageWaitingIndicator(true);
+
+            if (sms.isMwiDontStore()) {
+                handled = true;
+            }
+
+            if (Config.LOGD) {
+                Log.d(TAG,
+                        "Received voice mail indicator set SMS shouldStore="
+                         + !handled);
+            }
+        } else if (sms.isMWIClearMessage()) {
+            ((GSMPhone) mPhone).updateMessageWaitingIndicator(false);
+
+            if (sms.isMwiDontStore()) {
+                handled = true;
+            }
+
+            if (Config.LOGD) {
+                Log.d(TAG,
+                        "Received voice mail indicator clear SMS shouldStore="
+                        + !handled);
+            }
+        }
+
+        if (handled) {
+            return;
+        }
+
+        // Parse the headers to see if this is partial, or port addressed
+        int referenceNumber = -1;
+        int count = 0;
+        int sequence = 0;
+        int destPort = -1;
+
+        SmsHeader header = sms.getUserDataHeader();
+        if (header != null) {
+            for (SmsHeader.Element element : header.getElements()) {
+                try {
+                    switch (element.getID()) {
+                        case SmsHeader.CONCATENATED_8_BIT_REFERENCE: {
+                            byte[] data = element.getData();
+                            
+                            referenceNumber = data[0] & 0xff;
+                            count = data[1] & 0xff;
+                            sequence = data[2] & 0xff;
+                            
+                            // Per TS 23.040, 9.2.3.24.1: If the count is zero, sequence
+                            // is zero, or sequence > count, ignore the entire element
+                            if (count == 0 || sequence == 0 || sequence > count) {
+                                referenceNumber = -1;
+                            }
+                            break;
+                        }
+                        
+                        case SmsHeader.CONCATENATED_16_BIT_REFERENCE: {
+                            byte[] data = element.getData();
+                            
+                            referenceNumber = (data[0] & 0xff) * 256 + (data[1] & 0xff);
+                            count = data[2] & 0xff;
+                            sequence = data[3] & 0xff;
+                            
+                            // Per TS 23.040, 9.2.3.24.8: If the count is zero, sequence
+                            // is zero, or sequence > count, ignore the entire element
+                            if (count == 0 || sequence == 0 || sequence > count) {
+                                referenceNumber = -1;
+                            }
+                            break;
+                        }
+                        
+                        case SmsHeader.APPLICATION_PORT_ADDRESSING_16_BIT: {
+                            byte[] data = element.getData();
+                            
+                            destPort = (data[0] & 0xff) << 8;
+                            destPort |= (data[1] & 0xff);
+                            
+                            break;
+                        }
+                    }
+                } catch (ArrayIndexOutOfBoundsException e) {
+                    Log.e(TAG, "Bad element in header", e);
+                    return;  // TODO: NACK the message or something, don't just discard.
+                }
+            }
+        }
+
+        if (referenceNumber == -1) {
+            // notify everyone of the message if it isn't partial
+            byte[][] pdus = new byte[1][];
+            pdus[0] = sms.getPdu();
+
+            if (destPort != -1) {
+                if (destPort == SmsHeader.PORT_WAP_PUSH) {
+                    mWapPush.dispatchWapPdu(sms.getUserData());
+                }
+                // The message was sent to a port, so concoct a URI for it
+                dispatchPortAddressedPdus(pdus, destPort);
+            } else {
+                // It's a normal message, dispatch it
+                dispatchPdus(pdus);
+            }
+        } else {
+            // Process the message part
+            processMessagePart(sms, referenceNumber, sequence, count, destPort);
+        }
+    }
+
+    /** {@inheritDoc} */
+    protected void sendMultipartText(String destinationAddress, String scAddress,
+            ArrayList<String> parts, ArrayList<PendingIntent> sentIntents,
+            ArrayList<PendingIntent> deliveryIntents) {
+        int ref = ++sConcatenatedRef & 0xff;
+
+        for (int i = 0, count = parts.size(); i < count; i++) {
+            // build SmsHeader
+            byte[] data = new byte[3];
+            data[0] = (byte) ref;   // reference #, unique per message
+            data[1] = (byte) count; // total part count
+            data[2] = (byte) (i + 1);  // 1-based sequence
+            SmsHeader header = new SmsHeader();
+            header.add(new SmsHeader.Element(SmsHeader.CONCATENATED_8_BIT_REFERENCE, data));
+            PendingIntent sentIntent = null;
+            PendingIntent deliveryIntent = null;
+
+            if (sentIntents != null && sentIntents.size() > i) {
+                sentIntent = sentIntents.get(i);
+            }
+            if (deliveryIntents != null && deliveryIntents.size() > i) {
+                deliveryIntent = deliveryIntents.get(i);
+            }
+
+            SmsMessage.SubmitPdu pdus = SmsMessage.getSubmitPdu(scAddress, destinationAddress,
+                    parts.get(i), deliveryIntent != null, header.toByteArray());
+
+            sendRawPdu(pdus.encodedScAddress, pdus.encodedMessage, sentIntent, deliveryIntent);
+        }
+    }
+
+    /**
+     * Send a multi-part text based SMS which already passed SMS control check.
+     *
+     * It is the working function for sendMultipartText().
+     * 
+     * @param destinationAddress the address to send the message to
+     * @param scAddress is the service center address or null to use
+     *   the current default SMSC
+     * @param parts an <code>ArrayList</code> of strings that, in order,
+     *   comprise the original message
+     * @param sentIntents if not null, an <code>ArrayList</code> of
+     *   <code>PendingIntent</code>s (one for each message part) that is
+     *   broadcast when the corresponding message part has been sent.
+     *   The result code will be <code>Activity.RESULT_OK<code> for success,
+     *   or one of these errors:
+     *   <code>RESULT_ERROR_GENERIC_FAILURE</code>
+     *   <code>RESULT_ERROR_RADIO_OFF</code>
+     *   <code>RESULT_ERROR_NULL_PDU</code>.
+     * @param deliveryIntents if not null, an <code>ArrayList</code> of
+     *   <code>PendingIntent</code>s (one for each message part) that is
+     *   broadcast when the corresponding message part has been delivered
+     *   to the recipient.  The raw pdu of the status report is in the
+     *   extended data ("pdu").
+     */
+    private void sendMultipartTextWithPermit(String destinationAddress, 
+            String scAddress, ArrayList<String> parts,
+            ArrayList<PendingIntent> sentIntents, 
+            ArrayList<PendingIntent> deliveryIntents) {
+        
+        PendingIntent sentIntent = null;
+        PendingIntent deliveryIntent = null;
+        
+        // check if in service
+        int ss = mPhone.getServiceState().getState();
+        if (ss != ServiceState.STATE_IN_SERVICE) {
+            for (int i = 0, count = parts.size(); i < count; i++) {
+                if (sentIntents != null && sentIntents.size() > i) {
+                    sentIntent = sentIntents.get(i);
+                }
+                SmsTracker tracker = SmsTrackerFactory(null, sentIntent, null);
+                handleNotInService(ss, tracker);
+            }
+            return;
+        }
+
+        int ref = ++sConcatenatedRef & 0xff;
+
+        for (int i = 0, count = parts.size(); i < count; i++) {
+            // build SmsHeader
+            byte[] data = new byte[3];
+            data[0] = (byte) ref;   // reference #, unique per message
+            data[1] = (byte) count; // total part count
+            data[2] = (byte) (i + 1);  // 1-based sequence
+            SmsHeader header = new SmsHeader();
+            header.add(new SmsHeader.Element(SmsHeader.CONCATENATED_8_BIT_REFERENCE, data));
+ 
+            if (sentIntents != null && sentIntents.size() > i) {
+                sentIntent = sentIntents.get(i);
+            }
+            if (deliveryIntents != null && deliveryIntents.size() > i) {
+                deliveryIntent = deliveryIntents.get(i);
+            }
+
+            SmsMessage.SubmitPdu pdus = SmsMessage.getSubmitPdu(scAddress, destinationAddress,
+                    parts.get(i), deliveryIntent != null, header.toByteArray());
+
+            HashMap<String, Object> map = new HashMap<String, Object>();
+            map.put("smsc", pdus.encodedScAddress);
+            map.put("pdu", pdus.encodedMessage);
+
+            SmsTracker tracker =  SmsTrackerFactory(map, sentIntent, deliveryIntent);
+            sendSms(tracker);
+        }        
+    }
+
+    /** {@inheritDoc} */
+    protected void sendSms(SmsTracker tracker) {
+        HashMap map = tracker.mData;
+
+        byte smsc[] = (byte[]) map.get("smsc");
+        byte pdu[] = (byte[]) map.get("pdu");
+
+        Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);
+        mCm.sendSMS(IccUtils.bytesToHexString(smsc),
+                IccUtils.bytesToHexString(pdu), reply);
+    }
+
+    /**
+     * Send the multi-part SMS based on multipart Sms tracker
+     * 
+     * @param tracker holds the multipart Sms tracker ready to be sent
+     */
+    protected void sendMultipartSms (SmsTracker tracker) {
+        ArrayList<String> parts;
+        ArrayList<PendingIntent> sentIntents;
+        ArrayList<PendingIntent> deliveryIntents;
+        
+        HashMap map = tracker.mData;
+        
+        String destinationAddress = (String) map.get("destination");
+        String scAddress = (String) map.get("scaddress");
+        
+        parts = (ArrayList<String>) map.get("parts");
+        sentIntents = (ArrayList<PendingIntent>) map.get("sentIntents");
+        deliveryIntents = (ArrayList<PendingIntent>) map.get("deliveryIntents");
+     
+        sendMultipartTextWithPermit(destinationAddress, 
+                scAddress, parts, sentIntents, deliveryIntents);
+
+    }
+
+    /** {@inheritDoc} */
+    protected void acknowledgeLastIncomingSms(boolean success, Message response){
+        // FIXME unit test leaves cm == null. this should change
+        if (mCm != null) {
+            mCm.acknowledgeLastIncomingSMS(success, response);
+        }
+    }
+
+    /** {@inheritDoc} */
+    protected void activateCellBroadcastSms(int activate, Message response) {
+        // Unless CBS is implemented for GSM, this point should be unreachable.
+        Log.e(TAG, "Error! The functionality cell broadcast sms is not implemented for GSM.");
+        response.recycle();
+    }
+
+    /** {@inheritDoc} */
+    protected void getCellBroadcastSmsConfig(Message response){
+        // Unless CBS is implemented for GSM, this point should be unreachable.
+        Log.e(TAG, "Error! The functionality cell broadcast sms is not implemented for GSM.");
+        response.recycle();
+    }
+
+    /** {@inheritDoc} */
+    protected  void setCellBroadcastConfig(int[] configValuesArray, Message response) {
+        // Unless CBS is implemented for GSM, this point should be unreachable.
+        Log.e(TAG, "Error! The functionality cell broadcast sms is not implemented for GSM.");
+        response.recycle();
+    }
+
+}
+
diff --git a/telephony/java/com/android/internal/telephony/gsm/ServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
similarity index 87%
rename from telephony/java/com/android/internal/telephony/gsm/ServiceStateTracker.java
rename to telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index e336d7d..3c0b603 100644
--- a/telephony/java/com/android/internal/telephony/gsm/ServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -16,19 +16,7 @@
 
 package com.android.internal.telephony.gsm;
 
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ALPHA;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISROAMING;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_NUMERIC;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_SIM_OPERATOR_ALPHA;
-import static com.android.internal.telephony.TelephonyProperties.PROPERTY_SIM_OPERATOR_NUMERIC;
-
-import com.android.internal.telephony.SimCard;
-import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.gsm.DataConnectionTracker.State;
-
 import android.app.AlarmManager;
 import android.app.Notification;
 import android.app.NotificationManager;
@@ -49,13 +37,32 @@
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
 import android.provider.Telephony.Intents;
-import android.telephony.gsm.GsmCellLocation;
 import android.telephony.ServiceState;
+import android.telephony.gsm.GsmCellLocation;
 import android.text.TextUtils;
 import android.util.Config;
+import android.util.EventLog;
 import android.util.Log;
 import android.util.TimeUtils;
-import android.util.EventLog;
+
+import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.DataConnectionTracker;
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneProxy;
+import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.ServiceStateTracker;
+import com.android.internal.telephony.TelephonyEventLog;
+import com.android.internal.telephony.TelephonyIntents;
+
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ALPHA;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISROAMING;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_NUMERIC;
 
 import java.util.Arrays;
 import java.util.Calendar;
@@ -65,30 +72,9 @@
 /**
  * {@hide}
  */
-final class ServiceStateTracker extends Handler
-{
-    /**
-     *  The access technology currently in use:
-     *  0 = unknown
-     *  1 = GPRS only
-     *  2 = EDGE
-     *  3 = UMTS
-     */
-    static final int DATA_ACCESS_UNKNOWN = 0;
-    static final int DATA_ACCESS_GPRS = 1;
-    static final int DATA_ACCESS_EDGE = 2;
-    static final int DATA_ACCESS_UMTS = 3;
-    
-    static final int MAX_NUM_DATA_STATE_READS = 15;
-    static final int DATA_STATE_POLL_SLEEP_MS = 100;
-
+final class GsmServiceStateTracker extends ServiceStateTracker {
     //***** Instance Variables
-
     GSMPhone phone;
-    CommandsInterface cm;
-
-    ServiceState ss;
-    ServiceState newSS;
     GsmCellLocation cellLoc;
     GsmCellLocation newCellLoc;
     int mPreferredNetworkType;
@@ -97,18 +83,6 @@
     int rssi = 99;     // signal strength 0-31, 99=unknown
                        // That's "received signal strength indication" fyi
 
-    int[] pollingContext;  // Used as a unique identifier to
-                            // track requests associated with a poll
-                            // and ignore stale responses.
-                            // The value is a count-down of expected responses
-                            // in this pollingContext
-
-    boolean mDesiredPowerState;
-
-    boolean dontPollSignalStrength = false; // Default is to poll strength
-        // If we're getting unsolicited signal strength updates from the radio,
-        // set value to true and don't bother polling any more
-
     private int gprsState = ServiceState.STATE_OUT_OF_SERVICE;
     private int newGPRSState = ServiceState.STATE_OUT_OF_SERVICE;
 
@@ -120,14 +94,10 @@
     /* gsm roaming status solely based on TS 27.007 7.2 CREG */
     private boolean mGsmRoaming = false;
 
-    private RegistrantList networkAttachedRegistrants = new RegistrantList();
     private RegistrantList gprsAttachedRegistrants = new RegistrantList();
     private RegistrantList gprsDetachedRegistrants = new RegistrantList();
-    private RegistrantList roamingOnRegistrants = new RegistrantList();
-    private RegistrantList roamingOffRegistrants = new RegistrantList();
     private RegistrantList psRestrictEnabledRegistrants = new RegistrantList();
     private RegistrantList psRestrictDisabledRegistrants = new RegistrantList();
-    
 
     // Sometimes we get the NITZ time before we know what country we are in.
     // Keep the time zone information from the NITZ string so we can fix
@@ -137,6 +107,7 @@
     private boolean mZoneDst;
     private long mZoneTime;
     private boolean mGotCountryCode = false;
+    private ContentResolver cr;
 
     String mSavedTimeZone;
     long mSavedTime;
@@ -170,13 +141,10 @@
     static final boolean DBG = true;
     static final String LOG_TAG = "GSM";
 
-    // signal strength poll rate
-    static final int POLL_PERIOD_MILLIS = 20 * 1000;
-
     // waiting period before recheck gprs and voice registration
     static final int DEFAULT_GPRS_CHECK_PERIOD_MILLIS = 60 * 1000;
 
-    // restricted state type
+    // notification type
     static final int PS_ENABLED = 1001;             // Access Control blocks data service
     static final int PS_DISABLED = 1002;            // Access Control enables data service
     static final int CS_ENABLED = 1003;             // Access Control blocks all voice/sms service
@@ -187,72 +155,21 @@
     // notification id
     static final int PS_NOTIFICATION = 888; //id to update and cancel PS restricted 
     static final int CS_NOTIFICATION = 999; //id to update and cancel CS restricted
-    
-    //***** Events
-    static final int EVENT_RADIO_STATE_CHANGED       = 1;
-    static final int EVENT_NETWORK_STATE_CHANGED        = 2;
-    static final int EVENT_GET_SIGNAL_STRENGTH  = 3;
-    static final int EVENT_POLL_STATE_REGISTRATION = 4;
-    static final int EVENT_POLL_STATE_GPRS = 5;
-    static final int EVENT_POLL_STATE_OPERATOR         = 6;
-    static final int EVENT_POLL_SIGNAL_STRENGTH = 10;
-    static final int EVENT_NITZ_TIME = 11;
-    static final int EVENT_SIGNAL_STRENGTH_UPDATE = 12;
-    static final int EVENT_RADIO_AVAILABLE = 13;
-    static final int EVENT_POLL_STATE_NETWORK_SELECTION_MODE = 14;
-    static final int EVENT_GET_LOC_DONE = 15;
-    static final int EVENT_SIM_RECORDS_LOADED = 16;
-    static final int EVENT_SIM_READY = 17;
-    static final int EVENT_LOCATION_UPDATES_ENABLED = 18;
-    static final int EVENT_GET_PREFERRED_NETWORK_TYPE = 19;
-    static final int EVENT_SET_PREFERRED_NETWORK_TYPE = 20;
-    static final int EVENT_RESET_PREFERRED_NETWORK_TYPE = 21;
-    static final int EVENT_CHECK_REPORT_GPRS = 22;
-    static final int EVENT_RESTRICTED_STATE_CHANGED = 23;
-
-  //***** Time Zones
-
-    private static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
-
-    // List of ISO codes for countries that can have an offset of GMT+0
-    // when not in daylight savings time.  This ignores some small places
-    // such as the Canary Islands (Spain) and Danmarkshavn (Denmark).
-    // The list must be sorted by code.
-    private static final String[] GMT_COUNTRY_CODES = {
-        "bf", // Burkina Faso
-        "ci", // Cote d'Ivoire
-        "eh", // Western Sahara
-        "fo", // Faroe Islands, Denmark
-        "gh", // Ghana
-        "gm", // Gambia
-        "gn", // Guinea
-        "gw", // Guinea Bissau
-        "ie", // Ireland
-        "lr", // Liberia
-        "is", // Iceland
-        "ma", // Morocco
-        "ml", // Mali
-        "mr", // Mauritania
-        "pt", // Portugal
-        "sl", // Sierra Leone
-        "sn", // Senegal
-        "st", // Sao Tome and Principe
-        "tg", // Togo
-        "uk", // U.K
-    };
 
     private ContentObserver mAutoTimeObserver = new ContentObserver(new Handler()) {
         @Override
         public void onChange(boolean selfChange) {
-            Log.i("ServiceStateTracker", "Auto time state changed");
+            Log.i("GsmServiceStateTracker", "Auto time state changed");
             revertToNitz();
         }
     };
-    
+
+
     //***** Constructors
 
-    ServiceStateTracker(GSMPhone phone)
-    {
+    public GsmServiceStateTracker(GSMPhone phone) {
+        super();
+
         this.phone = phone;
         cm = phone.mCM;
         ss = new ServiceState();
@@ -265,13 +182,13 @@
                 (PowerManager)phone.getContext().getSystemService(Context.POWER_SERVICE);
         mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG);
 
-        cm.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);        
+        cm.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
         cm.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null);
 
         cm.registerForNetworkStateChanged(this, EVENT_NETWORK_STATE_CHANGED, null);
         cm.setOnNITZTime(this, EVENT_NITZ_TIME, null);
         cm.setOnSignalStrengthUpdate(this, EVENT_SIGNAL_STRENGTH_UPDATE, null);
-        cm.setOnRestrictedStateChanged(this, EVENT_RESTRICTED_STATE_CHANGED, null);       
+        cm.setOnRestrictedStateChanged(this, EVENT_RESTRICTED_STATE_CHANGED, null);
         cm.registerForSIMReady(this, EVENT_SIM_READY, null);
 
         // system setting property AIRPLANE_MODE_ON is set in Settings.
@@ -280,7 +197,7 @@
                 Settings.System.AIRPLANE_MODE_ON, 0);
         mDesiredPowerState = ! (airplaneMode > 0);
 
-        ContentResolver cr = phone.getContext().getContentResolver();
+        cr = phone.getContext().getContentResolver();
         cr.registerContentObserver(
                 Settings.System.getUriFor(Settings.System.AUTO_TIME), true,
                 mAutoTimeObserver);
@@ -288,6 +205,24 @@
         mNeedToRegForSimLoaded = true;
     }
 
+    public void dispose() {
+        //Unregister for all events
+        cm.unregisterForAvailable(this);
+        cm.unregisterForRadioStateChanged(this);
+        cm.unregisterForNetworkStateChanged(this);
+        cm.unregisterForSIMReady(this);
+
+        phone.mSIMRecords.unregisterForRecordsLoaded(this);
+        cm.unSetOnSignalStrengthUpdate(this);
+        cm.unSetOnRestrictedStateChanged(this);
+        cm.unSetOnNITZTime(this);
+        cr.unregisterContentObserver(this.mAutoTimeObserver);
+    }
+
+    protected void finalize() {
+        if(DBG) Log.d(LOG_TAG, "GsmServiceStateTracker finalized");
+    }
+
     /**
      * Registration point for transition into GPRS attached.
      * @param h handler to notify
@@ -303,7 +238,11 @@
         }
     }
 
-    void registerForNetworkAttach(Handler h, int what, Object obj) {
+    /*protected*/ void unregisterForGprsAttached(Handler h) {
+        gprsAttachedRegistrants.remove(h);
+    }
+
+    /*protected*/  void registerForNetworkAttach(Handler h, int what, Object obj) {
         Registrant r = new Registrant(h, what, obj);
         networkAttachedRegistrants.add(r);
 
@@ -311,6 +250,10 @@
             r.notifyRegistrant();
         }
     }
+
+    /*protected*/  void unregisterForNetworkAttach(Handler h) {
+        networkAttachedRegistrants.remove(h);
+    }
     /**
      * Registration point for transition into GPRS detached.
      * @param h handler to notify
@@ -326,52 +269,8 @@
         }
     }
 
-    /**
-     * Registration point for combined roaming on
-     * combined roaming is true when roaming is true and ONS differs SPN
-     *
-     * @param h handler to notify
-     * @param what what code of message when delivered
-     * @param obj placed in Message.obj
-     */
-    void registerForRoamingOn(Handler h, int what, Object obj) {
-        Registrant r = new Registrant(h, what, obj);
-        roamingOnRegistrants.add(r);
-
-        if (ss.getRoaming()) {
-            r.notifyRegistrant();
-        }
-    }
-
-    /**
-     * Registration point for combined roaming off
-     * combined roaming is true when roaming is true and ONS differs SPN
-     *
-     * @param h handler to notify
-     * @param what what code of message when delivered
-     * @param obj placed in Message.obj
-     */
-    void registerForRoamingOff(Handler h, int what, Object obj) {
-        Registrant r = new Registrant(h, what, obj);
-        roamingOffRegistrants.add(r);
-
-        if (!ss.getRoaming()) {
-            r.notifyRegistrant();
-        }
-    }
-
-    /**
-     * Reregister network through toggle perferred network type
-     * This is a work aorund to deregister and register network since there is
-     * no ril api to set COPS=2 (deregister) only.
-     *
-     * @param onComplete is dispatched when this is complete.  it will be
-     * an AsyncResult, and onComplete.obj.exception will be non-null
-     * on failure.
-     */
-    void reRegisterNetwork(Message onComplete) {
-        cm.getPreferredNetworkType(
-                obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE, onComplete));
+    /*protected*/  void unregisterForGprsDetached(Handler h) {
+        gprsDetachedRegistrants.remove(h);
     }
 
     /**
@@ -380,7 +279,7 @@
      * @param what what code of message when delivered
      * @param obj placed in Message.obj
      */
-    void registerForPsRestrictedEnabled(Handler h, int what, Object obj) {
+    /*protected*/  void registerForPsRestrictedEnabled(Handler h, int what, Object obj) {
         Log.d(LOG_TAG, "[DSAC DEB] " + "registerForPsRestrictedEnabled "); 
         Registrant r = new Registrant(h, what, obj);
         psRestrictEnabledRegistrants.add(r);
@@ -389,14 +288,18 @@
             r.notifyRegistrant();
         }
     }
-    
+
+    /*protected*/  void unregisterForPsRestrictedEnabled(Handler h) {
+        psRestrictEnabledRegistrants.remove(h);
+    }
+
     /**
      * Registration point for transition out of packet service restricted zone.
      * @param h handler to notify
      * @param what what code of message when delivered
      * @param obj placed in Message.obj
      */
-    void registerForPsRestrictedDisabled(Handler h, int what, Object obj) {
+    /*protected*/  void registerForPsRestrictedDisabled(Handler h, int what, Object obj) {
         Log.d(LOG_TAG, "[DSAC DEB] " + "registerForPsRestrictedDisabled "); 
         Registrant r = new Registrant(h, what, obj);
         psRestrictDisabledRegistrants.add(r);
@@ -406,34 +309,21 @@
         }
     }
     
-    //***** Called from GSMPhone
-
-    public void
-    setRadioPower(boolean power)
-    {
-        mDesiredPowerState = power;
-
-        setPowerStateToDesired();
+    /*protected*/  void unregisterForPsRestrictedDisabled(Handler h) {
+        psRestrictDisabledRegistrants.remove(h);
     }
 
+    //***** Called from GSMPhone
     public void
     getLacAndCid(Message onComplete) {
         cm.getRegistrationState(obtainMessage(
                         EVENT_GET_LOC_DONE, onComplete));
     }
 
-    /*package*/ void enableLocationUpdates() {
-        cm.setLocationUpdates(true, obtainMessage(EVENT_LOCATION_UPDATES_ENABLED));
-    }
 
-    /*package*/ void disableLocationUpdates() {
-        cm.setLocationUpdates(false, null);
-    }
-    //***** Overridden from Handler
-
+    //***** Overridden from ServiceStateTracker
     public void
-    handleMessage (Message msg)
-    {
+    handleMessage (Message msg) {
         AsyncResult ar;
         int[] ints;
         String[] strings;
@@ -476,8 +366,8 @@
                 // This callback is called when signal strength is polled
                 // all by itself
 
-                if (!(cm.getRadioState().isOn())) {
-                    // Polling will continue when radio turns back on
+                if (!(cm.getRadioState().isOn()) || (cm.getRadioState().isCdma())) {
+                    // Polling will continue when radio turns back on and not CDMA
                     return;
                 }
                 ar = (AsyncResult) msg.obj;
@@ -591,13 +481,11 @@
                 if (ar.exception == null) {
                     mPreferredNetworkType = ((int[])ar.result)[0];
                 } else {
-                    mPreferredNetworkType = Phone.NT_AUTO_TYPE;
+                    mPreferredNetworkType = RILConstants.NETWORK_MODE_GLOBAL;
                 }
 
                 message = obtainMessage(EVENT_SET_PREFERRED_NETWORK_TYPE, ar.userObj);
-                int toggledNetworkType =
-                        (mPreferredNetworkType == Phone.NT_AUTO_TYPE) ?
-                        Phone.NT_GSM_TYPE : Phone.NT_AUTO_TYPE;
+                int toggledNetworkType = RILConstants.NETWORK_MODE_GLOBAL;
 
                 cm.setPreferredNetworkType(toggledNetworkType, message);
                 break;
@@ -630,12 +518,47 @@
                 onRestrictedStateChanged(ar);
                 break;
 
+            default:
+                Log.e(LOG_TAG, "Unhandled message with number: " + msg.what);
+            break;
         }
     }
 
     //***** Private Instance Methods
 
-    private void updateSpnDisplay() {
+    protected void setPowerStateToDesired()
+    {
+        // If we want it on and it's off, turn it on
+        if (mDesiredPowerState
+            && cm.getRadioState() == CommandsInterface.RadioState.RADIO_OFF) {
+            cm.setRadioPower(true, null);
+        } else if (!mDesiredPowerState && cm.getRadioState().isOn()) {
+            DataConnectionTracker dcTracker = phone.mDataConnection;
+            if (! dcTracker.isDataConnectionAsDesired()) {
+
+                EventLog.List val = new EventLog.List(
+                        dcTracker.getStateInString(),
+                        (dcTracker.getAnyDataEnabled() ? 1 : 0) );
+                EventLog.writeEvent(TelephonyEventLog.EVENT_DATA_STATE_RADIO_OFF, val);
+            }
+            dcTracker.cleanConnectionBeforeRadioOff();
+            
+            // poll data state up to 15 times, with a 100ms delay
+            // totaling 1.5 sec. Normal data disable action will finish in 100ms.
+            for (int i = 0; i < MAX_NUM_DATA_STATE_READS; i++) {
+                if (dcTracker.getState() != DataConnectionTracker.State.CONNECTED 
+                        && dcTracker.getState() != DataConnectionTracker.State.DISCONNECTING) {
+                    Log.d(LOG_TAG, "Data shutdown complete.");
+                    break;
+                }
+                SystemClock.sleep(DATA_STATE_POLL_SLEEP_MS);
+            }
+            // If it's on and available and we want it off..
+            cm.setRadioPower(false, null);
+        } // Otherwise, we're in the desired state
+    }
+    
+    protected void updateSpnDisplay() {
         int rule = phone.mSIMRecords.getDisplayRule(ss.getOperatorNumeric());
         String spn = phone.mSIMRecords.getServiceProviderName();
         String plmn = ss.getOperatorAlphaLong();
@@ -659,55 +582,12 @@
         curPlmn = plmn;
     }
 
-    private void
-    setPowerStateToDesired()
-    {
-        // If we want it on and it's off, turn it on
-        if (mDesiredPowerState
-            && cm.getRadioState() == CommandsInterface.RadioState.RADIO_OFF
-        ) {
-            cm.setRadioPower(true, null);
-        } else if (!mDesiredPowerState && cm.getRadioState().isOn()) {
-            DataConnectionTracker dcTracker = phone.mDataConnection;
-            if (! dcTracker.isDataConnectionAsDesired()) {
-
-                EventLog.List val = new EventLog.List(
-                        dcTracker.getStateInString(),
-                        (dcTracker.getAnyDataEnabled() ? 1 : 0) );
-                EventLog.writeEvent(TelephonyEventLog.EVENT_DATA_STATE_RADIO_OFF, val);
-            }
-            dcTracker.cleanConnectionBeforeRadioOff();
-            
-            // poll data state up to 15 times, with a 100ms delay
-            // totaling 1.5 sec. Normal data disable action will finish in 100ms.
-            for (int i = 0; i < MAX_NUM_DATA_STATE_READS; i++) {
-                if (dcTracker.state != State.CONNECTED 
-                        && dcTracker.state != State.DISCONNECTING) {
-                    Log.d(LOG_TAG, "Data shutdown complete.");
-                    break;
-                }
-                SystemClock.sleep(DATA_STATE_POLL_SLEEP_MS);
-            }
-            // If it's on and available and we want it off..
-            cm.setRadioPower(false, null);
-        } // Otherwise, we're in the desired state
-    }
-
-    /** Cancel a pending (if any) pollState() operation */
-    private void
-    cancelPollState()
-    {
-        // This will effectively cancel the rest of the poll requests
-        pollingContext = new int[1];
-    }
-
     /**
      * Handle the result of one of the pollState()-related requests
      */
 
-    private void
-    handlePollStateResult (int what, AsyncResult ar)
-    {
+    protected void
+    handlePollStateResult (int what, AsyncResult ar) {
         int ints[];
         String states[];
 
@@ -820,8 +700,7 @@
     }
 
     private void
-    setRssiDefaultValues()
-    {
+    setRssiDefaultValues() {
         rssi = 99;
     }
 
@@ -835,8 +714,7 @@
      */
 
     private void
-    pollState()
-    {
+    pollState() {
         pollingContext = new int[1];
         pollingContext[0] = 0;
 
@@ -850,7 +728,6 @@
                 pollStateDone();
             break;
 
-
             case RADIO_OFF:
                 newSS.setStateOff();
                 newCellLoc.setStateInvalid();
@@ -860,6 +737,20 @@
                 pollStateDone();
             break;
 
+            case RUIM_NOT_READY:
+            case RUIM_READY:
+            case RUIM_LOCKED_OR_ABSENT:
+            case NV_NOT_READY:
+            case NV_READY:
+                Log.d(LOG_TAG, "Radio Technology Change ongoing, setting SS to off");
+                newSS.setStateOff();
+                newCellLoc.setStateInvalid();
+                setRssiDefaultValues();
+                mGotCountryCode = false;
+
+                pollStateDone();
+                break;
+
             default:
                 // Issue all poll-related commands at once
                 // then count down the responses, which
@@ -889,6 +780,7 @@
     }
 
     private static String networkTypeToString(int type) {
+        //Network Type from GPRS_REGISTRATION_STATE
         String ret = "unknown";
 
         switch (type) {
@@ -901,14 +793,16 @@
             case DATA_ACCESS_UMTS:
                 ret = "UMTS";
                 break;
+            default:
+                Log.e(LOG_TAG, "Wrong network type: " + Integer.toString(type));
+                break;
         }
 
         return ret;
     }
 
     private void
-    pollStateDone()
-    {
+    pollStateDone() {
         if (DBG) {
             Log.d(LOG_TAG, "Poll ServiceState done: " +
                 " oldSS=[" + ss + "] newSS=[" + newSS +
@@ -1131,9 +1025,8 @@
     }
 
     private void
-    queueNextSignalStrengthPoll()
-    {
-        if (dontPollSignalStrength) {
+    queueNextSignalStrengthPoll() {
+        if (dontPollSignalStrength || (cm.getRadioState().isCdma())) {
             // The radio is telling us about signal strength changes
             // we don't have to ask it
             return;
@@ -1155,8 +1048,7 @@
      *  Called both for solicited and unsolicited signal stength updates
      */
     private void
-    onSignalStrengthResult(AsyncResult ar)
-    {
+    onSignalStrengthResult(AsyncResult ar) {
         int oldRSSI = rssi;
 
         if (ar.exception != null) {
@@ -1176,15 +1068,21 @@
         }
 
         if (rssi != oldRSSI) {
-            phone.notifySignalStrength();
+            try { // This takes care of delayed EVENT_POLL_SIGNAL_STRENGTH (scheduled after
+                  // POLL_PERIOD_MILLIS) during Radio Technology Change)
+                phone.notifySignalStrength();
+           } catch (NullPointerException ex) {
+                Log.d(LOG_TAG, "onSignalStrengthResult() Phone already destroyed: " + ex 
+                        + "Signal Stranth not notified");
+           }
         }
     }
-    
+
     /**
      * Set restricted state based on the OnRestrictedStateChanged notification
      * If any voice or packet restricted state changes, trigger a UI
      * notification and notify registrants when sim is ready.
-     * 
+     *
      * @param ar an int value of RIL_RESTRICTED_STATE_*
      */
     private void onRestrictedStateChanged(AsyncResult ar)
@@ -1201,10 +1099,8 @@
             newRs.setCsEmergencyRestricted(
                     ((state & RILConstants.RIL_RESTRICTED_STATE_CS_EMERGENCY) != 0) ||
                     ((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) );
-            
-
             //ignore the normal call and data restricted state before SIM READY
-            if (phone.getSimCard().getState() == SimCard.State.READY){ 
+            if (phone.getIccCard().getState() == IccCard.State.READY) { 
                 newRs.setCsNormalRestricted(
                         ((state & RILConstants.RIL_RESTRICTED_STATE_CS_NORMAL) != 0) ||
                         ((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) );
@@ -1272,7 +1168,7 @@
                     setNotification(CS_NORMAL_ENABLED); 
                 }
             }
-            
+
             rs = newRs;
         }
         Log.d(LOG_TAG, "[DSAC DEB] " + "current rs at return "+ rs);
@@ -1280,8 +1176,7 @@
 
     /** code is registration state 0-5 from TS 27.007 7.2 */
     private int
-    regCodeToServiceState(int code)
-    {
+    regCodeToServiceState(int code) {
         switch (code) {
             case 0:
             case 2: // 2 is "searching"
@@ -1308,8 +1203,7 @@
      * returns true if registered roam, false otherwise
      */
     private boolean
-    regCodeIsRoaming (int code)
-    {
+    regCodeIsRoaming (int code) {
         // 5 is  "in service -- roam"
         return 5 == code;
     }
@@ -1323,7 +1217,7 @@
      */
     private
     boolean isRoamingBetweenOperators(boolean gsmRoaming, ServiceState s) {
-        String spn = SystemProperties.get(PROPERTY_SIM_OPERATOR_ALPHA, "empty");
+        String spn = SystemProperties.get(PROPERTY_ICC_OPERATOR_ALPHA, "empty");
 
         String onsl = s.getOperatorAlphaLong();
         String onss = s.getOperatorAlphaShort();
@@ -1331,7 +1225,7 @@
         boolean equalsOnsl = onsl != null && spn.equals(onsl);
         boolean equalsOnss = onss != null && spn.equals(onss);
 
-        String simNumeric = SystemProperties.get(PROPERTY_SIM_OPERATOR_NUMERIC, "");
+        String simNumeric = SystemProperties.get(PROPERTY_ICC_OPERATOR_NUMERIC, "");
         String  operatorNumeric = s.getOperatorNumeric();
 
         boolean equalsMcc = true;
@@ -1345,8 +1239,7 @@
     }
 
     private static
-    int twoDigitsAt(String s, int offset)
-    {
+    int twoDigitsAt(String s, int offset) {
         int a, b;
 
         a = Character.digit(s.charAt(offset), 10);
@@ -1631,7 +1524,7 @@
                     + (SystemClock.elapsedRealtime() - mSavedAtTime));
         }
     }
-    
+
     /**
      * Post a notification to NotificationManager for restricted state
      * 
@@ -1640,7 +1533,6 @@
     private void setNotification(int notifyType) {
 
         Log.d(LOG_TAG, "[DSAC DEB] " + "create notification " + notifyType);
-        
         Context context = phone.getContext();
 
         mNotification = new Notification();
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java b/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java
new file mode 100644
index 0000000..c163803
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmSmsAddress.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony.gsm;
+
+import android.telephony.PhoneNumberUtils;
+
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.SmsAddress;
+
+public class GsmSmsAddress extends SmsAddress {
+
+    static final int OFFSET_ADDRESS_LENGTH = 0;
+
+    static final int OFFSET_TOA = 1;
+
+    static final int OFFSET_ADDRESS_VALUE = 2;
+
+    /**
+     * New GsmSmsAddress from TS 23.040 9.1.2.5 Address Field
+     *
+     * @param offset the offset of the Address-Length byte
+     * @param length the length in bytes rounded up, e.g. "2 +
+     *        (addressLength + 1) / 2"
+     */
+
+    public GsmSmsAddress(byte[] data, int offset, int length) {
+        origBytes = new byte[length];
+        System.arraycopy(data, offset, origBytes, 0, length);
+
+        // addressLength is the count of semi-octets, not bytes
+        int addressLength = origBytes[OFFSET_ADDRESS_LENGTH] & 0xff;
+
+        int toa = origBytes[OFFSET_TOA] & 0xff;
+        ton = 0x7 & (toa >> 4);
+
+        // TOA must have its high bit set
+        if ((toa & 0x80) != 0x80) {
+            throw new RuntimeException("Invalid TOA - high bit must be set");
+        }
+
+        if (isAlphanumeric()) {
+            // An alphanumeric address
+            int countSeptets = addressLength * 4 / 7;
+
+            address = GsmAlphabet.gsm7BitPackedToString(origBytes,
+                    OFFSET_ADDRESS_VALUE, countSeptets);
+        } else {
+            // TS 23.040 9.1.2.5 says
+            // that "the MS shall interpret reserved values as 'Unknown'
+            // but shall store them exactly as received"
+
+            byte lastByte = origBytes[length - 1];
+
+            if ((addressLength & 1) == 1) {
+                // Make sure the final unused BCD digit is 0xf
+                origBytes[length - 1] |= 0xf0;
+            }
+            address = PhoneNumberUtils.calledPartyBCDToString(origBytes,
+                    OFFSET_TOA, length - OFFSET_TOA);
+
+            // And restore origBytes
+            origBytes[length - 1] = lastByte;
+        }
+    }
+
+    public String getAddressString() {
+        return address;
+    }
+
+    /**
+     * Returns true if this is an alphanumeric address
+     */
+    public boolean isAlphanumeric() {
+        return ton == TON_ALPHANUMERIC;
+    }
+
+    public boolean isNetworkSpecific() {
+        return ton == TON_NETWORK;
+    }
+
+    /**
+     * Returns true of this is a valid CPHS voice message waiting indicator
+     * address
+     */
+    public boolean isCphsVoiceMessageIndicatorAddress() {
+        // CPHS-style MWI message
+        // See CPHS 4.7 B.4.2.1
+        //
+        // Basically:
+        //
+        // - Originating address should be 4 bytes long and alphanumeric
+        // - Decode will result with two chars:
+        // - Char 1
+        // 76543210
+        // ^ set/clear indicator (0 = clear)
+        // ^^^ type of indicator (000 = voice)
+        // ^^^^ must be equal to 0001
+        // - Char 2:
+        // 76543210
+        // ^ line number (0 = line 1)
+        // ^^^^^^^ set to 0
+        //
+        // Remember, since the alpha address is stored in 7-bit compact form,
+        // the "line number" is really the top bit of the first address value
+        // byte
+
+        return (origBytes[OFFSET_ADDRESS_LENGTH] & 0xff) == 4
+                && isAlphanumeric() && (origBytes[OFFSET_TOA] & 0x0f) == 0;
+    }
+
+    /**
+     * Returns true if this is a valid CPHS voice message waiting indicator
+     * address indicating a "set" of "indicator 1" of type "voice message
+     * waiting"
+     */
+    public boolean isCphsVoiceMessageSet() {
+        // 0x11 means "set" "voice message waiting" "indicator 1"
+        return isCphsVoiceMessageIndicatorAddress()
+                && (origBytes[OFFSET_ADDRESS_VALUE] & 0xff) == 0x11;
+
+    }
+
+    /**
+     * Returns true if this is a valid CPHS voice message waiting indicator
+     * address indicating a "clear" of "indicator 1" of type "voice message
+     * waiting"
+     */
+    public boolean isCphsVoiceMessageClear() {
+        // 0x10 means "clear" "voice message waiting" "indicator 1"
+        return isCphsVoiceMessageIndicatorAddress()
+                && (origBytes[OFFSET_ADDRESS_VALUE] & 0xff) == 0x10;
+
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/MccTable.java b/telephony/java/com/android/internal/telephony/gsm/MccTable.java
index bb17cc4..8473a21 100644
--- a/telephony/java/com/android/internal/telephony/gsm/MccTable.java
+++ b/telephony/java/com/android/internal/telephony/gsm/MccTable.java
@@ -62,11 +62,11 @@
     entryForMcc(int mcc)
     {
         int index;
-        
+
         MccEntry m;
 
         m = new MccEntry(mcc, null, 0);
-        
+
         index = Collections.binarySearch(table, m);
 
         if (index < 0) {
@@ -154,7 +154,7 @@
 
         /*
          * The table below is built from two resources:
-         * 
+         *
          * 1) ITU "Mobile Network Code (MNC) for the international
          *   identification plan for mobile terminals and mobile users"
          *   which is available as an annex to the ITU operational bulletin
diff --git a/telephony/java/com/android/internal/telephony/gsm/NetworkInfo.aidl b/telephony/java/com/android/internal/telephony/gsm/NetworkInfo.aidl
index c600530..d88d0b7 100644
--- a/telephony/java/com/android/internal/telephony/gsm/NetworkInfo.aidl
+++ b/telephony/java/com/android/internal/telephony/gsm/NetworkInfo.aidl
@@ -16,11 +16,11 @@
 
 package com.android.internal.telephony.gsm;
 
-/** 
+/**
  * Used to indicate that the NetworkInfo object is parcelable to aidl.
  * This is a simple effort to make NetworkInfo parcelable rather than
  * trying to make the conventional containing object (AsyncResult),
- * implement parcelable.  This functionality is needed for the 
+ * implement parcelable.  This functionality is needed for the
  * NetworkQueryService to fix 1128695
  */
 parcelable NetworkInfo;
diff --git a/telephony/java/com/android/internal/telephony/gsm/NetworkInfo.java b/telephony/java/com/android/internal/telephony/gsm/NetworkInfo.java
index bebf9ba..04fd13e 100644
--- a/telephony/java/com/android/internal/telephony/gsm/NetworkInfo.java
+++ b/telephony/java/com/android/internal/telephony/gsm/NetworkInfo.java
@@ -22,8 +22,7 @@
 /**
  * {@hide}
  */
-public class NetworkInfo implements Parcelable
-{
+public class NetworkInfo implements Parcelable {
     public enum State {
         UNKNOWN,
         AVAILABLE,
@@ -39,34 +38,29 @@
 
 
     public String
-    getOperatorAlphaLong()
-    {
+    getOperatorAlphaLong() {
         return operatorAlphaLong;
     }
 
     public String
-    getOperatorAlphaShort()
-    {
+    getOperatorAlphaShort() {
         return operatorAlphaShort;
     }
 
     public String
-    getOperatorNumeric()
-    {
+    getOperatorNumeric() {
         return operatorNumeric;
     }
 
     public State
-    getState()
-    {
+    getState() {
         return state;
     }
 
-    NetworkInfo(String operatorAlphaLong, 
-                String operatorAlphaShort, 
-                String operatorNumeric, 
-                State state)
-    {
+    NetworkInfo(String operatorAlphaLong,
+                String operatorAlphaShort,
+                String operatorNumeric,
+                State state) {
 
         this.operatorAlphaLong = operatorAlphaLong;
         this.operatorAlphaShort = operatorAlphaShort;
@@ -76,20 +70,18 @@
     }
 
 
-    NetworkInfo(String operatorAlphaLong, 
-                String operatorAlphaShort, 
-                String operatorNumeric, 
-                String stateString)
-    {
-        this (operatorAlphaLong, operatorAlphaShort, 
+    public NetworkInfo(String operatorAlphaLong,
+                String operatorAlphaShort,
+                String operatorNumeric,
+                String stateString) {
+        this (operatorAlphaLong, operatorAlphaShort,
                 operatorNumeric, rilStateToState(stateString));
     }
 
     /**
      * See state strings defined in ril.h RIL_REQUEST_QUERY_AVAILABLE_NETWORKS
      */
-    private static State rilStateToState(String s)
-    {
+    private static State rilStateToState(String s) {
         if (s.equals("unknown")) {
             return State.UNKNOWN;
         } else if (s.equals("available")) {
@@ -105,29 +97,28 @@
     }
 
 
-    public String toString()
-    {
-        return "NetworkInfo " + operatorAlphaLong 
-                + "/" + operatorAlphaShort 
-                + "/" + operatorNumeric 
+    public String toString() {
+        return "NetworkInfo " + operatorAlphaLong
+                + "/" + operatorAlphaShort
+                + "/" + operatorNumeric
                 + "/" + state;
     }
-    
-    /** 
+
+    /**
      * Parcelable interface implemented below.
      * This is a simple effort to make NetworkInfo parcelable rather than
      * trying to make the conventional containing object (AsyncResult),
-     * implement parcelable.  This functionality is needed for the 
+     * implement parcelable.  This functionality is needed for the
      * NetworkQueryService to fix 1128695.
      */
-    
+
     public int describeContents() {
         return 0;
     }
 
-    /** 
+    /**
      * Implement the Parcelable interface.
-     * Method to serialize a NetworkInfo object. 
+     * Method to serialize a NetworkInfo object.
      */
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeString(operatorAlphaLong);
@@ -136,9 +127,9 @@
         dest.writeSerializable(state);
     }
 
-    /** 
+    /**
      * Implement the Parcelable interface
-     * Method to deserialize a NetworkInfo object, or an array thereof. 
+     * Method to deserialize a NetworkInfo object, or an array thereof.
      */
     public static final Creator<NetworkInfo> CREATOR =
         new Creator<NetworkInfo>() {
diff --git a/telephony/java/com/android/internal/telephony/gsm/PDPContextState.java b/telephony/java/com/android/internal/telephony/gsm/PDPContextState.java
index d5d481a..feb78f8 100644
--- a/telephony/java/com/android/internal/telephony/gsm/PDPContextState.java
+++ b/telephony/java/com/android/internal/telephony/gsm/PDPContextState.java
@@ -19,8 +19,7 @@
 /**
  * {@hide}
  */
-public class PDPContextState
-{
+public class PDPContextState {
     public int cid;
     public boolean active;
     public String type;
diff --git a/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java b/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java
index 66f8b72..88acb1b 100644
--- a/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java
@@ -17,88 +17,26 @@
 package com.android.internal.telephony.gsm;
 
 import android.os.*;
-import android.database.Cursor;
-import android.provider.Telephony;
 import android.text.util.Regex;
 import android.util.EventLog;
 import android.util.Log;
 
-import java.util.ArrayList;
+import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.DataConnection;
+import com.android.internal.telephony.DataLink;
 import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.TelephonyEventLog;
 
 /**
  * {@hide}
  */
-public class PdpConnection extends Handler {
+public class PdpConnection extends DataConnection {
 
     private static final String LOG_TAG = "GSM";
     private static final boolean DBG  = true;
     private static final boolean FAKE_FAIL = false;
 
-    public enum PdpState {
-        ACTIVE,     /* has active pdp context */
-        ACTIVATING, /* during connecting process */
-        INACTIVE;    /* has empty pdp context */
-
-        public String toString() {
-            switch (this) {
-                case ACTIVE: return "active";
-                case ACTIVATING: return "setting up";
-                default: return "inactive";
-            }
-        }
-
-        public boolean isActive() {
-            return this == ACTIVE;
-        }
-
-        public boolean isInactive() {
-            return this == INACTIVE;
-        }
-    }
-
-    public enum PdpFailCause {
-        NONE,
-        BAD_APN,
-        BAD_PAP_SECRET,
-        BARRED,
-        USER_AUTHENTICATION,
-        SERVICE_OPTION_NOT_SUPPORTED,
-        SERVICE_OPTION_NOT_SUBSCRIBED,
-        SIM_LOCKED,
-        RADIO_OFF,
-        NO_SIGNAL,
-        NO_DATA_PLAN,
-        RADIO_NOT_AVIALABLE,
-        SUSPENED_TEMPORARY,
-        RADIO_ERROR_RETRY,
-        UNKNOWN;
-
-        public boolean isPermanentFail() {
-            return (this == RADIO_OFF);
-        }
-
-        public String toString() {
-            switch (this) {
-                case NONE: return "no error";
-                case BAD_APN: return "bad apn";
-                case BAD_PAP_SECRET:return "bad pap secret";
-                case BARRED: return "barred";
-                case USER_AUTHENTICATION: return "error user autentication";
-                case SERVICE_OPTION_NOT_SUPPORTED: return "data not supported";
-                case SERVICE_OPTION_NOT_SUBSCRIBED: return "datt not subcribed";
-                case SIM_LOCKED: return "sim locked";
-                case RADIO_OFF: return "radio is off";
-                case NO_SIGNAL: return "no signal";
-                case NO_DATA_PLAN: return "no data plan";
-                case RADIO_NOT_AVIALABLE: return "radio not available";
-                case SUSPENED_TEMPORARY: return "suspend temporary";
-                case RADIO_ERROR_RETRY: return "transient radio error";
-                default: return "unknown data error";
-            }
-        }
-    }
-
     /** Fail cause of last PDP activate, from RIL_LastPDPActivateFailCause */
     private static final int PDP_FAIL_RIL_BARRED = 8;
     private static final int PDP_FAIL_RIL_BAD_APN = 27;
@@ -107,54 +45,20 @@
     private static final int PDP_FAIL_RIL_SERVICE_OPTION_NOT_SUBSCRIBED = 33;
     private static final int PDP_FAIL_RIL_ERROR_UNSPECIFIED = 0xffff;
 
-    //***** Event codes
-    private static final int EVENT_SETUP_PDP_DONE = 1;
-    private static final int EVENT_GET_LAST_FAIL_DONE = 2;
-    private static final int EVENT_LINK_STATE_CHANGED = 3;
-    private static final int EVENT_DEACTIVATE_DONE = 4;
-    private static final int EVENT_FORCE_RETRY = 5;
-
     //***** Instance Variables
-    private GSMPhone phone;
     private String pdp_name;
-    private PdpState state;
-    private Message onConnectCompleted;
-    private Message onDisconnect;
-    private int cid;
-    private long createTime;
-    private long lastFailTime;
-    private PdpFailCause lastFailCause;
     private ApnSetting apn;
-    private String interfaceName;
-    private String ipAddress;
-    private String gatewayAddress;
-    private String[] dnsServers;
-
-    private static final String NULL_IP = "0.0.0.0";
 
     // dataLink is only used to support pppd link
-    DataLink dataLink;
-    // receivedDisconnectReq is set when disconnect pdp link during activating
-    private boolean receivedDisconnectReq;
+    private DataLink dataLink;
 
     //***** Constructor
-    PdpConnection(GSMPhone phone)
-    {
-        this.phone = phone;
-        this.state = PdpState.INACTIVE;
-        onConnectCompleted = null;
-        onDisconnect = null;
-        this.cid = -1;
-        this.createTime = -1;
-        this.lastFailTime = -1;
-        this.lastFailCause = PdpFailCause.NONE;
-        this.apn = null;
+    PdpConnection(GSMPhone phone) {
+        super(phone);
         this.dataLink = null;
-        receivedDisconnectReq = false;
-        this.dnsServers = new String[2];
 
         if (SystemProperties.get("ro.radio.use-ppp","no").equals("yes")) {
-            dataLink = new PppLink(phone.mDataConnection);
+            dataLink = new PppLink((GsmDataConnectionTracker) phone.mDataConnection, phone);
             dataLink.setOnLinkChange(this, EVENT_LINK_STATE_CHANGED, null);
         }
     }
@@ -171,37 +75,37 @@
 
         setHttpProxy (apn.proxy, apn.port);
 
-        state = PdpState.ACTIVATING;
+        state = State.ACTIVATING;
         this.apn = apn;
         onConnectCompleted = onCompleted;
         createTime = -1;
         lastFailTime = -1;
-        lastFailCause = PdpFailCause.NONE;
+        lastFailCause = FailCause.NONE;
         receivedDisconnectReq = false;
 
         if (FAKE_FAIL) {
             // for debug before baseband implement error in setup PDP
             if (apn.apn.equalsIgnoreCase("badapn")){
-                notifyFail(PdpFailCause.BAD_APN, onConnectCompleted);
+                notifyFail(FailCause.BAD_APN, onConnectCompleted);
                 return;
             }
         }
 
-        phone.mCM.setupDefaultPDP(apn.apn, apn.user, apn.password,
-                obtainMessage(EVENT_SETUP_PDP_DONE));
+        phone.mCM.setupDataCall(Integer.toString(RILConstants.GSM_PHONE), null, apn.apn, apn.user,
+                apn.password, obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE));
     }
 
-    void disconnect(Message msg) {
+    protected void disconnect(Message msg) {
         onDisconnect = msg;
-        if (state == PdpState.ACTIVE) {
+        if (state == State.ACTIVE) {
             if (dataLink != null) {
                 dataLink.disconnect();
             }
 
             if (phone.mCM.getRadioState().isOn()) {
-                phone.mCM.deactivateDefaultPDP(cid, obtainMessage(EVENT_DEACTIVATE_DONE, msg));
+                phone.mCM.deactivateDataCall(cid, obtainMessage(EVENT_DEACTIVATE_DONE, msg));
             }
-        } else if (state == PdpState.ACTIVATING) {
+        } else if (state == State.ACTIVATING) {
             receivedDisconnectReq = true;
         } else {
             // state == INACTIVE.  Nothing to do, so notify immediately.
@@ -209,20 +113,9 @@
         }
     }
 
-    private void
-    setHttpProxy(String httpProxy, String httpPort)
-    {
-        if (httpProxy == null || httpProxy.length() == 0) {
-            phone.setSystemProperty("net.gprs.http-proxy", null);
-            return;
-        }
-
-        if (httpPort == null || httpPort.length() == 0) {
-            httpPort = "8080";     // Default to port 8080
-        }
-
-        phone.setSystemProperty("net.gprs.http-proxy",
-                "http://" + httpProxy + ":" + httpPort + "/");
+    public void clearSettings() {
+        super.clearSettings();
+        apn = null;
     }
 
     public String toString() {
@@ -231,61 +124,30 @@
                " lastFailCause=" + lastFailCause;
     }
 
-    public long getConnectionTime() {
-        return createTime;
-    }
 
-    public long getLastFailTime() {
-        return lastFailTime;
-    }
-
-    public PdpFailCause getLastFailCause() {
-        return lastFailCause;
-    }
-
-    public ApnSetting getApn() {
-        return apn;
-    }
-
-    String getInterface() {
-        return interfaceName;
-    }
-
-    String getIpAddress() {
-        return ipAddress;
-    }
-
-    String getGatewayAddress() {
-        return gatewayAddress;
-    }
-
-    String[] getDnsServers() {
-        return dnsServers;
-    }
-
-    public PdpState getState() {
-        return state;
-    }
-
-    private void notifyFail(PdpFailCause cause, Message onCompleted) {
+    protected void notifyFail(FailCause cause, Message onCompleted) {
         if (onCompleted == null) return;
 
-        state = PdpState.INACTIVE;
+        state = State.INACTIVE;
         lastFailCause = cause;
         lastFailTime = System.currentTimeMillis();
         onConnectCompleted = null;
 
-        if (DBG) log("Notify PDP fail at " + lastFailTime
-                + " due to " + lastFailCause);
+        if (DBG) {
+            log("Notify PDP fail at " + lastFailTime +
+                    " due to " + lastFailCause);
+        }
 
         AsyncResult.forMessage(onCompleted, cause, new Exception());
         onCompleted.sendToTarget();
     }
 
-    private void notifySuccess(Message onCompleted) {
-        if (onCompleted == null) return;
+    protected void notifySuccess(Message onCompleted) {
+        if (onCompleted == null) {
+            return;
+        }
 
-        state = PdpState.ACTIVE;
+        state = State.ACTIVE;
         createTime = System.currentTimeMillis();
         onConnectCompleted = null;
         onCompleted.arg1 = cid;
@@ -296,7 +158,7 @@
         onCompleted.sendToTarget();
     }
 
-    private void notifyDisconnect(Message msg) {
+    protected void notifyDisconnect(Message msg) {
         if (DBG) log("Notify PDP disconnect");
 
         if (msg != null) {
@@ -306,22 +168,7 @@
         clearSettings();
     }
 
-    void clearSettings() {
-        state = PdpState.INACTIVE;
-        receivedDisconnectReq = false;
-        createTime = -1;
-        lastFailTime = -1;
-        lastFailCause = PdpFailCause.NONE;
-        apn = null;
-        onConnectCompleted = null;
-        interfaceName = null;
-        ipAddress = null;
-        gatewayAddress = null;
-        dnsServers[0] = null;
-        dnsServers[1] = null;
-    }
-
-    private void onLinkStateChanged(DataLink.LinkState linkState) {
+    protected void onLinkStateChanged(DataLink.LinkState linkState) {
         switch (linkState) {
             case LINK_UP:
                 notifySuccess(onConnectCompleted);
@@ -335,151 +182,110 @@
         }
     }
 
-    private PdpFailCause getFailCauseFromRequest(int rilCause) {
-        PdpFailCause cause;
+    protected FailCause getFailCauseFromRequest(int rilCause) {
+        FailCause cause;
 
         switch (rilCause) {
             case PDP_FAIL_RIL_BARRED:
-                cause = PdpFailCause.BARRED;
+                cause = FailCause.BARRED;
                 break;
             case PDP_FAIL_RIL_BAD_APN:
-                cause = PdpFailCause.BAD_APN;
+                cause = FailCause.BAD_APN;
                 break;
             case PDP_FAIL_RIL_USER_AUTHENTICATION:
-                cause = PdpFailCause.USER_AUTHENTICATION;
+                cause = FailCause.USER_AUTHENTICATION;
                 break;
             case PDP_FAIL_RIL_SERVICE_OPTION_NOT_SUPPORTED:
-                cause = PdpFailCause.SERVICE_OPTION_NOT_SUPPORTED;
+                cause = FailCause.SERVICE_OPTION_NOT_SUPPORTED;
                 break;
             case PDP_FAIL_RIL_SERVICE_OPTION_NOT_SUBSCRIBED:
-                cause = PdpFailCause.SERVICE_OPTION_NOT_SUBSCRIBED;
+                cause = FailCause.SERVICE_OPTION_NOT_SUBSCRIBED;
                 break;
             default:
-                cause = PdpFailCause.UNKNOWN;
+                cause = FailCause.UNKNOWN;
         }
         return cause;
     }
 
-
-    private void log(String s) {
+    protected void log(String s) {
         Log.d(LOG_TAG, "[PdpConnection] " + s);
     }
 
     @Override
-    public void handleMessage(Message msg) {
-        AsyncResult ar;
+    protected void onDeactivated(AsyncResult ar) {
+        notifyDisconnect((Message) ar.userObj);
+        if (DBG) log("PDP Connection Deactivated");
+    }
 
-        switch (msg.what) {
-            case EVENT_SETUP_PDP_DONE:
-                ar = (AsyncResult) msg.obj;
+    @Override
+    protected void onSetupConnectionCompleted(AsyncResult ar) {
+        if (ar.exception != null) {
+            Log.e(LOG_TAG, "PDP Context Init failed " + ar.exception);
 
-                if (ar.exception != null) {
-                    Log.e(LOG_TAG, "PDP Context Init failed " + ar.exception);
+            if (receivedDisconnectReq) {
+                // Don't bother reporting the error if there's already a
+                // pending disconnect request, since DataConnectionTracker
+                // has already updated its state.
+                notifyDisconnect(onDisconnect);
+            } else {
+                if ( ar.exception instanceof CommandException &&
+                        ((CommandException) (ar.exception)).getCommandError()
+                        == CommandException.Error.RADIO_NOT_AVAILABLE) {
+                    notifyFail(FailCause.RADIO_NOT_AVAILABLE,
+                            onConnectCompleted);
+                } else {
+                    phone.mCM.getLastPdpFailCause(
+                            obtainMessage(EVENT_GET_LAST_FAIL_DONE));
+                }
+            }
+        } else {
+            if (receivedDisconnectReq) {
+                // Don't bother reporting success if there's already a
+                // pending disconnect request, since DataConnectionTracker
+                // has already updated its state.
+                disconnect(onDisconnect);
+            } else {
+                String[] response = ((String[]) ar.result);
+                cid = Integer.parseInt(response[0]);
 
-                    if (receivedDisconnectReq) {
-                        // Don't bother reporting the error if there's already a
-                        // pending disconnect request, since DataConnectionTracker
-                        // has already updated its state.
-                        notifyDisconnect(onDisconnect);
-                    } else {
-                        if ( ar.exception instanceof CommandException &&
-                                ((CommandException) (ar.exception)).getCommandError()
-                                == CommandException.Error.RADIO_NOT_AVAILABLE) {
-                            notifyFail(PdpFailCause.RADIO_NOT_AVIALABLE,
-                                    onConnectCompleted);
-                        } else {
-                            phone.mCM.getLastPdpFailCause(
-                                    obtainMessage(EVENT_GET_LAST_FAIL_DONE));
+                if (response.length > 2) {
+                    interfaceName = response[1];
+                    ipAddress = response[2];
+                    String prefix = "net." + interfaceName + ".";
+                    gatewayAddress = SystemProperties.get(prefix + "gw");
+                    dnsServers[0] = SystemProperties.get(prefix + "dns1");
+                    dnsServers[1] = SystemProperties.get(prefix + "dns2");
+                    if (DBG) {
+                        log("interface=" + interfaceName + " ipAddress=" + ipAddress
+                            + " gateway=" + gatewayAddress + " DNS1=" + dnsServers[0]
+                            + " DNS2=" + dnsServers[1]);
+                    }
+
+                    if (NULL_IP.equals(dnsServers[0]) && NULL_IP.equals(dnsServers[1])
+                                        && !((GSMPhone) phone).isDnsCheckDisabled()) {
+                        // Work around a race condition where QMI does not fill in DNS:
+                        // Deactivate PDP and let DataConnectionTracker retry.
+                        // Do not apply the race condition workaround for MMS APN
+                        // if Proxy is an IP-address.
+                        // Otherwise, the default APN will not be restored anymore.
+                        if (!apn.types[0].equals(Phone.APN_TYPE_MMS)
+                                || !isIpAddress(apn.mmsProxy)) {
+                            EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_BAD_DNS_ADDRESS,
+                                    dnsServers[0]);
+                            phone.mCM.deactivateDataCall(cid, obtainMessage(EVENT_FORCE_RETRY));
+                            return;
                         }
                     }
-                } else {
-                    if (receivedDisconnectReq) {
-                        // Don't bother reporting success if there's already a
-                        // pending disconnect request, since DataConnectionTracker
-                        // has already updated its state.
-                        // Set ACTIVE so that disconnect does the right thing.
-                        state = PdpState.ACTIVE;
-                        disconnect(onDisconnect);
-                    } else {
-                        String[] response = ((String[]) ar.result);
-                        cid = Integer.parseInt(response[0]);
-
-                        if (response.length > 2) {
-                            interfaceName = response[1];
-                            ipAddress = response[2];
-                            String prefix = "net." + interfaceName + ".";
-                            gatewayAddress = SystemProperties.get(prefix + "gw");
-                            dnsServers[0] = SystemProperties.get(prefix + "dns1");
-                            dnsServers[1] = SystemProperties.get(prefix + "dns2");
-                            if (DBG) {
-                                log("interface=" + interfaceName + " ipAddress=" + ipAddress
-                                    + " gateway=" + gatewayAddress + " DNS1=" + dnsServers[0]
-                                    + " DNS2=" + dnsServers[1]);
-                            }
-
-                            if (NULL_IP.equals(dnsServers[0]) && NULL_IP.equals(dnsServers[1])
-                                    && !phone.isDnsCheckDisabled()) {
-                                // Work around a race condition where QMI does not fill in DNS:
-                                // Deactivate PDP and let DataConnectionTracker retry.
-                                // Do not apply the race condition workaround for MMS APN
-                                // if Proxy is an IP-address.
-                                // Otherwise, the default APN will not be restored anymore.
-                                if (!apn.types[0].equals(Phone.APN_TYPE_MMS)
-                                        || !isIpAddress(apn.mmsProxy)) {
-                                    EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_BAD_DNS_ADDRESS,
-                                            dnsServers[0]);
-                                    phone.mCM.deactivateDefaultPDP(cid,
-                                            obtainMessage(EVENT_FORCE_RETRY));
-                                    break;
-                                }
-                            }
-                        }
-
-                        if (dataLink != null) {
-                            dataLink.connect();
-                        } else {
-                            onLinkStateChanged(DataLink.LinkState.LINK_UP);
-                        }
-
-                        if (DBG) log("PDP setup on cid = " + cid);
-                    }
-                }
-                break;
-            case EVENT_FORCE_RETRY:
-                if (receivedDisconnectReq) {
-                    notifyDisconnect(onDisconnect);
-                } else {
-                    ar = (AsyncResult) msg.obj;
-                    notifyFail(PdpFailCause.RADIO_ERROR_RETRY, onConnectCompleted);
-                }
-                break;
-            case EVENT_GET_LAST_FAIL_DONE:
-                if (receivedDisconnectReq) {
-                    // Don't bother reporting the error if there's already a
-                    // pending disconnect request, since DataConnectionTracker
-                    // has already updated its state.
-                    notifyDisconnect(onDisconnect);
-                } else {
-                    ar = (AsyncResult) msg.obj;
-                    PdpFailCause cause = PdpFailCause.UNKNOWN;
-
-                    if (ar.exception == null) {
-                        int rilFailCause = ((int[]) (ar.result))[0];
-                        cause = getFailCauseFromRequest(rilFailCause);
-                    }
-                    notifyFail(cause, onConnectCompleted);
                 }
 
-                break;
-            case EVENT_LINK_STATE_CHANGED:
-                ar = (AsyncResult) msg.obj;
-                DataLink.LinkState ls  = (DataLink.LinkState) ar.result;
-                onLinkStateChanged(ls);
-                break;
-            case EVENT_DEACTIVATE_DONE:
-                ar = (AsyncResult) msg.obj;
-                notifyDisconnect((Message) ar.userObj);
-                break;
+                if (dataLink != null) {
+                    dataLink.connect();
+                } else {
+                    onLinkStateChanged(DataLink.LinkState.LINK_UP);
+                }
+
+                if (DBG) log("PDP setup on cid = " + cid);
+            }
         }
     }
 
@@ -488,4 +294,8 @@
 
         return Regex.IP_ADDRESS_PATTERN.matcher(apn.mmsProxy).matches();
     }
+
+    public ApnSetting getApn() {
+        return this.apn;
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/PppLink.java b/telephony/java/com/android/internal/telephony/gsm/PppLink.java
index 43d4f1f..9627696 100644
--- a/telephony/java/com/android/internal/telephony/gsm/PppLink.java
+++ b/telephony/java/com/android/internal/telephony/gsm/PppLink.java
@@ -16,28 +16,31 @@
 
 package com.android.internal.telephony.gsm;
 
+import android.database.Cursor;
+import android.os.Message;
+import android.os.SystemProperties;
+import android.os.SystemService;
+import android.util.Log;
+
+import com.android.internal.telephony.DataLink;
+import com.android.internal.telephony.DataConnectionTracker.State;
+import com.android.internal.telephony.PhoneBase;
+import com.android.internal.util.ArrayUtils;
+
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.RandomAccessFile;
 
-import android.database.Cursor;
-import android.os.Message;
-import android.os.SystemProperties;
-import android.os.SystemService;
-import com.android.internal.telephony.gsm.DataConnectionTracker.State;
-import com.android.internal.util.ArrayUtils;
-import android.util.Log;
-
 /**
  * Represents a PPP link.
- * 
+ *
  * Ideally this would be managed by the RIL implementation, but
  * we currently have implementations where this is not the case.
  *
  * {@hide}
  */
-final class PppLink extends DataLink implements DataLinkInterface {
+final class PppLink extends DataLink {
     private static final String LOG_TAG = "GSM";
 
     static final String PATH_PPP_OPERSTATE = "/sys/class/net/ppp0/operstate";
@@ -69,11 +72,14 @@
     };
     private final byte[] mCheckPPPBuffer = new byte[32];
 
+    private PhoneBase phone;
+
     int lastPppdExitCode = EXIT_OK;
 
 
-    PppLink(DataConnectionTracker dc) {
+    PppLink(GsmDataConnectionTracker dc, GSMPhone p) {
         super(dc);
+        this.phone = p;
     }
 
     public void connect() {
@@ -131,7 +137,7 @@
                 checkPPP();
 
                 // keep polling in case interface goes down
-                if (dataConnection.state != State.IDLE) {                    
+                if (dataConnection.getState() != State.IDLE) {
                     Message poll = obtainMessage();
                     poll.what = EVENT_POLL_DATA_CONNECTION;
                     sendMessageDelayed(poll, POLL_SYSFS_MILLIS);
@@ -141,7 +147,7 @@
     }
 
     private void checkPPP() {
-        boolean connecting = (dataConnection.state == State.CONNECTING);
+        boolean connecting = (dataConnection.getState() == State.CONNECTING);
 
         try {
             RandomAccessFile file = new RandomAccessFile(PATH_PPP_OPERSTATE, "r");
@@ -152,10 +158,10 @@
             // "unknown" where one might otherwise expect "up"
             if (ArrayUtils.equals(mCheckPPPBuffer, UP_ASCII_STRING, UP_ASCII_STRING.length)
                     || ArrayUtils.equals(mCheckPPPBuffer, UNKNOWN_ASCII_STRING,
-                            UNKNOWN_ASCII_STRING.length) 
-                            && dataConnection.state == State.CONNECTING) {
+                    UNKNOWN_ASCII_STRING.length)
+                    && dataConnection.getState() == State.CONNECTING) {
 
-                Log.i(LOG_TAG, 
+                Log.i(LOG_TAG,
                 "found ppp interface. Notifying GPRS connected");
 
                 if (mLinkChangeRegistrant != null) {
@@ -163,23 +169,23 @@
                 }
 
                 connecting = false;
-            } else if (dataConnection.state == State.CONNECTED 
+            } else if (dataConnection.getState() == State.CONNECTED
                     && ArrayUtils.equals(mCheckPPPBuffer, DOWN_ASCII_STRING,
-                            DOWN_ASCII_STRING.length)) {
+                    DOWN_ASCII_STRING.length)) {
 
-                Log.i(LOG_TAG, 
+                Log.i(LOG_TAG,
                 "ppp interface went down. Reconnecting...");
 
                 if (mLinkChangeRegistrant != null) {
                     mLinkChangeRegistrant.notifyResult(LinkState.LINK_DOWN);
                 }
-            }                                    
+            }
         } catch (IOException ex) {
             if (! (ex instanceof FileNotFoundException)) {
                 Log.i(LOG_TAG, "Poll ppp0 ex " + ex.toString());
             }
 
-            if (dataConnection.state == State.CONNECTED &&
+            if (dataConnection.getState() == State.CONNECTED &&
                     mLinkChangeRegistrant != null) {
                 mLinkChangeRegistrant.notifyResult(LinkState.LINK_DOWN);
             }
@@ -206,4 +212,8 @@
         }
 
     }
+
+    protected void log(String s) {
+        Log.d(LOG_TAG, "[PppLink] " + s);
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/SIMFileHandler.java b/telephony/java/com/android/internal/telephony/gsm/SIMFileHandler.java
index 81fc657..ead1327 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SIMFileHandler.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SIMFileHandler.java
@@ -16,506 +16,54 @@
 
 package com.android.internal.telephony.gsm;
 
-import com.android.internal.telephony.*;
-import com.android.internal.telephony.gsm.stk.ImageDescriptor;
 import android.os.*;
 import android.os.AsyncResult;
-import android.os.RegistrantList;
-import android.os.Registrant;
 import android.util.Log;
+
+import com.android.internal.telephony.IccConstants;
+import com.android.internal.telephony.IccException;
+import com.android.internal.telephony.IccFileHandler;
+import com.android.internal.telephony.IccFileTypeMismatch;
+import com.android.internal.telephony.IccIoResult;
+import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.PhoneProxy;
+
 import java.util.ArrayList;
 
 /**
  * {@hide}
  */
-public final class SIMFileHandler extends Handler
-{
+public final class SIMFileHandler extends IccFileHandler {
     static final String LOG_TAG = "GSM";
 
-    //from TS 11.11 9.1 or elsewhere
-    static private final int COMMAND_READ_BINARY = 0xb0;
-    static private final int COMMAND_UPDATE_BINARY = 0xd6;
-    static private final int COMMAND_READ_RECORD = 0xb2;
-    static private final int COMMAND_UPDATE_RECORD = 0xdc;
-    static private final int COMMAND_SEEK = 0xa2;
-    static private final int COMMAND_GET_RESPONSE = 0xc0;
-
-    // from TS 11.11 9.2.5
-    static private final int READ_RECORD_MODE_ABSOLUTE = 4;
-
-    //***** types of files  TS 11.11 9.3
-    static private final int EF_TYPE_TRANSPARENT = 0;
-    static private final int EF_TYPE_LINEAR_FIXED = 1;
-    static private final int EF_TYPE_CYCLIC = 3;
-
-    //***** types of files  TS 11.11 9.3
-    static private final int TYPE_RFU = 0;
-    static private final int TYPE_MF  = 1;
-    static private final int TYPE_DF  = 2;
-    static private final int TYPE_EF  = 4;
-    
-    // size of GET_RESPONSE for EF
-    static private final int GET_RESPONSE_EF_SIZE_BYTES = 15;
-
-    // Byte order received in response to COMMAND_GET_RESPONSE
-    // Refer TS 51.011 Section 9.2.1
-    static private final int RESPONSE_DATA_RFU_1 = 0;
-    static private final int RESPONSE_DATA_RFU_2 = 1;
-
-    static private final int RESPONSE_DATA_FILE_SIZE_1 = 2;
-    static private final int RESPONSE_DATA_FILE_SIZE_2 = 3;
-
-    static private final int RESPONSE_DATA_FILE_ID_1 = 4;
-    static private final int RESPONSE_DATA_FILE_ID_2 = 5;
-    static private final int RESPONSE_DATA_FILE_TYPE = 6;
-    static private final int RESPONSE_DATA_RFU_3 = 7;
-    static private final int RESPONSE_DATA_ACCESS_CONDITION_1 = 8;
-    static private final int RESPONSE_DATA_ACCESS_CONDITION_2 = 9;
-    static private final int RESPONSE_DATA_ACCESS_CONDITION_3 = 10;
-    static private final int RESPONSE_DATA_FILE_STATUS = 11;
-    static private final int RESPONSE_DATA_LENGTH = 12;
-    static private final int RESPONSE_DATA_STRUCTURE = 13;
-    static private final int RESPONSE_DATA_RECORD_LENGTH = 14;
-
-
     //***** Instance Variables
-    GSMPhone phone;
-
-    //***** Events
-
-    /** Finished retrieving size of transparent EF; start loading. */
-    static private final int EVENT_GET_BINARY_SIZE_DONE = 4;
-    /** Finished loading contents of transparent EF; post result. */
-    static private final int EVENT_READ_BINARY_DONE = 5;
-    /** Finished retrieving size of records for linear-fixed EF; now load. */
-    static private final int EVENT_GET_RECORD_SIZE_DONE = 6;
-    /** Finished loading single record from a linear-fixed EF; post result. */
-    static private final int EVENT_READ_RECORD_DONE = 7;
-    /** Finished retrieving record size; post result. */
-    static private final int EVENT_GET_EF_LINEAR_RECORD_SIZE_DONE = 8;
-    /** Finished retrieving image instance record; post result. */
-    static private final int EVENT_READ_IMG_DONE = 9;
-    /** Finished retrieving icon data; post result. */
-    static private final int EVENT_READ_ICON_DONE = 10;
-
-    //***** Inner Classes
-
-    static class LoadLinearFixedContext
-    {
-        
-        int efid;
-        int recordNum, recordSize, countRecords;
-        boolean loadAll;
-
-        Message onLoaded;
-
-        ArrayList<byte[]> results;
-
-        LoadLinearFixedContext(int efid, int recordNum, Message onLoaded)
-        {
-            this.efid = efid;
-            this.recordNum = recordNum;
-            this.onLoaded = onLoaded;
-            this.loadAll = false;
-        }
-
-        LoadLinearFixedContext(int efid, Message onLoaded)
-        {
-            this.efid = efid;
-            this.recordNum = 1;
-            this.loadAll = true;
-            this.onLoaded = onLoaded;
-        }
- 
-    }
-
 
     //***** Constructor
 
-    SIMFileHandler(GSMPhone phone)
-    {
-        this.phone = phone;
+    SIMFileHandler(GSMPhone phone) {
+        super(phone);
     }
 
-    //***** Public Methods
-
-    /**
-     * Load a record from a SIM Linear Fixed EF
-     *
-     * @param fileid EF id
-     * @param recordNum 1-based (not 0-based) record number
-     * @param onLoaded
-     *
-     * ((AsyncResult)(onLoaded.obj)).result is the byte[]     
-     *  
-     */
-    void loadEFLinearFixed(int fileid, int recordNum, Message onLoaded)
-    {
-        Message response 
-            = obtainMessage(EVENT_GET_RECORD_SIZE_DONE,
-                        new LoadLinearFixedContext(fileid, recordNum, onLoaded));
-
-        phone.mCM.simIO(COMMAND_GET_RESPONSE, fileid, null,
-                        0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, response);
+    public void dispose() {
+        super.dispose();
     }
 
-    /**
-     * Load a image instance record from a SIM Linear Fixed EF-IMG
-     * 
-     * @param recordNum 1-based (not 0-based) record number
-     * @param onLoaded
-     * 
-     * ((AsyncResult)(onLoaded.obj)).result is the byte[]
-     * 
-     */
-    public void loadEFImgLinearFixed(int recordNum, Message onLoaded) {
-        Message response = obtainMessage(EVENT_READ_IMG_DONE,
-                new LoadLinearFixedContext(SimConstants.EF_IMG, recordNum,
-                        onLoaded));
-
-        phone.mCM.simIO(COMMAND_GET_RESPONSE, SimConstants.EF_IMG, "img",
-                recordNum, READ_RECORD_MODE_ABSOLUTE,
-                ImageDescriptor.ID_LENGTH, null, null, response);
+    protected void finalize() {
+        Log.d(LOG_TAG, "SIMFileHandler finalized");
     }
 
-    /**
-     * get record size for a linear fixed EF
-     * 
-     * @param fileid EF id
-     * @param onLoaded ((AsnyncResult)(onLoaded.obj)).result is the recordSize[]
-     *        int[0] is the record length int[1] is the total length of the EF
-     *        file int[3] is the number of records in the EF file So int[0] *
-     *        int[3] = int[1]
-     */
-    void getEFLinearRecordSize(int fileid, Message onLoaded)
-    {
-        Message response
-                = obtainMessage(EVENT_GET_EF_LINEAR_RECORD_SIZE_DONE,
-                        new LoadLinearFixedContext(fileid, onLoaded));
-        phone.mCM.simIO(COMMAND_GET_RESPONSE, fileid, null,
-                    0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, response);
+    //***** Overridden from IccFileHandler
+
+    @Override
+    public void handleMessage(Message msg) {
+        super.handleMessage(msg);
     }
 
-    /**
-     * Load all records from a SIM Linear Fixed EF
-     *
-     * @param fileid EF id
-     * @param onLoaded
-     *
-     * ((AsyncResult)(onLoaded.obj)).result is an ArrayList<byte[]>
-     *  
-     */
-    void loadEFLinearFixedAll(int fileid, Message onLoaded)
-    {
-        Message response = obtainMessage(EVENT_GET_RECORD_SIZE_DONE,
-                        new LoadLinearFixedContext(fileid,onLoaded));
-
-        phone.mCM.simIO(COMMAND_GET_RESPONSE, fileid, null,
-                        0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, response);
+    protected void logd(String msg) {
+        Log.d(LOG_TAG, "[SIMFileHandler] " + msg);
     }
 
-    /**
-     * Load a SIM Transparent EF
-     *
-     * @param fileid EF id
-     * @param onLoaded
-     *
-     * ((AsyncResult)(onLoaded.obj)).result is the byte[]     
-     *  
-     */
-
-    void loadEFTransparent(int fileid, Message onLoaded)
-    {
-        Message response = obtainMessage(EVENT_GET_BINARY_SIZE_DONE,
-                        fileid, 0, onLoaded);
-
-        phone.mCM.simIO(COMMAND_GET_RESPONSE, fileid, null,
-                        0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, response);
-    }
-
-    /**
-     * Load a SIM Transparent EF-IMG. Used right after loadEFImgLinearFixed to
-     * retrive STK's icon data.
-     * 
-     * @param fileid EF id
-     * @param onLoaded
-     * 
-     * ((AsyncResult)(onLoaded.obj)).result is the byte[]
-     * 
-     */
-    public void loadEFImgTransparent(int fileid, int highOffset, int lowOffset,
-            int length, Message onLoaded) {
-        Message response = obtainMessage(EVENT_READ_ICON_DONE, fileid, 0,
-                onLoaded);
-
-        phone.mCM.simIO(COMMAND_READ_BINARY, fileid, "img", highOffset, lowOffset,
-                length, null, null, response);
-    }
-
-    /**
-     * Update a record in a linear fixed EF
-     * @param fileid EF id
-     * @param recordNum 1-based (not 0-based) record number
-     * @param data must be exactly as long as the record in the EF
-     * @param pin2 for CHV2 operations, otherwist must be null
-     * @param onComplete onComplete.obj will be an AsyncResult
-     *                   onComplete.obj.userObj will be a SimIoResult on success
-     */
-    void updateEFLinearFixed(int fileid, int recordNum, byte[] data,
-            String pin2, Message onComplete)
-    {
-        phone.mCM.simIO(COMMAND_UPDATE_RECORD, fileid, null,
-                        recordNum, READ_RECORD_MODE_ABSOLUTE, data.length,
-                        SimUtils.bytesToHexString(data), pin2, onComplete);
-    }
-
-    /**
-     * Update a transparent EF
-     * @param fileid EF id
-     * @param data must be exactly as long as the EF
-     */
-    void updateEFTransparent(int fileid, byte[] data, Message onComplete)
-    {
-        phone.mCM.simIO(COMMAND_UPDATE_BINARY, fileid, null,
-                        0, 0, data.length,
-                        SimUtils.bytesToHexString(data), null, onComplete);
-    }
-
-    //***** Overridden from Handler
-
-    public void handleMessage(Message msg)
-    {
-        AsyncResult ar;
-        SimIoResult result;
-        Message response = null;
-        String str;
-        LoadLinearFixedContext lc;
-
-        SimException simException;
-        byte data[];
-        int size;
-        int fileid;
-        int recordNum;
-        int recordSize[];
-
-        try {
-            switch (msg.what) {
-            case EVENT_READ_IMG_DONE:
-                ar = (AsyncResult) msg.obj;
-                lc = (LoadLinearFixedContext) ar.userObj;
-                result = (SimIoResult) ar.result;
-                response = lc.onLoaded;
-
-                simException = result.getException();
-                if (simException != null) {
-                    sendResult(response, result.payload, ar.exception);
-                }
-                break;
-            case EVENT_READ_ICON_DONE:
-                ar = (AsyncResult) msg.obj;
-                response = (Message) ar.userObj;
-                result = (SimIoResult) ar.result;
-
-                simException = result.getException();
-                if (simException != null) {
-                    sendResult(response, result.payload, ar.exception);
-                }
-                break;
-            case EVENT_GET_EF_LINEAR_RECORD_SIZE_DONE:
-                ar = (AsyncResult)msg.obj;
-                lc = (LoadLinearFixedContext) ar.userObj;
-                result = (SimIoResult) ar.result;
-                response = lc.onLoaded;
-
-                if (ar.exception != null) {
-                    sendResult(response, null, ar.exception);
-                    break;
-                }
-
-                simException = result.getException();
-                if (simException != null) {
-                    sendResult(response, null, simException);
-                    break;
-                }
-
-                data = result.payload;
-
-                if (TYPE_EF != data[RESPONSE_DATA_FILE_TYPE] ||
-                    EF_TYPE_LINEAR_FIXED != data[RESPONSE_DATA_STRUCTURE]) {
-                    throw new SimFileTypeMismatch();
-                }
-
-                recordSize = new int[3];
-                recordSize[0] = data[RESPONSE_DATA_RECORD_LENGTH] & 0xFF;
-                recordSize[1] = ((data[RESPONSE_DATA_FILE_SIZE_1] & 0xff) << 8)
-                       + (data[RESPONSE_DATA_FILE_SIZE_2] & 0xff);
-                recordSize[2] = recordSize[1] / recordSize[0];
-
-                sendResult(response, recordSize, null);
-                break;
-             case EVENT_GET_RECORD_SIZE_DONE:
-                ar = (AsyncResult)msg.obj;
-                lc = (LoadLinearFixedContext) ar.userObj;
-                result = (SimIoResult) ar.result;
-                response = lc.onLoaded;
-
-                if (ar.exception != null) {
-                    sendResult(response, null, ar.exception);
-                    break;
-                }
-
-                simException = result.getException();
-                
-                if (simException != null) {
-                    sendResult(response, null, simException);
-                    break;
-                }
-
-                data = result.payload;
-                fileid = lc.efid;
-                recordNum = lc.recordNum;
-
-                if (TYPE_EF != data[RESPONSE_DATA_FILE_TYPE]) {
-                    throw new SimFileTypeMismatch();
-                }
-
-                if (EF_TYPE_LINEAR_FIXED != data[RESPONSE_DATA_STRUCTURE]) {
-                    throw new SimFileTypeMismatch();
-                }
-
-                lc.recordSize = data[RESPONSE_DATA_RECORD_LENGTH] & 0xFF;
-
-                size = ((data[RESPONSE_DATA_FILE_SIZE_1] & 0xff) << 8)
-                       + (data[RESPONSE_DATA_FILE_SIZE_2] & 0xff);
-
-                lc.countRecords = size / lc.recordSize;
-
-                 if (lc.loadAll) {
-                     lc.results = new ArrayList<byte[]>(lc.countRecords);
-                 }
-
-                 phone.mCM.simIO(COMMAND_READ_RECORD, lc.efid, null,
-                         lc.recordNum,
-                         READ_RECORD_MODE_ABSOLUTE,
-                         lc.recordSize, null, null,
-                         obtainMessage(EVENT_READ_RECORD_DONE, lc));
-                 break;
-            case EVENT_GET_BINARY_SIZE_DONE:
-                ar = (AsyncResult)msg.obj;
-                response = (Message) ar.userObj;
-                result = (SimIoResult) ar.result;
-
-                if (ar.exception != null) {
-                    sendResult(response, null, ar.exception);
-                    break;
-                }
-
-                simException = result.getException();
-                
-                if (simException != null) {
-                    sendResult(response, null, simException);
-                    break;
-                }
-
-                data = result.payload;
-
-                fileid = msg.arg1;
-
-                if (TYPE_EF != data[RESPONSE_DATA_FILE_TYPE]) {
-                    throw new SimFileTypeMismatch();
-                }
-
-                if (EF_TYPE_TRANSPARENT != data[RESPONSE_DATA_STRUCTURE]) {
-                    throw new SimFileTypeMismatch();
-                }
-
-                size = ((data[RESPONSE_DATA_FILE_SIZE_1] & 0xff) << 8)
-                       + (data[RESPONSE_DATA_FILE_SIZE_2] & 0xff);
-
-                phone.mCM.simIO(COMMAND_READ_BINARY, fileid, null,
-                                0, 0, size, null, null, 
-                                obtainMessage(EVENT_READ_BINARY_DONE,
-                                              fileid, 0, response));
-            break;
-
-            case EVENT_READ_RECORD_DONE:
-
-                ar = (AsyncResult)msg.obj;
-                lc = (LoadLinearFixedContext) ar.userObj;
-                result = (SimIoResult) ar.result;
-                response = lc.onLoaded;
-
-                if (ar.exception != null) {
-                    sendResult(response, null, ar.exception);
-                    break;
-                }
-
-                simException = result.getException();
-                
-                if (simException != null) {
-                    sendResult(response, null, simException);
-                    break;
-                }
-
-                if (!lc.loadAll) {
-                    sendResult(response, result.payload, null);
-                } else {
-                    lc.results.add(result.payload);
-
-                    lc.recordNum++;
-
-                    if (lc.recordNum > lc.countRecords) {
-                        sendResult(response, lc.results, null);
-                    } else {                   
-                        phone.mCM.simIO(COMMAND_READ_RECORD, lc.efid, null,
-                                    lc.recordNum,
-                                    READ_RECORD_MODE_ABSOLUTE,
-                                    lc.recordSize, null, null,
-                                    obtainMessage(EVENT_READ_RECORD_DONE, lc));
-                    }
-                }                
-
-            break;
-            
-            case EVENT_READ_BINARY_DONE:
-                ar = (AsyncResult)msg.obj;
-                response = (Message) ar.userObj;
-                result = (SimIoResult) ar.result;
-
-                if (ar.exception != null) {
-                    sendResult(response, null, ar.exception);
-                    break;
-                }
-
-                simException = result.getException();
-                
-                if (simException != null) {
-                    sendResult(response, null, simException);
-                    break;
-                }
-
-                sendResult(response, result.payload, null);
-            break;
-
-        }} catch (Exception exc) {
-            if (response != null) {
-                sendResult(response, null, exc);
-            } else {
-                Log.e(LOG_TAG, "uncaught exception", exc);
-            }            
-        }
-    }
-
-    //***** Private Methods
-
-    private void sendResult(Message response, Object result, Throwable ex)
-    {
-        if (response == null) {
-            return;
-        }
-
-        AsyncResult.forMessage(response, result, ex);
-
-        response.sendToTarget();
+    protected void loge(String msg) {
+        Log.e(LOG_TAG, "[SIMFileHandler] " + msg);
     }
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
index 4467536..09a17f5 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
@@ -16,26 +16,45 @@
 
 package com.android.internal.telephony.gsm;
 
+import android.app.ActivityManagerNative;
 import android.app.AlarmManager;
+import android.app.IActivityManager;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.os.AsyncResult;
-import android.os.RegistrantList;
-import android.os.Registrant;
 import android.os.Handler;
 import android.os.Message;
 import android.os.SystemProperties;
-import android.telephony.gsm.SmsMessage;
+import android.os.Registrant;
 import android.util.Log;
 import java.util.ArrayList;
 
+
 import static com.android.internal.telephony.TelephonyProperties.*;
-import com.android.internal.telephony.SimCard;
+
+import com.android.internal.telephony.AdnRecord;
+import com.android.internal.telephony.AdnRecordCache;
+import com.android.internal.telephony.AdnRecordLoader;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.gsm.SimCard;
+import com.android.internal.telephony.gsm.SmsMessage;
+import com.android.internal.telephony.IccFileHandler;
+import com.android.internal.telephony.IccRecords;
+import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.IccVmFixedException;
+import com.android.internal.telephony.IccVmNotSupportedException;
+import com.android.internal.telephony.PhoneProxy;
+
+
+
+
+
+
 
 /**
  * {@hide}
  */
-public final class SIMRecords extends Handler implements SimConstants
-{
+public final class SIMRecords extends IccRecords {
     static final String LOG_TAG = "GSM";
 
     private static final boolean CRASH_RIL = false;
@@ -44,37 +63,19 @@
 
     //***** Instance Variables
 
-    GSMPhone phone;
-    RegistrantList recordsLoadedRegistrants = new RegistrantList();
-
-    int recordsToLoad;  // number of pending load requests
-
-    AdnRecordCache adnCache;
-
     VoiceMailConstants mVmConfig;
+
+
     SpnOverride mSpnOverride;
     
     //***** Cached SIM State; cleared on channel close
 
-    boolean recordsRequested = false; // true if we've made requests for the sim records
-
     String imsi;
-    String iccid;
-    String msisdn = null;  // My mobile number
-    String msisdnTag = null;
-    String voiceMailNum = null;
-    String voiceMailTag = null;
-    String newVoiceMailNum = null;
-    String newVoiceMailTag = null;
-    boolean isVoiceMailFixed = false;
-    int countVoiceMessages = 0;
     boolean callForwardingEnabled;
-    int mncLength = 0;   // 0 is used to indicate that the value
-                         // is not initialized
-    int mailboxIndex = 0; // 0 is no mailbox dailing number associated
+
 
     /**
-     * Sates only used by getSpnFsm FSM
+     * States only used by getSpnFsm FSM
      */
     private Get_Spn_Fsm_State spnState;
 
@@ -157,9 +158,8 @@
 
     //***** Constructor
 
-    SIMRecords(GSMPhone phone)
-    {
-        this.phone = phone;
+    SIMRecords(GSMPhone p) {
+        super(p);
 
         adnCache = new AdnRecordCache(phone);
 
@@ -172,30 +172,35 @@
         recordsToLoad = 0;
 
 
-        phone.mCM.registerForSIMReady(this, EVENT_SIM_READY, null);
-        phone.mCM.registerForOffOrNotAvailable(
+        p.mCM.registerForSIMReady(this, EVENT_SIM_READY, null);
+        p.mCM.registerForOffOrNotAvailable(
                         this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
-        phone.mCM.setOnSmsOnSim(this, EVENT_SMS_ON_SIM, null);
-        phone.mCM.setOnSimRefresh(this, EVENT_SIM_REFRESH, null);
+        p.mCM.setOnSmsOnSim(this, EVENT_SMS_ON_SIM, null);
+        p.mCM.setOnIccRefresh(this, EVENT_SIM_REFRESH, null);
 
         // Start off by setting empty state
-        onRadioOffOrNotAvailable();        
+        onRadioOffOrNotAvailable();
 
     }
 
-    AdnRecordCache getAdnCache() {
-        return adnCache;
+    public void dispose() {
+        //Unregister for all events
+        phone.mCM.unregisterForSIMReady(this);
+        phone.mCM.unregisterForOffOrNotAvailable( this);
+        phone.mCM.unSetOnIccRefresh(this);
     }
 
-    private void onRadioOffOrNotAvailable()
-    {
+    protected void finalize() {
+        if(DBG) Log.d(LOG_TAG, "SIMRecords finalized");
+    }
+
+    protected void onRadioOffOrNotAvailable() {
         imsi = null;
         msisdn = null;
         voiceMailNum = null;
         countVoiceMessages = 0;
         mncLength = 0;
         iccid = null;
-        spn = null;
         // -1 means no EF_SPN found; treat accordingly.
         spnDisplayCondition = -1;
         efMWIS = null;
@@ -205,9 +210,9 @@
 
         adnCache.reset();
 
-        phone.setSystemProperty(PROPERTY_SIM_OPERATOR_NUMERIC, null);
-        phone.setSystemProperty(PROPERTY_SIM_OPERATOR_ALPHA, null);
-        phone.setSystemProperty(PROPERTY_SIM_OPERATOR_ISO_COUNTRY, null);
+        phone.setSystemProperty(PROPERTY_ICC_OPERATOR_NUMERIC, null);
+        phone.setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, null);
+        phone.setSystemProperty(PROPERTY_ICC_OPERATOR_ISO_COUNTRY, null);
 
         // recordsRequested is set to false indicating that the SIM
         // read requests made so far are not valid. This is set to
@@ -217,24 +222,13 @@
 
 
     //***** Public Methods
-    public void registerForRecordsLoaded(Handler h, int what, Object obj)
-    {
-        Registrant r = new Registrant(h, what, obj);
-        recordsLoadedRegistrants.add(r);
-
-        if (recordsToLoad == 0 && recordsRequested == true) {
-            r.notifyRegistrant(new AsyncResult(null, null, null));
-        }
-    }
 
     /** Returns null if SIM is not yet ready */
-    public String getIMSI()
-    {
+    public String getIMSI() {
         return imsi;
     }
 
-    public String getMsisdnNumber()
-    {
+    public String getMsisdnNumber() {
         return msisdn;
     }
 
@@ -272,28 +266,18 @@
         return msisdnTag;
     }
 
-    public String getVoiceMailNumber()
-    {
+    public String getVoiceMailNumber() {
         return voiceMailNum;
     }
 
     /**
-     * Return Service Provider Name stored in SIM
-     * @return null if SIM is not yet ready
-     */
-    String getServiceProviderName()
-    {
-        return spn;
-    }
-
-    /**
      * Set voice mail number to SIM record
      *
      * The voice mail number can be stored either in EF_MBDN (TS 51.011) or
      * EF_MAILBOX_CPHS (CPHS 4.2)
      *
      * If EF_MBDN is available, store the voice mail number to EF_MBDN
-     * 
+     *
      * If EF_MAILBOX_CPHS is enabled, store the voice mail number to EF_CHPS
      *
      * So the voice mail number will be stored in both EFs if both are available
@@ -314,7 +298,7 @@
             Message onComplete) {
         if (isVoiceMailFixed) {
             AsyncResult.forMessage((onComplete)).exception =
-                    new SimVmFixedException("Voicemail number is fixed by operator");
+                    new IccVmFixedException("Voicemail number is fixed by operator");
             onComplete.sendToTarget();
             return;
         }
@@ -336,9 +320,9 @@
                     EF_EXT1, 1, null,
                     obtainMessage(EVENT_SET_CPHS_MAILBOX_DONE, onComplete));
 
-        }else {
+        } else {
             AsyncResult.forMessage((onComplete)).exception =
-                    new SimVmNotSupportedException("Update SIM voice mailbox error");
+                    new IccVmNotSupportedException("Update SIM voice mailbox error");
             onComplete.sendToTarget();
         }
     }
@@ -352,12 +336,11 @@
      * Sets the SIM voice message waiting indicator records
      * @param line GSM Subscriber Profile Number, one-based. Only '1' is supported
      * @param countWaiting The number of messages waiting, if known. Use
-     *                     -1 to indicate that an unknown number of 
+     *                     -1 to indicate that an unknown number of
      *                      messages are waiting
      */
     public void
-    setVoiceMessageWaiting(int line, int countWaiting)
-    {
+    setVoiceMessageWaiting(int line, int countWaiting) {
         if (line != 1) {
             // only profile 1 is supported
             return;
@@ -374,14 +357,14 @@
 
         countVoiceMessages = countWaiting;
 
-        phone.notifyMessageWaitingIndicator();
+        ((GSMPhone) phone).notifyMessageWaitingIndicator();
 
         try {
             if (efMWIS != null) {
                 // TS 51.011 10.3.45
 
                 // lsb of byte 0 is 'voicemail' status
-                efMWIS[0] = (byte)((efMWIS[0] & 0xfe) 
+                efMWIS[0] = (byte)((efMWIS[0] & 0xfe)
                                     | (countVoiceMessages == 0 ? 0 : 1));
 
                 // byte 1 is the number of voice messages waiting
@@ -393,17 +376,17 @@
                     efMWIS[1] = (byte) countWaiting;
                 }
 
-                phone.mSIMFileHandler.updateEFLinearFixed(
+                phone.getIccFileHandler().updateEFLinearFixed(
                     EF_MWIS, 1, efMWIS, null,
                     obtainMessage (EVENT_UPDATE_DONE, EF_MWIS));
-            } 
+            }
 
             if (efCPHS_MWI != null) {
                     // Refer CPHS4_2.WW6 B4.2.3
-                efCPHS_MWI[0] = (byte)((efCPHS_MWI[0] & 0xf0) 
+                efCPHS_MWI[0] = (byte)((efCPHS_MWI[0] & 0xf0)
                             | (countVoiceMessages == 0 ? 0x5 : 0xa));
 
-                phone.mSIMFileHandler.updateEFTransparent(
+                phone.getIccFileHandler().updateEFTransparent(
                     EF_VOICE_MAIL_INDICATOR_CPHS, efCPHS_MWI,
                     obtainMessage (EVENT_UPDATE_DONE, EF_VOICE_MAIL_INDICATOR_CPHS));
             }
@@ -413,22 +396,6 @@
         }
     }
 
-    /** @return  true if there are messages waiting, false otherwise. */
-    public boolean getVoiceMessageWaiting()
-    {
-        return countVoiceMessages != 0;
-    }
-
-    /**
-     * Returns number of voice messages waiting, if available
-     * If not available (eg, on an older CPHS SIM) -1 is returned if 
-     * getVoiceMessageWaiting() is true
-     */
-    public int getCountVoiceMessages()
-    {
-        return countVoiceMessages;
-    }
-
     public boolean getVoiceCallForwardingFlag() {
         return callForwardingEnabled;
     }
@@ -439,7 +406,7 @@
 
         callForwardingEnabled = enable;
 
-        phone.notifyCallForwardingIndicator();
+        ((GSMPhone) phone).notifyCallForwardingIndicator();
 
         try {
             if (mEfCfis != null) {
@@ -453,7 +420,7 @@
                 // TODO: Should really update other fields in EF_CFIS, eg,
                 // dialing number.  We don't read or use it right now.
 
-                phone.mSIMFileHandler.updateEFLinearFixed(
+                phone.getIccFileHandler().updateEFLinearFixed(
                         EF_CFIS, 1, mEfCfis, null,
                         obtainMessage (EVENT_UPDATE_DONE, EF_CFIS));
             }
@@ -467,7 +434,7 @@
                             | CFF_UNCONDITIONAL_DEACTIVE);
                 }
 
-                phone.mSIMFileHandler.updateEFTransparent(
+                phone.getIccFileHandler().updateEFTransparent(
                         EF_CFF_CPHS, mEfCff,
                         obtainMessage (EVENT_UPDATE_DONE, EF_CFF_CPHS));
             }
@@ -496,8 +463,7 @@
     /** Returns the 5 or 6 digit MCC/MNC of the operator that
      *  provided the SIM card. Returns null of SIM is not yet ready
      */
-    String getSIMOperatorNumeric()
-    {
+    String getSIMOperatorNumeric() {
         if (imsi == null) {
             return null;
         }
@@ -517,17 +483,8 @@
 
         return imsi.substring(0, 3 + MccTable.smallestDigitsMccForMnc(mcc));
     }
-
-    boolean getRecordsLoaded()
-    {
-        if (recordsToLoad == 0 && recordsRequested == true) {
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    /**
+    
+     /**
      * If the timezone is not already set, set it based on the MCC of the SIM.
      * @param mcc Mobile Country Code of the SIM
      */
@@ -557,8 +514,7 @@
     }
 
     //***** Overridden from Handler
-    public void handleMessage(Message msg)
-    {
+    public void handleMessage(Message msg) {
         AsyncResult ar;
         AdnRecord adn;
 
@@ -573,19 +529,19 @@
 
             case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
                 onRadioOffOrNotAvailable();
-            break;  
+            break;
 
             /* IO events */
             case EVENT_GET_IMSI_DONE:
                 isRecordLoadResponse = true;
-            
+
                 ar = (AsyncResult)msg.obj;
 
                 if (ar.exception != null) {
                     Log.e(LOG_TAG, "Exception querying IMSI, Exception:" + ar.exception);
                     break;
-                } 
-                
+                }
+
                 imsi = (String) ar.result;
 
                 // IMSI (MCC+MNC+MSIN) is at least 6 digits, but not more
@@ -594,11 +550,11 @@
                     Log.e(LOG_TAG, "invalid IMSI " + imsi);
                     imsi = null;
                 }
-                
+
                 Log.d(LOG_TAG, "IMSI: " + imsi.substring(0, 6) + "xxxxxxxxx");
-                phone.mSimCard.updateImsiConfiguration(imsi);
-                phone.mSimCard.broadcastSimStateChangedIntent(
-                        SimCard.INTENT_VALUE_SIM_IMSI, null);
+                ((GSMPhone) phone).mSimCard.updateImsiConfiguration(imsi);
+                ((GSMPhone) phone).mSimCard.broadcastSimStateChangedIntent(
+                        SimCard.INTENT_VALUE_ICC_IMSI, null);
 
                 int mcc = Integer.parseInt(imsi.substring(0, 3));
                 setTimezoneFromMccIfNeeded(mcc);
@@ -616,7 +572,7 @@
                 if (ar.exception == null) {
                     // Refer TS 51.011 Section 10.3.44 for content details
                     Log.d(LOG_TAG, "EF_MBI: " +
-                            SimUtils.bytesToHexString(data));
+                            IccUtils.bytesToHexString(data));
 
                     // Voice mail record number stored first
                     mailboxIndex = (int)data[0] & 0xff;
@@ -651,20 +607,20 @@
                 ar = (AsyncResult)msg.obj;
 
                 if (ar.exception != null) {
-                
-                    Log.d(LOG_TAG, "Invalid or missing EF" 
+
+                    Log.d(LOG_TAG, "Invalid or missing EF"
                         + ((msg.what == EVENT_GET_CPHS_MAILBOX_DONE) ? "[MAILBOX]" : "[MBDN]"));
 
                     // Bug #645770 fall back to CPHS
                     // FIXME should use SST to decide
 
                     if (msg.what == EVENT_GET_MBDN_DONE) {
-                        //load CPHS on fail... 
+                        //load CPHS on fail...
                         // FIXME right now, only load line1's CPHS voice mail entry
 
                         recordsToLoad += 1;
                         new AdnRecordLoader(phone).loadFromEF(
-                                EF_MAILBOX_CPHS, EF_EXT1, 1, 
+                                EF_MAILBOX_CPHS, EF_EXT1, 1,
                                 obtainMessage(EVENT_GET_CPHS_MAILBOX_DONE));
                     }
                     break;
@@ -672,7 +628,8 @@
 
                 adn = (AdnRecord)ar.result;
 
-                Log.d(LOG_TAG, "VM: " + adn + ((msg.what == EVENT_GET_CPHS_MAILBOX_DONE) ? " EF[MAILBOX]" : " EF[MBDN]"));
+                Log.d(LOG_TAG, "VM: " + adn +
+                        ((msg.what == EVENT_GET_CPHS_MAILBOX_DONE) ? " EF[MAILBOX]" : " EF[MBDN]"));
 
                 if (adn.isEmpty() && msg.what == EVENT_GET_MBDN_DONE) {
                     // Bug #645770 fall back to CPHS
@@ -680,7 +637,7 @@
                     // FIXME right now, only load line1's CPHS voice mail entry
                     recordsToLoad += 1;
                     new AdnRecordLoader(phone).loadFromEF(
-                            EF_MAILBOX_CPHS, EF_EXT1, 1, 
+                            EF_MAILBOX_CPHS, EF_EXT1, 1,
                             obtainMessage(EVENT_GET_CPHS_MAILBOX_DONE));
 
                     break;
@@ -730,7 +687,7 @@
                 }
 
                 Log.d(LOG_TAG, "EF_MWIS: " +
-                   SimUtils.bytesToHexString(data));
+                   IccUtils.bytesToHexString(data));
 
                 efMWIS = data;
 
@@ -744,11 +701,11 @@
                 countVoiceMessages = data[1] & 0xff;
 
                 if (voiceMailWaiting && countVoiceMessages == 0) {
-                    // Unknown count = -1 
+                    // Unknown count = -1
                     countVoiceMessages = -1;
                 }
 
-                phone.notifyMessageWaitingIndicator();
+                ((GSMPhone) phone).notifyMessageWaitingIndicator();
             break;
 
             case EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE:
@@ -777,7 +734,7 @@
                         countVoiceMessages = 0;
                     }
 
-                    phone.notifyMessageWaitingIndicator();
+                    ((GSMPhone) phone).notifyMessageWaitingIndicator();
                 }
             break;
 
@@ -786,13 +743,13 @@
 
                 ar = (AsyncResult)msg.obj;
                 data = (byte[])ar.result;
-                
+
                 if (ar.exception != null) {
                     break;
-                }                
+                }
 
-                iccid = SimUtils.bcdToString(data, 0, data.length);
-            
+                iccid = IccUtils.bcdToString(data, 0, data.length);
+
                 Log.d(LOG_TAG, "iccid: " + iccid);
 
             break;
@@ -809,7 +766,7 @@
                 }
 
                 Log.d(LOG_TAG, "EF_AD: " +
-                    SimUtils.bytesToHexString(data));
+                    IccUtils.bytesToHexString(data));
 
                 if (data.length < 3) {
                     Log.d(LOG_TAG, "SIMRecords: Corrupt AD data on SIM");
@@ -851,14 +808,14 @@
                 }
 
                 Log.d(LOG_TAG, "EF_CFF_CPHS: " +
-                        SimUtils.bytesToHexString(data));
+                        IccUtils.bytesToHexString(data));
                 mEfCff = data;
 
                 if (mEfCfis == null) {
                     callForwardingEnabled =
                         ((data[0] & CFF_LINE1_MASK) == CFF_UNCONDITIONAL_ACTIVE);
 
-                    phone.notifyCallForwardingIndicator();
+                    ((GSMPhone) phone).notifyCallForwardingIndicator();
                 }
                 break;
 
@@ -872,7 +829,7 @@
                     break;
                 }
 
-                parseEfSpdi(data);                                
+                parseEfSpdi(data);
             break;
 
             case EVENT_UPDATE_DONE:
@@ -896,8 +853,8 @@
 
                 for ( ; tlv.isValidObject() ; tlv.nextObject()) {
                     if (tlv.getTag() == TAG_FULL_NETWORK_NAME) {
-                        pnnHomeName 
-                            = SimUtils.networkNameToString(
+                        pnnHomeName
+                            = IccUtils.networkNameToString(
                                 tlv.getData(), 0, tlv.getData().length);
                         break;
                     }
@@ -931,7 +888,8 @@
                             + ar.exception + " length " + index.length);
                 } else {
                     Log.d(LOG_TAG, "READ EF_SMS RECORD index=" + index[0]);
-                    phone.mSIMFileHandler.loadEFLinearFixed(EF_SMS,index[0],obtainMessage(EVENT_GET_SMS_DONE));
+                    phone.getIccFileHandler().loadEFLinearFixed(EF_SMS,index[0],
+                            obtainMessage(EVENT_GET_SMS_DONE));
                 }
                 break;
 
@@ -955,7 +913,7 @@
                     break;
                 }
 
-                //Log.d(LOG_TAG, "SST: " + SimUtils.bytesToHexString(data));
+                //Log.d(LOG_TAG, "SST: " + IccUtils.bytesToHexString(data));
             break;
 
             case EVENT_GET_INFO_CPHS_DONE:
@@ -969,7 +927,7 @@
 
                 mCphsInfo = (byte[])ar.result;
 
-                if (DBG) log("iCPHS: " + SimUtils.bytesToHexString(mCphsInfo));
+                if (DBG) log("iCPHS: " + IccUtils.bytesToHexString(mCphsInfo));
             break;
 
             case EVENT_SET_MBDN_DONE:
@@ -1050,20 +1008,20 @@
                 }
 
                 Log.d(LOG_TAG, "EF_CFIS: " +
-                   SimUtils.bytesToHexString(data));
+                   IccUtils.bytesToHexString(data));
 
                 mEfCfis = data;
                 
                 // Refer TS 51.011 Section 10.3.46 for the content description
                 callForwardingEnabled = ((data[1] & 0x01) != 0);
 
-                phone.notifyCallForwardingIndicator();
+                ((GSMPhone) phone).notifyCallForwardingIndicator();
                 break;
 
         }}catch (RuntimeException exc) {
             // I don't want these exceptions to be fatal
             Log.w(LOG_TAG, "Exception parsing SIM record", exc);
-        } finally {        
+        } finally {
             // Count up record load responses even if they are fails
             if (isRecordLoadResponse) {
                 onRecordLoaded();
@@ -1076,12 +1034,12 @@
             case EF_MBDN:
                 recordsToLoad++;
                 new AdnRecordLoader(phone).loadFromEF(EF_MBDN, EF_EXT6,
-                        mailboxIndex, obtainMessage(EVENT_GET_MBDN_DONE));            
+                        mailboxIndex, obtainMessage(EVENT_GET_MBDN_DONE));
                 break;
             case EF_MAILBOX_CPHS:
                 recordsToLoad++;
                 new AdnRecordLoader(phone).loadFromEF(EF_MAILBOX_CPHS, EF_EXT1,
-                        1, obtainMessage(EVENT_GET_CPHS_MAILBOX_DONE));          
+                        1, obtainMessage(EVENT_GET_CPHS_MAILBOX_DONE));
                 break;
             default:
                 // For now, fetch all records if this is not a
@@ -1093,7 +1051,7 @@
         }
     }
 
-    private void handleSimRefresh(int[] result) { 
+    private void handleSimRefresh(int[] result) {
         if (result == null || result.length == 0) {
 	    if (DBG) log("handleSimRefresh without input");
             return;
@@ -1102,7 +1060,7 @@
         switch ((result[0])) {
             case CommandsInterface.SIM_REFRESH_FILE_UPDATED:
  		if (DBG) log("handleSimRefresh with SIM_REFRESH_FILE_UPDATED");
-		// result[1] contains the EFID of the updated file.
+                // result[1] contains the EFID of the updated file.
                 int efid = result[1];
                 handleFileUpdate(efid);
                 break;
@@ -1130,8 +1088,7 @@
         }
     }
 
-    private void handleSms(byte[] ba)
-    {
+    private void handleSms(byte[] ba) {
         if (ba[0] != 0)
             Log.d("ENF", "status : " + ba[0]);
 
@@ -1145,12 +1102,13 @@
             byte[] nba = new byte[n - 1];
             System.arraycopy(ba, 1, nba, 0, n - 1);
 
-            String pdu = SimUtils.bytesToHexString(nba);
+            String pdu = IccUtils.bytesToHexString(nba);
             // XXX first line is bogus
             SmsMessage message = SmsMessage.newFromCMT(
                                 new String[] { "", pdu });
 
-            phone.mSMS.dispatchMessage(message);
+
+            ((GSMPhone) phone).mSMS.dispatchMessage(message);
         }
     }
 
@@ -1175,12 +1133,13 @@
                 byte[] nba = new byte[n - 1];
                 System.arraycopy(ba, 1, nba, 0, n - 1);
 
-                String pdu = SimUtils.bytesToHexString(nba);
+                String pdu = IccUtils.bytesToHexString(nba);
                 // XXX first line is bogus
                 SmsMessage message = SmsMessage.newFromCMT(
                         new String[] { "", pdu });
 
-                phone.mSMS.dispatchMessage(message);
+
+                ((GSMPhone) phone).mSMS.dispatchMessage(message);
 
                 // 3GPP TS 51.011 v5.0.0 (20011-12)  10.5.3
                 // 1 == "received by MS from network; message read"
@@ -1188,18 +1147,14 @@
                 ba[0] = 1;
 
                 if (false) { // XXX writing seems to crash RdoServD
-                    phone.mSIMFileHandler.updateEFLinearFixed(EF_SMS, i, ba, null,
-                                    obtainMessage(EVENT_MARK_SMS_READ_DONE, i));
+                    phone.getIccFileHandler().updateEFLinearFixed(EF_SMS,
+                            i, ba, null, obtainMessage(EVENT_MARK_SMS_READ_DONE, i));
                 }
             }
         }
     }
 
-
-    //***** Private Methods
-
-    private void onRecordLoaded()
-    {
+    protected void onRecordLoaded() {
         // One record loaded successfully or failed, In either case
         // we need to update the recordsToLoad count
         recordsToLoad -= 1;
@@ -1211,21 +1166,19 @@
             recordsToLoad = 0;
         }
     }
-    
-    private void onAllRecordsLoaded()
-    {
+
+    protected void onAllRecordsLoaded() {
         Log.d(LOG_TAG, "SIMRecords: record load complete");
 
         String operator = getSIMOperatorNumeric();
 
         // Some fields require more than one SIM record to set
 
-        phone.setSystemProperty(PROPERTY_SIM_OPERATOR_NUMERIC, operator);
+        phone.setSystemProperty(PROPERTY_ICC_OPERATOR_NUMERIC, operator);
 
         if (imsi != null) {
-            phone.setSystemProperty(PROPERTY_SIM_OPERATOR_ISO_COUNTRY,
-                                        MccTable.countryCodeForMcc(
-                                            Integer.parseInt(imsi.substring(0,3))));
+            phone.setSystemProperty(PROPERTY_ICC_OPERATOR_ISO_COUNTRY,
+                    MccTable.countryCodeForMcc(Integer.parseInt(imsi.substring(0,3))));
         }
         else {
             Log.e("SIM", "[SIMRecords] onAllRecordsLoaded: imsi is NULL!");
@@ -1236,16 +1189,19 @@
 
         recordsLoadedRegistrants.notifyRegistrants(
             new AsyncResult(null, null, null));
-        phone.mSimCard.broadcastSimStateChangedIntent(
-                SimCard.INTENT_VALUE_SIM_LOADED, null);
+        ((GSMPhone) phone).mSimCard.broadcastSimStateChangedIntent(
+                SimCard.INTENT_VALUE_ICC_LOADED, null);
     }
 
+    //***** Private methods
+
     private void setSpnFromConfig(String carrier) {
         if (mSpnOverride.containsCarrier(carrier)) {
             spn = mSpnOverride.getSpn(carrier);
         }
     }
 
+
     private void setVoiceMailByCountry (String spn) {
         if (mVmConfig.containsCarrier(spn)) {
             isVoiceMailFixed = true;
@@ -1258,22 +1214,22 @@
         /* broadcast intent SIM_READY here so that we can make sure
           READY is sent before IMSI ready
         */
-        phone.mSimCard.broadcastSimStateChangedIntent(
-                SimCard.INTENT_VALUE_SIM_READY, null);
+        ((GSMPhone) phone).mSimCard.broadcastSimStateChangedIntent(
+                SimCard.INTENT_VALUE_ICC_READY, null);
 
         fetchSimRecords();
     }
 
     private void fetchSimRecords() {
         recordsRequested = true;
+        IccFileHandler iccFh = phone.getIccFileHandler();
 
-	Log.v(LOG_TAG, "SIMRecords:fetchSimRecords " + recordsToLoad);
+        Log.v(LOG_TAG, "SIMRecords:fetchSimRecords " + recordsToLoad);
 
         phone.mCM.getIMSI(obtainMessage(EVENT_GET_IMSI_DONE));
         recordsToLoad++;
 
-        phone.mSIMFileHandler.loadEFTransparent(EF_ICCID, 
-                            obtainMessage(EVENT_GET_ICCID_DONE));
+        iccFh.loadEFTransparent(EF_ICCID, obtainMessage(EVENT_GET_ICCID_DONE));
         recordsToLoad++;
 
         // FIXME should examine EF[MSISDN]'s capability configuration
@@ -1283,17 +1239,14 @@
         recordsToLoad++;
 
         // Record number is subscriber profile
-        phone.mSIMFileHandler.loadEFLinearFixed(EF_MBI, 1, 
-                        obtainMessage(EVENT_GET_MBI_DONE));
+        iccFh.loadEFLinearFixed(EF_MBI, 1, obtainMessage(EVENT_GET_MBI_DONE));
         recordsToLoad++;
 
-        phone.mSIMFileHandler.loadEFTransparent(EF_AD,  
-                        obtainMessage(EVENT_GET_AD_DONE));
+        iccFh.loadEFTransparent(EF_AD, obtainMessage(EVENT_GET_AD_DONE));
         recordsToLoad++;
 
         // Record number is subscriber profile
-        phone.mSIMFileHandler.loadEFLinearFixed(EF_MWIS, 1, 
-                        obtainMessage(EVENT_GET_MWIS_DONE));
+        iccFh.loadEFLinearFixed(EF_MWIS, 1, obtainMessage(EVENT_GET_MWIS_DONE));
         recordsToLoad++;
 
 
@@ -1301,50 +1254,49 @@
         // the same info as EF[MWIS]. If both exist, both are updated
         // but the EF[MWIS] data is preferred
         // Please note this must be loaded after EF[MWIS]
-        phone.mSIMFileHandler.loadEFTransparent(
-                EF_VOICE_MAIL_INDICATOR_CPHS, 
+        iccFh.loadEFTransparent(
+                EF_VOICE_MAIL_INDICATOR_CPHS,
                 obtainMessage(EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE));
         recordsToLoad++;
 
         // Same goes for Call Forward Status indicator: fetch both
         // EF[CFIS] and CPHS-EF, with EF[CFIS] preferred.
-        phone.mSIMFileHandler.loadEFLinearFixed(EF_CFIS, 1, obtainMessage(EVENT_GET_CFIS_DONE));
+        iccFh.loadEFLinearFixed(EF_CFIS, 1, obtainMessage(EVENT_GET_CFIS_DONE));
         recordsToLoad++;
-        phone.mSIMFileHandler.loadEFTransparent(EF_CFF_CPHS,
-                obtainMessage(EVENT_GET_CFF_DONE));
+        iccFh.loadEFTransparent(EF_CFF_CPHS, obtainMessage(EVENT_GET_CFF_DONE));
         recordsToLoad++;
 
 
         getSpnFsm(true, null);
 
-        phone.mSIMFileHandler.loadEFTransparent(EF_SPDI, 
-            obtainMessage(EVENT_GET_SPDI_DONE));
+        iccFh.loadEFTransparent(EF_SPDI, obtainMessage(EVENT_GET_SPDI_DONE));
         recordsToLoad++;
 
-        phone.mSIMFileHandler.loadEFLinearFixed(EF_PNN, 1,
-            obtainMessage(EVENT_GET_PNN_DONE));
+        iccFh.loadEFLinearFixed(EF_PNN, 1, obtainMessage(EVENT_GET_PNN_DONE));
         recordsToLoad++;
 
-        phone.mSIMFileHandler.loadEFTransparent(EF_SST,
-            obtainMessage(EVENT_GET_SST_DONE));
+        iccFh.loadEFTransparent(EF_SST, obtainMessage(EVENT_GET_SST_DONE));
         recordsToLoad++;
 
-        phone.mSIMFileHandler.loadEFTransparent(EF_INFO_CPHS,
-                obtainMessage(EVENT_GET_INFO_CPHS_DONE));
+        iccFh.loadEFTransparent(EF_INFO_CPHS, obtainMessage(EVENT_GET_INFO_CPHS_DONE));
         recordsToLoad++;
 
         // XXX should seek instead of examining them all
         if (false) { // XXX
-            phone.mSIMFileHandler.loadEFLinearFixedAll(EF_SMS,
-                obtainMessage(EVENT_GET_ALL_SMS_DONE));
+            iccFh.loadEFLinearFixedAll(EF_SMS, obtainMessage(EVENT_GET_ALL_SMS_DONE));
             recordsToLoad++;
         }
 
         if (CRASH_RIL) {
-            String sms = "0107912160130310f20404d0110041007030208054832b0120ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";
-            byte[] ba = SimUtils.hexStringToBytes(sms);
+            String sms = "0107912160130310f20404d0110041007030208054832b0120"
+                         + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+                         + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+                         + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+                         + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+                         + "ffffffffffffffffffffffffffffff";
+            byte[] ba = IccUtils.hexStringToBytes(sms);
 
-            phone.mSIMFileHandler.updateEFLinearFixed(EF_SMS, 1, ba, null,
+            iccFh.updateEFLinearFixed(EF_SMS, 1, ba, null,
                             obtainMessage(EVENT_MARK_SMS_READ_DONE, 1));
         }
     }
@@ -1356,7 +1308,7 @@
      *
      * If the SPN is not found on the SIM, the rule is always PLMN_ONLY.
      */
-    int getDisplayRule(String plmn) {
+    protected int getDisplayRule(String plmn) {
         int rule;
         if (spn == null || spnDisplayCondition == -1) {
             // EF_SPN was not found on the SIM, or not yet loaded.  Just show ONS.
@@ -1431,7 +1383,7 @@
             case INIT:
                 spn = null;
 
-                phone.mSIMFileHandler.loadEFTransparent( EF_SPN,
+                phone.getIccFileHandler().loadEFTransparent( EF_SPN,
                         obtainMessage(EVENT_GET_SPN_DONE));
                 recordsToLoad++;
 
@@ -1441,20 +1393,20 @@
                 if (ar != null && ar.exception == null) {
                     data = (byte[]) ar.result;
                     spnDisplayCondition = 0xff & data[0];
-                    spn = SimUtils.adnStringFieldToString(data, 1, data.length - 1);
+                    spn = IccUtils.adnStringFieldToString(data, 1, data.length - 1);
 
                     if (DBG) log("Load EF_SPN: " + spn
                             + " spnDisplayCondition: " + spnDisplayCondition);
-                    phone.setSystemProperty(PROPERTY_SIM_OPERATOR_ALPHA, spn);
+                    phone.setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, spn);
 
                     spnState = Get_Spn_Fsm_State.IDLE;
                 } else {
-                    phone.mSIMFileHandler.loadEFTransparent( EF_SPN_CPHS,
+                    phone.getIccFileHandler().loadEFTransparent( EF_SPN_CPHS,
                             obtainMessage(EVENT_GET_SPN_DONE));
                     recordsToLoad++;
 
                     spnState = Get_Spn_Fsm_State.READ_SPN_CPHS;
-                    
+
                     // See TS 51.011 10.3.11.  Basically, default to
                     // show PLMN always, and SPN also if roaming.
                     spnDisplayCondition = -1;
@@ -1463,16 +1415,16 @@
             case READ_SPN_CPHS:
                 if (ar != null && ar.exception == null) {
                     data = (byte[]) ar.result;
-                    spn = SimUtils.adnStringFieldToString(
+                    spn = IccUtils.adnStringFieldToString(
                             data, 0, data.length - 1 );
 
                     if (DBG) log("Load EF_SPN_CPHS: " + spn);
-                    phone.setSystemProperty(PROPERTY_SIM_OPERATOR_ALPHA, spn);
+                    phone.setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, spn);
 
                     spnState = Get_Spn_Fsm_State.IDLE;
                 } else {
-                    phone.mSIMFileHandler.loadEFTransparent( EF_SPN_SHORT_CPHS,
-                            obtainMessage(EVENT_GET_SPN_DONE));
+                    phone.getIccFileHandler().loadEFTransparent(
+                            EF_SPN_SHORT_CPHS, obtainMessage(EVENT_GET_SPN_DONE));
                     recordsToLoad++;
 
                     spnState = Get_Spn_Fsm_State.READ_SPN_SHORT_CPHS;
@@ -1481,11 +1433,11 @@
             case READ_SPN_SHORT_CPHS:
                 if (ar != null && ar.exception == null) {
                     data = (byte[]) ar.result;
-                    spn = SimUtils.adnStringFieldToString(
+                    spn = IccUtils.adnStringFieldToString(
                             data, 0, data.length - 1);
 
                     if (DBG) log("Load EF_SPN_SHORT_CPHS: " + spn);
-                    phone.setSystemProperty(PROPERTY_SIM_OPERATOR_ALPHA, spn);
+                    phone.setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, spn);
                 }else {
                     if (DBG) log("No SPN loaded in either CHPS or 3GPP");
                 }
@@ -1503,8 +1455,7 @@
      * are treated specially when determining SPN display
      */
     private void
-    parseEfSpdi(byte[] data)
-    {
+    parseEfSpdi(byte[] data) {
         SimTlv tlv = new SimTlv(data, 0, data.length);
 
         byte[] plmnEntries = null;
@@ -1524,8 +1475,8 @@
         spdiNetworks = new ArrayList<String>(plmnEntries.length / 3);
 
         for (int i = 0 ; i + 2 < plmnEntries.length ; i += 3) {
-            String plmnCode;        
-            plmnCode = SimUtils.bcdToString(plmnEntries, i, 3);
+            String plmnCode;
+            plmnCode = IccUtils.bcdToString(plmnEntries, i, 3);
 
             // Valid operator codes are 5 or 6 digits
             if (plmnCode.length() >= 5) {
@@ -1543,7 +1494,11 @@
         return ((mCphsInfo[1] & CPHS_SST_MBN_MASK) == CPHS_SST_MBN_ENABLED );
     }
 
-    private void log(String s) {
+    protected void log(String s) {
         Log.d(LOG_TAG, "[SIMRecords] " + s);
     }
+
 }
+
+
+
diff --git a/telephony/java/com/android/internal/telephony/gsm/SMSDispatcher.java b/telephony/java/com/android/internal/telephony/gsm/SMSDispatcher.java
deleted file mode 100644
index 5585524..0000000
--- a/telephony/java/com/android/internal/telephony/gsm/SMSDispatcher.java
+++ /dev/null
@@ -1,979 +0,0 @@
-/*
- * Copyright (C) 2006 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.internal.telephony.gsm;
-
-import android.app.Activity;
-import android.app.PendingIntent;
-import android.app.AlertDialog;
-import android.app.PendingIntent.CanceledException;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
-import android.content.DialogInterface;
-import android.content.res.Resources;
-import android.database.Cursor;
-import android.database.SQLException;
-import android.net.Uri;
-import android.os.AsyncResult;
-import android.os.Handler;
-import android.os.Message;
-import android.os.PowerManager;
-import android.provider.Telephony;
-import android.provider.Settings;
-import android.provider.Telephony.Sms.Intents;
-import android.telephony.gsm.SmsMessage;
-import android.telephony.gsm.SmsManager;
-import com.android.internal.telephony.WapPushOverSms;
-import android.telephony.ServiceState;
-import android.util.Config;
-import com.android.internal.util.HexDump;
-import android.util.Log;
-import android.view.WindowManager;
-
-import java.io.ByteArrayOutputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Random;
-
-import com.android.internal.R;
-
-final class SMSDispatcher extends Handler {
-    private static final String TAG = "GSM";
-
-    /** Default checking period for SMS sent without uesr permit */
-    private static final int DEFAULT_SMS_CHECK_PERIOD = 3600000;
-
-    /** Default number of SMS sent in checking period without uesr permit */
-    private static final int DEFAULT_SMS_MAX_COUNT = 100;
-
-    /** Default timeout for SMS sent query */
-    private static final int DEFAULT_SMS_TIMOUEOUT = 6000;
-
-    private static final String[] RAW_PROJECTION = new String[] {
-        "pdu",
-        "sequence",
-    };
-
-    static final int MAIL_SEND_SMS = 1;
-
-    static final int EVENT_NEW_SMS = 1;
-
-    static final int EVENT_SEND_SMS_COMPLETE = 2;
-
-    /** Retry sending a previously failed SMS message */
-    static final int EVENT_SEND_RETRY = 3;
-
-    /** Status report received */
-    static final int EVENT_NEW_SMS_STATUS_REPORT = 5;
-
-    /** SIM storage is full */
-    static final int EVENT_SIM_FULL = 6;
-
-    /** SMS confirm required */
-    static final int EVENT_POST_ALERT = 7;
-
-    /** Send the user confirmed SMS */
-    static final int EVENT_SEND_CONFIRMED_SMS = 8;
-
-    /** Alert is timeout */
-    static final int EVENT_ALERT_TIMEOUT = 9;
-
-    private final GSMPhone mPhone;
-
-    private final WapPushOverSms mWapPush;
-
-    private final Context mContext;
-
-    private final ContentResolver mResolver;
-
-    private final CommandsInterface mCm;
-
-    private final Uri mRawUri = Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, "raw");
-
-    /** Maximum number of times to retry sending a failed SMS. */
-    private static final int MAX_SEND_RETRIES = 3;
-    /** Delay before next send attempt on a failed SMS, in milliseconds. */
-    private static final int SEND_RETRY_DELAY = 2000; 
-    /** single part SMS */
-    private static final int SINGLE_PART_SMS = 1;
-
-    /**
-     * Message reference for a CONCATENATED_8_BIT_REFERENCE or
-     * CONCATENATED_16_BIT_REFERENCE message set.  Should be
-     * incremented for each set of concatenated messages.
-     */
-    private static int sConcatenatedRef;
-
-    private SmsCounter mCounter;
-
-    private SmsTracker mSTracker;
-
-    /** Wake lock to ensure device stays awake while dispatching the SMS intent. */
-    private PowerManager.WakeLock mWakeLock;
-
-    /**
-     * Hold the wake lock for 5 seconds, which should be enough time for 
-     * any receiver(s) to grab its own wake lock.
-     */
-    private final int WAKE_LOCK_TIMEOUT = 5000;
-
-    /**
-     *  Implement the per-application based SMS control, which only allows
-     *  a limit on the number of SMS/MMS messages an app can send in checking
-     *  period.
-     */
-    private class SmsCounter {
-        private int mCheckPeriod;
-        private int mMaxAllowed;
-        private HashMap<String, ArrayList<Long>> mSmsStamp;
-
-        /**
-         * Create SmsCounter
-         * @param mMax is the number of SMS allowed without user permit
-         * @param mPeriod is the checking period
-         */
-        SmsCounter(int mMax, int mPeriod) {
-            mMaxAllowed = mMax;
-            mCheckPeriod = mPeriod;
-            mSmsStamp = new HashMap<String, ArrayList<Long>> ();
-        }
-
-        /**
-         * Check to see if an application allow to send new SMS messages
-         *  
-         * @param appName is the application sending sms
-         * @param smsWaiting is the number of new sms wants to be sent
-         * @return true if application is allowed to send the requested number 
-         *         of new sms messages 
-         */
-        boolean check(String appName, int smsWaiting) {
-            if (!mSmsStamp.containsKey(appName)) {
-                mSmsStamp.put(appName, new ArrayList<Long>());
-            }
-
-            return isUnderLimit(mSmsStamp.get(appName), smsWaiting);
-        }
-
-        private boolean isUnderLimit(ArrayList<Long> sent, int smsWaiting) {
-            Long ct =  System.currentTimeMillis();
-
-            Log.d(TAG, "SMS send size=" + sent.size() + "time=" + ct);
-
-            while (sent.size() > 0 && (ct - sent.get(0)) > mCheckPeriod ) {
-                    sent.remove(0);
-            }
-            
-            if ( (sent.size() + smsWaiting) <= mMaxAllowed) {
-                for (int i = 0; i < smsWaiting; i++ ) {
-                    sent.add(ct);
-                }
-                return true;
-            }
-            return false;
-        }
-    }
-
-    SMSDispatcher(GSMPhone phone) {
-        mPhone = phone;
-        mWapPush = new WapPushOverSms(phone);
-        mContext = phone.getContext();
-        mResolver = mContext.getContentResolver();
-        mCm = phone.mCM;
-        mSTracker = null;
-
-        createWakelock();
-
-        int check_period = Settings.Gservices.getInt(mResolver,
-                Settings.Gservices.SMS_OUTGOING_CEHCK_INTERVAL_MS,
-                DEFAULT_SMS_CHECK_PERIOD);
-        int max_count = Settings.Gservices.getInt(mResolver,
-                Settings.Gservices.SMS_OUTGOING_CEHCK_MAX_COUNT,
-                DEFAULT_SMS_MAX_COUNT);
-        mCounter = new SmsCounter(max_count, check_period);
-
-        mCm.setOnNewSMS(this, EVENT_NEW_SMS, null);
-        mCm.setOnSmsStatus(this, EVENT_NEW_SMS_STATUS_REPORT, null);
-        mCm.setOnSimSmsFull(this, EVENT_SIM_FULL, null);
-
-        // Don't always start message ref at 0.
-        sConcatenatedRef = new Random().nextInt(256);
-    }
-
-    /* TODO: Need to figure out how to keep track of status report routing in a
-     *       persistent manner. If the phone process restarts (reboot or crash),
-     *       we will lose this list and any status reports that come in after
-     *       will be dropped.
-     */
-    /** Sent messages awaiting a delivery status report. */
-    private final ArrayList<SmsTracker> deliveryPendingList = new ArrayList<SmsTracker>();
-
-    /**
-     * Handles events coming from the phone stack. Overridden from handler.
-     *
-     * @param msg the message to handle
-     */
-    @Override
-    public void handleMessage(Message msg) {
-        AsyncResult ar;
-
-        switch (msg.what) {
-        case EVENT_NEW_SMS:
-            // A new SMS has been received by the device
-            if (Config.LOGD) {
-                Log.d(TAG, "New SMS Message Received");
-            }
-
-            SmsMessage sms;
-
-            ar = (AsyncResult) msg.obj;
-
-            // FIXME unit test leaves cm == null. this should change
-            if (mCm != null) {
-                // FIXME only acknowledge on store
-                mCm.acknowledgeLastIncomingSMS(true, null);
-            }
-
-            if (ar.exception != null) {
-                Log.e(TAG, "Exception processing incoming SMS. Exception:" + ar.exception);
-                return;
-            }
-
-            sms = (SmsMessage) ar.result;
-            dispatchMessage(sms);
-
-            break;
-
-        case EVENT_SEND_SMS_COMPLETE:
-            // An outbound SMS has been sucessfully transferred, or failed.
-            handleSendComplete((AsyncResult) msg.obj);
-            break;
-
-        case EVENT_SEND_RETRY:
-            sendSms((SmsTracker) msg.obj);
-            break;
-
-        case EVENT_NEW_SMS_STATUS_REPORT:
-            handleStatusReport((AsyncResult)msg.obj);
-            break;
-
-        case EVENT_SIM_FULL:
-            handleSimFull();
-            break;
-
-        case EVENT_POST_ALERT:
-            handleReachSentLimit((SmsTracker)(msg.obj));
-            break;
-
-        case EVENT_ALERT_TIMEOUT:
-            ((AlertDialog)(msg.obj)).dismiss();
-            msg.obj = null;
-            mSTracker = null;
-            break;
-
-        case EVENT_SEND_CONFIRMED_SMS:
-            if (mSTracker!=null) {
-                if (isMultipartTracker(mSTracker)) {
-                    sendMultipartSms(mSTracker);
-                } else {
-                    sendSms(mSTracker);
-                } 
-                mSTracker = null;
-            }
-            break;
-        }
-    }
-
-    private void createWakelock() {
-        PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
-        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "SMSDispatcher");
-        mWakeLock.setReferenceCounted(true);
-    }
-
-    private void sendBroadcast(Intent intent, String permission) {
-        // Hold a wake lock for WAKE_LOCK_TIMEOUT seconds, enough to give any
-        // receivers time to take their own wake locks.
-        mWakeLock.acquire(WAKE_LOCK_TIMEOUT);
-        mContext.sendBroadcast(intent, permission);
-    }
-
-    /**
-     * Called when SIM_FULL message is received from the RIL.  Notifies interested
-     * parties that SIM storage for SMS messages is full.
-     */
-    private void handleSimFull() {
-        // broadcast SIM_FULL intent
-        Intent intent = new Intent(Intents.SIM_FULL_ACTION);
-        sendBroadcast(intent, "android.permission.RECEIVE_SMS");
-    }
-
-    /**
-     * Called when a status report is received.  This should correspond to
-     * a previously successful SEND.
-     *
-     * @param ar AsyncResult passed into the message handler.  ar.result should
-     *           be a String representing the status report PDU, as ASCII hex.
-     */
-    private void handleStatusReport(AsyncResult ar) {
-        String pduString = (String) ar.result;
-        SmsMessage sms = SmsMessage.newFromCDS(pduString);
-
-        if (sms != null) {
-            int messageRef = sms.messageRef;
-            for (int i = 0, count = deliveryPendingList.size(); i < count; i++) {
-                SmsTracker tracker = deliveryPendingList.get(i);
-                if (tracker.mMessageRef == messageRef) {
-                    // Found it.  Remove from list and broadcast.
-                    deliveryPendingList.remove(i);
-                    PendingIntent intent = tracker.mDeliveryIntent;
-                    Intent fillIn = new Intent();
-                    fillIn.putExtra("pdu", SimUtils.hexStringToBytes(pduString));
-                    try {
-                        intent.send(mContext, Activity.RESULT_OK, fillIn);
-                    } catch (CanceledException ex) {}
-
-                    // Only expect to see one tracker matching this messageref
-                    break;
-                }
-            }
-        }
-
-        if (mCm != null) {
-            mCm.acknowledgeLastIncomingSMS(true, null);
-        }
-    }
-
-    /**
-     * Called when SMS send completes. Broadcasts a sentIntent on success.
-     * On failure, either sets up retries or broadcasts a sentIntent with
-     * the failure in the result code.
-     *
-     * @param ar AsyncResult passed into the message handler.  ar.result should
-     *           an SmsResponse instance if send was successful.  ar.userObj
-     *           should be an SmsTracker instance.
-     */
-    private void handleSendComplete(AsyncResult ar) {
-        SmsTracker tracker = (SmsTracker) ar.userObj;
-        PendingIntent sentIntent = tracker.mSentIntent;
-
-        if (ar.exception == null) {
-            if (Config.LOGD) {
-                Log.d(TAG, "SMS send complete. Broadcasting "
-                        + "intent: " + sentIntent);
-            }
-
-            if (tracker.mDeliveryIntent != null) {
-                // Expecting a status report.  Add it to the list.
-                int messageRef = ((SmsResponse)ar.result).messageRef;
-                tracker.mMessageRef = messageRef;
-                deliveryPendingList.add(tracker);
-            }
-
-            if (sentIntent != null) {
-                try {
-                    sentIntent.send(Activity.RESULT_OK);
-                } catch (CanceledException ex) {}
-            }
-        } else {
-            if (Config.LOGD) {
-                Log.d(TAG, "SMS send failed");
-            }
-
-            int ss = mPhone.getServiceState().getState();
-
-            if (ss != ServiceState.STATE_IN_SERVICE) {
-                handleNotInService(ss, tracker);
-            } else if ((((CommandException)(ar.exception)).getCommandError()
-                    == CommandException.Error.SMS_FAIL_RETRY) &&
-                   tracker.mRetryCount < MAX_SEND_RETRIES) {
-                // Retry after a delay if needed.
-                // TODO: According to TS 23.040, 9.2.3.6, we should resend
-                //       with the same TP-MR as the failed message, and
-                //       TP-RD set to 1.  However, we don't have a means of
-                //       knowing the MR for the failed message (EF_SMSstatus
-                //       may or may not have the MR corresponding to this
-                //       message, depending on the failure).  Also, in some
-                //       implementations this retry is handled by the baseband.
-                tracker.mRetryCount++;
-                Message retryMsg = obtainMessage(EVENT_SEND_RETRY, tracker);
-                sendMessageDelayed(retryMsg, SEND_RETRY_DELAY);
-            } else if (tracker.mSentIntent != null) {
-                // Done retrying; return an error to the app.
-                try {
-                    tracker.mSentIntent.send(SmsManager.RESULT_ERROR_GENERIC_FAILURE);
-                } catch (CanceledException ex) {}
-            }
-        }
-    }
-
-    /**
-     * Handles outbound message when the phone is not in service.
-     *
-     * @param ss     Current service state.  Valid values are:
-     *                  OUT_OF_SERVICE
-     *                  EMERGENCY_ONLY
-     *                  POWER_OFF
-     * @param tracker   An SmsTracker for the current message.
-     */
-    private void handleNotInService(int ss, SmsTracker tracker) {
-        if (tracker.mSentIntent != null) {
-            try {
-                if (ss == ServiceState.STATE_POWER_OFF) {
-                    tracker.mSentIntent.send(SmsManager.RESULT_ERROR_RADIO_OFF);
-                } else {
-                    tracker.mSentIntent.send(SmsManager.RESULT_ERROR_NO_SERVICE);
-                }
-            } catch (CanceledException ex) {}
-        }
-    }
-
-    /**
-     * Dispatches an incoming SMS messages.
-     *
-     * @param sms the incoming message from the phone
-     */
-    /* package */ void dispatchMessage(SmsMessage sms) {
-
-        // If sms is null, means there was a parsing error.
-        // TODO: Should NAK this.
-        if (sms == null) {
-            return;
-        }
-
-        boolean handled = false;
-
-        // Special case the message waiting indicator messages
-        if (sms.isMWISetMessage()) {
-            mPhone.updateMessageWaitingIndicator(true);
-
-            if (sms.isMwiDontStore()) {
-                handled = true;
-            }
-
-            if (Config.LOGD) {
-                Log.d(TAG,
-                        "Received voice mail indicator set SMS shouldStore="
-                         + !handled);
-            }
-        } else if (sms.isMWIClearMessage()) {
-            mPhone.updateMessageWaitingIndicator(false);
-
-            if (sms.isMwiDontStore()) {
-                handled = true;
-            }
-
-            if (Config.LOGD) {
-                Log.d(TAG,
-                        "Received voice mail indicator clear SMS shouldStore="
-                        + !handled);
-            }
-        }
-
-        if (handled) {
-            return;
-        }
-
-        // Parse the headers to see if this is partial, or port addressed
-        int referenceNumber = -1;
-        int count = 0;
-        int sequence = 0;
-        int destPort = -1;
-
-        SmsHeader header = sms.getUserDataHeader();
-        if (header != null) {
-            for (SmsHeader.Element element : header.getElements()) {
-                try {
-                    switch (element.getID()) {
-                        case SmsHeader.CONCATENATED_8_BIT_REFERENCE: {
-                            byte[] data = element.getData();
-                            
-                            referenceNumber = data[0] & 0xff;
-                            count = data[1] & 0xff;
-                            sequence = data[2] & 0xff;
-                            
-                            // Per TS 23.040, 9.2.3.24.1: If the count is zero, sequence
-                            // is zero, or sequence > count, ignore the entire element
-                            if (count == 0 || sequence == 0 || sequence > count) {
-                                referenceNumber = -1;
-                            }
-                            break;
-                        }
-                        
-                        case SmsHeader.CONCATENATED_16_BIT_REFERENCE: {
-                            byte[] data = element.getData();
-                            
-                            referenceNumber = (data[0] & 0xff) * 256 + (data[1] & 0xff);
-                            count = data[2] & 0xff;
-                            sequence = data[3] & 0xff;
-                            
-                            // Per TS 23.040, 9.2.3.24.8: If the count is zero, sequence
-                            // is zero, or sequence > count, ignore the entire element
-                            if (count == 0 || sequence == 0 || sequence > count) {
-                                referenceNumber = -1;
-                            }
-                            break;
-                        }
-                        
-                        case SmsHeader.APPLICATION_PORT_ADDRESSING_16_BIT: {
-                            byte[] data = element.getData();
-                            
-                            destPort = (data[0] & 0xff) << 8;
-                            destPort |= (data[1] & 0xff);
-                            
-                            break;
-                        }
-                    }
-                } catch (ArrayIndexOutOfBoundsException e) {
-                    Log.e(TAG, "Bad element in header", e);
-                    return;  // TODO: NACK the message or something, don't just discard.
-                }
-            }
-        }
-
-        if (referenceNumber == -1) {
-            // notify everyone of the message if it isn't partial
-            byte[][] pdus = new byte[1][];
-            pdus[0] = sms.getPdu();
-
-            if (destPort != -1) {
-                if (destPort == SmsHeader.PORT_WAP_PUSH) {
-                    mWapPush.dispatchWapPdu(sms.getUserData());
-                }
-                // The message was sent to a port, so concoct a URI for it
-                dispatchPortAddressedPdus(pdus, destPort);
-            } else {
-                // It's a normal message, dispatch it
-                dispatchPdus(pdus);
-            }
-        } else {
-            // Process the message part
-            processMessagePart(sms, referenceNumber, sequence, count, destPort);
-        }
-    }
-
-    /**
-     * If this is the last part send the parts out to the application, otherwise
-     * the part is stored for later processing.
-     */
-    private void processMessagePart(SmsMessage sms, int referenceNumber,
-            int sequence, int count, int destinationPort) {
-        // Lookup all other related parts
-        StringBuilder where = new StringBuilder("reference_number =");
-        where.append(referenceNumber);
-        where.append(" AND address = ?");
-        String[] whereArgs = new String[] {sms.getOriginatingAddress()};
-
-        byte[][] pdus = null;
-        Cursor cursor = null;
-        try {
-            cursor = mResolver.query(mRawUri, RAW_PROJECTION, where.toString(), whereArgs, null);
-            int cursorCount = cursor.getCount();
-            if (cursorCount != count - 1) {
-                // We don't have all the parts yet, store this one away
-                ContentValues values = new ContentValues();
-                values.put("date", new Long(sms.getTimestampMillis()));
-                values.put("pdu", HexDump.toHexString(sms.getPdu()));
-                values.put("address", sms.getOriginatingAddress());
-                values.put("reference_number", referenceNumber);
-                values.put("count", count);
-                values.put("sequence", sequence);
-                if (destinationPort != -1) {
-                    values.put("destination_port", destinationPort);
-                }
-                mResolver.insert(mRawUri, values);
-
-                return;
-            }
-
-            // All the parts are in place, deal with them
-            int pduColumn = cursor.getColumnIndex("pdu");
-            int sequenceColumn = cursor.getColumnIndex("sequence");
-
-            pdus = new byte[count][];
-            for (int i = 0; i < cursorCount; i++) {
-                cursor.moveToNext();
-                int cursorSequence = (int)cursor.getLong(sequenceColumn);
-                pdus[cursorSequence - 1] = HexDump.hexStringToByteArray(
-                        cursor.getString(pduColumn));
-            }
-            // This one isn't in the DB, so add it
-            pdus[sequence - 1] = sms.getPdu();
-
-            // Remove the parts from the database
-            mResolver.delete(mRawUri, where.toString(), whereArgs);
-        } catch (SQLException e) {
-            Log.e(TAG, "Can't access multipart SMS database", e);
-            return;  // TODO: NACK the message or something, don't just discard.
-        } finally {
-            if (cursor != null) cursor.close();
-        }
-
-        // Dispatch the PDUs to applications
-        switch (destinationPort) {
-        case SmsHeader.PORT_WAP_PUSH: {
-            // Build up the data stream
-            ByteArrayOutputStream output = new ByteArrayOutputStream();
-            for (int i = 0; i < count; i++) {
-                SmsMessage msg = SmsMessage.createFromPdu(pdus[i]);
-                byte[] data = msg.getUserData();
-                output.write(data, 0, data.length);
-            }
-
-            // Handle the PUSH
-            mWapPush.dispatchWapPdu(output.toByteArray());
-            break;
-        }
-
-        case -1:
-            // The messages were not sent to a port
-            dispatchPdus(pdus);
-            break;
-
-        default:
-            // The messages were sent to a port, so concoct a URI for it
-            dispatchPortAddressedPdus(pdus, destinationPort);
-            break;
-        }
-    }
-
-    /**
-     * Dispatches standard PDUs to interested applications
-     *
-     * @param pdus The raw PDUs making up the message
-     */
-    private void dispatchPdus(byte[][] pdus) {
-        Intent intent = new Intent(Intents.SMS_RECEIVED_ACTION);
-        intent.putExtra("pdus", pdus);
-        sendBroadcast(intent, "android.permission.RECEIVE_SMS");
-    }
-
-    /**
-     * Dispatches port addressed PDUs to interested applications
-     *
-     * @param pdus The raw PDUs making up the message
-     * @param port The destination port of the messages
-     */
-    private void dispatchPortAddressedPdus(byte[][] pdus, int port) {
-        Uri uri = Uri.parse("sms://localhost:" + port);
-        Intent intent = new Intent(Intents.DATA_SMS_RECEIVED_ACTION, uri);
-        intent.putExtra("pdus", pdus);
-        sendBroadcast(intent, "android.permission.RECEIVE_SMS");
-    }
-
-
-    /**
-     * Send a multi-part text based SMS.
-     *
-     * @param destinationAddress the address to send the message to
-     * @param scAddress is the service center address or null to use
-     *   the current default SMSC
-     * @param parts an <code>ArrayList</code> of strings that, in order,
-     *   comprise the original message
-     * @param sentIntents if not null, an <code>ArrayList</code> of
-     *   <code>PendingIntent</code>s (one for each message part) that is
-     *   broadcast when the corresponding message part has been sent.
-     *   The result code will be <code>Activity.RESULT_OK<code> for success,
-     *   or one of these errors:
-     *   <code>RESULT_ERROR_GENERIC_FAILURE</code>
-     *   <code>RESULT_ERROR_RADIO_OFF</code>
-     *   <code>RESULT_ERROR_NULL_PDU</code>.
-     *  The per-application based SMS control checks sentIntent. If sentIntent
-     *  is NULL the caller will be checked against all unknown applicaitons,
-     *  which cause smaller number of SMS to be sent in checking period.
-     * @param deliveryIntents if not null, an <code>ArrayList</code> of
-     *   <code>PendingIntent</code>s (one for each message part) that is
-     *   broadcast when the corresponding message part has been delivered
-     *   to the recipient.  The raw pdu of the status report is in the
-     *   extended data ("pdu").
-     */
-    void sendMultipartText(String destinationAddress, String scAddress, ArrayList<String> parts,
-            ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) {
-
-        PendingIntent sentIntent = null;
-        
-        
-        int ss = mPhone.getServiceState().getState();
-        
-        if (ss == ServiceState.STATE_IN_SERVICE) {
-            // Only check SMS sending limit while in service
-            if (sentIntents != null && sentIntents.size() > 0) {
-                sentIntent = sentIntents.get(0);
-            }
-            String appName = getAppNameByIntent(sentIntent);
-            if ( !mCounter.check(appName, parts.size())) {
-                HashMap<String, Object> map = new HashMap<String, Object>();
-                map.put("destination", destinationAddress);
-                map.put("scaddress", scAddress);
-                map.put("parts", parts);
-                map.put("sentIntents", sentIntents);
-                map.put("deliveryIntents", deliveryIntents);
-                
-                SmsTracker multipartParameter = new SmsTracker(map, null, null);
-
-                sendMessage(obtainMessage(EVENT_POST_ALERT, multipartParameter));
-                return;
-            }
-        }
-        
-        sendMultipartTextWithPermit(destinationAddress, 
-                scAddress, parts, sentIntents, deliveryIntents);
-    }
-
-    /**
-     * Send a multi-part text based SMS which already passed SMS control check.
-     *
-     * It is the working function for sendMultipartText().
-     * 
-     * @param destinationAddress the address to send the message to
-     * @param scAddress is the service center address or null to use
-     *   the current default SMSC
-     * @param parts an <code>ArrayList</code> of strings that, in order,
-     *   comprise the original message
-     * @param sentIntents if not null, an <code>ArrayList</code> of
-     *   <code>PendingIntent</code>s (one for each message part) that is
-     *   broadcast when the corresponding message part has been sent.
-     *   The result code will be <code>Activity.RESULT_OK<code> for success,
-     *   or one of these errors:
-     *   <code>RESULT_ERROR_GENERIC_FAILURE</code>
-     *   <code>RESULT_ERROR_RADIO_OFF</code>
-     *   <code>RESULT_ERROR_NULL_PDU</code>.
-     * @param deliveryIntents if not null, an <code>ArrayList</code> of
-     *   <code>PendingIntent</code>s (one for each message part) that is
-     *   broadcast when the corresponding message part has been delivered
-     *   to the recipient.  The raw pdu of the status report is in the
-     *   extended data ("pdu").
-     */
-    private void sendMultipartTextWithPermit(String destinationAddress, 
-            String scAddress, ArrayList<String> parts,
-            ArrayList<PendingIntent> sentIntents, 
-            ArrayList<PendingIntent> deliveryIntents) {
-        
-        PendingIntent sentIntent = null;
-        PendingIntent deliveryIntent = null;
-        
-        // check if in service
-        int ss = mPhone.getServiceState().getState();
-        if (ss != ServiceState.STATE_IN_SERVICE) {
-            for (int i = 0, count = parts.size(); i < count; i++) {
-                if (sentIntents != null && sentIntents.size() > i) {
-                    sentIntent = sentIntents.get(i);
-                }
-                SmsTracker tracker = new SmsTracker(null, sentIntent, null);
-                handleNotInService(ss, tracker);
-            }
-            return;
-        }
-
-        int ref = ++sConcatenatedRef & 0xff;
-
-        for (int i = 0, count = parts.size(); i < count; i++) {
-            // build SmsHeader
-            byte[] data = new byte[3];
-            data[0] = (byte) ref;   // reference #, unique per message
-            data[1] = (byte) count; // total part count
-            data[2] = (byte) (i + 1);  // 1-based sequence
-            SmsHeader header = new SmsHeader();
-            header.add(new SmsHeader.Element(SmsHeader.CONCATENATED_8_BIT_REFERENCE, data));
- 
-            if (sentIntents != null && sentIntents.size() > i) {
-                sentIntent = sentIntents.get(i);
-            }
-            if (deliveryIntents != null && deliveryIntents.size() > i) {
-                deliveryIntent = deliveryIntents.get(i);
-            }
-
-            SmsMessage.SubmitPdu pdus = SmsMessage.getSubmitPdu(scAddress, destinationAddress,
-                    parts.get(i), deliveryIntent != null, header.toByteArray());
-
-            HashMap<String, Object> map = new HashMap<String, Object>();
-            map.put("smsc", pdus.encodedScAddress);
-            map.put("pdu", pdus.encodedMessage);
-
-            SmsTracker tracker = new SmsTracker(map, sentIntent,
-                    deliveryIntent);
-            sendSms(tracker);
-        }        
-    }
-
-    /**
-     * Send a SMS
-     *
-     * @param smsc the SMSC to send the message through, or NULL for the
-     *  defatult SMSC
-     * @param pdu the raw PDU to send
-     * @param sentIntent if not NULL this <code>Intent</code> is
-     *  broadcast when the message is sucessfully sent, or failed.
-     *  The result code will be <code>Activity.RESULT_OK<code> for success,
-     *  or one of these errors:
-     *  <code>RESULT_ERROR_GENERIC_FAILURE</code>
-     *  <code>RESULT_ERROR_RADIO_OFF</code>
-     *  <code>RESULT_ERROR_NULL_PDU</code>.
-     *  The per-application based SMS control checks sentIntent. If sentIntent
-     *  is NULL the caller will be checked against all unknown applicaitons,
-     *  which cause smaller number of SMS to be sent in checking period.
-     * @param deliveryIntent if not NULL this <code>Intent</code> is
-     *  broadcast when the message is delivered to the recipient.  The
-     *  raw pdu of the status report is in the extended data ("pdu").
-     */
-    void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent,
-            PendingIntent deliveryIntent) {
-        if (pdu == null) {
-            if (sentIntent != null) {
-                try {
-                    sentIntent.send(SmsManager.RESULT_ERROR_NULL_PDU);
-                } catch (CanceledException ex) {}
-            }
-            return;
-        }
-
-        HashMap<String, Object> map = new HashMap<String, Object>();
-        map.put("smsc", smsc);
-        map.put("pdu", pdu);
-
-        SmsTracker tracker = new SmsTracker(map, sentIntent,
-                deliveryIntent);
-        int ss = mPhone.getServiceState().getState();
-
-        if (ss != ServiceState.STATE_IN_SERVICE) {
-            handleNotInService(ss, tracker);
-        } else {
-            String appName = getAppNameByIntent(sentIntent);
-            if (mCounter.check(appName, SINGLE_PART_SMS)) {
-                sendSms(tracker);
-            } else {
-                sendMessage(obtainMessage(EVENT_POST_ALERT, tracker));
-            }
-        }
-    }
-
-    /**
-     * Post an alert while SMS needs user confirm.
-     *
-     * An SmsTracker for the current message.
-     */
-    private void handleReachSentLimit(SmsTracker tracker) {
-
-        Resources r = Resources.getSystem();
-
-        String appName = getAppNameByIntent(tracker.mSentIntent);
-
-        AlertDialog d = new AlertDialog.Builder(mContext)
-                .setTitle(r.getString(R.string.sms_control_title))
-                .setMessage(appName + " " + r.getString(R.string.sms_control_message))
-                .setPositiveButton(r.getString(R.string.sms_control_yes), mListener)
-                .setNegativeButton(r.getString(R.string.sms_control_no), null)
-                .create();
-
-        d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
-        d.show();
-
-        mSTracker = tracker;
-        sendMessageDelayed ( obtainMessage(EVENT_ALERT_TIMEOUT, d),
-                DEFAULT_SMS_TIMOUEOUT);
-    }
-
-    private String getAppNameByIntent(PendingIntent intent) {
-        Resources r = Resources.getSystem();
-        return (intent != null) ? intent.getTargetPackage()
-            : r.getString(R.string.sms_control_default_app_name);
-    }
-
-    /**
-     * Send the message along to the radio.
-     *
-     * @param tracker holds the SMS message to send
-     */
-    private void sendSms(SmsTracker tracker) {
-        HashMap map = tracker.mData;
-
-        byte smsc[] = (byte[]) map.get("smsc");
-        byte pdu[] = (byte[]) map.get("pdu");
-
-        Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);
-        mCm.sendSMS(SimUtils.bytesToHexString(smsc),
-                SimUtils.bytesToHexString(pdu), reply);
-    }
-
-    /**
-     * Send the multi-part SMS based on multipart Sms tracker
-     * 
-     * @param tracker holds the multipart Sms tracker ready to be sent
-     */
-    private void sendMultipartSms (SmsTracker tracker) {
-        ArrayList<String> parts;
-        ArrayList<PendingIntent> sentIntents;
-        ArrayList<PendingIntent> deliveryIntents;
-        
-        HashMap map = tracker.mData;
-        
-        String destinationAddress = (String) map.get("destination");
-        String scAddress = (String) map.get("scaddress");
-        
-        parts = (ArrayList<String>) map.get("parts");
-        sentIntents = (ArrayList<PendingIntent>) map.get("sentIntents");
-        deliveryIntents = (ArrayList<PendingIntent>) map.get("deliveryIntents");
-     
-        sendMultipartTextWithPermit(destinationAddress, 
-                scAddress, parts, sentIntents, deliveryIntents);
-
-    }
-    
-    /**
-     * Check if a SmsTracker holds multi-part Sms
-     * 
-     * @param tracker a SmsTracker could hold a multi-part Sms
-     * @return true for tracker holds Multi-parts Sms
-     */
-    private boolean isMultipartTracker (SmsTracker tracker) {
-        HashMap map = tracker.mData;
-        return ( map.get("parts") != null);
-    }
-    
-    /**
-     * Keeps track of an SMS that has been sent to the RIL, until it it has
-     * successfully been sent, or we're done trying.
-     *
-     */
-    static class SmsTracker {
-        HashMap mData;
-        int mRetryCount;
-        int mMessageRef;
-
-        PendingIntent mSentIntent;
-        PendingIntent mDeliveryIntent;
-
-        SmsTracker(HashMap data, PendingIntent sentIntent,
-                PendingIntent deliveryIntent) {
-            mData = data;
-            mSentIntent = sentIntent;
-            mDeliveryIntent = deliveryIntent;
-            mRetryCount = 0;
-        }
-
-    }
-
-    private DialogInterface.OnClickListener mListener =
-            new DialogInterface.OnClickListener() {
-
-                public void onClick(DialogInterface dialog, int which) {
-                    if (which == DialogInterface.BUTTON_POSITIVE) {
-                        Log.d(TAG, "click YES to send out sms");
-                        sendMessage(obtainMessage(EVENT_SEND_CONFIRMED_SMS));
-                    }
-                }
-            };
-}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSimCard.java b/telephony/java/com/android/internal/telephony/gsm/SimCard.java
similarity index 86%
rename from telephony/java/com/android/internal/telephony/gsm/GsmSimCard.java
rename to telephony/java/com/android/internal/telephony/gsm/SimCard.java
index a4cded9..9af3aa6 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmSimCard.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SimCard.java
@@ -16,6 +16,9 @@
 
 package com.android.internal.telephony.gsm;
 
+import android.app.ActivityManagerNative;
+import android.content.Intent;
+import android.content.res.Configuration;
 import android.os.AsyncResult;
 import android.os.RemoteException;
 import android.os.Handler;
@@ -23,32 +26,34 @@
 import android.os.Registrant;
 import android.os.RegistrantList;
 import android.util.Log;
-import com.android.internal.telephony.SimCard;
-import com.android.internal.telephony.TelephonyProperties;
+
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.IccCard;
 import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneProxy;
 import com.android.internal.telephony.TelephonyIntents;
-import android.content.Intent;
-import android.content.res.Configuration;
-import android.app.ActivityManagerNative;
+import com.android.internal.telephony.TelephonyProperties;
 
 import static android.Manifest.permission.READ_PHONE_STATE;
 
 /**
+ * Note: this class shares common code with RuimCard, consider a base class to minimize code
+ * duplication.
  * {@hide}
  */
-public final class GsmSimCard extends Handler implements SimCard {
+public final class SimCard extends Handler implements IccCard {
     static final String LOG_TAG="GSM";
-    
+
     //***** Instance Variables
     private static final boolean DBG = true;
 
     private GSMPhone phone;
-    private CommandsInterface.SimStatus status = null;
+    private CommandsInterface.IccStatus status = null;
+    private boolean mDesiredPinLocked;
+    private boolean mDesiredFdnEnabled;
     private boolean mSimPinLocked = true; // Default to locked
     private boolean mSimFdnEnabled = false; // Default to disabled.
                                             // Will be updated when SIM_READY.
-    private boolean mDesiredPinLocked;
-    private boolean mDesiredFdnEnabled;
 
     //***** Constants
 
@@ -72,8 +77,7 @@
 
     //***** Constructor
 
-    GsmSimCard(GSMPhone phone)
-    {
+    SimCard(GSMPhone phone) {
         this.phone = phone;
 
         phone.mCM.registerForSIMLockedOrAbsent(
@@ -87,12 +91,22 @@
 
         updateStateProperty();
     }
-    
+
+    public void dispose() {
+        //Unregister for all events
+        phone.mCM.unregisterForSIMLockedOrAbsent(this);
+        phone.mCM.unregisterForOffOrNotAvailable(this);
+        phone.mCM.unregisterForSIMReady(this);
+    }
+
+    protected void finalize() {
+        if(DBG) Log.d(LOG_TAG, "SimCard finalized");
+    }
+
     //***** SimCard implementation
 
     public State
-    getState()
-    {
+    getState() {
         if (status == null) {
             switch(phone.mCM.getRadioState()) {
                 /* This switch block must not return anything in
@@ -111,12 +125,12 @@
             }
         } else {
             switch (status) {
-                case SIM_ABSENT:            return State.ABSENT;
-                case SIM_NOT_READY:         return State.UNKNOWN;
-                case SIM_READY:             return State.READY;
-                case SIM_PIN:               return State.PIN_REQUIRED;
-                case SIM_PUK:               return State.PUK_REQUIRED;
-                case SIM_NETWORK_PERSONALIZATION: return State.NETWORK_LOCKED;
+                case ICC_ABSENT:            return State.ABSENT;
+                case ICC_NOT_READY:         return State.UNKNOWN;
+                case ICC_READY:             return State.READY;
+                case ICC_PIN:               return State.PIN_REQUIRED;
+                case ICC_PUK:               return State.PUK_REQUIRED;
+                case ICC_NETWORK_PERSONALIZATION: return State.NETWORK_LOCKED;
             }
         }
 
@@ -129,8 +143,7 @@
     private RegistrantList networkLockedRegistrants = new RegistrantList();
 
 
-    public void registerForAbsent(Handler h, int what, Object obj)
-    {
+    public void registerForAbsent(Handler h, int what, Object obj) {
         Registrant r = new Registrant (h, what, obj);
 
         absentRegistrants.add(r);
@@ -139,9 +152,9 @@
             r.notifyRegistrant();
         }
     }
-    
+
     public void unregisterForAbsent(Handler h) {
-    	absentRegistrants.remove(h);
+        absentRegistrants.remove(h);
     }
 
     public void registerForNetworkLocked(Handler h, int what, Object obj) {
@@ -155,11 +168,10 @@
     }
 
     public void unregisterForNetworkLocked(Handler h) {
-    	networkLockedRegistrants.remove(h);
+        networkLockedRegistrants.remove(h);
     }
-    
-    public void registerForLocked(Handler h, int what, Object obj)
-    {
+
+    public void registerForLocked(Handler h, int what, Object obj) {
         Registrant r = new Registrant (h, what, obj);
 
         pinLockedRegistrants.add(r);
@@ -169,50 +181,44 @@
         }
     }
 
-    public void unregisterForLocked(Handler h)
-    {
+    public void unregisterForLocked(Handler h) {
         pinLockedRegistrants.remove(h);
     }
 
 
-    public void supplyPin (String pin, Message onComplete)
-    {
-        phone.mCM.supplySimPin(pin, 
+    public void supplyPin (String pin, Message onComplete) {
+        phone.mCM.supplyIccPin(pin,
                             obtainMessage(EVENT_PINPUK_DONE, onComplete));
     }
 
-    public void supplyPuk (String puk, String newPin, Message onComplete)
-    {
-        phone.mCM.supplySimPuk(puk, newPin,
+    public void supplyPuk (String puk, String newPin, Message onComplete) {
+        phone.mCM.supplyIccPuk(puk, newPin,
                         obtainMessage(EVENT_PINPUK_DONE, onComplete));
     }
-    public void supplyPin2 (String pin2, Message onComplete)
-    {
-        phone.mCM.supplySimPin2(pin2, 
+    public void supplyPin2 (String pin2, Message onComplete) {
+        phone.mCM.supplyIccPin2(pin2,
                         obtainMessage(EVENT_PINPUK_DONE, onComplete));
     }
-    public void supplyPuk2 (String puk2, String newPin2, Message onComplete)
-    {
-        phone.mCM.supplySimPuk2(puk2, newPin2,
+    public void supplyPuk2 (String puk2, String newPin2, Message onComplete) {
+        phone.mCM.supplyIccPuk2(puk2, newPin2,
                 obtainMessage(EVENT_PINPUK_DONE, onComplete));
     }
 
-    public void supplyNetworkDepersonalization (String pin, Message onComplete)
-    {
+    public void supplyNetworkDepersonalization (String pin, Message onComplete) {
         if(DBG) log("Network Despersonalization: " + pin);
         phone.mCM.supplyNetworkDepersonalization(pin,
                         obtainMessage(EVENT_PINPUK_DONE, onComplete));
     }
 
-    public boolean getSimLockEnabled() {
+    public boolean getIccLockEnabled() {
        return mSimPinLocked;
     }
 
-    public boolean getSimFdnEnabled() {
+    public boolean getIccFdnEnabled() {
        return mSimFdnEnabled;
     }
 
-    public void setSimLockEnabled (boolean enabled,
+    public void setIccLockEnabled (boolean enabled,
             String password, Message onComplete) {
         int serviceClassX;
         serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE +
@@ -226,7 +232,7 @@
                 obtainMessage(EVENT_CHANGE_FACILITY_LOCK_DONE, onComplete));
     }
 
-    public void setSimFdnEnabled (boolean enabled,
+    public void setIccFdnEnabled (boolean enabled,
             String password, Message onComplete) {
         int serviceClassX;
         serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE +
@@ -241,18 +247,18 @@
                 obtainMessage(EVENT_CHANGE_FACILITY_FDN_DONE, onComplete));
     }
 
-    public void changeSimLockPassword(String oldPassword, String newPassword,
+    public void changeIccLockPassword(String oldPassword, String newPassword,
             Message onComplete) {
         if(DBG) log("Change Pin1 old: " + oldPassword + " new: " + newPassword);
-        phone.mCM.changeSimPin(oldPassword, newPassword,
+        phone.mCM.changeIccPin(oldPassword, newPassword,
                 obtainMessage(EVENT_CHANGE_SIM_PASSWORD_DONE, onComplete));
 
     }
 
-    public void changeSimFdnPassword(String oldPassword, String newPassword,
+    public void changeIccFdnPassword(String oldPassword, String newPassword,
             Message onComplete) {
         if(DBG) log("Change Pin2 old: " + oldPassword + " new: " + newPassword);
-        phone.mCM.changeSimPin2(oldPassword, newPassword,
+        phone.mCM.changeIccPin2(oldPassword, newPassword,
                 obtainMessage(EVENT_CHANGE_SIM_PASSWORD_DONE, onComplete));
 
     }
@@ -275,11 +281,11 @@
             case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
                 status = null;
                 updateStateProperty();
-                broadcastSimStateChangedIntent(SimCard.INTENT_VALUE_SIM_NOT_READY, null);
+                broadcastSimStateChangedIntent(SimCard.INTENT_VALUE_ICC_NOT_READY, null);
                 break;
             case EVENT_SIM_READY:
                 //TODO: put facility read in SIM_READY now, maybe in REG_NW
-                phone.mCM.getSimStatus(obtainMessage(EVENT_GET_SIM_STATUS_DONE));
+                phone.mCM.getIccStatus(obtainMessage(EVENT_GET_SIM_STATUS_DONE));
                 phone.mCM.queryFacilityLock (
                         CommandsInterface.CB_FACILITY_BA_SIM, "", serviceClassX,
                         obtainMessage(EVENT_QUERY_FACILITY_LOCK_DONE));
@@ -288,7 +294,7 @@
                         obtainMessage(EVENT_QUERY_FACILITY_FDN_DONE));
                 break;
             case EVENT_SIM_LOCKED_OR_ABSENT:
-                phone.mCM.getSimStatus(obtainMessage(EVENT_GET_SIM_STATUS_DONE));
+                phone.mCM.getIccStatus(obtainMessage(EVENT_GET_SIM_STATUS_DONE));
                 phone.mCM.queryFacilityLock (
                         CommandsInterface.CB_FACILITY_BA_SIM, "", serviceClassX,
                         obtainMessage(EVENT_QUERY_FACILITY_LOCK_DONE));
@@ -306,7 +312,7 @@
                 // TODO should abstract these exceptions
                 AsyncResult.forMessage(((Message)ar.userObj)).exception
                                                     = ar.exception;
-                phone.mCM.getSimStatus(
+                phone.mCM.getIccStatus(
                     obtainMessage(EVENT_REPOLL_STATUS_DONE, ar.userObj));
                 break;
             case EVENT_REPOLL_STATUS_DONE:
@@ -415,24 +421,24 @@
     private void
     getSimStatusDone(AsyncResult ar) {
         if (ar.exception != null) {
-            Log.e(LOG_TAG,"Error getting SIM status. "
-                    + "RIL_REQUEST_GET_SIM_STATUS should "
+            Log.e(LOG_TAG,"Error getting ICC status. "
+                    + "RIL_REQUEST_GET_ICC_STATUS should "
                     + "never return an error", ar.exception);
             return;
         }
 
-        CommandsInterface.SimStatus newStatus 
-            = (CommandsInterface.SimStatus)  ar.result;
+        CommandsInterface.IccStatus newStatus
+            = (CommandsInterface.IccStatus)  ar.result;
 
         handleSimStatus(newStatus);
     }
 
     private void
-    handleSimStatus(CommandsInterface.SimStatus newStatus) {
+    handleSimStatus(CommandsInterface.IccStatus newStatus) {
         boolean transitionedIntoPinLocked;
         boolean transitionedIntoAbsent;
         boolean transitionedIntoNetworkLocked;
-        
+
         SimCard.State oldState, newState;
 
         oldState = getState();
@@ -451,17 +457,17 @@
         if (transitionedIntoPinLocked) {
             if(DBG) log("Notify SIM pin or puk locked.");
             pinLockedRegistrants.notifyRegistrants();
-            broadcastSimStateChangedIntent(SimCard.INTENT_VALUE_SIM_LOCKED, 
+            broadcastSimStateChangedIntent(SimCard.INTENT_VALUE_ICC_LOCKED,
                     (newState == State.PIN_REQUIRED) ?
                        INTENT_VALUE_LOCKED_ON_PIN : INTENT_VALUE_LOCKED_ON_PUK);
         } else if (transitionedIntoAbsent) {
             if(DBG) log("Notify SIM missing.");
             absentRegistrants.notifyRegistrants();
-            broadcastSimStateChangedIntent(SimCard.INTENT_VALUE_SIM_ABSENT, null);
+            broadcastSimStateChangedIntent(SimCard.INTENT_VALUE_ICC_ABSENT, null);
         } else if (transitionedIntoNetworkLocked) {
             if(DBG) log("Notify SIM network locked.");
             networkLockedRegistrants.notifyRegistrants();
-            broadcastSimStateChangedIntent(SimCard.INTENT_VALUE_SIM_LOCKED,
+            broadcastSimStateChangedIntent(SimCard.INTENT_VALUE_ICC_LOCKED,
                   INTENT_VALUE_LOCKED_NETWORK);
         }
     }
@@ -469,7 +475,7 @@
     public void broadcastSimStateChangedIntent(String value, String reason) {
         Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
         intent.putExtra(Phone.PHONE_NAME_KEY, phone.getPhoneName());
-        intent.putExtra(SimCard.INTENT_KEY_SIM_STATE, value);
+        intent.putExtra(SimCard.INTENT_KEY_ICC_STATE, value);
         intent.putExtra(SimCard.INTENT_KEY_LOCKED_REASON, reason);
         if(DBG) log("Broadcasting intent SIM_STATE_CHANGED_ACTION " +  value
                 + " reason " + reason);
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimException.java b/telephony/java/com/android/internal/telephony/gsm/SimException.java
deleted file mode 100644
index 1c0daba..0000000
--- a/telephony/java/com/android/internal/telephony/gsm/SimException.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2006 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.internal.telephony.gsm;
-
-/**
- * {@hide}
- */
-public class SimException extends Exception
-{
-    SimException()
-    {
-
-    }
-
-    SimException(String s)
-    {
-        super(s);
-    }
-}
-
-final class SimVmFixedException extends SimException {
-    SimVmFixedException()
-    {
-
-    }
-
-    SimVmFixedException(String s)
-    {
-        super(s);
-    }    
-}
-
-final class SimVmNotSupportedException extends SimException {
-    SimVmNotSupportedException()
-    {
-
-    }
-
-    SimVmNotSupportedException(String s)
-    {
-        super(s);
-    }    
-}
-
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimFileNotFound.java b/telephony/java/com/android/internal/telephony/gsm/SimFileNotFound.java
deleted file mode 100644
index 982e2fd..0000000
--- a/telephony/java/com/android/internal/telephony/gsm/SimFileNotFound.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2006 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.internal.telephony.gsm;
-
-/**
- * {@hide}
- */
-public class SimFileNotFound extends SimException
-{
-    SimFileNotFound()
-    {
-
-    }
-
-    SimFileNotFound(String s)
-    {
-        super(s);
-    }
-
-    SimFileNotFound(int ef)
-    {
-        super("SIM EF Not Found 0x" + Integer.toHexString(ef));
-    }
-}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java b/telephony/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java
index 7cc9a80..076da6b 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java
@@ -25,6 +25,11 @@
 import android.telephony.PhoneNumberUtils;
 import android.util.Log;
 
+import com.android.internal.telephony.AdnRecord;
+import com.android.internal.telephony.AdnRecordCache;
+import com.android.internal.telephony.IccPhoneBookInterfaceManager;
+import com.android.internal.telephony.PhoneProxy;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -32,247 +37,65 @@
  * SimPhoneBookInterfaceManager to provide an inter-process communication to
  * access ADN-like SIM records.
  */
-public class SimPhoneBookInterfaceManager extends ISimPhoneBook.Stub {
+
+
+public class SimPhoneBookInterfaceManager extends IccPhoneBookInterfaceManager {
     static final String LOG_TAG = "GSM";
-    static final boolean DBG = false;
 
-    private GSMPhone phone;
-    private AdnRecordCache adnCache;
-    private final Object mLock = new Object();
-    private int recordSize[];
-    private boolean success;
-    private List<AdnRecord> records;
-
-    private static final boolean ALLOW_SIM_OP_IN_UI_THREAD = false;
-
-    private static final int EVENT_GET_SIZE_DONE = 1;
-    private static final int EVENT_LOAD_DONE = 2;
-    private static final int EVENT_UPDATE_DONE = 3;
 
     Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
             AsyncResult ar;
 
-            switch (msg.what) {
-                case EVENT_GET_SIZE_DONE:
-                    ar = (AsyncResult) msg.obj;
-                    synchronized (mLock) {
-                        if (ar.exception == null) {
-                            recordSize = (int[])ar.result;
-                            // recordSize[0]  is the record length
-                            // recordSize[1]  is the total length of the EF file
-                            // recordSize[2]  is the number of records in the EF file
-                            log("GET_RECORD_SIZE Size " + recordSize[0] +
-                                    " total " + recordSize[1] +
-                                    " #record " + recordSize[2]);
-                            mLock.notifyAll();
-                        }
-                    }
-                    break;
-                case EVENT_UPDATE_DONE:
-                    ar = (AsyncResult) msg.obj;
-                    synchronized (mLock) {
-                        success = (ar.exception == null);
-                        mLock.notifyAll();
-                    }
-                    break;
-                case EVENT_LOAD_DONE:
-                    ar = (AsyncResult)msg.obj;
-                    synchronized (mLock) {
-                        if (ar.exception == null) {
-                            records = (List<AdnRecord>)
-                                    ((ArrayList<AdnRecord>) ar.result);
-                        } else {
-                            if(DBG) log("Cannot load ADN records");
-                            if (records != null) {
-                                records.clear();
-                            }
-                        }
-                        mLock.notifyAll();
-                    }
+            switch(msg.what) {
+                default:
+                    mBaseHandler.handleMessage(msg);
                     break;
             }
         }
     };
 
     public SimPhoneBookInterfaceManager(GSMPhone phone) {
-        this.phone = phone;
+        super(phone);
         adnCache = phone.mSIMRecords.getAdnCache();
-        publish();
+        //NOTE service "simphonebook" added by IccSmsInterfaceManagerProxy
     }
 
-    private void publish() {
-        ServiceManager.addService("simphonebook", this);
+    public void dispose() {
+        super.dispose();
     }
 
-    /**
-     * Replace oldAdn with newAdn in ADN-like record in EF
-     *
-     * getAdnRecordsInEf must be called at least once before this function,
-     * otherwise an error will be returned
-     * throws SecurityException if no WRITE_CONTACTS permission
-     *
-     * @param efid must be one among EF_ADN, EF_FDN, and EF_SDN
-     * @param oldTag adn tag to be replaced
-     * @param oldPhoneNumber adn number to be replaced
-     *        Set both oldTag and oldPhoneNubmer to "" means to replace an
-     *        empty record, aka, insert new record
-     * @param newTag adn tag to be stored
-     * @param newPhoneNumber adn number ot be stored
-     *        Set both newTag and newPhoneNubmer to "" means to replace the old
-     *        record with empty one, aka, delete old record
-     * @param pin2 required to update EF_FDN, otherwise must be null
-     * @return true for success
-     */
-    public boolean
-    updateAdnRecordsInEfBySearch (int efid,
-            String oldTag, String oldPhoneNumber,
-            String newTag, String newPhoneNumber, String pin2) {
-
-
-        if (phone.getContext().checkCallingOrSelfPermission(
-                android.Manifest.permission.WRITE_CONTACTS)
-            != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException(
-                    "Requires android.permission.WRITE_CONTACTS permission");
-        }
-
-        
-        if (DBG) log("updateAdnRecordsInEfBySearch: efid=" + efid +
-                " ("+ oldTag + "," + oldPhoneNumber + ")"+ "==>" +
-                " ("+ newTag + "," + newPhoneNumber + ")"+ " pin2=" + pin2);
-        synchronized(mLock) {
-            checkThread();
-            success = false;
-            Message response = mHandler.obtainMessage(EVENT_UPDATE_DONE);
-            AdnRecord oldAdn = new AdnRecord(oldTag, oldPhoneNumber);
-            AdnRecord newAdn = new AdnRecord(newTag, newPhoneNumber);
-            adnCache.updateAdnBySearch(efid, oldAdn, newAdn, pin2, response);
-            try {
-                mLock.wait();
-            } catch (InterruptedException e) {
-                log("interrupted while trying to update by search");
-            }
-        }
-        return success;
+    protected void finalize() {
+        if(DBG) Log.d(LOG_TAG, "SimPhoneBookInterfaceManager finalized");
     }
 
-    /**
-     * Update an ADN-like EF record by record index
-     *
-     * This is useful for iteration the whole ADN file, such as write the whole
-     * phone book or erase/format the whole phonebook
-     * throws SecurityException if no WRITE_CONTACTS permission
-     *
-     * @param efid must be one among EF_ADN, EF_FDN, and EF_SDN
-     * @param newTag adn tag to be stored
-     * @param newPhoneNumber adn number to be stored
-     *        Set both newTag and newPhoneNubmer to "" means to replace the old
-     *        record with empty one, aka, delete old record
-     * @param index is 1-based adn record index to be updated
-     * @param pin2 required to update EF_FDN, otherwise must be null
-     * @return true for success
-     */
-    public boolean
-    updateAdnRecordsInEfByIndex(int efid, String newTag,
-            String newPhoneNumber, int index, String pin2) {
-
-        if (phone.getContext().checkCallingOrSelfPermission(
-                android.Manifest.permission.WRITE_CONTACTS)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException(
-                    "Requires android.permission.WRITE_CONTACTS permission");
-        }
-
-        if (DBG) log("updateAdnRecordsInEfByIndex: efid=" + efid +
-                " Index=" + index + " ==> " +
-                "("+ newTag + "," + newPhoneNumber + ")"+ " pin2=" + pin2);
-        synchronized(mLock) {
-            checkThread();
-            success = false;
-            Message response = mHandler.obtainMessage(EVENT_UPDATE_DONE);
-            AdnRecord newAdn = new AdnRecord(newTag, newPhoneNumber);
-            adnCache.updateAdnByIndex(efid, newAdn, index, pin2, response);
-            try {
-                mLock.wait();
-            } catch (InterruptedException e) {
-                log("interrupted while trying to update by index");
-            }
-        }
-        return success;
-    }
-
-    /**
-     * Get the capacity of records in efid
-     *
-     * @param efid the EF id of a ADN-like SIM
-     * @return  int[3] array
-     *            recordSizes[0]  is the single record length
-     *            recordSizes[1]  is the total length of the EF file
-     *            recordSizes[2]  is the number of records in the EF file
-     */
     public int[] getAdnRecordsSize(int efid) {
-        if (DBG) log("getAdnRecordsSize: efid=" + efid);
+        if (DBG) logd("getAdnRecordsSize: efid=" + efid);
         synchronized(mLock) {
             checkThread();
             recordSize = new int[3];
-            Message response = mHandler.obtainMessage(EVENT_GET_SIZE_DONE);
-            phone.mSIMFileHandler.getEFLinearRecordSize(efid, response);
+
+            //Using mBaseHandler, no difference in EVENT_GET_SIZE_DONE handling
+            Message response = mBaseHandler.obtainMessage(EVENT_GET_SIZE_DONE);
+
+            phone.getIccFileHandler().getEFLinearRecordSize(efid, response);
             try {
                 mLock.wait();
             } catch (InterruptedException e) {
-                log("interrupted while trying to load from the SIM");
+                logd("interrupted while trying to load from the SIM");
             }
         }
 
         return recordSize;
     }
 
-    /**
-     * Loads the AdnRecords in efid and returns them as a
-     * List of AdnRecords
-     *
-     * throws SecurityException if no READ_CONTACTS permission
-     *
-     * @param efid the EF id of a ADN-like SIM
-     * @return List of AdnRecord
-     */
-    public List<AdnRecord> getAdnRecordsInEf(int efid) {
-
-        if (phone.getContext().checkCallingOrSelfPermission(
-                android.Manifest.permission.READ_CONTACTS)
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException(
-                    "Requires android.permission.READ_CONTACTS permission");
-        }
-
-        if (DBG) log("getAdnRecordsInEF: efid=" + efid);
-
-        synchronized(mLock) {
-            checkThread();
-            Message response = mHandler.obtainMessage(EVENT_LOAD_DONE);
-            adnCache.requestLoadAllAdnLike(efid, response);
-            try {
-                mLock.wait();
-            } catch (InterruptedException e) {
-                log("interrupted while trying to load from the SIM");
-            }
-        }
-            return records;
+    protected void logd(String msg) {
+        Log.d(LOG_TAG, "[SimPbInterfaceManager] " + msg);
     }
 
-    private void checkThread() {
-        if (!ALLOW_SIM_OP_IN_UI_THREAD) {
-            // Make sure this isn't the UI thread, since it will block
-            if (mHandler.getLooper().equals(Looper.myLooper())) {
-                Log.e(LOG_TAG, "query() called on the main UI thread!");
-                throw new IllegalStateException("You cannot call query on this provder from the main UI thread.");
-            }
-        }
-    }
-
-    private void log(String msg) {
-        Log.d(LOG_TAG, "[SpbInterfaceManager] " + msg);
+    protected void loge(String msg) {
+        Log.e(LOG_TAG, "[SimPbInterfaceManager] " + msg);
     }
 }
+
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java b/telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java
index c3df0d0..875d8d0 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SimSmsInterfaceManager.java
@@ -16,27 +16,31 @@
 
 package com.android.internal.telephony.gsm;
 
-import android.app.PendingIntent;
 import android.content.Context;
 import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.Message;
-import android.os.ServiceManager;
-import android.telephony.gsm.SmsManager;
 import android.util.Log;
 
+import com.android.internal.telephony.IccConstants;
+import com.android.internal.telephony.IccSmsInterfaceManager;
+import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.PhoneProxy;
+import com.android.internal.telephony.SmsRawData;
+
 import java.util.ArrayList;
 import java.util.List;
 
+import static android.telephony.SmsManager.STATUS_ON_ICC_FREE;
+
 /**
  * SimSmsInterfaceManager to provide an inter-process communication to
  * access Sms in Sim.
  */
-public class SimSmsInterfaceManager extends ISms.Stub {
+public class SimSmsInterfaceManager extends IccSmsInterfaceManager {
     static final String LOG_TAG = "GSM";
-    static final boolean DBG = false;
+    static final boolean DBG = true;
 
-    private GSMPhone mPhone;
     private final Object mLock = new Object();
     private boolean mSuccess;
     private List<SmsRawData> mSms;
@@ -76,33 +80,31 @@
     };
 
     public SimSmsInterfaceManager(GSMPhone phone) {
-        this.mPhone = phone;
-        ServiceManager.addService("isms", this);
+        super(phone);
+        mDispatcher = new GsmSMSDispatcher(phone);
     }
 
-    private void enforceReceiveAndSend(String message) {
-        Context context = mPhone.getContext();
+    public void dispose() {
+    }
 
-        context.enforceCallingPermission(
-                "android.permission.RECEIVE_SMS", message);
-        context.enforceCallingPermission(
-                "android.permission.SEND_SMS", message);
+    protected void finalize() {
+        if(DBG) Log.d(LOG_TAG, "SimSmsInterfaceManager finalized");
     }
 
     /**
      * Update the specified message on the SIM.
      *
      * @param index record index of message to update
-     * @param status new message status (STATUS_ON_SIM_READ,
-     *                  STATUS_ON_SIM_UNREAD, STATUS_ON_SIM_SENT,
-     *                  STATUS_ON_SIM_UNSENT, STATUS_ON_SIM_FREE)
+     * @param status new message status (STATUS_ON_ICC_READ,
+     *                  STATUS_ON_ICC_UNREAD, STATUS_ON_ICC_SENT,
+     *                  STATUS_ON_ICC_UNSENT, STATUS_ON_ICC_FREE)
      * @param pdu the raw PDU to store
      * @return success or not
      *
      */
     public boolean
-    updateMessageOnSimEf(int index, int status, byte[] pdu) {
-        if (DBG) log("updateMessageOnSimEf: index=" + index +
+    updateMessageOnIccEf(int index, int status, byte[] pdu) {
+        if (DBG) log("updateMessageOnIccEf: index=" + index +
                 " status=" + status + " ==> " +
                 "("+ pdu + ")");
         enforceReceiveAndSend("Updating message on SIM");
@@ -110,13 +112,14 @@
             mSuccess = false;
             Message response = mHandler.obtainMessage(EVENT_UPDATE_DONE);
 
-            if (status == SmsManager.STATUS_ON_SIM_FREE) {
+            if (status == STATUS_ON_ICC_FREE) {
                 // Special case FREE: call deleteSmsOnSim instead of
                 // manipulating the SIM record
                 mPhone.mCM.deleteSmsOnSim(index, response);
             } else {
                 byte[] record = makeSmsRecordData(status, pdu);
-                mPhone.mSIMFileHandler.updateEFLinearFixed( SimConstants.EF_SMS,
+                ((SIMFileHandler)mPhone.getIccFileHandler()).updateEFLinearFixed(
+                        IccConstants.EF_SMS,
                         index, record, null, response);
             }
             try {
@@ -132,21 +135,21 @@
      * Copy a raw SMS PDU to the SIM.
      *
      * @param pdu the raw PDU to store
-     * @param status message status (STATUS_ON_SIM_READ, STATUS_ON_SIM_UNREAD,
-     *               STATUS_ON_SIM_SENT, STATUS_ON_SIM_UNSENT)
+     * @param status message status (STATUS_ON_ICC_READ, STATUS_ON_ICC_UNREAD,
+     *               STATUS_ON_ICC_SENT, STATUS_ON_ICC_UNSENT)
      * @return success or not
      *
      */
-    public boolean copyMessageToSimEf(int status, byte[] pdu, byte[] smsc) {
-        if (DBG) log("copyMessageToSimEf: status=" + status + " ==> " +
+    public boolean copyMessageToIccEf(int status, byte[] pdu, byte[] smsc) {
+        if (DBG) log("copyMessageToIccEf: status=" + status + " ==> " +
                 "pdu=("+ pdu + "), smsm=(" + smsc +")");
         enforceReceiveAndSend("Copying message to SIM");
         synchronized(mLock) {
             mSuccess = false;
             Message response = mHandler.obtainMessage(EVENT_UPDATE_DONE);
 
-            mPhone.mCM.writeSmsToSim(status, SimUtils.bytesToHexString(smsc),
-                    SimUtils.bytesToHexString(pdu), response);
+            mPhone.mCM.writeSmsToSim(status, IccUtils.bytesToHexString(smsc),
+                    IccUtils.bytesToHexString(pdu), response);
 
             try {
                 mLock.wait();
@@ -158,11 +161,11 @@
     }
 
     /**
-     * Retrieves all messages currently stored on SIM.
+     * Retrieves all messages currently stored on ICC.
      *
-     * @return list of SmsRawData of all sms on SIM
+     * @return list of SmsRawData of all sms on ICC
      */
-    public List<SmsRawData> getAllMessagesFromSimEf() {
+    public List<SmsRawData> getAllMessagesFromIccEf() {
         if (DBG) log("getAllMessagesFromEF");
 
         Context context = mPhone.getContext();
@@ -172,7 +175,7 @@
                 "Reading messages from SIM");
         synchronized(mLock) {
             Message response = mHandler.obtainMessage(EVENT_LOAD_DONE);
-            mPhone.mSIMFileHandler.loadEFLinearFixedAll(SimConstants.EF_SMS,
+            ((SIMFileHandler)mPhone.getIccFileHandler()).loadEFLinearFixedAll(IccConstants.EF_SMS,
                     response);
 
             try {
@@ -184,119 +187,7 @@
         return mSms;
     }
 
-    /**
-     * Send a Raw PDU SMS
-     *
-     * @param smsc the SMSC to send the message through, or NULL for the
-     *  defatult SMSC
-     * @param pdu the raw PDU to send
-     * @param sentIntent if not NULL this <code>Intent</code> is
-     *  broadcast when the message is sucessfully sent, or failed.
-     *  The result code will be <code>Activity.RESULT_OK<code> for success,
-     *  or one of these errors:
-     *  <code>RESULT_ERROR_GENERIC_FAILURE</code>
-     *  <code>RESULT_ERROR_RADIO_OFF</code>
-     *  <code>RESULT_ERROR_NULL_PDU</code>.
-     * @param deliveryIntent if not NULL this <code>Intent</code> is
-     *  broadcast when the message is delivered to the recipient.  The
-     *  raw pdu of the status report is in the extended data ("pdu").
-     */
-    public void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent,
-            PendingIntent deliveryIntent) {
-        Context context = mPhone.getContext();
-
-        context.enforceCallingPermission(
-                "android.permission.SEND_SMS",
-                "Sending SMS message");
-        if (DBG) log("sendRawPdu: smsc=" + smsc +
-                " pdu="+ pdu + " sentIntent" + sentIntent +
-                " deliveryIntent" + deliveryIntent);
-        mPhone.mSMS.sendRawPdu(smsc, pdu, sentIntent, deliveryIntent);
-    }
-
-    /**
-     * Send a multi-part text based SMS.
-     * 
-     * @param destinationAddress the address to send the message to
-     * @param scAddress is the service center address or null to use
-     *   the current default SMSC
-     * @param parts an <code>ArrayList</code> of strings that, in order,
-     *   comprise the original message
-     * @param sentIntents if not null, an <code>ArrayList</code> of 
-     *   <code>PendingIntent</code>s (one for each message part) that is
-     *   broadcast when the corresponding message part has been sent.
-     *   The result code will be <code>Activity.RESULT_OK<code> for success,
-     *   or one of these errors:
-     *   <code>RESULT_ERROR_GENERIC_FAILURE</code>
-     *   <code>RESULT_ERROR_RADIO_OFF</code>
-     *   <code>RESULT_ERROR_NULL_PDU</code>.
-     * @param deliveryIntents if not null, an <code>ArrayList</code> of 
-     *   <code>PendingIntent</code>s (one for each message part) that is
-     *   broadcast when the corresponding message part has been delivered
-     *   to the recipient.  The raw pdu of the status report is in the
-     *   extended data ("pdu").
-     */
-    public void sendMultipartText(String destinationAddress, String scAddress, List<String> parts,
-            List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents) {
-        Context context = mPhone.getContext();
-
-        context.enforceCallingPermission(
-                "android.permission.SEND_SMS",
-                "Sending SMS message");
-        if (DBG) log("sendMultipartText");
-        mPhone.mSMS.sendMultipartText(destinationAddress, scAddress, (ArrayList<String>) parts,
-                (ArrayList<PendingIntent>) sentIntents, (ArrayList<PendingIntent>) deliveryIntents);
-    }
-
-    /**
-     * Generates an EF_SMS record from status and raw PDU.
-     *
-     * @param status Message status.  See TS 51.011 10.5.3.
-     * @param pdu Raw message PDU.
-     * @return byte array for the record.
-     */
-    private byte[] makeSmsRecordData(int status, byte[] pdu) {
-        byte[] data = new byte[SimConstants.SMS_RECORD_LENGTH];
-
-        // Status bits for this record.  See TS 51.011 10.5.3
-        data[0] = (byte)(status & 7);
-
-        System.arraycopy(pdu, 0, data, 1, pdu.length);
-
-        // Pad out with 0xFF's.
-        for (int j = pdu.length+1; j < SimConstants.SMS_RECORD_LENGTH; j++) {
-            data[j] = -1;
-        }
-
-        return data;
-    }
-
-    /**
-     * create SmsRawData lists from all sms record byte[]
-     * Use null to indicate "free" record
-     *
-     * @param messages List of message records from EF_SMS.
-     * @return SmsRawData list of all in-used records
-     */
-    private ArrayList<SmsRawData> buildValidRawData(ArrayList<byte[]> messages) {
-        int count = messages.size();
-        ArrayList<SmsRawData> ret;
-
-        ret = new ArrayList<SmsRawData>(count);
-
-        for (int i = 0; i < count; i++) {
-            byte[] ba = messages.get(i);
-            if (ba[0] == 0) {
-                ret.add(null);
-            } else {
-                ret.add(new SmsRawData(messages.get(i)));
-            }
-        }
-
-        return ret;
-    }
-
-    private void log(String msg) {
-        Log.d(LOG_TAG, "[SmsInterfaceManager] " + msg);
+    protected void log(String msg) {
+        Log.d(LOG_TAG, "[SimSmsInterfaceManager] " + msg);
     }
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimTlv.java b/telephony/java/com/android/internal/telephony/gsm/SimTlv.java
index 00879ce..30543c7 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimTlv.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SimTlv.java
@@ -34,9 +34,8 @@
     int curDataOffset;
     int curDataLength;
     boolean hasValidTlvObject;
-    
-    public SimTlv(byte[] record, int offset, int length)
-    {
+
+    public SimTlv(byte[] record, int offset, int length) {
         this.record = record;
 
         this.tlvOffset = offset;
@@ -46,19 +45,15 @@
         hasValidTlvObject = parseCurrentTlvObject();
     }
 
-    public boolean
-    nextObject()
-    {
+    public boolean nextObject() {
         if (!hasValidTlvObject) return false;
 
         curOffset = curDataOffset + curDataLength;
-        hasValidTlvObject = parseCurrentTlvObject(); 
+        hasValidTlvObject = parseCurrentTlvObject();
         return hasValidTlvObject;
     }
 
-    public boolean
-    isValidObject()
-    {
+    public boolean isValidObject() {
         return hasValidTlvObject;
     }
 
@@ -68,9 +63,7 @@
      * 0 and 0xff are invalid tag values
      * valid tags range from 1 - 0xfe
      */
-    public int
-    getTag()
-    {
+    public int getTag() {
         if (!hasValidTlvObject) return 0;
         return record[curOffset] & 0xff;
     }
@@ -79,10 +72,8 @@
      * Returns data associated with current TLV object
      * returns null if !isValidObject()
      */
-    
-    public byte[]
-    getData()
-    {
+
+    public byte[] getData() {
         if (!hasValidTlvObject) return null;
 
         byte[] ret = new byte[curDataLength];
@@ -95,14 +86,12 @@
      * @return false on invalid record, true on valid record
      */
 
-    private boolean
-    parseCurrentTlvObject()
-    {   
+    private boolean parseCurrentTlvObject() {
         // 0x00 and 0xff are invalid tag values
         if (record[curOffset] == 0 || (record[curOffset] & 0xff) == 0xff) {
             return false;
         }
-        
+
         try {
             if ((record[curOffset + 1] & 0xff) < 0x80) {
                 // one byte length 0 - 0x7f
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
new file mode 100644
index 0000000..867b719
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
@@ -0,0 +1,1058 @@
+/*
+ * Copyright (C) 2006 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.internal.telephony.gsm;
+
+import android.os.Parcel;
+import android.telephony.PhoneNumberUtils;
+import android.text.format.Time;
+import android.util.Config;
+import android.util.Log;
+import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.EncodeException;
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.SmsHeader;
+import com.android.internal.telephony.SmsMessageBase;
+
+import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
+
+import static android.telephony.SmsMessage.ENCODING_7BIT;
+import static android.telephony.SmsMessage.ENCODING_8BIT;
+import static android.telephony.SmsMessage.ENCODING_16BIT;
+import static android.telephony.SmsMessage.ENCODING_UNKNOWN;
+import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES;
+import static android.telephony.SmsMessage.MAX_USER_DATA_BYTES_WITH_HEADER;
+import static android.telephony.SmsMessage.MAX_USER_DATA_SEPTETS;
+import static android.telephony.SmsMessage.MAX_USER_DATA_SEPTETS_WITH_HEADER;
+import static android.telephony.SmsMessage.MessageClass;
+
+/**
+ * A Short Message Service message.
+ *
+ */
+public class SmsMessage extends SmsMessageBase{
+    static final String LOG_TAG = "GSM";
+
+    private MessageClass messageClass;
+
+    /**
+     * TP-Message-Type-Indicator
+     * 9.2.3
+     */
+    private int mti;
+
+    /** TP-Protocol-Identifier (TP-PID) */
+    private int protocolIdentifier;
+
+    // TP-Data-Coding-Scheme
+    // see TS 23.038
+    private int dataCodingScheme;
+
+    // TP-Reply-Path
+    // e.g. 23.040 9.2.2.1
+    private boolean replyPathPresent = false;
+
+    // "Message Marked for Automatic Deletion Group"
+    // 23.038 Section 4
+    private boolean automaticDeletion;
+
+    /** True if Status Report is for SMS-SUBMIT; false for SMS-COMMAND. */
+    private boolean forSubmit;
+
+    /** The address of the receiver. */
+    private GsmSmsAddress recipientAddress;
+
+    /** Time when SMS-SUBMIT was delivered from SC to MSE. */
+    private long dischargeTimeMillis;
+
+    /**
+     *  TP-Status - status of a previously submitted SMS.
+     *  This field applies to SMS-STATUS-REPORT messages.  0 indicates success;
+     *  see TS 23.040, 9.2.3.15 for description of other possible values.
+     */
+    private int status;
+
+    /**
+     *  TP-Status - status of a previously submitted SMS.
+     *  This field is true iff the message is a SMS-STATUS-REPORT message.
+     */
+    private boolean isStatusReportMessage = false;
+
+    public static class SubmitPdu extends SubmitPduBase {
+    }
+
+    /**
+     * Create an SmsMessage from a raw PDU.
+     */
+    public static SmsMessage createFromPdu(byte[] pdu) {
+        try {
+            SmsMessage msg = new SmsMessage();
+            msg.parsePdu(pdu);
+            return msg;
+        } catch (RuntimeException ex) {
+            Log.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
+            return null;
+        }
+    }
+
+    /**
+     * TS 27.005 3.4.1 lines[0] and lines[1] are the two lines read from the
+     * +CMT unsolicited response (PDU mode, of course)
+     *  +CMT: [&lt;alpha>],<length><CR><LF><pdu>
+     *
+     * Only public for debugging
+     *
+     * {@hide}
+     */
+    public static SmsMessage newFromCMT(String[] lines) {
+        try {
+            SmsMessage msg = new SmsMessage();
+            msg.parsePdu(IccUtils.hexStringToBytes(lines[1]));
+            return msg;
+        } catch (RuntimeException ex) {
+            Log.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
+            return null;
+        }
+    }
+
+    /** @hide */
+    public static SmsMessage newFromCMTI(String line) {
+        // the thinking here is not to read the message immediately
+        // FTA test case
+        Log.e(LOG_TAG, "newFromCMTI: not yet supported");
+        return null;
+    }
+
+    /** @hide */
+    public static SmsMessage newFromCDS(String line) {
+        try {
+            SmsMessage msg = new SmsMessage();
+            msg.parsePdu(IccUtils.hexStringToBytes(line));
+            return msg;
+        } catch (RuntimeException ex) {
+            Log.e(LOG_TAG, "CDS SMS PDU parsing failed: ", ex);
+            return null;
+        }
+    }
+
+    /**
+     * Note: This functionality is currently not supported in GSM mode.
+     * @hide
+     */
+    public static SmsMessageBase newFromParcel(Parcel p){
+        Log.w(LOG_TAG, "newFromParcel: is not supported in GSM mode.");
+        return null;
+    }
+
+    /**
+     * Create an SmsMessage from an SMS EF record.
+     *
+     * @param index Index of SMS record. This should be index in ArrayList
+     *              returned by SmsManager.getAllMessagesFromSim + 1.
+     * @param data Record data.
+     * @return An SmsMessage representing the record.
+     *
+     * @hide
+     */
+    public static SmsMessage createFromEfRecord(int index, byte[] data) {
+        try {
+            SmsMessage msg = new SmsMessage();
+
+            msg.indexOnIcc = index;
+
+            // First byte is status: RECEIVED_READ, RECEIVED_UNREAD, STORED_SENT,
+            // or STORED_UNSENT
+            // See TS 51.011 10.5.3
+            if ((data[0] & 1) == 0) {
+                Log.w(LOG_TAG,
+                        "SMS parsing failed: Trying to parse a free record");
+                return null;
+            } else {
+                msg.statusOnIcc = data[0] & 0x07;
+            }
+
+            int size = data.length - 1;
+
+            // Note: Data may include trailing FF's.  That's OK; message
+            // should still parse correctly.
+            byte[] pdu = new byte[size];
+            System.arraycopy(data, 1, pdu, 0, size);
+            msg.parsePdu(pdu);
+            return msg;
+        } catch (RuntimeException ex) {
+            Log.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
+            return null;
+        }
+    }
+
+    /**
+     * Get the TP-Layer-Length for the given SMS-SUBMIT PDU Basically, the
+     * length in bytes (not hex chars) less the SMSC header
+     */
+    public static int getTPLayerLengthForPDU(String pdu) {
+        int len = pdu.length() / 2;
+        int smscLen = 0;
+
+        smscLen = Integer.parseInt(pdu.substring(0, 2), 16);
+
+        return len - smscLen - 1;
+    }
+
+    /**
+     * Get an SMS-SUBMIT PDU for a destination address and a message
+     *
+     * @param scAddress Service Centre address.  Null means use default.
+     * @return a <code>SubmitPdu</code> containing the encoded SC
+     *         address, if applicable, and the encoded message.
+     *         Returns null on encode error.
+     * @hide
+     */
+    public static SubmitPdu getSubmitPdu(String scAddress,
+            String destinationAddress, String message,
+            boolean statusReportRequested, byte[] header) {
+
+        // Perform null parameter checks.
+        if (message == null || destinationAddress == null) {
+            return null;
+        }
+
+        SubmitPdu ret = new SubmitPdu();
+        // MTI = SMS-SUBMIT, UDHI = header != null
+        byte mtiByte = (byte)(0x01 | (header != null ? 0x40 : 0x00));
+        ByteArrayOutputStream bo = getSubmitPduHead(
+                scAddress, destinationAddress, mtiByte,
+                statusReportRequested, ret);
+
+        try {
+            // First, try encoding it with the GSM alphabet
+
+            // User Data (and length)
+            byte[] userData = GsmAlphabet.stringToGsm7BitPackedWithHeader(message, header);
+
+            if ((0xff & userData[0]) > MAX_USER_DATA_SEPTETS) {
+                // Message too long
+                return null;
+            }
+
+            // TP-Data-Coding-Scheme
+            // Default encoding, uncompressed
+            bo.write(0x00);
+
+            // (no TP-Validity-Period)
+
+            bo.write(userData, 0, userData.length);
+        } catch (EncodeException ex) {
+            byte[] userData, textPart;
+            // Encoding to the 7-bit alphabet failed. Let's see if we can
+            // send it as a UCS-2 encoded message
+
+            try {
+                textPart = message.getBytes("utf-16be");
+            } catch (UnsupportedEncodingException uex) {
+                Log.e(LOG_TAG,
+                      "Implausible UnsupportedEncodingException ",
+                      uex);
+                return null;
+            }
+
+            if (header != null) {
+                userData = new byte[header.length + textPart.length];
+
+                System.arraycopy(header, 0, userData, 0, header.length);
+                System.arraycopy(textPart, 0, userData, header.length, textPart.length);
+            }
+            else {
+                userData = textPart;
+            }
+
+            if (userData.length > MAX_USER_DATA_BYTES) {
+                // Message too long
+                return null;
+            }
+
+            // TP-Data-Coding-Scheme
+            // Class 3, UCS-2 encoding, uncompressed
+            bo.write(0x0b);
+
+            // (no TP-Validity-Period)
+
+            // TP-UDL
+            bo.write(userData.length);
+
+            bo.write(userData, 0, userData.length);
+        }
+
+        ret.encodedMessage = bo.toByteArray();
+        return ret;
+    }
+
+    /**
+     * Get an SMS-SUBMIT PDU for a destination address and a message
+     *
+     * @param scAddress Service Centre address.  Null means use default.
+     * @return a <code>SubmitPdu</code> containing the encoded SC
+     *         address, if applicable, and the encoded message.
+     *         Returns null on encode error.
+     */
+    public static SubmitPdu getSubmitPdu(String scAddress,
+            String destinationAddress, String message,
+            boolean statusReportRequested) {
+
+        return getSubmitPdu(scAddress, destinationAddress, message, statusReportRequested, null);
+    }
+
+    /**
+     * Get an SMS-SUBMIT PDU for a data message to a destination address &amp; port
+     *
+     * @param scAddress Service Centre address. null == use default
+     * @param destinationAddress the address of the destination for the message
+     * @param destinationPort the port to deliver the message to at the
+     *        destination
+     * @param data the dat for the message
+     * @return a <code>SubmitPdu</code> containing the encoded SC
+     *         address, if applicable, and the encoded message.
+     *         Returns null on encode error.
+     */
+    public static SubmitPdu getSubmitPdu(String scAddress,
+            String destinationAddress, short destinationPort, byte[] data,
+            boolean statusReportRequested) {
+        if (data.length > (MAX_USER_DATA_BYTES - 7 /* UDH size */)) {
+            Log.e(LOG_TAG, "SMS data message may only contain "
+                    + (MAX_USER_DATA_BYTES - 7) + " bytes");
+            return null;
+        }
+
+        SubmitPdu ret = new SubmitPdu();
+        ByteArrayOutputStream bo = getSubmitPduHead(
+                scAddress, destinationAddress, (byte) 0x41, // MTI = SMS-SUBMIT,
+                                                            // TP-UDHI = true
+                statusReportRequested, ret);
+
+        // TP-Data-Coding-Scheme
+        // No class, 8 bit data
+        bo.write(0x04);
+
+        // (no TP-Validity-Period)
+
+        // User data size
+        bo.write(data.length + 7);
+
+        // User data header size
+        bo.write(0x06); // header is 6 octets
+
+        // User data header, indicating the destination port
+        bo.write(SmsHeader.APPLICATION_PORT_ADDRESSING_16_BIT); // port
+                                                                // addressing
+                                                                // header
+        bo.write(0x04); // each port is 2 octets
+        bo.write((destinationPort >> 8) & 0xFF); // MSB of destination port
+        bo.write(destinationPort & 0xFF); // LSB of destination port
+        bo.write(0x00); // MSB of originating port
+        bo.write(0x00); // LSB of originating port
+
+        // User data
+        bo.write(data, 0, data.length);
+
+        ret.encodedMessage = bo.toByteArray();
+        return ret;
+    }
+
+    /**
+     * Create the beginning of a SUBMIT PDU.  This is the part of the
+     * SUBMIT PDU that is common to the two versions of {@link #getSubmitPdu},
+     * one of which takes a byte array and the other of which takes a
+     * <code>String</code>.
+     *
+     * @param scAddress Service Centre address. null == use default
+     * @param destinationAddress the address of the destination for the message
+     * @param mtiByte
+     * @param ret <code>SubmitPdu</code> containing the encoded SC
+     *        address, if applicable, and the encoded message
+     */
+    private static ByteArrayOutputStream getSubmitPduHead(
+            String scAddress, String destinationAddress, byte mtiByte,
+            boolean statusReportRequested, SubmitPdu ret) {
+        ByteArrayOutputStream bo = new ByteArrayOutputStream(
+                MAX_USER_DATA_BYTES + 40);
+
+        // SMSC address with length octet, or 0
+        if (scAddress == null) {
+            ret.encodedScAddress = null;
+        } else {
+            ret.encodedScAddress = PhoneNumberUtils.networkPortionToCalledPartyBCDWithLength(
+                    scAddress);
+        }
+
+        // TP-Message-Type-Indicator (and friends)
+        if (statusReportRequested) {
+            // Set TP-Status-Report-Request bit.
+            mtiByte |= 0x20;
+            if (Config.LOGD) Log.d(LOG_TAG, "SMS status report requested");
+        }
+        bo.write(mtiByte);
+
+        // space for TP-Message-Reference
+        bo.write(0);
+
+        byte[] daBytes;
+
+        daBytes = PhoneNumberUtils.networkPortionToCalledPartyBCD(destinationAddress);
+
+        // destination address length in BCD digits, ignoring TON byte and pad
+        // TODO Should be better.
+        bo.write((daBytes.length - 1) * 2
+                - ((daBytes[daBytes.length - 1] & 0xf0) == 0xf0 ? 1 : 0));
+
+        // destination address
+        bo.write(daBytes, 0, daBytes.length);
+
+        // TP-Protocol-Identifier
+        bo.write(0);
+        return bo;
+    }
+
+    static class PduParser {
+        byte pdu[];
+        int cur;
+        SmsHeader userDataHeader;
+        byte[] userData;
+        int mUserDataSeptetPadding;
+        int mUserDataSize;
+
+        PduParser(String s) {
+            this(IccUtils.hexStringToBytes(s));
+        }
+
+        PduParser(byte[] pdu) {
+            this.pdu = pdu;
+            cur = 0;
+            mUserDataSeptetPadding = 0;
+        }
+
+        /**
+         * Parse and return the SC address prepended to SMS messages coming via
+         * the TS 27.005 / AT interface.  Returns null on invalid address
+         */
+        String getSCAddress() {
+            int len;
+            String ret;
+
+            // length of SC Address
+            len = getByte();
+
+            if (len == 0) {
+                // no SC address
+                ret = null;
+            } else {
+                // SC address
+                try {
+                    ret = PhoneNumberUtils
+                            .calledPartyBCDToString(pdu, cur, len);
+                } catch (RuntimeException tr) {
+                    Log.d(LOG_TAG, "invalid SC address: ", tr);
+                    ret = null;
+                }
+            }
+
+            cur += len;
+
+            return ret;
+        }
+
+        /**
+         * returns non-sign-extended byte value
+         */
+        int getByte() {
+            return pdu[cur++] & 0xff;
+        }
+
+        /**
+         * Any address except the SC address (eg, originating address) See TS
+         * 23.040 9.1.2.5
+         */
+        GsmSmsAddress getAddress() {
+            GsmSmsAddress ret;
+
+            // "The Address-Length field is an integer representation of
+            // the number field, i.e. excludes any semi octet containing only
+            // fill bits."
+            // The TOA field is not included as part of this
+            int addressLength = pdu[cur] & 0xff;
+            int lengthBytes = 2 + (addressLength + 1) / 2;
+
+            ret = new GsmSmsAddress(pdu, cur, lengthBytes);
+
+            cur += lengthBytes;
+
+            return ret;
+        }
+
+        /**
+         * Parses an SC timestamp and returns a currentTimeMillis()-style
+         * timestamp
+         */
+
+        long getSCTimestampMillis() {
+            // TP-Service-Centre-Time-Stamp
+            int year = IccUtils.bcdByteToInt(pdu[cur++]);
+            int month = IccUtils.bcdByteToInt(pdu[cur++]);
+            int day = IccUtils.bcdByteToInt(pdu[cur++]);
+            int hour = IccUtils.bcdByteToInt(pdu[cur++]);
+            int minute = IccUtils.bcdByteToInt(pdu[cur++]);
+            int second = IccUtils.bcdByteToInt(pdu[cur++]);
+
+            // For the timezone, the most significant bit of the
+            // least signficant nibble is the sign byte
+            // (meaning the max range of this field is 79 quarter-hours,
+            // which is more than enough)
+
+            byte tzByte = pdu[cur++];
+
+            // Mask out sign bit.
+            int timezoneOffset = IccUtils
+                    .bcdByteToInt((byte) (tzByte & (~0x08)));
+
+            timezoneOffset = ((tzByte & 0x08) == 0) ? timezoneOffset
+                    : -timezoneOffset;
+
+            Time time = new Time(Time.TIMEZONE_UTC);
+
+            // It's 2006.  Should I really support years < 2000?
+            time.year = year >= 90 ? year + 1900 : year + 2000;
+            time.month = month - 1;
+            time.monthDay = day;
+            time.hour = hour;
+            time.minute = minute;
+            time.second = second;
+
+            // Timezone offset is in quarter hours.
+            return time.toMillis(true) - (timezoneOffset * 15 * 60 * 1000);
+        }
+
+        /**
+         * Pulls the user data out of the PDU, and separates the payload from
+         * the header if there is one.
+         *
+         * @param hasUserDataHeader true if there is a user data header
+         * @param dataInSeptets true if the data payload is in septets instead
+         *  of octets
+         * @return the number of septets or octets in the user data payload
+         */
+        int constructUserData(boolean hasUserDataHeader, boolean dataInSeptets) {
+            int offset = cur;
+            int userDataLength = pdu[offset++] & 0xff;
+            int headerSeptets = 0;
+
+            if (hasUserDataHeader) {
+                int userDataHeaderLength = pdu[offset++] & 0xff;
+
+                byte[] udh = new byte[userDataHeaderLength];
+                System.arraycopy(pdu, offset, udh, 0, userDataHeaderLength);
+                userDataHeader = SmsHeader.parse(udh);
+                offset += userDataHeaderLength;
+
+                int headerBits = (userDataHeaderLength + 1) * 8;
+                headerSeptets = headerBits / 7;
+                headerSeptets += (headerBits % 7) > 0 ? 1 : 0;
+                mUserDataSeptetPadding = (headerSeptets * 7) - headerBits;
+            }
+
+            /*
+             * Here we just create the user data length to be the remainder of
+             * the pdu minus the user data hearder. This is because the count
+             * could mean the number of uncompressed sepets if the userdata is
+             * encoded in 7-bit.
+             */
+            userData = new byte[pdu.length - offset];
+            System.arraycopy(pdu, offset, userData, 0, userData.length);
+            cur = offset;
+
+            if (dataInSeptets) {
+                // Return the number of septets
+                return userDataLength - headerSeptets;
+            } else {
+                // Return the number of octets
+                return userData.length;
+            }
+        }
+
+        /**
+         * Returns the user data payload, not including the headers
+         *
+         * @return the user data payload, not including the headers
+         */
+        byte[] getUserData() {
+            return userData;
+        }
+
+        /**
+         * Returns the number of padding bits at the begining of the user data
+         * array before the start of the septets.
+         *
+         * @return the number of padding bits at the begining of the user data
+         * array before the start of the septets
+         */
+        int getUserDataSeptetPadding() {
+            return mUserDataSeptetPadding;
+        }
+
+        /**
+         * Returns an object representing the user data headers
+         *
+         * @return an object representing the user data headers
+         *
+         * {@hide}
+         */
+        SmsHeader getUserDataHeader() {
+            return userDataHeader;
+        }
+
+/*
+        XXX Not sure what this one is supposed to be doing, and no one is using
+        it.
+        String getUserDataGSM8bit() {
+            // System.out.println("remainder of pud:" +
+            // HexDump.dumpHexString(pdu, cur, pdu.length - cur));
+            int count = pdu[cur++] & 0xff;
+            int size = pdu[cur++];
+
+            // skip over header for now
+            cur += size;
+
+            if (pdu[cur - 1] == 0x01) {
+                int tid = pdu[cur++] & 0xff;
+                int type = pdu[cur++] & 0xff;
+
+                size = pdu[cur++] & 0xff;
+
+                int i = cur;
+
+                while (pdu[i++] != '\0') {
+                }
+
+                int length = i - cur;
+                String mimeType = new String(pdu, cur, length);
+
+                cur += length;
+
+                if (false) {
+                    System.out.println("tid = 0x" + HexDump.toHexString(tid));
+                    System.out.println("type = 0x" + HexDump.toHexString(type));
+                    System.out.println("header size = " + size);
+                    System.out.println("mimeType = " + mimeType);
+                    System.out.println("remainder of header:" +
+                     HexDump.dumpHexString(pdu, cur, (size - mimeType.length())));
+                }
+
+                cur += size - mimeType.length();
+
+                // System.out.println("data count = " + count + " cur = " + cur
+                // + " :" + HexDump.dumpHexString(pdu, cur, pdu.length - cur));
+
+                MMSMessage msg = MMSMessage.parseEncoding(mContext, pdu, cur,
+                        pdu.length - cur);
+            } else {
+                System.out.println(new String(pdu, cur, pdu.length - cur - 1));
+            }
+
+            return IccUtils.bytesToHexString(pdu);
+        }
+*/
+
+        /**
+         * Interprets the user data payload as pack GSM 7bit characters, and
+         * decodes them into a String.
+         *
+         * @param septetCount the number of septets in the user data payload
+         * @return a String with the decoded characters
+         */
+        String getUserDataGSM7Bit(int septetCount) {
+            String ret;
+
+            ret = GsmAlphabet.gsm7BitPackedToString(pdu, cur, septetCount,
+                    mUserDataSeptetPadding);
+
+            cur += (septetCount * 7) / 8;
+
+            return ret;
+        }
+
+        /**
+         * Interprets the user data payload as UCS2 characters, and
+         * decodes them into a String.
+         *
+         * @param byteCount the number of bytes in the user data payload
+         * @return a String with the decoded characters
+         */
+        String getUserDataUCS2(int byteCount) {
+            String ret;
+
+            try {
+                ret = new String(pdu, cur, byteCount, "utf-16");
+            } catch (UnsupportedEncodingException ex) {
+                ret = "";
+                Log.e(LOG_TAG, "implausible UnsupportedEncodingException", ex);
+            }
+
+            cur += byteCount;
+            return ret;
+        }
+
+        boolean moreDataPresent() {
+            return (pdu.length > cur);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public int getProtocolIdentifier() {
+        return protocolIdentifier;
+    }
+
+    /** {@inheritDoc} */
+    public boolean isReplace() {
+        return (protocolIdentifier & 0xc0) == 0x40
+                && (protocolIdentifier & 0x3f) > 0
+                && (protocolIdentifier & 0x3f) < 8;
+    }
+
+    /** {@inheritDoc} */
+    public boolean isCphsMwiMessage() {
+        return ((GsmSmsAddress) originatingAddress).isCphsVoiceMessageClear()
+                || ((GsmSmsAddress) originatingAddress).isCphsVoiceMessageSet();
+    }
+
+    /** {@inheritDoc} */
+    public boolean isMWIClearMessage() {
+        if (isMwi && (mwiSense == false)) {
+            return true;
+        }
+
+        return originatingAddress != null
+                && ((GsmSmsAddress) originatingAddress).isCphsVoiceMessageClear();
+    }
+
+    /** {@inheritDoc} */
+    public boolean isMWISetMessage() {
+        if (isMwi && (mwiSense == true)) {
+            return true;
+        }
+
+        return originatingAddress != null
+                && ((GsmSmsAddress) originatingAddress).isCphsVoiceMessageSet();
+    }
+
+    /** {@inheritDoc} */
+    public boolean isMwiDontStore() {
+        if (isMwi && mwiDontStore) {
+            return true;
+        }
+
+        if (isCphsMwiMessage()) {
+            // See CPHS 4.2 Section B.4.2.1
+            // If the user data is a single space char, do not store
+            // the message. Otherwise, store and display as usual
+            if (" ".equals(getMessageBody())) {
+                ;
+            }
+            return true;
+        }
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    public int getStatus() {
+        return status;
+    }
+
+    /** {@inheritDoc} */
+    public boolean isStatusReportMessage() {
+        return isStatusReportMessage;
+    }
+
+    /** {@inheritDoc} */
+    public boolean isReplyPathPresent() {
+        return replyPathPresent;
+    }
+
+    /**
+     * TS 27.005 3.1, <pdu> definition "In the case of SMS: 3GPP TS 24.011 [6]
+     * SC address followed by 3GPP TS 23.040 [3] TPDU in hexadecimal format:
+     * ME/TA converts each octet of TP data unit into two IRA character long
+     * hexad number (e.g. octet with integer value 42 is presented to TE as two
+     * characters 2A (IRA 50 and 65))" ...in the case of cell broadcast,
+     * something else...
+     */
+    private void parsePdu(byte[] pdu) {
+        mPdu = pdu;
+        // Log.d(LOG_TAG, "raw sms mesage:");
+        // Log.d(LOG_TAG, s);
+
+        PduParser p = new PduParser(pdu);
+
+        scAddress = p.getSCAddress();
+
+        if (scAddress != null) {
+            if (Config.LOGD) Log.d(LOG_TAG, "SMS SC address: " + scAddress);
+        }
+
+        // TODO(mkf) support reply path, user data header indicator
+
+        // TP-Message-Type-Indicator
+        // 9.2.3
+        int firstByte = p.getByte();
+
+        mti = firstByte & 0x3;
+        switch (mti) {
+        // TP-Message-Type-Indicator
+        // 9.2.3
+        case 0:
+            parseSmsDeliver(p, firstByte);
+            break;
+        case 2:
+            parseSmsStatusReport(p, firstByte);
+            break;
+        default:
+            // TODO(mkf) the rest of these
+            throw new RuntimeException("Unsupported message type");
+        }
+    }
+
+    /**
+     * Parses a SMS-STATUS-REPORT message.
+     *
+     * @param p A PduParser, cued past the first byte.
+     * @param firstByte The first byte of the PDU, which contains MTI, etc.
+     */
+    private void parseSmsStatusReport(PduParser p, int firstByte) {
+        isStatusReportMessage = true;
+
+        // TP-Status-Report-Qualifier bit == 0 for SUBMIT
+        forSubmit = (firstByte & 0x20) == 0x00;
+        // TP-Message-Reference
+        messageRef = p.getByte();
+        // TP-Recipient-Address
+        recipientAddress = p.getAddress();
+        // TP-Service-Centre-Time-Stamp
+        scTimeMillis = p.getSCTimestampMillis();
+        // TP-Discharge-Time
+        dischargeTimeMillis = p.getSCTimestampMillis();
+        // TP-Status
+        status = p.getByte();
+
+        // The following are optional fields that may or may not be present.
+        if (p.moreDataPresent()) {
+            // TP-Parameter-Indicator
+            int extraParams = p.getByte();
+            int moreExtraParams = extraParams;
+            while ((moreExtraParams & 0x80) != 0) {
+                // We only know how to parse a few extra parameters, all
+                // indicated in the first TP-PI octet, so skip over any
+                // additional TP-PI octets.
+                moreExtraParams = p.getByte();
+            }
+            // TP-Protocol-Identifier
+            if ((extraParams & 0x01) != 0) {
+                protocolIdentifier = p.getByte();
+            }
+            // TP-Data-Coding-Scheme
+            if ((extraParams & 0x02) != 0) {
+                dataCodingScheme = p.getByte();
+            }
+            // TP-User-Data-Length (implies existence of TP-User-Data)
+            if ((extraParams & 0x04) != 0) {
+                boolean hasUserDataHeader = (firstByte & 0x40) == 0x40;
+                parseUserData(p, hasUserDataHeader);
+            }
+        }
+    }
+
+    private void parseSmsDeliver(PduParser p, int firstByte) {
+        replyPathPresent = (firstByte & 0x80) == 0x80;
+
+        originatingAddress = p.getAddress();
+
+        if (originatingAddress != null) {
+            if (Config.LOGV) Log.v(LOG_TAG, "SMS originating address: "
+                    + originatingAddress.address);
+        }
+
+        // TP-Protocol-Identifier (TP-PID)
+        // TS 23.040 9.2.3.9
+        protocolIdentifier = p.getByte();
+
+        // TP-Data-Coding-Scheme
+        // see TS 23.038
+        dataCodingScheme = p.getByte();
+
+        if (Config.LOGV) {
+            Log.v(LOG_TAG, "SMS TP-PID:" + protocolIdentifier
+                    + " data coding scheme: " + dataCodingScheme);
+        }
+
+        scTimeMillis = p.getSCTimestampMillis();
+
+        if (Config.LOGD) Log.d(LOG_TAG, "SMS SC timestamp: " + scTimeMillis);
+
+        boolean hasUserDataHeader = (firstByte & 0x40) == 0x40;
+
+        parseUserData(p, hasUserDataHeader);
+    }
+
+    /**
+     * Parses the User Data of an SMS.
+     *
+     * @param p The current PduParser.
+     * @param hasUserDataHeader Indicates whether a header is present in the
+     *                          User Data.
+     */
+    private void parseUserData(PduParser p, boolean hasUserDataHeader) {
+        boolean hasMessageClass = false;
+        boolean userDataCompressed = false;
+
+        int encodingType = ENCODING_UNKNOWN;
+
+        // Look up the data encoding scheme
+        if ((dataCodingScheme & 0x80) == 0) {
+            // Bits 7..4 == 0xxx
+            automaticDeletion = (0 != (dataCodingScheme & 0x40));
+            userDataCompressed = (0 != (dataCodingScheme & 0x20));
+            hasMessageClass = (0 != (dataCodingScheme & 0x10));
+
+            if (userDataCompressed) {
+                Log.w(LOG_TAG, "4 - Unsupported SMS data coding scheme "
+                        + "(compression) " + (dataCodingScheme & 0xff));
+            } else {
+                switch ((dataCodingScheme >> 2) & 0x3) {
+                case 0: // GSM 7 bit default alphabet
+                    encodingType = ENCODING_7BIT;
+                    break;
+
+                case 2: // UCS 2 (16bit)
+                    encodingType = ENCODING_16BIT;
+                    break;
+
+                case 1: // 8 bit data
+                case 3: // reserved
+                    Log.w(LOG_TAG, "1 - Unsupported SMS data coding scheme "
+                            + (dataCodingScheme & 0xff));
+                    encodingType = ENCODING_8BIT;
+                    break;
+                }
+            }
+        } else if ((dataCodingScheme & 0xf0) == 0xf0) {
+            automaticDeletion = false;
+            hasMessageClass = true;
+            userDataCompressed = false;
+
+            if (0 == (dataCodingScheme & 0x04)) {
+                // GSM 7 bit default alphabet
+                encodingType = ENCODING_7BIT;
+            } else {
+                // 8 bit data
+                encodingType = ENCODING_8BIT;
+            }
+        } else if ((dataCodingScheme & 0xF0) == 0xC0
+                || (dataCodingScheme & 0xF0) == 0xD0
+                || (dataCodingScheme & 0xF0) == 0xE0) {
+            // 3GPP TS 23.038 V7.0.0 (2006-03) section 4
+
+            // 0xC0 == 7 bit, don't store
+            // 0xD0 == 7 bit, store
+            // 0xE0 == UCS-2, store
+
+            if ((dataCodingScheme & 0xF0) == 0xE0) {
+                encodingType = ENCODING_16BIT;
+            } else {
+                encodingType = ENCODING_7BIT;
+            }
+
+            userDataCompressed = false;
+            boolean active = ((dataCodingScheme & 0x08) == 0x08);
+
+            // bit 0x04 reserved
+
+            if ((dataCodingScheme & 0x03) == 0x00) {
+                isMwi = true;
+                mwiSense = active;
+                mwiDontStore = ((dataCodingScheme & 0xF0) == 0xC0);
+            } else {
+                isMwi = false;
+
+                Log.w(LOG_TAG, "MWI for fax, email, or other "
+                        + (dataCodingScheme & 0xff));
+            }
+        } else {
+            Log.w(LOG_TAG, "3 - Unsupported SMS data coding scheme "
+                    + (dataCodingScheme & 0xff));
+        }
+
+        // set both the user data and the user data header.
+        int count = p.constructUserData(hasUserDataHeader,
+                encodingType == ENCODING_7BIT);
+        this.userData = p.getUserData();
+        this.userDataHeader = p.getUserDataHeader();
+
+        switch (encodingType) {
+        case ENCODING_UNKNOWN:
+        case ENCODING_8BIT:
+            messageBody = null;
+            break;
+
+        case ENCODING_7BIT:
+            messageBody = p.getUserDataGSM7Bit(count);
+            break;
+
+        case ENCODING_16BIT:
+            messageBody = p.getUserDataUCS2(count);
+            break;
+        }
+
+        if (Config.LOGV) Log.v(LOG_TAG, "SMS message body (raw): '" + messageBody + "'");
+
+        if (messageBody != null) {
+            parseMessageBody();
+        }
+
+        if (!hasMessageClass) {
+            messageClass = MessageClass.UNKNOWN;
+        } else {
+            switch (dataCodingScheme & 0x3) {
+            case 0:
+                messageClass = MessageClass.CLASS_0;
+                break;
+            case 1:
+                messageClass = MessageClass.CLASS_1;
+                break;
+            case 2:
+                messageClass = MessageClass.CLASS_2;
+                break;
+            case 3:
+                messageClass = MessageClass.CLASS_3;
+                break;
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public MessageClass getMessageClass() {
+        return messageClass;
+    }
+
+}
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/BerTlv.java b/telephony/java/com/android/internal/telephony/gsm/stk/BerTlv.java
index 26c2175b..19d3279 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/BerTlv.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/BerTlv.java
@@ -20,9 +20,9 @@
 
 /**
  * Class for representing BER-TLV objects.
- * 
+ *
  * @see "ETSI TS 102 223 Annex C" for more information.
- * 
+ *
  * {@hide}
  */
 class BerTlv {
@@ -41,16 +41,16 @@
 
     /**
      * Gets a list of ComprehensionTlv objects contained in this BER-TLV object.
-     * 
+     *
      * @return A list of COMPREHENSION-TLV object
      */
     public List<ComprehensionTlv> getComprehensionTlvs() {
         return mCompTlvs;
     }
-    
+
     /**
      * Gets a tag id of the BER-TLV object.
-     * 
+     *
      * @return A tag integer.
      */
     public int getTag() {
@@ -59,7 +59,7 @@
 
     /**
      * Decodes a BER-TLV object from a byte array.
-     * 
+     *
      * @param data A byte array to decode from
      * @return A BER-TLV object decoded
      * @throws ResultException
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/CommandParams.java b/telephony/java/com/android/internal/telephony/gsm/stk/CommandParams.java
index 60e8148..a27c582 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/CommandParams.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/CommandParams.java
@@ -19,7 +19,7 @@
 import android.graphics.Bitmap;
 
 /**
- * Container class for proactive command parameters. 
+ * Container class for proactive command parameters.
  *
  */
 class CommandParams {
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/CommandParamsFactory.java b/telephony/java/com/android/internal/telephony/gsm/stk/CommandParamsFactory.java
index eb354e9..06b36a4 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/CommandParamsFactory.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/CommandParamsFactory.java
@@ -20,7 +20,7 @@
 import android.os.Handler;
 import android.os.Message;
 
-import com.android.internal.telephony.gsm.GsmAlphabet;
+import com.android.internal.telephony.GsmAlphabet;
 import com.android.internal.telephony.gsm.SIMFileHandler;
 
 import java.util.Iterator;
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/ComprehensionTlv.java b/telephony/java/com/android/internal/telephony/gsm/stk/ComprehensionTlv.java
index 833ff3c..4f746ac 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/ComprehensionTlv.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/ComprehensionTlv.java
@@ -22,9 +22,9 @@
 
 /**
  * Class for representing COMPREHENSION-TLV objects.
- * 
+ *
  * @see "ETSI TS 101 220 subsection 7.1.1"
- * 
+ *
  * {@hide}
  */
 class ComprehensionTlv {
@@ -38,7 +38,7 @@
      * Constructor. Private on purpose. Use
      * {@link #decodeMany(byte[], int) decodeMany} or
      * {@link #decode(byte[], int) decode} method.
-     * 
+     *
      * @param tag The tag for this object
      * @param cr Comprehension Required flag
      * @param length Length of the value
@@ -76,7 +76,7 @@
 
     /**
      * Parses a list of COMPREHENSION-TLV objects from a byte array.
-     * 
+     *
      * @param data A byte array containing data to be parsed
      * @param startIndex Index in data at which to start parsing
      * @return A list of COMPREHENSION-TLV objects parsed
@@ -97,7 +97,7 @@
 
     /**
      * Parses an COMPREHENSION-TLV object from a byte array.
-     * 
+     *
      * @param data A byte array containing data to be parsed
      * @param startIndex Index in data at which to start parsing
      * @return A COMPREHENSION-TLV object parsed
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/IconLoader.java b/telephony/java/com/android/internal/telephony/gsm/stk/IconLoader.java
index a63d1ca..fc02d2a 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/IconLoader.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/IconLoader.java
@@ -30,9 +30,9 @@
 import java.util.HashMap;
 
 /**
- * Class for loading icons from the SIM card. Has two states: single, for loading 
+ * Class for loading icons from the SIM card. Has two states: single, for loading
  * one icon. Multi, for loading icons list.
- * 
+ *
  */
 class IconLoader extends Handler {
     // members
@@ -51,13 +51,13 @@
 
     private static IconLoader sLoader = null;
 
-    // Loader state values. 
+    // Loader state values.
     private static final int STATE_SINGLE_ICON = 1;
     private static final int STATE_MULTI_ICONS = 2;
 
-    // Finished loading single record from a linear-fixed EF-IMG. 
+    // Finished loading single record from a linear-fixed EF-IMG.
     private static final int EVENT_READ_EF_IMG_RECOED_DONE  = 1;
-    // Finished loading single icon from a Transparent DF-Graphics. 
+    // Finished loading single icon from a Transparent DF-Graphics.
     private static final int EVENT_READ_ICON_DONE           = 2;
     // Finished loading single colour icon lookup table.
     private static final int EVENT_READ_CLUT_DONE           = 3;
@@ -170,10 +170,10 @@
     }
 
     /**
-     * Handles Image descriptor parsing and required processing. This is the 
+     * Handles Image descriptor parsing and required processing. This is the
      * first step required to handle retrieving icons from the SIM.
-     * 
-     * @param data byte [] containing Image Instance descriptor as defined in 
+     *
+     * @param data byte [] containing Image Instance descriptor as defined in
      * TS 51.011.
      */
     private boolean handleImageDescriptor(byte[] rawData) {
@@ -232,7 +232,7 @@
      * @param data The raw data
      * @param length The length of image body
      * @return The bitmap
-     */    
+     */
     public static Bitmap parseToBnW(byte[] data, int length){
         int valueIndex = 0;
         int width = data[valueIndex++] & 0xFF;
@@ -264,7 +264,7 @@
      * 0 is black
      * 1 is white
      * @param bit to decode
-     * @return RGB color  
+     * @return RGB color
      */
     private static int bitToBnW(int bit){
         if(bit == 1){
@@ -276,11 +276,11 @@
 
     /**
      * a TS 131.102 image instance of code scheme '11' into color Bitmap
-     * 
+     *
      * @param data The raw data
      * @param length the length of image body
      * @param transparency with or without transparency
-     * @param clut coulor lookup table 
+     * @param clut coulor lookup table
      * @return The color bitmap
      */
     public static Bitmap parseToRGB(byte[] data, int length,
@@ -321,9 +321,9 @@
         return Bitmap.createBitmap(pixels, width, height,
                 Bitmap.Config.ARGB_8888);
     }
-    
+
     /**
-     * Calculate bit mask for a given number of bits. The mask should enable to 
+     * Calculate bit mask for a given number of bits. The mask should enable to
      * make a bitwise and to the given number of bits.
      * @param numOfBits number of bits to calculate mask for.
      * @return bit mask
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/ImageDescriptor.java b/telephony/java/com/android/internal/telephony/gsm/stk/ImageDescriptor.java
index 7120a37..880b9e5 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/ImageDescriptor.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/ImageDescriptor.java
@@ -33,7 +33,8 @@
     static final int CODING_SCHEME_BASIC = 0x11;
     static final int CODING_SCHEME_COLOUR = 0x21;
 
-    public static final int ID_LENGTH = 9;
+    // public static final int ID_LENGTH = 9;
+    // ID_LENGTH substituted by IccFileHandlerBase.GET_RESPONSE_EF_IMG_SIZE_BYTES
 
     ImageDescriptor() {
         width = 0;
@@ -47,7 +48,7 @@
 
     /**
      * Extract descriptor information about image instance.
-     * 
+     *
      * @param rawData
      * @param valueIndex
      * @return ImageDescriptor
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/ResponseData.java b/telephony/java/com/android/internal/telephony/gsm/stk/ResponseData.java
index 9afa063..810afd2 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/ResponseData.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/ResponseData.java
@@ -16,8 +16,8 @@
 
 package com.android.internal.telephony.gsm.stk;
 
-import com.android.internal.telephony.gsm.EncodeException;
-import com.android.internal.telephony.gsm.GsmAlphabet;
+import com.android.internal.telephony.EncodeException;
+import com.android.internal.telephony.GsmAlphabet;
 
 import java.io.ByteArrayOutputStream;
 import java.io.UnsupportedEncodingException;
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/RilMessageDecoder.java b/telephony/java/com/android/internal/telephony/gsm/stk/RilMessageDecoder.java
index 5d82473..1cf38ed 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/RilMessageDecoder.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/RilMessageDecoder.java
@@ -17,7 +17,7 @@
 package com.android.internal.telephony.gsm.stk;
 
 import com.android.internal.telephony.gsm.SIMFileHandler;
-import com.android.internal.telephony.gsm.SimUtils;
+import com.android.internal.telephony.IccUtils;
 
 import android.os.Handler;
 import android.os.HandlerState;
@@ -142,7 +142,7 @@
         case StkService.MSG_ID_REFRESH:
             byte[] rawData = null;
             try {
-                rawData = SimUtils.hexStringToBytes((String) rilMsg.mData);
+                rawData = IccUtils.hexStringToBytes((String) rilMsg.mData);
             } catch (Exception e) {
                 // zombie messages are dropped
                 StkLog.d(this, "decodeMessageParams dropping zombie messages");
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/StkService.java b/telephony/java/com/android/internal/telephony/gsm/stk/StkService.java
index c0c4ceb..3de14f0 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/StkService.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/StkService.java
@@ -23,11 +23,13 @@
 import android.os.HandlerThread;
 import android.os.Message;
 
-import com.android.internal.telephony.gsm.CommandsInterface;
-import com.android.internal.telephony.gsm.GsmSimCard;
+import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.EncodeException;
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.gsm.SimCard;
 import com.android.internal.telephony.gsm.SIMFileHandler;
 import com.android.internal.telephony.gsm.SIMRecords;
-import com.android.internal.telephony.gsm.SimUtils;
 
 import android.util.Config;
 
@@ -115,10 +117,12 @@
  */
 public class StkService extends Handler implements AppInterface {
 
+    // Class members
+    private static SIMRecords mSimRecords;
+    
     // Service members.
     private static StkService sInstance;
     private CommandsInterface mCmdIf;
-    private SIMRecords mSimRecords;
     private Context mContext;
     private StkCmdMessage mCurrntCmd = null;
     private StkCmdMessage mMenuCmd = null;
@@ -147,7 +151,7 @@
 
     /* Intentionally private for singleton */
     private StkService(CommandsInterface ci, SIMRecords sr, Context context,
-            SIMFileHandler fh, GsmSimCard sc) {
+            SIMFileHandler fh, SimCard sc) {
         if (ci == null || sr == null || context == null || fh == null
                 || sc == null) {
             throw new NullPointerException(
@@ -172,6 +176,23 @@
         mSimRecords.registerForRecordsLoaded(this, MSG_ID_SIM_LOADED, null);
     }
 
+    public void dispose() {
+        mSimRecords.unregisterForRecordsLoaded(this);
+        mCmdIf.unSetOnStkSessionEnd(this);
+        mCmdIf.unSetOnStkProactiveCmd(this);
+        mCmdIf.unSetOnStkEvent(this);
+        mCmdIf.unSetOnStkCallSetUp(this);
+
+        this.removeCallbacksAndMessages(null);
+
+        //removing instance
+        sInstance = null;
+    }
+
+    protected void finalize() {
+        StkLog.d(this, "Service finalized");
+    }
+
     private void handleRilMsg(RilMessage rilMsg) {
         if (rilMsg == null) {
             return;
@@ -334,7 +355,7 @@
         }
 
         byte[] rawData = buf.toByteArray();
-        String hexString = SimUtils.bytesToHexString(rawData);
+        String hexString = IccUtils.bytesToHexString(rawData);
         if (Config.LOGD) {
             StkLog.d(this, "TERMINAL RESPONSE: " + hexString);
         }
@@ -380,7 +401,7 @@
         int len = rawData.length - 2; // minus (tag + length)
         rawData[1] = (byte) len;
 
-        String hexString = SimUtils.bytesToHexString(rawData);
+        String hexString = IccUtils.bytesToHexString(rawData);
 
         mCmdIf.sendEnvelope(hexString, null);
     }
@@ -423,7 +444,7 @@
         int len = rawData.length - 2; // minus (tag + length)
         rawData[1] = (byte) len;
 
-        String hexString = SimUtils.bytesToHexString(rawData);
+        String hexString = IccUtils.bytesToHexString(rawData);
 
         mCmdIf.sendEnvelope(hexString, null);
     }
@@ -439,7 +460,7 @@
      * @return The only Service object in the system
      */
     public static StkService getInstance(CommandsInterface ci, SIMRecords sr,
-            Context context, SIMFileHandler fh, GsmSimCard sc) {
+            Context context, SIMFileHandler fh, SimCard sc) {
         if (sInstance == null) {
             if (ci == null || sr == null || context == null || fh == null
                     || sc == null) {
@@ -448,6 +469,17 @@
             HandlerThread thread = new HandlerThread("Stk Telephony service");
             thread.start();
             sInstance = new StkService(ci, sr, context, fh, sc);
+            StkLog.d(sInstance, "NEW sInstance");
+        } else if ((sr != null) && (mSimRecords != sr)) {
+            StkLog.d(sInstance, String.format(
+                    "Reinitialize the Service with SIMRecords sr=0x%x.", sr));
+            mSimRecords = sr;
+
+            // re-Register for SIM ready event.
+            mSimRecords.registerForRecordsLoaded(sInstance, MSG_ID_SIM_LOADED, null);
+            StkLog.d(sInstance, "sr changed reinitialize and return current sInstance");
+        } else {
+            StkLog.d(sInstance, "Return current sInstance");
         }
         return sInstance;
     }
diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/ValueParser.java b/telephony/java/com/android/internal/telephony/gsm/stk/ValueParser.java
index 2cf87ba..8c8f977 100644
--- a/telephony/java/com/android/internal/telephony/gsm/stk/ValueParser.java
+++ b/telephony/java/com/android/internal/telephony/gsm/stk/ValueParser.java
@@ -16,8 +16,8 @@
 
 package com.android.internal.telephony.gsm.stk;
 
-import com.android.internal.telephony.gsm.GsmAlphabet;
-import com.android.internal.telephony.gsm.SimUtils;
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.IccUtils;
 import com.android.internal.telephony.gsm.stk.Duration.TimeUnit;
 
 import java.io.UnsupportedEncodingException;
@@ -117,7 +117,7 @@
 
             try {
                 int id = rawValue[valueIndex] & 0xff;
-                String text = SimUtils.adnStringFieldToString(rawValue,
+                String text = IccUtils.adnStringFieldToString(rawValue,
                         valueIndex + 1, textLen);
                 item = new Item(id, text);
             } catch (IndexOutOfBoundsException e) {
@@ -278,7 +278,7 @@
         int length = ctlv.getLength();
         if (length != 0) {
             try {
-                return SimUtils.adnStringFieldToString(rawValue, valueIndex,
+                return IccUtils.adnStringFieldToString(rawValue, valueIndex,
                         length);
             } catch (IndexOutOfBoundsException e) {
                 throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
diff --git a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
index 33c1679..3e53654 100644
--- a/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
+++ b/telephony/java/com/android/internal/telephony/test/SimulatedCommands.java
@@ -23,19 +23,18 @@
 import android.os.Message;
 import android.util.Log;
 
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.gsm.BaseCommands;
+import com.android.internal.telephony.BaseCommands;
+import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.gsm.CallFailCause;
-import com.android.internal.telephony.gsm.CommandException;
-import com.android.internal.telephony.gsm.CommandsInterface;
 import com.android.internal.telephony.gsm.PDPContextState;
 import com.android.internal.telephony.gsm.SuppServiceNotification;
+import com.android.internal.telephony.Phone;
 
 import java.util.ArrayList;
 
 public final class SimulatedCommands extends BaseCommands
-        implements CommandsInterface, SimulatedRadioControl
-{
+        implements CommandsInterface, SimulatedRadioControl {
     private final static String LOG_TAG = "SIM";
 
     private enum SimLockState {
@@ -43,14 +42,14 @@
         REQUIRE_PIN,
         REQUIRE_PUK,
         SIM_PERM_LOCKED
-    };
+    }
 
     private enum SimFdnState {
         NONE,
         REQUIRE_PIN2,
         REQUIRE_PUK2,
         SIM_PERM_LOCKED
-    };
+    }
 
     private final static SimLockState INITIAL_LOCK_STATE = SimLockState.NONE;
     private final static String DEFAULT_SIM_PIN_CODE = "1234";
@@ -103,11 +102,10 @@
 
     //***** CommandsInterface implementation
 
-    public void getSimStatus(Message result)
-    {
+    public void getIccStatus(Message result) {
         switch (mState) {
             case SIM_READY:
-                resultSuccess(result, SimStatus.SIM_READY);
+                resultSuccess(result, IccStatus.ICC_READY);
                 break;
 
             case SIM_LOCKED_OR_ABSENT:
@@ -115,7 +113,7 @@
                 break;
 
             default:
-                resultSuccess(result, SimStatus.SIM_NOT_READY);
+                resultSuccess(result, IccStatus.ICC_NOT_READY);
                 break;
         }
     }
@@ -123,13 +121,13 @@
     private void returnSimLockedStatus(Message result) {
         switch (mSimLockedState) {
             case REQUIRE_PIN:
-                Log.i(LOG_TAG, "[SimCmd] returnSimLockedStatus: SIM_PIN");
-                resultSuccess(result, SimStatus.SIM_PIN);
+                Log.i(LOG_TAG, "[SimCmd] returnSimLockedStatus: ICC_PIN");
+                resultSuccess(result, IccStatus.ICC_PIN);
                 break;
 
             case REQUIRE_PUK:
-                Log.i(LOG_TAG, "[SimCmd] returnSimLockedStatus: SIM_PUK");
-                resultSuccess(result, SimStatus.SIM_PUK);
+                Log.i(LOG_TAG, "[SimCmd] returnSimLockedStatus: ICC_PUK");
+                resultSuccess(result, IccStatus.ICC_PUK);
                 break;
 
             default:
@@ -139,9 +137,9 @@
         }
     }
 
-    public void supplySimPin(String pin, Message result)  {
+    public void supplyIccPin(String pin, Message result)  {
         if (mSimLockedState != SimLockState.REQUIRE_PIN) {
-            Log.i(LOG_TAG, "[SimCmd] supplySimPin: wrong state, state=" +
+            Log.i(LOG_TAG, "[SimCmd] supplyIccPin: wrong state, state=" +
                     mSimLockedState);
             CommandException ex = new CommandException(
                     CommandException.Error.PASSWORD_INCORRECT);
@@ -151,7 +149,7 @@
         }
 
         if (pin != null && pin.equals(mPinCode)) {
-            Log.i(LOG_TAG, "[SimCmd] supplySimPin: success!");
+            Log.i(LOG_TAG, "[SimCmd] supplyIccPin: success!");
             setRadioState(RadioState.SIM_READY);
             mPinUnlockAttempts = 0;
             mSimLockedState = SimLockState.NONE;
@@ -167,10 +165,10 @@
         if (result != null) {
             mPinUnlockAttempts ++;
 
-            Log.i(LOG_TAG, "[SimCmd] supplySimPin: failed! attempt=" +
+            Log.i(LOG_TAG, "[SimCmd] supplyIccPin: failed! attempt=" +
                     mPinUnlockAttempts);
             if (mPinUnlockAttempts >= 3) {
-                Log.i(LOG_TAG, "[SimCmd] supplySimPin: set state to REQUIRE_PUK");
+                Log.i(LOG_TAG, "[SimCmd] supplyIccPin: set state to REQUIRE_PUK");
                 mSimLockedState = SimLockState.REQUIRE_PUK;
             }
 
@@ -181,9 +179,9 @@
         }
     }
 
-    public void supplySimPuk(String puk, String newPin, Message result)  {
+    public void supplyIccPuk(String puk, String newPin, Message result)  {
         if (mSimLockedState != SimLockState.REQUIRE_PUK) {
-            Log.i(LOG_TAG, "[SimCmd] supplySimPuk: wrong state, state=" +
+            Log.i(LOG_TAG, "[SimCmd] supplyIccPuk: wrong state, state=" +
                     mSimLockedState);
             CommandException ex = new CommandException(
                     CommandException.Error.PASSWORD_INCORRECT);
@@ -193,7 +191,7 @@
         }
 
         if (puk != null && puk.equals(SIM_PUK_CODE)) {
-            Log.i(LOG_TAG, "[SimCmd] supplySimPuk: success!");
+            Log.i(LOG_TAG, "[SimCmd] supplyIccPuk: success!");
             setRadioState(RadioState.SIM_READY);
             mSimLockedState = SimLockState.NONE;
             mPukUnlockAttempts = 0;
@@ -209,10 +207,10 @@
         if (result != null) {
             mPukUnlockAttempts ++;
 
-            Log.i(LOG_TAG, "[SimCmd] supplySimPuk: failed! attempt=" +
+            Log.i(LOG_TAG, "[SimCmd] supplyIccPuk: failed! attempt=" +
                     mPukUnlockAttempts);
             if (mPukUnlockAttempts >= 10) {
-                Log.i(LOG_TAG, "[SimCmd] supplySimPuk: set state to SIM_PERM_LOCKED");
+                Log.i(LOG_TAG, "[SimCmd] supplyIccPuk: set state to SIM_PERM_LOCKED");
                 mSimLockedState = SimLockState.SIM_PERM_LOCKED;
             }
 
@@ -223,9 +221,9 @@
         }
     }
 
-    public void supplySimPin2(String pin2, Message result)  {
+    public void supplyIccPin2(String pin2, Message result)  {
         if (mSimFdnEnabledState != SimFdnState.REQUIRE_PIN2) {
-            Log.i(LOG_TAG, "[SimCmd] supplySimPin2: wrong state, state=" +
+            Log.i(LOG_TAG, "[SimCmd] supplyIccPin2: wrong state, state=" +
                     mSimFdnEnabledState);
             CommandException ex = new CommandException(
                     CommandException.Error.PASSWORD_INCORRECT);
@@ -235,7 +233,7 @@
         }
 
         if (pin2 != null && pin2.equals(mPin2Code)) {
-            Log.i(LOG_TAG, "[SimCmd] supplySimPin2: success!");
+            Log.i(LOG_TAG, "[SimCmd] supplyIccPin2: success!");
             mPin2UnlockAttempts = 0;
             mSimFdnEnabledState = SimFdnState.NONE;
 
@@ -250,10 +248,10 @@
         if (result != null) {
             mPin2UnlockAttempts ++;
 
-            Log.i(LOG_TAG, "[SimCmd] supplySimPin2: failed! attempt=" +
+            Log.i(LOG_TAG, "[SimCmd] supplyIccPin2: failed! attempt=" +
                     mPin2UnlockAttempts);
             if (mPin2UnlockAttempts >= 3) {
-                Log.i(LOG_TAG, "[SimCmd] supplySimPin2: set state to REQUIRE_PUK2");
+                Log.i(LOG_TAG, "[SimCmd] supplyIccPin2: set state to REQUIRE_PUK2");
                 mSimFdnEnabledState = SimFdnState.REQUIRE_PUK2;
             }
 
@@ -264,9 +262,9 @@
         }
     }
 
-    public void supplySimPuk2(String puk2, String newPin2, Message result)  {
+    public void supplyIccPuk2(String puk2, String newPin2, Message result)  {
         if (mSimFdnEnabledState != SimFdnState.REQUIRE_PUK2) {
-            Log.i(LOG_TAG, "[SimCmd] supplySimPuk2: wrong state, state=" +
+            Log.i(LOG_TAG, "[SimCmd] supplyIccPuk2: wrong state, state=" +
                     mSimLockedState);
             CommandException ex = new CommandException(
                     CommandException.Error.PASSWORD_INCORRECT);
@@ -276,7 +274,7 @@
         }
 
         if (puk2 != null && puk2.equals(SIM_PUK2_CODE)) {
-            Log.i(LOG_TAG, "[SimCmd] supplySimPuk2: success!");
+            Log.i(LOG_TAG, "[SimCmd] supplyIccPuk2: success!");
             mSimFdnEnabledState = SimFdnState.NONE;
             mPuk2UnlockAttempts = 0;
 
@@ -291,10 +289,10 @@
         if (result != null) {
             mPuk2UnlockAttempts ++;
 
-            Log.i(LOG_TAG, "[SimCmd] supplySimPuk2: failed! attempt=" +
+            Log.i(LOG_TAG, "[SimCmd] supplyIccPuk2: failed! attempt=" +
                     mPuk2UnlockAttempts);
             if (mPuk2UnlockAttempts >= 10) {
-                Log.i(LOG_TAG, "[SimCmd] supplySimPuk2: set state to SIM_PERM_LOCKED");
+                Log.i(LOG_TAG, "[SimCmd] supplyIccPuk2: set state to SIM_PERM_LOCKED");
                 mSimFdnEnabledState = SimFdnState.SIM_PERM_LOCKED;
             }
 
@@ -305,7 +303,7 @@
         }
     }
 
-    public void changeSimPin(String oldPin, String newPin, Message result)  {
+    public void changeIccPin(String oldPin, String newPin, Message result)  {
         if (oldPin != null && oldPin.equals(mPinCode)) {
             mPinCode = newPin;
             if (result != null) {
@@ -317,7 +315,7 @@
         }
 
         if (result != null) {
-            Log.i(LOG_TAG, "[SimCmd] changeSimPin: pin failed!");
+            Log.i(LOG_TAG, "[SimCmd] changeIccPin: pin failed!");
 
             CommandException ex = new CommandException(
                     CommandException.Error.PASSWORD_INCORRECT);
@@ -326,7 +324,7 @@
         }
     }
 
-    public void changeSimPin2(String oldPin2, String newPin2, Message result)  {
+    public void changeIccPin2(String oldPin2, String newPin2, Message result)  {
         if (oldPin2 != null && oldPin2.equals(mPin2Code)) {
             mPin2Code = newPin2;
             if (result != null) {
@@ -338,7 +336,7 @@
         }
 
         if (result != null) {
-            Log.i(LOG_TAG, "[SimCmd] changeSimPin: pin2 failed!");
+            Log.i(LOG_TAG, "[SimCmd] changeIccPin2: pin2 failed!");
 
             CommandException ex = new CommandException(
                     CommandException.Error.PASSWORD_INCORRECT);
@@ -348,14 +346,12 @@
     }
 
     public void
-    changeBarringPassword(String facility, String oldPwd, String newPwd, Message result)
-    {
+    changeBarringPassword(String facility, String oldPwd, String newPwd, Message result) {
         unimplemented(result);
     }
 
     public void
-    setSuppServiceNotifications(boolean enable, Message result)
-    {
+    setSuppServiceNotifications(boolean enable, Message result) {
         resultSuccess(result, null);
         
         if (enable && mSsnNotifyOn) {
@@ -477,8 +473,7 @@
      *  ar.result contains a List of DriverCall
      *      The ar.result List is sorted by DriverCall.index
      */
-    public void getCurrentCalls (Message result)  
-    {
+    public void getCurrentCalls (Message result) {
         if (mState == RadioState.SIM_READY) {
             //Log.i("GSM", "[SimCmds] getCurrentCalls");
             resultSuccess(result, simulatedCallState.getDriverCalls());
@@ -491,14 +486,20 @@
     }
 
     /** 
+     *  @deprecated
+     */
+    public void getPDPContextList(Message result) {
+        getDataCallList(result);
+    }
+
+    /**
      *  returned message
      *  retMsg.obj = AsyncResult ar
      *  ar.exception carries exception on failure
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result contains a List of PDPContextState
      */
-    public void getPDPContextList(Message result)  
-    {
+    public void getDataCallList(Message result) {
         resultSuccess(result, new ArrayList<PDPContextState>(0));
     }
 
@@ -513,8 +514,7 @@
      * CLIR_SUPPRESSION == on "CLIR suppression" (allow CLI presentation)
      * CLIR_INVOCATION  == on "CLIR invocation" (restrict CLI presentation)
      */
-    public void dial (String address, int clirMode, Message result)  
-    {
+    public void dial (String address, int clirMode, Message result) {
         simulatedCallState.onDial(address);
 
         resultSuccess(result, null);
@@ -527,8 +527,7 @@
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is String containing IMSI on success
      */
-    public void getIMSI(Message result)  
-    {
+    public void getIMSI(Message result) {
         resultSuccess(result, "012345678901234");
     }
 
@@ -539,8 +538,7 @@
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is String containing IMEI on success
      */
-    public void getIMEI(Message result)  
-    {
+    public void getIMEI(Message result) {
         resultSuccess(result, "012345678901234");
     }
 
@@ -551,8 +549,7 @@
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is String containing IMEISV on success
      */
-    public void getIMEISV(Message result)  
-    {
+    public void getIMEISV(Message result) {
         resultSuccess(result, "99");
     }
 
@@ -567,8 +564,7 @@
      *  3GPP 22.030 6.5.5
      *  "Releases a specific active call X"
      */
-    public void hangupConnection (int gsmIndex, Message result) 
-    {
+    public void hangupConnection (int gsmIndex, Message result) {
         boolean success;
         
         success = simulatedCallState.onChld('1', (char)('0'+gsmIndex));
@@ -590,8 +586,7 @@
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
      */
-    public void hangupWaitingOrBackground (Message result)
-    {
+    public void hangupWaitingOrBackground (Message result) {
         boolean success;
         
         success = simulatedCallState.onChld('0', '\0');
@@ -612,8 +607,7 @@
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
      */
-    public void hangupForegroundResumeBackground (Message result) 
-    {
+    public void hangupForegroundResumeBackground (Message result) {
         boolean success;
         
         success = simulatedCallState.onChld('1', '\0');
@@ -634,8 +628,7 @@
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
      */
-    public void switchWaitingOrHoldingAndActive (Message result)
-    {
+    public void switchWaitingOrHoldingAndActive (Message result) {
         boolean success;
         
         success = simulatedCallState.onChld('2', '\0');
@@ -655,8 +648,7 @@
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
      */    
-    public void conference (Message result)
-    {
+    public void conference (Message result) {
         boolean success;
         
         success = simulatedCallState.onChld('3', '\0');
@@ -676,8 +668,7 @@
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
      */
-    public void explicitCallTransfer (Message result)
-    {
+    public void explicitCallTransfer (Message result) {
         boolean success;
 
         success = simulatedCallState.onChld('4', '\0');
@@ -694,8 +685,7 @@
      * "Places all active calls on hold except call X with which 
      *  communication shall be supported."
      */
-    public void separateConnection (int gsmIndex, Message result) 
-    {
+    public void separateConnection (int gsmIndex, Message result) {
         boolean success;
 
         char ch = (char)(gsmIndex + '0');
@@ -714,8 +704,7 @@
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
      */    
-    public void acceptCall (Message result) 
-    {
+    public void acceptCall (Message result) {
         boolean success;
         
         success = simulatedCallState.onAnswer();
@@ -733,8 +722,7 @@
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
      */    
-    public void rejectCall (Message result)
-    {
+    public void rejectCall (Message result) {
         boolean success;
         
         success = simulatedCallState.onChld('0', '\0');
@@ -754,17 +742,22 @@
      * - Any defined in 22.001 F.4 (for generating busy/congestion)
      * - Cause 68: ACM >= ACMMax
      */
-    public void getLastCallFailCause (Message result)
-    {
+    public void getLastCallFailCause (Message result) {
         int[] ret = new int[1];
 
         ret[0] = nextCallFailCause;
         resultSuccess(result, ret);
     }
 
-    public void
-    getLastPdpFailCause (Message result)
-    {
+    /**
+     * @deprecated
+     */
+    public void getLastPdpFailCause (Message result) {
+        unimplemented(result);
+    }
+
+    public void getLastDataCallFailCause(Message result) {
+        //
         unimplemented(result);
     }
 
@@ -779,8 +772,7 @@
      * response.obj.result[1] is  bit error rate (0-7, 99) 
      * as defined in TS 27.007 8.5
      */
-    public void getSignalStrength (Message result)
-    {
+    public void getSignalStrength (Message result) {
         int ret[] = new int[2];
 
         ret[0] = 23;
@@ -850,8 +842,7 @@
      * Please note that registration state 4 ("unknown") is treated
      * as "out of service" above
      */
-    public void getRegistrationState (Message result)
-    {
+    public void getRegistrationState (Message result) {
         String ret[] = new String[3];
 
         ret[0] = "5"; // registered roam
@@ -878,8 +869,7 @@
      * Please note that registration state 4 ("unknown") is treated
      * as "out of service" in the Android telephony system
      */
-    public void getGPRSRegistrationState (Message result)
-    {
+    public void getGPRSRegistrationState (Message result) {
         String ret[] = new String[4];
 
         ret[0] = "5"; // registered roam
@@ -896,8 +886,7 @@
      * response.obj.result[1] is short alpha or null if unregistered
      * response.obj.result[2] is numeric or null if unregistered
      */ 
-    public void getOperator(Message result)
-    {
+    public void getOperator(Message result) {
         String[] ret = new String[3];
 
         ret[0] = "El Telco Loco";
@@ -912,8 +901,7 @@
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
      */    
-    public void sendDtmf(char c, Message result)
-    {
+    public void sendDtmf(char c, Message result) {
         resultSuccess(result, null);
     }
 
@@ -922,8 +910,7 @@
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
      */
-    public void startDtmf(char c, Message result)
-    {
+    public void startDtmf(char c, Message result) {
         resultSuccess(result, null);
     }
 
@@ -932,8 +919,7 @@
      *  ar.userObject contains the orignal value of result.obj
      *  ar.result is null on success and failure
      */
-    public void stopDtmf(Message result)
-    {
+    public void stopDtmf(Message result) {
         resultSuccess(result, null);
     }
 
@@ -950,16 +936,35 @@
         unimplemented(response);
     }
 
+    public void deleteSmsOnRuim(int index, Message response) {
+        Log.d(LOG_TAG, "Delete RUIM message at index " + index);
+        unimplemented(response);
+    }
+
     public void writeSmsToSim(int status, String smsc, String pdu, Message response) {
         Log.d(LOG_TAG, "Write SMS to SIM with status " + status);
         unimplemented(response);
     }
 
+    public void writeSmsToRuim(int status, String pdu, Message response) {
+        Log.d(LOG_TAG, "Write SMS to RUIM with status " + status);
+        unimplemented(response);
+    }
 
     public void setupDefaultPDP(String apn, String user, String password, Message result) {
         unimplemented(result);
     }
 
+    public void setupDataCall(String radioTechnology, String profile, String apn, String user,
+            String password, Message result) {
+        unimplemented(result);
+    }
+
+    public void deactivateDataCall(int cid, Message result) {unimplemented(result);}
+
+    /**
+     * @deprecated
+     */
     public void deactivateDefaultPDP(int cid, Message result) {unimplemented(result);}
 
     public void setPreferredNetworkType(int networkType , Message result) {
@@ -994,9 +999,8 @@
         }
         return false;
     }
-    
-    public void setRadioPower(boolean on, Message result)
-    {
+
+    public void setRadioPower(boolean on, Message result) {
         if(on) {
             if (isSimLocked()) {
                 Log.i("SIM", "[SimCmd] setRadioPower: SIM locked! state=" +
@@ -1016,12 +1020,16 @@
         unimplemented(result);
     }
 
+    public void acknowledgeLastIncomingCdmaSms(boolean success, Message result) {
+        unimplemented(result);
+    }
+
     /** 
      * parameters equivilient to 27.007 AT+CRSM command 
      * response.obj will be an AsyncResult
      * response.obj.userObj will be a SimIoResult on success
      */
-    public void simIO (int command, int fileid, String path, int p1, int p2,
+    public void iccIO (int command, int fileid, String path, int p1, int p2,
                        int p3, String data, String pin2, Message result) {
         unimplemented(result);
     }
@@ -1069,8 +1077,7 @@
      * @param response is callback message
      */
     
-    public void queryCallWaiting(int serviceClass, Message response)
-    {
+    public void queryCallWaiting(int serviceClass, Message response) {
         unimplemented(response);
     }
     
@@ -1081,8 +1088,7 @@
      */
     
     public void setCallWaiting(boolean enable, int serviceClass,
-            Message response)
-    {
+            Message response) {
         unimplemented(response);
     }
 
@@ -1092,7 +1098,7 @@
      * @param serviceClass is a sum of SERVICE_CLASSS_* 
      */
     public void setCallForward(int action, int cfReason, int serviceClass, 
-                String number, int timeSeconds, Message result) {unimplemented(result);}
+            String number, int timeSeconds, Message result) {unimplemented(result);}
 
     /**
      * cfReason is one of CF_REASON_*
@@ -1103,11 +1109,12 @@
      * An array of length 0 means "disabled for all codes"
      */
     public void queryCallForwardStatus(int cfReason, int serviceClass,
-                String number, Message result) {unimplemented(result);}
+            String number, Message result) {unimplemented(result);}
 
     public void setNetworkSelectionModeAutomatic(Message result) {unimplemented(result);}
 
-    public void setNetworkSelectionModeManual(String operatorNumeric, Message result) {unimplemented(result);}
+    public void setNetworkSelectionModeManual(
+            String operatorNumeric, Message result) {unimplemented(result);}
 
     /**
      * Queries whether the current network selection mode is automatic
@@ -1117,8 +1124,7 @@
      * a 0 for automatic selection and a 1 for manual selection
      */
 
-    public void getNetworkSelectionMode(Message result)
-    {
+    public void getNetworkSelectionMode(Message result) {
         int ret[] = new int[1];
 
         ret[0] = 0;
@@ -1132,8 +1138,7 @@
      */
     public void getAvailableNetworks(Message result) {unimplemented(result);}
 
-    public void getBasebandVersion (Message result) 
-    {
+    public void getBasebandVersion (Message result) {
         resultSuccess(result, "SimulatedCommands"); 
     }
 
@@ -1172,13 +1177,11 @@
     }
 
 
-    public void resetRadio(Message result)
-    {
+    public void resetRadio(Message result) {
         unimplemented(result);
     }
 
-    public void invokeOemRilRequestRaw(byte[] data, Message response)
-    {
+    public void invokeOemRilRequestRaw(byte[] data, Message response) {
         // Just echo back data
         if (response != null) {
             AsyncResult.forMessage(response).result = data;
@@ -1186,8 +1189,7 @@
         }
     }
 
-    public void invokeOemRilRequestStrings(String[] strings, Message response)
-    {
+    public void invokeOemRilRequestStrings(String[] strings, Message response) {
         // Just echo back data
         if (response != null) {
             AsyncResult.forMessage(response).result = strings;
@@ -1200,23 +1202,20 @@
     
     /** Start the simulated phone ringing */
     public void
-    triggerRing(String number)
-    {
+    triggerRing(String number) {
         simulatedCallState.triggerRing(number);
         mCallStateRegistrants.notifyRegistrants();
     }
 
     public void
-    progressConnectingCallState()
-    {
+    progressConnectingCallState() {
         simulatedCallState.progressConnectingCallState();
         mCallStateRegistrants.notifyRegistrants();
     }
 
     /** If a call is DIALING or ALERTING, progress it all the way to ACTIVE */
     public void
-    progressConnectingToActive()
-    {
+    progressConnectingToActive() {
         simulatedCallState.progressConnectingToActive();
         mCallStateRegistrants.notifyRegistrants();
     }
@@ -1225,40 +1224,34 @@
      *  default to true
      */
     public void
-    setAutoProgressConnectingCall(boolean b)
-    {
+    setAutoProgressConnectingCall(boolean b) {
         simulatedCallState.setAutoProgressConnectingCall(b);
     }
 
     public void
-    setNextDialFailImmediately(boolean b)
-    {
+    setNextDialFailImmediately(boolean b) {
         simulatedCallState.setNextDialFailImmediately(b);
     }
 
     public void 
-    setNextCallFailCause(int gsmCause)
-    {
+    setNextCallFailCause(int gsmCause) {
         nextCallFailCause = gsmCause;    
     }
 
     public void
-    triggerHangupForeground()
-    {
+    triggerHangupForeground() {
         simulatedCallState.triggerHangupForeground();
         mCallStateRegistrants.notifyRegistrants();
     }
 
     /** hangup holding calls */
     public void
-    triggerHangupBackground()
-    {
+    triggerHangupBackground() {
         simulatedCallState.triggerHangupBackground();
         mCallStateRegistrants.notifyRegistrants();
     }
 
-    public void triggerSsn(int type, int code)
-    {
+    public void triggerSsn(int type, int code) {
         SuppServiceNotification not = new SuppServiceNotification();
         not.notificationType = type;
         not.code = code;
@@ -1266,8 +1259,7 @@
     }
 
     public void
-    shutdown()
-    {
+    shutdown() {
         setRadioState(RadioState.RADIO_UNAVAILABLE);
         Looper looper = mHandlerThread.getLooper();
         if (looper != null) {
@@ -1278,27 +1270,23 @@
     /** hangup all */
 
     public void
-    triggerHangupAll()
-    {
+    triggerHangupAll() {
         simulatedCallState.triggerHangupAll();
         mCallStateRegistrants.notifyRegistrants();
     }
 
     public void
-    triggerIncomingSMS(String message)
-    {
+    triggerIncomingSMS(String message) {
         //TODO
     }
 
     public void
-    pauseResponses()
-    {
+    pauseResponses() {
         pausedResponseCount++;
     }
 
     public void
-    resumeResponses()
-    {
+    resumeResponses() {
         pausedResponseCount--;
 
         if (pausedResponseCount == 0) {
@@ -1313,8 +1301,7 @@
 
     //***** Private Methods
 
-    private void unimplemented(Message result)
-    {
+    private void unimplemented(Message result) {
         if (result != null) {
             AsyncResult.forMessage(result).exception 
                 = new RuntimeException("Unimplemented");
@@ -1327,8 +1314,7 @@
         }
     }
 
-    private void resultSuccess(Message result, Object ret)
-    {
+    private void resultSuccess(Message result, Object ret) {
         if (result != null) {
             AsyncResult.forMessage(result).result = ret;
             if (pausedResponseCount > 0) {
@@ -1339,8 +1325,7 @@
         }
     }
 
-    private void resultFail(Message result, Throwable tr)
-    {
+    private void resultFail(Message result, Throwable tr) {
         if (result != null) {
             AsyncResult.forMessage(result).exception = tr;
             if (pausedResponseCount > 0) {
@@ -1351,4 +1336,103 @@
         }
     }
 
+    // ***** Methods for CDMA support
+    public void
+    getDeviceIdentity(Message response) {
+        Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
+        unimplemented(response);
+    }
+
+    public void 
+    getCDMASubscription(Message response) {
+        Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
+        unimplemented(response);
+    }
+
+    public void 
+    setCdmaSubscription(int cdmaSubscriptionType, Message response) {
+        Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
+        unimplemented(response);
+    }
+
+    public void queryCdmaRoamingPreference(Message response) {
+        Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
+        unimplemented(response);
+    }
+
+    public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) {
+        Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
+        unimplemented(response);
+    }
+
+    public void
+    setPhoneType(int phoneType) {
+        Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
+    }
+
+    public void getPreferredVoicePrivacy(Message result) {
+        Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
+        unimplemented(result);
+    }
+
+    public void setPreferredVoicePrivacy(boolean enable, Message result) {
+        Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
+        unimplemented(result);
+    }
+
+    /**
+     *  Set the TTY mode for the CDMA phone
+     *
+     * @param enable is true to enable, false to disable
+     * @param serviceClass is a sum of SERVICE_CLASS_*
+     * @param response is callback message
+     */
+    public void setTTYModeEnabled(boolean enable, Message response) {
+        Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
+        unimplemented(response);
+    }
+
+    /**
+     *  Query the TTY mode for the CDMA phone
+     * (AsyncResult)response.obj).result is an int[] with element [0] set to
+     * 0 for disabled, 1 for enabled. 
+     *  
+     * @param serviceClass is a sum of SERVICE_CLASS_*
+     * @param response is callback message
+     */
+    public void queryTTYModeEnabled(Message response) {
+        Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
+        unimplemented(response);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void sendCDMAFeatureCode(String FeatureCode, Message response) {
+        Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
+        unimplemented(response);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void sendCdmaSms(byte[] pdu, Message response){
+       Log.w(LOG_TAG, "CDMA not implemented in SimulatedCommands");
+    }
+
+    public void activateCdmaBroadcastSms(int activate, Message result) {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void getCdmaBroadcastConfig(Message result) {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void setCdmaBroadcastConfig(int[] configValuesArray, Message result) {
+        // TODO Auto-generated method stub
+
+    }
+
 }
diff --git a/telephony/java/com/android/internal/telephony/test/SimulatedGsmCallState.java b/telephony/java/com/android/internal/telephony/test/SimulatedGsmCallState.java
index 340d788..803735c 100644
--- a/telephony/java/com/android/internal/telephony/test/SimulatedGsmCallState.java
+++ b/telephony/java/com/android/internal/telephony/test/SimulatedGsmCallState.java
@@ -21,14 +21,13 @@
 import android.os.Handler;
 import android.telephony.PhoneNumberUtils;
 import com.android.internal.telephony.ATParseEx;
-import com.android.internal.telephony.gsm.DriverCall;
+import com.android.internal.telephony.DriverCall;
 import java.util.List;
 import java.util.ArrayList;
 
 import android.util.Log;
 
-class CallInfo
-{
+class CallInfo {
     enum State {
         ACTIVE(0),
         HOLDING(1),
@@ -49,8 +48,7 @@
     String number;
     int TOA;
 
-    CallInfo (boolean isMT, State state, boolean isMpty, String number)
-    {
+    CallInfo (boolean isMT, State state, boolean isMpty, String number) {
         this.isMT = isMT;
         this.state = state;
         this.isMpty = isMpty;
@@ -64,20 +62,17 @@
     }
 
     static CallInfo
-    createOutgoingCall(String number)
-    {
+    createOutgoingCall(String number) {
         return new CallInfo (false, State.DIALING, false, number);
     }
 
     static CallInfo
-    createIncomingCall(String number)
-    {
+    createIncomingCall(String number) {
         return new CallInfo (true, State.INCOMING, false, number);
     }
 
     String
-    toCLCCLine(int index)
-    {
+    toCLCCLine(int index) {
         return 
             "+CLCC: "
             + index + "," + (isMT ? "1" : "0") +","
@@ -86,8 +81,7 @@
     }
 
     DriverCall
-    toDriverCall(int index)
-    {
+    toDriverCall(int index) {
         DriverCall ret; 
 
         ret = new DriverCall();
@@ -112,36 +106,30 @@
 
 
     boolean
-    isActiveOrHeld()
-    {
+    isActiveOrHeld() {
         return state == State.ACTIVE || state == State.HOLDING;
     }
 
     boolean
-    isConnecting()
-    {
+    isConnecting() {
         return state == State.DIALING || state == State.ALERTING;
     }
 
     boolean
-    isRinging()
-    {
+    isRinging() {
         return state == State.INCOMING || state == State.WAITING;
     }
 
 }
 
-class InvalidStateEx extends Exception
-{
-    InvalidStateEx()
-    {
+class InvalidStateEx extends Exception {
+    InvalidStateEx() {
 
     }
 }
 
 
-class SimulatedGsmCallState extends Handler
-{
+class SimulatedGsmCallState extends Handler {
     //***** Instance Variables
 
     CallInfo calls[] = new CallInfo[MAX_CALLS];
@@ -168,8 +156,7 @@
     }
 
     public void
-    handleMessage(Message msg)
-    {
+    handleMessage(Message msg) {
         synchronized(this) { switch (msg.what) {
             // PLEASE REMEMBER
             // calls may have hung up by the time delayed events happen
@@ -181,15 +168,13 @@
     }
 
     //***** Public Methods
-   
-    
+
     /** 
      * Start the simulated phone ringing 
      * true if succeeded, false if failed
      */
     public boolean
-    triggerRing(String number)
-    {
+    triggerRing(String number) {
         synchronized (this) {
             int empty = -1;
             boolean isCallWaiting = false;
@@ -230,8 +215,7 @@
 
     /** If a call is DIALING or ALERTING, progress it to the next state */
     public void
-    progressConnectingCallState()
-    {
+    progressConnectingCallState() {
         synchronized (this)  {
             for (int i = 0 ; i < calls.length ; i++) {
                 CallInfo call = calls[i];
@@ -257,8 +241,7 @@
 
     /** If a call is DIALING or ALERTING, progress it all the way to ACTIVE */
     public void
-    progressConnectingToActive()
-    {
+    progressConnectingToActive() {
         synchronized (this)  {
             for (int i = 0 ; i < calls.length ; i++) {
                 CallInfo call = calls[i];
@@ -277,14 +260,12 @@
      *  default to true
      */
     public void
-    setAutoProgressConnectingCall(boolean b)
-    {        
+    setAutoProgressConnectingCall(boolean b) {
         autoProgressConnecting = b;
     }
     
     public void
-    setNextDialFailImmediately(boolean b)
-    {
+    setNextDialFailImmediately(boolean b) {
         nextDialFailImmediately = b;
     }
 
@@ -293,8 +274,7 @@
      * returns true if call was hung up, false if not
      */
     public boolean
-    triggerHangupForeground()
-    {
+    triggerHangupForeground() {
         synchronized (this) {
             boolean found;
 
@@ -333,8 +313,7 @@
      * returns true if call was hung up, false if not
      */
     public boolean
-    triggerHangupBackground()
-    {
+    triggerHangupBackground() {
         synchronized (this) {
             boolean found = false;
 
@@ -356,8 +335,7 @@
      * returns true if call was hung up, false if not
      */
     public boolean
-    triggerHangupAll()
-    {
+    triggerHangupAll() {
         synchronized(this) {
             boolean found = false;
 
@@ -376,8 +354,7 @@
     }
 
     public boolean
-    onAnswer()
-    {
+    onAnswer() {
         synchronized (this) {
             for (int i = 0 ; i < calls.length ; i++) {
                 CallInfo call = calls[i];
@@ -395,8 +372,7 @@
     }
 
     public boolean
-    onHangup()
-    {
+    onHangup() {
         boolean found = false;
 
         for (int i = 0 ; i < calls.length ; i++) {
@@ -412,8 +388,7 @@
     }
 
     public boolean
-    onChld(char c0, char c1)
-    {
+    onChld(char c0, char c1) {
         boolean ret;
         int callIndex = 0;
 
@@ -499,8 +474,7 @@
 
 
     public boolean
-    releaseActiveAcceptHeldOrWaiting()
-    {
+    releaseActiveAcceptHeldOrWaiting() {
         boolean foundHeld = false;
         boolean foundActive = false;
 
@@ -555,8 +529,7 @@
     }
 
     public boolean
-    switchActiveAndHeldOrWaiting()
-    {
+    switchActiveAndHeldOrWaiting() {
         boolean hasHeld = false;
         
         // first, are there held calls?
@@ -589,8 +562,7 @@
 
 
     public boolean
-    separateCall(int index)
-    {
+    separateCall(int index) {
         try {
             CallInfo c;
 
@@ -631,8 +603,7 @@
 
 
     public boolean
-    conference() 
-    {
+    conference() {
         int countCalls = 0;
 
         // if there's connecting calls, we can't do this yet
@@ -662,8 +633,7 @@
     }
 
     public boolean
-    explicitCallTransfer()
-    {
+    explicitCallTransfer() {
         int countCalls = 0;
 
         // if there's connecting calls, we can't do this yet
@@ -684,8 +654,7 @@
     }
 
     public boolean
-    onDial(String address)
-    {
+    onDial(String address) {
         CallInfo call;
         int freeSlot = -1;
 
@@ -758,8 +727,7 @@
     }
 
     public List<DriverCall>
-    getDriverCalls()
-    {
+    getDriverCalls() {
         ArrayList<DriverCall> ret = new ArrayList<DriverCall>(calls.length);
 
         for (int i = 0 ; i < calls.length ; i++) {
@@ -779,8 +747,7 @@
     }
 
     public List<String>
-    getClccLines()
-    {
+    getClccLines() {
         ArrayList<String> ret = new ArrayList<String>(calls.length);
 
         for (int i = 0 ; i < calls.length ; i++) {
@@ -795,8 +762,7 @@
     }
 
     private int
-    countActiveLines() throws InvalidStateEx
-    {
+    countActiveLines() throws InvalidStateEx {
         boolean hasMpty = false;
         boolean hasHeld = false;
         boolean hasActive = false;
diff --git a/telephony/jni/cdmasms/Android.mk b/telephony/jni/cdmasms/Android.mk
new file mode 100644
index 0000000..b0c96b4
--- /dev/null
+++ b/telephony/jni/cdmasms/Android.mk
@@ -0,0 +1,24 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+  cdma_sms_jni.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+	libutils \
+	libandroid_runtime \
+	libnativehelper
+
+LOCAL_MODULE:= libcdma_sms_jni
+
+LOCAL_C_INCLUDES += \
+	$(JNI_H_INCLUDE) \
+	hardware/ril/include/telephony
+
+LOCAL_C_INCLUDES += hardware/ril/reference-cdma-sms
+LOCAL_SHARED_LIBRARIES += libreference-cdma-sms
+LOCAL_CFLAGS += -DREFERENCE_CDMA_SMS
+
+LOCAL_PRELINK_MODULE := false
+include $(BUILD_SHARED_LIBRARY)
diff --git a/telephony/jni/cdmasms/cdma_sms_jni.cpp b/telephony/jni/cdmasms/cdma_sms_jni.cpp
new file mode 100644
index 0000000..2a8e825
--- /dev/null
+++ b/telephony/jni/cdmasms/cdma_sms_jni.cpp
@@ -0,0 +1,1300 @@
+/*
+ * Copyright (C) 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.
+ * 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.
+ */
+
+/**
+ * @file cdma_sms_jni.cpp
+ *
+ * This file implement the Java Native Interface
+ * for encoding and decoding of SMS
+ */
+
+
+#include <nativehelper/jni.h>
+#include <nativehelper/JNIHelp.h>
+#include <android_runtime/AndroidRuntime.h>
+#include <cdma_sms_jni.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif //__cplusplus
+
+#include <reference-cdma-sms.h>
+
+#ifdef __cplusplus
+}
+#endif //__cplusplus
+
+#undef LOG_TAG
+#define LOG_TAG "CDMA"
+#include <utils/Log.h>
+
+static RIL_CDMA_SMS_ClientBd *clientBdData = NULL;
+
+
+static jint getObjectIntField(JNIEnv * env, jobject obj, const char *name, jint * value)
+{
+    jclass clazz;
+    jfieldID field;
+
+#ifdef DBG_LOG_LEVEL_B
+    LOGD("getObjectIntField():");
+#endif
+
+    clazz = env->GetObjectClass(obj);
+    if (NULL == clazz) {
+        jniThrowException(env, "java/lang/Exception", NULL);
+        return JNI_FAILURE;
+    }
+
+    field = env->GetFieldID(clazz, name, "I");
+    env->DeleteLocalRef(clazz);
+
+    if (NULL == field) {
+        jniThrowException(env, "java/lang/NoSuchFieldException", name);
+        return JNI_FAILURE;
+    }
+
+    *value = env->GetIntField(obj, field);
+
+#ifdef DBG_LOG_LEVEL_B
+    LOGD("  %s = %d\n", name, *value);
+#endif
+
+    return JNI_SUCCESS;
+}
+
+static jint setObjectIntField(JNIEnv * env, jobject obj, const char *name, jint value)
+{
+    jclass clazz;
+    jfieldID field;
+
+#ifdef DBG_LOG_LEVEL_B
+    LOGD("setObjectIntField(): %s = %d\n", name, value);
+#endif
+
+    clazz = env->GetObjectClass(obj);
+    if (NULL == clazz) {
+        jniThrowException(env, "java/lang/Exception", NULL);
+        return JNI_FAILURE;
+    }
+
+    field = env->GetFieldID(clazz, name, "I");
+    env->DeleteLocalRef(clazz);
+
+    if (NULL == field) {
+        jniThrowException(env, "java/lang/NoSuchFieldException", name);
+        return JNI_FAILURE;
+    }
+
+    env->SetIntField(obj, field, value);
+
+    return JNI_SUCCESS;
+}
+
+static jint getObjectByteField(JNIEnv * env, jobject obj, const char *name, jbyte * value)
+{
+    jclass clazz;
+    jfieldID field;
+
+#ifdef DBG_LOG_LEVEL_B
+    LOGD("getObjectByteField():");
+#endif
+
+    clazz = env->GetObjectClass(obj);
+    if (NULL == clazz) {
+        jniThrowException(env, "java/lang/Exception", NULL);
+        return JNI_FAILURE;
+    }
+
+    field = env->GetFieldID(clazz, name, "B");
+    env->DeleteLocalRef(clazz);
+
+    if (NULL == field) {
+        jniThrowException(env, "java/lang/NoSuchFieldException", name);
+        return JNI_FAILURE;
+    }
+
+    *value = env->GetByteField(obj, field);
+
+#ifdef DBG_LOG_LEVEL_B
+    LOGD("  %s = %02x\n", name, *value);
+#endif
+
+    return JNI_SUCCESS;
+}
+
+static jint setObjectByteField(JNIEnv * env, jobject obj, const char *name, jbyte value)
+{
+    jclass clazz;
+    jfieldID field;
+#ifdef DBG_LOG_LEVEL_B
+    LOGD("setObjectByteField(): %s = 0x%02x\n", name, value);
+#endif
+
+    clazz = env->GetObjectClass(obj);
+    if (NULL == clazz) {
+        jniThrowException(env, "java/lang/Exception", NULL);
+        return JNI_FAILURE;
+    }
+
+    field = env->GetFieldID(clazz, name, "B");
+    env->DeleteLocalRef(clazz);
+
+    if (NULL == field) {
+        jniThrowException(env, "java/lang/NoSuchFieldException", name);
+        return JNI_FAILURE;
+    }
+
+    env->SetByteField(obj, field, value);
+
+    return JNI_SUCCESS;
+}
+
+static jint getObjectBooleanField(JNIEnv * env, jobject obj, const char *name, jboolean * value)
+{
+    jclass clazz;
+    jfieldID field;
+
+#ifdef DBG_LOG_LEVEL_B
+    LOGD("getObjectBooleanField():");
+#endif
+
+    clazz = env->GetObjectClass(obj);
+    if (NULL == clazz) {
+        jniThrowException(env, "java/lang/Exception", NULL);
+        return JNI_FAILURE;
+    }
+
+    field = env->GetFieldID(clazz, name, "Z");
+    env->DeleteLocalRef(clazz);
+
+    if (NULL == field) {
+        jniThrowException(env, "java/lang/NoSuchFieldException", name);
+        return JNI_FAILURE;
+    }
+
+    *value = env->GetBooleanField(obj, field);
+
+#ifdef DBG_LOG_LEVEL_B
+    LOGD("  %s = %d\n", name, *value);
+#endif
+
+    return JNI_SUCCESS;
+}
+
+static jint setObjectBooleanField(JNIEnv * env, jobject obj, const char *name, jboolean value)
+{
+    jclass clazz;
+    jfieldID field;
+
+#ifdef DBG_LOG_LEVEL_B
+    LOGD("setObjectBooleanField(): %s = %d\n", name, value);
+#endif
+
+    clazz = env->GetObjectClass(obj);
+    if (NULL == clazz) {
+        jniThrowException(env, "java/lang/Exception", NULL);
+        return JNI_FAILURE;
+    }
+
+    field = env->GetFieldID(clazz, name, "Z");
+    env->DeleteLocalRef(clazz);
+
+    if (NULL == field) {
+        jniThrowException(env, "java/lang/NoSuchFieldException", name);
+        return JNI_FAILURE;
+    }
+
+    env->SetBooleanField(obj, field, value);
+
+    return JNI_SUCCESS;
+}
+
+static jint getObjectByteArrayField(JNIEnv * env, jobject obj, const char *name, jbyte* arrData, int* length)
+{
+    jclass clazz;
+    jfieldID field;
+    jbyte * data_buf;
+
+#ifdef DBG_LOG_LEVEL_B
+    LOGD("getObjectByteArrayField(): %s\n", name);
+#endif
+
+    clazz = env->GetObjectClass(obj);
+    if (NULL == clazz) {
+        jniThrowException(env, "java/lang/Exception", NULL);
+        return JNI_FAILURE;
+    }
+
+    field = env->GetFieldID(clazz, name, "[B");
+    env->DeleteLocalRef(clazz);
+
+    if (NULL == field) {
+        jniThrowException(env, "java/lang/NoSuchFieldException", name);
+        return JNI_FAILURE;
+    }
+
+    jbyteArray buffer = (jbyteArray)(env->GetObjectField(obj, field));
+    if (buffer != NULL) {
+        int len = env->GetArrayLength(buffer);
+        data_buf = env->GetByteArrayElements(buffer, NULL);
+        for (int i=0; i<len; i++) {
+            *arrData++ = data_buf[i];
+#ifdef DBG_LOG_LEVEL_B
+            LOGD("  [%d] = 0x%02x\n", i, data_buf[i]);
+#endif
+        }
+        *length = len;
+    } else {
+        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        return JNI_FAILURE;
+    }
+
+    return JNI_SUCCESS;
+}
+
+static jint setObjectByteArrayField(JNIEnv * env, jobject obj, const char *name, jbyte* arrData, int length)
+{
+    jclass clazz;
+    jfieldID field;
+    jbyte* byte_buf;
+
+#ifdef DBG_LOG_LEVEL_B
+    LOGD("setObjectByteArrayField(): %s\n", name);
+#endif
+
+    clazz = env->GetObjectClass(obj);
+    if (NULL == clazz) {
+        jniThrowException(env, "java/lang/Exception", NULL);
+        return JNI_FAILURE;
+    }
+
+    field = env->GetFieldID(clazz, name, "[B");
+    env->DeleteLocalRef(clazz);
+
+    if (NULL == field) {
+        jniThrowException(env, "java/lang/NoSuchFieldException", name);
+        return JNI_FAILURE;
+    }
+
+    jbyteArray buffer = (jbyteArray)(env->GetObjectField(obj, field));
+    if (buffer == NULL) {
+#ifdef DBG_LOG_LEVEL_B
+        LOGD("setObjectByteArrayField(): %s = null\n", name);
+#endif
+        buffer = env->NewByteArray(length);
+        env->SetObjectField(obj, field, buffer);
+    }
+
+    if (buffer != NULL) {
+#ifdef DBG_LOG_LEVEL_B
+        for (int i=0; i<length; i++) {
+            LOGD("  [%d] = 0x%02x\n", i, arrData[i]);
+        }
+#endif
+        env->SetByteArrayRegion(buffer, 0, length, arrData);
+    } else {
+        jniThrowException(env, "java/lang/NullPointerException", NULL);
+        return JNI_FAILURE;
+    }
+
+    return JNI_SUCCESS;
+}
+
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsConstructClientBD
+  (JNIEnv * env, jobject obj)
+{
+#ifdef DBG_LOG_LEVEL_B
+    LOGD("nativeCdmaSmsConstructClientBD()...\n");
+#endif
+
+    clientBdData = (RIL_CDMA_SMS_ClientBd *)malloc(sizeof(RIL_CDMA_SMS_ClientBd));
+    if (NULL == clientBdData) {
+        jniThrowException(env, "java/lang/OutOfMemoryError", "clientBdData memory allocation failed");
+        return JNI_FAILURE;
+    }
+    memset(clientBdData, 0, sizeof(RIL_CDMA_SMS_ClientBd));
+    return JNI_SUCCESS;
+}
+
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsDestructClientBD
+  (JNIEnv * env, jobject obj)
+{
+#ifdef DBG_LOG_LEVEL_B
+    LOGD("nativeCdmaSmsDestructClientBD()...\n");
+#endif
+
+    if (clientBdData == NULL) {
+        jniThrowException(env, "java/lang/NullPointerException", "clientBdData is null");
+        return JNI_FAILURE;
+    }
+    free(clientBdData);
+    return JNI_SUCCESS;
+}
+
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsSetBearerDataPrimitives
+  (JNIEnv * env, jobject obj, jobject bearerData)
+{
+    jbyteArray mc_time = NULL;
+    jbyte mctime_buffer[6];
+    int length;
+    jint intData;
+    jbyte byteData;
+    jboolean booleanData;
+
+#ifdef DBG_LOG_LEVEL_B
+    LOGD("nativeCdmaSmsSetBearerDataPrimitives()...\n");
+#endif
+
+    // mask
+    if (getObjectIntField(env, bearerData, "mask", &intData) != JNI_SUCCESS)
+        return JNI_FAILURE;
+    clientBdData->mask = intData;
+#ifdef DBG_LOG_LEVEL_A
+    LOGD("clientBdData->mask = 0x%x\n", clientBdData->mask);
+#endif
+
+    // message_id.type
+    if (getObjectByteField(env, bearerData, "messageType", &byteData) != JNI_SUCCESS)
+        return JNI_FAILURE;
+    clientBdData->message_id.type = (RIL_CDMA_SMS_BdMessageType)(byteData);
+#ifdef DBG_LOG_LEVEL_A
+    LOGD("clientBdData->message_id.type = 0x%02x\n", clientBdData->message_id.type);
+#endif
+
+    // message_id.id_number
+    if ((clientBdData->mask & WMS_MASK_BD_MSG_ID) == WMS_MASK_BD_MSG_ID) {
+        if (getObjectIntField(env, bearerData, "messageID", &intData) != JNI_SUCCESS)
+            return JNI_FAILURE;
+        clientBdData->message_id.id_number = (RIL_CDMA_SMS_MessageNumber)(intData);
+#ifdef DBG_LOG_LEVEL_A
+        LOGD("clientBdData->message_id.id_number = %d\n", clientBdData->message_id.id_number);
+#endif
+    }
+
+    // message_id.udh_present
+    if (getObjectBooleanField(env, bearerData, "hasUserDataHeader", &booleanData) != JNI_SUCCESS)
+        return JNI_FAILURE;
+    clientBdData->message_id.udh_present = (unsigned char)(booleanData);
+#ifdef DBG_LOG_LEVEL_A
+    LOGD("clientBdData->message_id.udh_present = %d\n", clientBdData->message_id.udh_present);
+#endif
+
+    // user_response
+    // TODO
+
+    // mc_time
+    if ((clientBdData->mask & WMS_MASK_BD_MC_TIME) == WMS_MASK_BD_MC_TIME) {
+        if (getObjectByteArrayField(env, bearerData, "timeStamp", mctime_buffer, &length) != JNI_SUCCESS)
+            return JNI_FAILURE;
+        if (mctime_buffer != NULL) {
+            clientBdData->mc_time.year     = mctime_buffer[0];
+            clientBdData->mc_time.month    = mctime_buffer[1];
+            clientBdData->mc_time.day      = mctime_buffer[2];
+            clientBdData->mc_time.hour     = mctime_buffer[3];
+            clientBdData->mc_time.minute   = mctime_buffer[4];
+            clientBdData->mc_time.second   = mctime_buffer[5];
+#ifdef DBG_LOG_LEVEL_A
+            LOGD("clientBdData->mc_time.year   = %d\n", clientBdData->mc_time.year);
+            LOGD("clientBdData->mc_time.month  = %d\n", clientBdData->mc_time.month);
+            LOGD("clientBdData->mc_time.day    = %d\n", clientBdData->mc_time.day);
+            LOGD("clientBdData->mc_time.hour   = %d\n", clientBdData->mc_time.hour);
+            LOGD("clientBdData->mc_time.minute = %d\n", clientBdData->mc_time.minute);
+            LOGD("clientBdData->mc_time.second = %d\n", clientBdData->mc_time.second);
+#endif
+        }
+    }
+
+    // clientBdData->mc_time.timezone
+    // TODO
+
+    // validity_absolute;
+    // TODO
+
+    // validity_relative;
+    // TODO
+
+    // deferred_absolute
+    // TODO
+
+    // deferred_relative;
+    // TODO
+
+    // priority
+    // TODO
+
+    // privacy
+    // TODO
+
+    if ((clientBdData->mask & WMS_MASK_BD_REPLY_OPTION) == WMS_MASK_BD_REPLY_OPTION) {
+        // reply_option.user_ack_requested
+        if (getObjectBooleanField(env, bearerData, "userAckReq", &booleanData) != JNI_SUCCESS)
+            return JNI_FAILURE;
+        clientBdData->reply_option.user_ack_requested = (unsigned char)(booleanData);
+#ifdef DBG_LOG_LEVEL_A
+        LOGD("clientBdData->reply_option.user_ack_requested = %d\n", clientBdData->reply_option.user_ack_requested);
+#endif
+        // reply_option.user_ack_requested
+        if (getObjectBooleanField(env, bearerData, "deliveryAckReq", &booleanData) != JNI_SUCCESS)
+            return JNI_FAILURE;
+        clientBdData->reply_option.delivery_ack_requested = (unsigned char)(booleanData);
+#ifdef DBG_LOG_LEVEL_A
+        LOGD("clientBdData->reply_option.delivery_ack_requested = %d\n", clientBdData->reply_option.delivery_ack_requested);
+#endif
+        // reply_option.user_ack_requested
+        if (getObjectBooleanField(env, bearerData, "readAckReq", &booleanData) != JNI_SUCCESS)
+            return JNI_FAILURE;
+        clientBdData->reply_option.read_ack_requested = (unsigned char)(booleanData);
+#ifdef DBG_LOG_LEVEL_A
+            LOGD("clientBdData->reply_option.read_ack_requested = %d\n", clientBdData->reply_option.read_ack_requested);
+#endif
+    }
+
+    // num_messages
+    if ((clientBdData->mask & WMS_MASK_BD_NUM_OF_MSGS) == WMS_MASK_BD_NUM_OF_MSGS) {
+        if (getObjectIntField(env, bearerData, "numberOfMessages", &intData) != JNI_SUCCESS)
+            return JNI_FAILURE;
+        clientBdData->num_messages = (unsigned char)(intData);
+#ifdef DBG_LOG_LEVEL_A
+        LOGD("clientBdData->num_messages = %d\n", clientBdData->num_messages);
+#endif
+    }
+
+    // alert_mode
+    // TODO
+
+    // language
+    // TODO
+
+    // display_mode
+    if ((clientBdData->mask & WMS_MASK_BD_DISPLAY_MODE) == WMS_MASK_BD_DISPLAY_MODE) {
+        if (getObjectByteField(env, bearerData, "displayMode", &byteData) != JNI_SUCCESS)
+            return JNI_FAILURE;
+        clientBdData->display_mode = (RIL_CDMA_SMS_DisplayMode)(byteData);
+#ifdef DBG_LOG_LEVEL_A
+        LOGD("clientBdData->display_mode = 0x%02x\n", clientBdData->display_mode);
+#endif
+    }
+
+    // delivery_status
+    if ((clientBdData->mask & WMS_MASK_BD_DELIVERY_STATUS) == WMS_MASK_BD_DELIVERY_STATUS) {
+        // delivery_status.error_class
+        if (getObjectIntField(env, bearerData, "errorClass", &intData) != JNI_SUCCESS)
+            return JNI_FAILURE;
+        clientBdData->delivery_status.error_class = (RIL_CDMA_SMS_ErrorClass)(intData);
+#ifdef DBG_LOG_LEVEL_A
+        LOGD("clientBdData->delivery_status.error_class = %d\n", clientBdData->delivery_status.error_class);
+#endif
+        // delivery_status.status
+        if (getObjectIntField(env, bearerData, "messageStatus", &intData) != JNI_SUCCESS)
+            return JNI_FAILURE;
+        clientBdData->delivery_status.status = (RIL_CDMA_SMS_DeliveryStatusE)(intData);
+#ifdef DBG_LOG_LEVEL_A
+        LOGD("clientBdData->delivery_status.status = %d\n", clientBdData->delivery_status.status);
+#endif
+    }
+
+    // deposit_index
+    // TODO
+
+    // ip_address
+    // TODO
+
+    // rsn_no_notify
+    // TODO
+
+    // other
+    // TODO
+
+    return JNI_SUCCESS;
+}
+
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsGetBearerDataPrimitives
+  (JNIEnv * env, jobject obj, jobject bearerData)
+{
+    jclass BearerDataClass;
+    jfieldID field;
+    jbyte mctime_buffer[6];
+    jbyteArray addr_array;
+    int length;
+
+#ifdef DBG_LOG_LEVEL_B
+    LOGD("nativeCdmaSmsGetBearerDataPrimitives()...\n");
+#endif
+
+    // mask
+#ifdef DBG_LOG_LEVEL_A
+    LOGD("clientBdData->mask = 0x%x\n", clientBdData->mask);
+#endif
+    if (setObjectIntField(env, bearerData, "mask", clientBdData->mask) != JNI_SUCCESS)
+        return JNI_FAILURE;
+
+    // message_id.type
+#ifdef DBG_LOG_LEVEL_A
+    LOGD("clientBdData->message_id.type = 0x%02x\n", clientBdData->message_id.type);
+#endif
+    if (setObjectByteField(env, bearerData, "messageType", (jbyte)clientBdData->message_id.type) != JNI_SUCCESS)
+        return JNI_FAILURE;
+
+    // message_id.id_number
+    if ((clientBdData->mask & WMS_MASK_BD_MSG_ID) == WMS_MASK_BD_MSG_ID) {
+#ifdef DBG_LOG_LEVEL_A
+        LOGD("clientBdData->message_id.id_number = %d\n", clientBdData->message_id.id_number);
+#endif
+        if (setObjectIntField(env, bearerData, "messageID", clientBdData->message_id.id_number) != JNI_SUCCESS)
+            return JNI_FAILURE;
+    }
+
+    // message_id.udh_present
+#ifdef DBG_LOG_LEVEL_A
+    LOGD("clientBdData->message_id.udh_present = %d\n", clientBdData->message_id.udh_present);
+#endif
+    if (setObjectBooleanField(env, bearerData, "hasUserDataHeader", (jboolean)clientBdData->message_id.udh_present) != JNI_SUCCESS)
+        return JNI_FAILURE;
+
+    // user_response
+    // TODO
+
+    // mc_time
+    if ((clientBdData->mask & WMS_MASK_BD_MC_TIME) == WMS_MASK_BD_MC_TIME) {
+        jclass clazz= env->GetObjectClass(bearerData);
+        if (NULL == clazz)
+            return JNI_FAILURE;
+        jfieldID field = env->GetFieldID(clazz, "timeStamp", "[B");
+        env->DeleteLocalRef(clazz);
+
+        addr_array = env->NewByteArray((jsize)6);
+        env->SetObjectField(bearerData, field, addr_array);
+
+#ifdef DBG_LOG_LEVEL_A
+        LOGD("clientBdData->mc_time.year   = %d\n", clientBdData->mc_time.year);
+        LOGD("clientBdData->mc_time.month  = %d\n", clientBdData->mc_time.month);
+        LOGD("clientBdData->mc_time.day    = %d\n", clientBdData->mc_time.day);
+        LOGD("clientBdData->mc_time.hour   = %d\n", clientBdData->mc_time.hour);
+        LOGD("clientBdData->mc_time.minute = %d\n", clientBdData->mc_time.minute);
+        LOGD("clientBdData->mc_time.second = %d\n", clientBdData->mc_time.second);
+#endif
+        mctime_buffer[0] = clientBdData->mc_time.year;
+        mctime_buffer[1] = clientBdData->mc_time.month;
+        mctime_buffer[2] = clientBdData->mc_time.day;
+        mctime_buffer[3] = clientBdData->mc_time.hour;
+        mctime_buffer[4] = clientBdData->mc_time.minute;
+        mctime_buffer[5] = clientBdData->mc_time.second;
+        length = sizeof(mctime_buffer) / sizeof(jbyte);
+        if (setObjectByteArrayField(env, bearerData, "timeStamp", mctime_buffer, length) != JNI_SUCCESS)
+            return JNI_FAILURE;
+    }
+
+    // clientBdData->mc_time.timezone
+    // TODO
+
+    // validity_absolute;
+    // TODO
+
+    // validity_relative;
+    // TODO
+
+    // deferred_absolute
+    // TODO
+
+    // deferred_relative;
+    // TODO
+
+    // priority
+    // TODO
+
+    // privacy
+    // TODO
+
+    if ((clientBdData->mask & WMS_MASK_BD_REPLY_OPTION) == WMS_MASK_BD_REPLY_OPTION) {
+        // reply_option.user_ack_requested
+#ifdef DBG_LOG_LEVEL_A
+        LOGD("clientBdData->reply_option.user_ack_requested = %d\n", clientBdData->reply_option.user_ack_requested);
+#endif
+        if (setObjectBooleanField(env, bearerData, "userAckReq", (jboolean)clientBdData->reply_option.user_ack_requested) != JNI_SUCCESS)
+            return JNI_FAILURE;
+
+        // reply_option.user_ack_requested
+#ifdef DBG_LOG_LEVEL_A
+        LOGD("clientBdData->reply_option.delivery_ack_requested = %d\n", clientBdData->reply_option.delivery_ack_requested);
+#endif
+        if (setObjectBooleanField(env, bearerData, "deliveryAckReq", (jboolean)clientBdData->reply_option.delivery_ack_requested) != JNI_SUCCESS)
+            return JNI_FAILURE;
+
+        // reply_option.user_ack_requested
+#ifdef DBG_LOG_LEVEL_A
+        LOGD("clientBdData->reply_option.read_ack_requested = %d\n", clientBdData->reply_option.read_ack_requested);
+#endif
+        if (setObjectBooleanField(env, bearerData, "readAckReq", (jboolean)clientBdData->reply_option.read_ack_requested) != JNI_SUCCESS)
+            return JNI_FAILURE;
+    }
+
+    // num_messages
+    if ((clientBdData->mask & WMS_MASK_BD_NUM_OF_MSGS) == WMS_MASK_BD_NUM_OF_MSGS) {
+#ifdef DBG_LOG_LEVEL_A
+        LOGD("clientBdData->num_messages = %d\n", clientBdData->num_messages);
+#endif
+        if (setObjectIntField(env, bearerData, "numberOfMessages", (int)clientBdData->num_messages) != JNI_SUCCESS)
+            return JNI_FAILURE;
+    }
+
+    // alert_mode
+    // TODO
+
+    // language
+    // TODO
+
+    // display_mode
+    if ((clientBdData->mask & WMS_MASK_BD_DISPLAY_MODE) == WMS_MASK_BD_DISPLAY_MODE) {
+#ifdef DBG_LOG_LEVEL_A
+        LOGD("clientBdData->display_mode = 0x%02x\n", clientBdData->display_mode);
+#endif
+        if (setObjectByteField(env, bearerData, "displayMode", (jbyte)clientBdData->display_mode) != JNI_SUCCESS)
+            return JNI_FAILURE;
+    }
+
+    // delivery_status
+    if ((clientBdData->mask & WMS_MASK_BD_DELIVERY_STATUS) == WMS_MASK_BD_DELIVERY_STATUS) {
+#ifdef DBG_LOG_LEVEL_A
+        LOGD("clientBdData->delivery_status.error_class = %d\n", clientBdData->delivery_status.error_class);
+#endif
+        // delivery_status.error_class
+        if (setObjectIntField(env, bearerData, "errorClass", (int)clientBdData->delivery_status.error_class) != JNI_SUCCESS)
+            return JNI_FAILURE;
+#ifdef DBG_LOG_LEVEL_A
+        LOGD("clientBdData->delivery_status.status = %d\n", clientBdData->delivery_status.status);
+#endif
+        // delivery_status.status
+        if (setObjectIntField(env, bearerData, "messageStatus", (int)clientBdData->delivery_status.status) != JNI_SUCCESS)
+            return JNI_FAILURE;
+    }
+
+    // deposit_index
+    // TODO
+
+    // ip_address
+    // TODO
+
+    // rsn_no_notify
+    // TODO
+
+    // other
+    // TODO
+
+    return JNI_SUCCESS;
+}
+
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsSetUserData
+  (JNIEnv * env, jobject obj, jobject userData)
+{
+    jclass UserDataClass;
+    jfieldID field;
+    jbyteArray arrData = NULL;
+    jbyte data_buf[RIL_CDMA_SMS_USER_DATA_MAX];
+    int length;
+    jint intData;
+    jbyte byteData;
+    jboolean booleanData;
+
+#ifdef DBG_LOG_LEVEL_B
+    LOGD("nativeCdmaSmsSetUserData()...\n");
+#endif
+
+    // set num_headers to 0 here, increment later
+    clientBdData->user_data.num_headers = 0;
+
+    // user_data.encoding
+    if (getObjectIntField(env, userData, "userDataEncoding", &intData) != JNI_SUCCESS)
+        return JNI_FAILURE;
+    clientBdData->user_data.encoding = (RIL_CDMA_SMS_UserDataEncoding)(intData);
+#ifdef DBG_LOG_LEVEL_A
+    LOGD("clientBdData->user_data.encoding = %d\n", clientBdData->user_data.encoding);
+#endif
+
+    // is91ep_type
+    // TODO
+
+    // user_data.padding_bits
+    if (getObjectIntField(env, userData, "paddingBits", &intData) != JNI_SUCCESS)
+        return JNI_FAILURE;
+    clientBdData->user_data.padding_bits = (unsigned char)(intData);
+#ifdef DBG_LOG_LEVEL_A
+    LOGD("clientBdData->user_data.padding_bits = %d\n", clientBdData->user_data.padding_bits);
+#endif
+
+    // user_data.data
+    if (getObjectByteArrayField(env, userData, "userData", data_buf, &length) != JNI_SUCCESS )
+        return JNI_FAILURE;
+    for (int i = 0; i < length; i++) {
+        clientBdData->user_data.data[i] = data_buf[i];
+#ifdef DBG_LOG_LEVEL_A
+        LOGD("clientBdData->user_data.data[%d] = 0x%02x\n", i, clientBdData->user_data.data[i]);
+#endif
+    }
+
+    // user_data.data_len
+    // TODO
+
+    // number_of_digits
+    clientBdData->user_data.number_of_digits = (unsigned char)(length);
+#ifdef DBG_LOG_LEVEL_A
+    LOGD("clientBdData->user_data.number_of_digits = %d\n", clientBdData->user_data.number_of_digits);
+#endif
+
+    return JNI_SUCCESS;
+}
+
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsGetUserData
+  (JNIEnv * env, jobject obj, jobject userData)
+{
+    jclass UserDataClass;
+    jfieldID field;
+    jbyte *data_buf;
+    int length;
+
+#ifdef DBG_LOG_LEVEL_B
+    LOGD("nativeCdmaSmsGetUserData()...\n");
+#endif
+
+    // user_data.num_headers
+//    if (setObjectIntField(env, userData, "mNumberOfHeaders", (int)clientBdData->user_data.num_headers) != JNI_SUCCESS)
+//        return JNI_FAILURE;
+
+    // user_data.encoding
+#ifdef DBG_LOG_LEVEL_A
+    LOGD("clientBdData->user_data.encoding = %d\n", clientBdData->user_data.encoding);
+#endif
+    if (setObjectIntField(env, userData, "userDataEncoding", clientBdData->user_data.encoding) != JNI_SUCCESS)
+        return JNI_FAILURE;
+
+    // is91ep_type
+    // TODO
+
+    // user_data.data_len
+//    if (setObjectIntField(env, userData, "mDataLength", (int)clientBdData->user_data.data_len) != JNI_SUCCESS)
+//        return JNI_FAILURE;
+
+    // user_data.padding_bits
+#ifdef DBG_LOG_LEVEL_A
+    LOGD("clientBdData->user_data.padding_bits = %d\n", clientBdData->user_data.padding_bits);
+#endif
+    if (setObjectIntField(env, userData, "paddingBits", (int)clientBdData->user_data.padding_bits) != JNI_SUCCESS)
+        return JNI_FAILURE;
+
+    // user_data.data
+#ifdef DBG_LOG_LEVEL_A
+    LOGD("clientBdData->user_data.data_len = %d\n", clientBdData->user_data.data_len);
+#endif
+    length = clientBdData->user_data.data_len;
+#ifdef DBG_LOG_LEVEL_A
+    for (int i = 0; i < length; i++) {
+        LOGD("clientBdData->user_data.data[%d] = 0x%02x\n", i, clientBdData->user_data.data[i]);
+    }
+#endif
+    data_buf = (jbyte*)clientBdData->user_data.data;
+    if (setObjectByteArrayField(env, userData, "userData", data_buf, length) != JNI_SUCCESS)
+        return JNI_FAILURE;
+
+    // number_of_digits
+    // TODO
+
+    return JNI_SUCCESS;
+}
+
+
+/* native interface */
+JNIEXPORT jint JNICALL Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsSetUserDataHeader
+  (JNIEnv * env, jobject obj, jint ID, jbyteArray data, jint length, jint index)
+{
+    jbyte data_buf[length];
+
+#ifdef DBG_LOG_LEVEL_B
+    LOGD("nativeCdmaSmsSetUserDataHeader()...\n");
+#endif
+
+    env->GetByteArrayRegion(data, 0, length, data_buf);
+
+    // user_data.headers[index].header_id
+    clientBdData->user_data.headers[index].header_id = (RIL_CDMA_SMS_UdhId)(ID);
+
+    // user_data.headers[index].u
+    // TODO: add support for all udh id's
+    switch(clientBdData->user_data.headers[index].header_id)
+    {
+        case RIL_CDMA_SMS_UDH_CONCAT_8:
+            clientBdData->user_data.headers[index].u.concat_8.msg_ref  = data_buf[0];
+            clientBdData->user_data.headers[index].u.concat_8.total_sm = data_buf[1];
+            clientBdData->user_data.headers[index].u.concat_8.seq_num  = data_buf[2];
+#ifdef DBG_LOG_LEVEL_A
+            LOGD("clientBdData->user_data.headers[%d].u.concat_8.msg_ref  = 0x%02x\n", index, clientBdData->user_data.headers[index].u.concat_8.msg_ref);
+            LOGD("clientBdData->user_data.headers[%d].u.concat_8.total_sm = 0x%02x\n", index, clientBdData->user_data.headers[index].u.concat_8.total_sm);
+            LOGD("clientBdData->user_data.headers[%d].u.concat_8.seq_num  = 0x%02x\n", index, clientBdData->user_data.headers[index].u.concat_8.seq_num);
+#endif
+        break;
+        case RIL_CDMA_SMS_UDH_SPECIAL_SM:
+            clientBdData->user_data.headers[index].u.special_sm.msg_waiting      = (RIL_CDMA_SMS_GWMsgWaiting)(
+                                                                                   (data_buf[0] << 23) | (data_buf[1] << 15) |
+                                                                                   (data_buf[2] << 7)  |  data_buf[3]);
+            clientBdData->user_data.headers[index].u.special_sm.msg_waiting_kind = (RIL_CDMA_SMS_GWMsgWaitingKind)(
+                                                                                   (data_buf[4] << 23) | (data_buf[5] << 15) |
+                                                                                   (data_buf[6] << 7)  |  data_buf[7]);
+            clientBdData->user_data.headers[index].u.special_sm.message_count    =  data_buf[8];
+#ifdef DBG_LOG_LEVEL_A
+            LOGD("clientBdData->user_data.headers[%d].u.special_sm.msg_waiting      = 0x%04x\n", index, clientBdData->user_data.headers[index].u.special_sm.msg_waiting);
+            LOGD("clientBdData->user_data.headers[%d].u.special_sm.msg_waiting_kind = 0x%04x\n", index, clientBdData->user_data.headers[index].u.special_sm.msg_waiting_kind);
+            LOGD("clientBdData->user_data.headers[%d].u.special_sm.message_count    = 0x%02x\n", index, clientBdData->user_data.headers[index].u.special_sm.message_count);
+#endif
+        break;
+        case RIL_CDMA_SMS_UDH_PORT_8:
+            clientBdData->user_data.headers[index].u.wap_8.dest_port = data_buf[0];
+            clientBdData->user_data.headers[index].u.wap_8.orig_port = data_buf[1];
+#ifdef DBG_LOG_LEVEL_A
+            LOGD("clientBdData->user_data.headers[%d].u.wap_8.dest_port = 0x%02x\n", index, clientBdData->user_data.headers[index].u.wap_8.dest_port);
+            LOGD("clientBdData->user_data.headers[%d].u.wap_8.orig_port = 0x%02x\n", index, clientBdData->user_data.headers[index].u.wap_8.orig_port);
+#endif
+        break;
+        case RIL_CDMA_SMS_UDH_PORT_16:
+            clientBdData->user_data.headers[index].u.wap_16.dest_port = (data_buf[0] << 7) | data_buf[1]; // unsigned short
+            clientBdData->user_data.headers[index].u.wap_16.orig_port = (data_buf[2] << 7) | data_buf[3]; // unsigned short
+#ifdef DBG_LOG_LEVEL_A
+            LOGD("clientBdData->user_data.headers[%d].u.wap_16.dest_port = 0x%04x\n", index, clientBdData->user_data.headers[index].u.wap_16.dest_port);
+            LOGD("clientBdData->user_data.headers[%d].u.wap_16.orig_port = 0x%04x\n", index, clientBdData->user_data.headers[index].u.wap_16.orig_port);
+#endif
+        break;
+        case RIL_CDMA_SMS_UDH_CONCAT_16:
+            clientBdData->user_data.headers[index].u.concat_16.msg_ref  = (data_buf[0] << 7) | data_buf[1]; // unsigned short
+            clientBdData->user_data.headers[index].u.concat_16.total_sm =  data_buf[2];
+            clientBdData->user_data.headers[index].u.concat_16.seq_num  =  data_buf[3];
+#ifdef DBG_LOG_LEVEL_A
+            LOGD("clientBdData->user_data.headers[%d].u.concat_16.msg_ref  = 0x%04x\n", index, clientBdData->user_data.headers[index].u.concat_16.msg_ref);
+            LOGD("clientBdData->user_data.headers[%d].u.concat_16.total_sm = 0x%04x\n", index, clientBdData->user_data.headers[index].u.concat_16.total_sm);
+            LOGD("clientBdData->user_data.headers[%d].u.concat_16.seq_num  = 0x%04x\n", index, clientBdData->user_data.headers[index].u.concat_16.seq_num);
+#endif
+        break;
+        default:
+        break;
+    }
+
+    // increment num_of_headers
+    clientBdData->user_data.num_headers++;
+
+    return JNI_SUCCESS;
+}
+
+
+/* native interface */
+JNIEXPORT jbyteArray JNICALL
+Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsGetUserDataHeader
+  (JNIEnv * env, jobject obj)
+{
+    jbyteArray arrData = NULL;
+    jbyte data_buf[sizeof(clientBdData->user_data.headers)];
+    int length = 0;
+
+#ifdef DBG_LOG_LEVEL_B
+    LOGD("nativeCdmaSmsGetUserDataHeader()...\n");
+#endif
+
+#ifdef DBG_LOG_LEVEL_A
+    LOGD("clientBdData->user_data.num_headers = %d, size = %d\n", clientBdData->user_data.num_headers, sizeof(clientBdData->user_data.headers));
+#endif
+
+    for (int index = 0; index < clientBdData->user_data.num_headers; index++) {
+        // user_data.headers[index].header_id
+        data_buf[length++] = (jbyte)clientBdData->user_data.headers[index].header_id;
+#ifdef DBG_LOG_LEVEL_A
+        LOGD("clientBdData->user_data.headers[%d].header_id = %d", index, clientBdData->user_data.headers[index].header_id);
+#endif
+
+        // user_data.headers[index].u
+        // TODO: add support for all udh id's
+        switch(clientBdData->user_data.headers[index].header_id)
+        {
+            case RIL_CDMA_SMS_UDH_CONCAT_8:
+#ifdef DBG_LOG_LEVEL_A
+                LOGD("clientBdData->user_data.headers[%d].u.concat_8.msg_ref  = 0x%02x\n", index, clientBdData->user_data.headers[index].u.concat_8.msg_ref);
+                LOGD("clientBdData->user_data.headers[%d].u.concat_8.total_sm = 0x%02x\n", index, clientBdData->user_data.headers[index].u.concat_8.total_sm);
+                LOGD("clientBdData->user_data.headers[%d].u.concat_8.seq_num  = 0x%02x\n", index, clientBdData->user_data.headers[index].u.concat_8.seq_num);
+#endif
+                data_buf[length++] = 3;
+                data_buf[length++] = clientBdData->user_data.headers[index].u.concat_8.msg_ref;
+                data_buf[length++] = clientBdData->user_data.headers[index].u.concat_8.total_sm;
+                data_buf[length++] = clientBdData->user_data.headers[index].u.concat_8.seq_num;
+            break;
+            case RIL_CDMA_SMS_UDH_SPECIAL_SM:
+#ifdef DBG_LOG_LEVEL_A
+                LOGD("clientBdData->user_data.headers[%d].u.special_sm.msg_waiting      = 0x%04x\n", index, clientBdData->user_data.headers[index].u.special_sm.msg_waiting);
+                LOGD("clientBdData->user_data.headers[%d].u.special_sm.msg_waiting_kind = 0x%04x\n", index, clientBdData->user_data.headers[index].u.special_sm.msg_waiting_kind);
+                LOGD("clientBdData->user_data.headers[%d].u.special_sm.message_count    = 0x%02x\n", index, clientBdData->user_data.headers[index].u.special_sm.message_count);
+#endif
+                data_buf[length++] = 9;
+                data_buf[length++] = (clientBdData->user_data.headers[index].u.special_sm.msg_waiting & 0xFF000000) >> 23; // int
+                data_buf[length++] = (clientBdData->user_data.headers[index].u.special_sm.msg_waiting & 0x00FF0000) >> 15;
+                data_buf[length++] = (clientBdData->user_data.headers[index].u.special_sm.msg_waiting & 0x0000FF00) >> 7;
+                data_buf[length++] =  clientBdData->user_data.headers[index].u.special_sm.msg_waiting & 0x000000FF;
+                data_buf[length++] = (clientBdData->user_data.headers[index].u.special_sm.msg_waiting_kind & 0xFF000000) >> 23; // int
+                data_buf[length++] = (clientBdData->user_data.headers[index].u.special_sm.msg_waiting_kind & 0x00FF0000) >> 15;
+                data_buf[length++] = (clientBdData->user_data.headers[index].u.special_sm.msg_waiting_kind & 0x0000FF00) >> 7;
+                data_buf[length++] =  clientBdData->user_data.headers[index].u.special_sm.msg_waiting_kind & 0x000000FF;
+                data_buf[length++] =  clientBdData->user_data.headers[index].u.special_sm.message_count;
+            break;
+            case RIL_CDMA_SMS_UDH_PORT_8:
+#ifdef DBG_LOG_LEVEL_A
+                LOGD("clientBdData->user_data.headers[%d].u.wap_8.dest_port = 0x%02x\n", index, clientBdData->user_data.headers[index].u.wap_8.dest_port);
+                LOGD("clientBdData->user_data.headers[%d].u.wap_8.orig_port = 0x%02x\n", index, clientBdData->user_data.headers[index].u.wap_8.orig_port);
+#endif
+                data_buf[length++] = 2;
+                data_buf[length++] = clientBdData->user_data.headers[index].u.wap_8.dest_port;
+                data_buf[length++] = clientBdData->user_data.headers[index].u.wap_8.orig_port;
+            break;
+            case RIL_CDMA_SMS_UDH_PORT_16:
+#ifdef DBG_LOG_LEVEL_A
+                LOGD("clientBdData->user_data.headers[%d].u.wap_16.dest_port = 0x%04x\n", index, clientBdData->user_data.headers[index].u.wap_16.dest_port);
+                LOGD("clientBdData->user_data.headers[%d].u.wap_16.orig_port = 0x%04x\n", index, clientBdData->user_data.headers[index].u.wap_16.orig_port);
+#endif
+                data_buf[length++] = 4;
+                data_buf[length++] = (clientBdData->user_data.headers[index].u.wap_16.dest_port & 0xFF00) >> 7; // unsigned short
+                data_buf[length++] =  clientBdData->user_data.headers[index].u.wap_16.dest_port & 0x00FF;
+                data_buf[length++] = (clientBdData->user_data.headers[index].u.wap_16.orig_port & 0xFF00) >> 7; // unsigned short
+                data_buf[length++] =  clientBdData->user_data.headers[index].u.wap_16.orig_port & 0x00FF;
+            break;
+            case RIL_CDMA_SMS_UDH_CONCAT_16:
+#ifdef DBG_LOG_LEVEL_A
+                LOGD("clientBdData->user_data.headers[%d].u.concat_16.msg_ref  = 0x%04x\n", index, clientBdData->user_data.headers[index].u.concat_16.msg_ref);
+                LOGD("clientBdData->user_data.headers[%d].u.concat_16.total_sm = 0x%04x\n", index, clientBdData->user_data.headers[index].u.concat_16.total_sm);
+                LOGD("clientBdData->user_data.headers[%d].u.concat_16.seq_num  = 0x%04x\n", index, clientBdData->user_data.headers[index].u.concat_16.seq_num);
+#endif
+                data_buf[length++] = 4;
+                data_buf[length++] = (clientBdData->user_data.headers[index].u.concat_16.msg_ref & 0xFF00) >> 7; // unsigned short
+                data_buf[length++] =  clientBdData->user_data.headers[index].u.concat_16.msg_ref & 0x00FF;
+                data_buf[length++] =  clientBdData->user_data.headers[index].u.concat_16.total_sm;
+                data_buf[length++] =  clientBdData->user_data.headers[index].u.concat_16.seq_num;
+            break;
+            default:
+            break;
+        }
+    }
+
+    if (length != 0) {
+        arrData = env->NewByteArray((jsize)length);
+        env->SetByteArrayRegion(arrData, 0, length, data_buf);
+    }
+
+    return arrData;
+}
+
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsSetSmsAddress
+  (JNIEnv * env, jobject obj, jobject smsAddress)
+{
+    jclass SmsAddressClass;
+    jfieldID field;
+    jbyteArray arrData = NULL;
+    jbyte byte_buf[RIL_CDMA_SMS_ADDRESS_MAX];
+    int length;
+    jint intData;
+    jbyte byteData;
+    jboolean booleanData;
+
+#ifdef DBG_LOG_LEVEL_B
+    LOGD("nativeCdmaSmsSetSmsAddress()...\n");
+#endif
+
+    // callback.digit_mode
+    if (getObjectByteField(env, smsAddress, "digitMode", &byteData) != JNI_SUCCESS)
+        return JNI_FAILURE;
+    clientBdData->callback.digit_mode = (RIL_CDMA_SMS_DigitMode)(byteData);
+#ifdef DBG_LOG_LEVEL_A
+    LOGD("clientBdData->callback.digit_mode = 0x%02x\n", clientBdData->callback.digit_mode);
+#endif
+
+    // callback.number_mode
+    if (getObjectByteField(env, smsAddress, "numberMode", &byteData) != JNI_SUCCESS)
+        return JNI_FAILURE;
+    clientBdData->callback.number_mode = (RIL_CDMA_SMS_NumberMode)(byteData);
+#ifdef DBG_LOG_LEVEL_A
+    LOGD("clientBdData->callback.number_mode = 0x%02x\n", clientBdData->callback.number_mode);
+#endif
+
+    // callback.number_type
+    if (getObjectIntField(env, smsAddress, "ton", &intData) != JNI_SUCCESS)
+        return JNI_FAILURE;
+    clientBdData->callback.number_type = (RIL_CDMA_SMS_NumberType)(intData);
+#ifdef DBG_LOG_LEVEL_A
+    LOGD("clientBdData->callback.number_type = %d\n", clientBdData->callback.number_type);
+#endif
+
+    // callback.number_plan
+    if (getObjectByteField(env, smsAddress, "numberPlan", &byteData) != JNI_SUCCESS)
+        return JNI_FAILURE;
+    clientBdData->callback.number_plan = (RIL_CDMA_SMS_NumberPlan)(byteData);
+#ifdef DBG_LOG_LEVEL_A
+    LOGD("clientBdData->callback.number_plan = 0x%02x\n", clientBdData->callback.number_plan);
+#endif
+
+    // callback.number_of_digits
+    if (getObjectByteField(env, smsAddress, "numberOfDigits", &byteData) != JNI_SUCCESS)
+        return JNI_FAILURE;
+    clientBdData->callback.number_of_digits = byteData;
+#ifdef DBG_LOG_LEVEL_A
+    LOGD("clientBdData->callback.number_of_digits = %d\n",clientBdData->callback.number_of_digits);
+#endif
+
+    // callback.digits
+    if (getObjectByteArrayField(env, smsAddress, "origBytes", byte_buf, &length) != JNI_SUCCESS)
+        return JNI_FAILURE;
+    for (int i = 0; i < clientBdData->callback.number_of_digits; i++) {
+        clientBdData->callback.digits[i] = byte_buf[i];
+#ifdef DBG_LOG_LEVEL_A
+        LOGD("clientBdData->callback.digits[%d] = 0x%02x\n", i, clientBdData->callback.digits[i]);
+#endif
+    }
+
+    return JNI_SUCCESS;
+}
+
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsGetSmsAddress
+  (JNIEnv * env, jobject obj, jobject smsAddress)
+{
+    jclass SmsAddressClass;
+    jfieldID field;
+    jbyteArray arrData = NULL;
+    jbyte *byte_buf;
+    int length;
+
+#ifdef DBG_LOG_LEVEL_B
+    LOGD("nativeCdmaSmsGetSmsAddress()...\n");
+#endif
+
+    // callback.digit_mode
+#ifdef DBG_LOG_LEVEL_A
+    LOGD("clientBdData->callback.digit_mode = 0x%02x\n", clientBdData->callback.digit_mode);
+#endif
+    if (setObjectByteField(env, smsAddress, "digitMode", (jbyte)clientBdData->callback.digit_mode) != JNI_SUCCESS)
+        return JNI_FAILURE;
+
+    // callback.number_mode
+#ifdef DBG_LOG_LEVEL_A
+    LOGD("clientBdData->callback.number_mode = 0x%02x\n", clientBdData->callback.number_mode);
+#endif
+    if (setObjectByteField(env, smsAddress, "numberMode", (jbyte)clientBdData->callback.number_mode) != JNI_SUCCESS)
+        return JNI_FAILURE;
+
+    // callback.number_type
+#ifdef DBG_LOG_LEVEL_A
+    LOGD("clientBdData->callback.number_type = %d\n", clientBdData->callback.number_type);
+#endif
+    if (setObjectIntField(env, smsAddress, "ton", (jint)clientBdData->callback.number_type) != JNI_SUCCESS)
+        return JNI_FAILURE;
+
+    // callback.number_plan
+#ifdef DBG_LOG_LEVEL_A
+    LOGD("clientBdData->callback.number_plan = 0x%02x\n", clientBdData->callback.number_plan);
+#endif
+    if (setObjectByteField(env, smsAddress, "numberPlan", (jbyte)clientBdData->callback.number_plan) != JNI_SUCCESS)
+        return JNI_FAILURE;
+
+    // callback.number_of_digits
+#ifdef DBG_LOG_LEVEL_A
+    LOGD("clientBdData->callback.number_of_digits = %d\n", clientBdData->callback.number_of_digits);
+#endif
+    if (setObjectByteField(env, smsAddress, "numberOfDigits", (jbyte)clientBdData->callback.number_of_digits) != JNI_SUCCESS)
+        return JNI_FAILURE;
+
+    // callback.digits
+    byte_buf = (jbyte*)clientBdData->callback.digits;
+    length = clientBdData->callback.number_of_digits;
+#ifdef DBG_LOG_LEVEL_A
+    for (int i = 0; i < length; i++) {
+        LOGD("clientBdData->callback.digits[%d] = 0x%02x\n", i, clientBdData->callback.digits[i]);
+    }
+#endif
+
+    if (setObjectByteArrayField(env, smsAddress, "origBytes", byte_buf, length) != JNI_SUCCESS)
+        return JNI_FAILURE;
+
+    return JNI_SUCCESS;
+}
+
+
+/* native interface */
+JNIEXPORT jbyteArray JNICALL
+Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsEncodeSms
+  (JNIEnv * env, jobject obj)
+{
+    RIL_CDMA_Encoded_SMS *encoded_sms = (RIL_CDMA_Encoded_SMS *)malloc(sizeof(RIL_CDMA_Encoded_SMS));
+    jbyte* data_buf;
+    jint result = JNI_SUCCESS;
+    jbyteArray encodedSMS;
+
+#ifdef DBG_LOG_LEVEL_B
+    LOGD("nativeCdmaSmsEncodeSms(): entry\n");
+#endif
+
+    if (NULL == encoded_sms) {
+        jniThrowException(env, "java/lang/NullPointerException", "encoded_sms is null");
+        return NULL;
+    }
+    memset(encoded_sms, 0, sizeof(RIL_CDMA_Encoded_SMS));
+
+    // call CDMA SMS encode function
+    if(wmsts_ril_cdma_encode_sms(clientBdData, encoded_sms) != RIL_E_SUCCESS) {
+        jniThrowException(env, "java/lang/Exception", "CDMA SMS Encoding failed");
+        return NULL;
+    }
+
+#ifdef DBG_LOG_LEVEL_A
+    LOGD("  EncodeSMS: length = %i\n", encoded_sms->length);
+#endif
+    encodedSMS = env->NewByteArray((jsize)encoded_sms->length);
+    env->SetByteArrayRegion(encodedSMS, 0, encoded_sms->length, (jbyte*)encoded_sms->data);
+    free(encoded_sms);
+
+    return encodedSMS;
+}
+
+
+/* native interface */
+JNIEXPORT jint JNICALL
+Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsDecodeSms
+  (JNIEnv * env, jobject obj, jbyteArray encodedSMS)
+{
+    RIL_CDMA_Encoded_SMS *encoded_sms = (RIL_CDMA_Encoded_SMS *)malloc(sizeof(RIL_CDMA_Encoded_SMS));
+    jbyte* data_buf;
+    jint result = JNI_SUCCESS;
+    jsize length;
+
+#ifdef DBG_LOG_LEVEL_B
+    LOGD("nativeCdmaSmsDecodeSms(): entry\n");
+#endif
+
+    if (NULL == encoded_sms) {
+        jniThrowException(env, "java/lang/NullPointerException", "encoded_sms is null");
+        return JNI_FAILURE;
+    }
+    memset(encoded_sms, 0, sizeof(RIL_CDMA_Encoded_SMS));
+
+    length = env->GetArrayLength(encodedSMS);
+    if (length < 0 || length > 255) {
+        jniThrowException(env, "java/lang/ArrayIndexOutOfBounds", "wrong encoded SMS data length");
+        return JNI_FAILURE;
+    }
+    encoded_sms->length = length;
+#ifdef DBG_LOG_LEVEL_A
+    LOGD("  DecodeSMS: arrayLength = %d\n", encoded_sms->length);
+#endif
+    data_buf = env->GetByteArrayElements(encodedSMS, NULL);
+    encoded_sms->data = (unsigned char*)data_buf;
+    env->ReleaseByteArrayElements(encodedSMS, data_buf, 0);
+
+    // call CDMA SMS decode function
+    if(wmsts_ril_cdma_decode_sms(encoded_sms, clientBdData) != RIL_E_SUCCESS) {
+        jniThrowException(env, "java/lang/Exception", "CDMA SMS Decoding failed");
+        result = JNI_FAILURE;
+    }
+
+    free(encoded_sms);
+
+    return result;
+}
+
+
+// ---------------------------------------------------------------------------
+
+static const char *classPathName = "com/android/internal/telephony/cdma/sms/SmsDataCoding";
+
+static JNINativeMethod methods[] = {
+    /* name, signature, funcPtr */
+    {"nativeCdmaSmsConstructClientBD", "()I",
+      (void*)Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsConstructClientBD },
+    {"nativeCdmaSmsDestructClientBD", "()I",
+      (void*)Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsDestructClientBD },
+    {"nativeCdmaSmsSetBearerDataPrimitives", "(Lcom/android/internal/telephony/cdma/sms/BearerData;)I",
+      (void*)Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsSetBearerDataPrimitives },
+    {"nativeCdmaSmsGetBearerDataPrimitives", "(Lcom/android/internal/telephony/cdma/sms/BearerData;)I",
+      (void*)Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsGetBearerDataPrimitives },
+    {"nativeCdmaSmsSetUserData", "(Lcom/android/internal/telephony/cdma/sms/UserData;)I",
+      (void*)Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsSetUserData },
+    {"nativeCdmaSmsGetUserData", "(Lcom/android/internal/telephony/cdma/sms/UserData;)I",
+      (void*)Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsGetUserData },
+    {"nativeCdmaSmsSetUserDataHeader", "(I[BII)I",
+      (void*)Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsSetUserDataHeader },
+    {"nativeCdmaSmsGetUserDataHeader", "()[B",
+      (void*)Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsGetUserDataHeader },
+    {"nativeCdmaSmsSetSmsAddress", "(Lcom/android/internal/telephony/cdma/sms/CdmaSmsAddress;)I",
+      (void*)Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsSetSmsAddress },
+    {"nativeCdmaSmsGetSmsAddress", "(Lcom/android/internal/telephony/cdma/sms/CdmaSmsAddress;)I",
+      (void*)Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsGetSmsAddress },
+    {"nativeCdmaSmsEncodeSms", "()[B",
+      (void*)Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsEncodeSms },
+    {"nativeCdmaSmsDecodeSms", "([B)I",
+      (void*)Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsDecodeSms },
+};
+
+int register_android_cdma_sms_methods(JNIEnv *_env)
+{
+    return android::AndroidRuntime::registerNativeMethods(
+            _env, classPathName, methods, NELEM(methods));
+}
+
+// ---------------------------------------------------------------------------
+
+jint JNI_OnLoad(JavaVM* vm, void* reserved)
+{
+    JNIEnv* env = NULL;
+    jint result = -1;
+
+    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
+        LOGE("ERROR: GetEnv failed\n");
+        goto bail;
+    }
+    assert(env != NULL);
+
+    if (register_android_cdma_sms_methods(env) < 0) {
+        LOGE("ERROR: CDMA SMS native registration failed\n");
+        goto bail;
+    }
+
+    /* success -- return valid version number */
+    result = JNI_VERSION_1_4;
+
+bail:
+    return result;
+}
diff --git a/telephony/jni/cdmasms/cdma_sms_jni.h b/telephony/jni/cdmasms/cdma_sms_jni.h
new file mode 100644
index 0000000..253c006
--- /dev/null
+++ b/telephony/jni/cdmasms/cdma_sms_jni.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 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.
+ * 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.
+ */
+
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_android_internal_telephony_cdma_sms_SmsDataCoding */
+
+#ifndef _Included_com_android_internal_telephony_cdma_sms_SmsDataCoding
+#define _Included_com_android_internal_telephony_cdma_sms_SmsDataCoding
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_android_internal_telephony_cdma_sms_SmsDataCoding_CDMA_SMS_WMS_MASK_BD_NULL
+#define com_android_internal_telephony_cdma_sms_SmsDataCoding_CDMA_SMS_WMS_MASK_BD_NULL 0L
+#undef com_android_internal_telephony_cdma_sms_SmsDataCoding_CDMA_SMS_WMS_MASK_BD_MSG_ID
+#define com_android_internal_telephony_cdma_sms_SmsDataCoding_CDMA_SMS_WMS_MASK_BD_MSG_ID 1L
+#undef com_android_internal_telephony_cdma_sms_SmsDataCoding_CDMA_SMS_WMS_MASK_BD_USER_DATA
+#define com_android_internal_telephony_cdma_sms_SmsDataCoding_CDMA_SMS_WMS_MASK_BD_USER_DATA 2L
+#undef com_android_internal_telephony_cdma_sms_SmsDataCoding_CDMA_SMS_WMS_MASK_BD_MC_TIME
+#define com_android_internal_telephony_cdma_sms_SmsDataCoding_CDMA_SMS_WMS_MASK_BD_MC_TIME 8L
+#undef com_android_internal_telephony_cdma_sms_SmsDataCoding_CDMA_SMS_WMS_MASK_BD_NUM_OF_MSGS
+#define com_android_internal_telephony_cdma_sms_SmsDataCoding_CDMA_SMS_WMS_MASK_BD_NUM_OF_MSGS 2048L
+#undef com_android_internal_telephony_cdma_sms_SmsDataCoding_CDMA_SMS_WMS_MASK_BD_CALLBACK
+#define com_android_internal_telephony_cdma_sms_SmsDataCoding_CDMA_SMS_WMS_MASK_BD_CALLBACK 16384L
+#undef com_android_internal_telephony_cdma_sms_SmsDataCoding_CDMA_SMS_WMS_MASK_BD_DISPLAY_MODE
+#define com_android_internal_telephony_cdma_sms_SmsDataCoding_CDMA_SMS_WMS_MASK_BD_DISPLAY_MODE 32768L
+#undef com_android_internal_telephony_cdma_sms_SmsDataCoding_JNI_CDMA_SMS_SUCCESS
+#define com_android_internal_telephony_cdma_sms_SmsDataCoding_JNI_CDMA_SMS_SUCCESS 0L
+#undef com_android_internal_telephony_cdma_sms_SmsDataCoding_JNI_CDMA_SMS_FAILURE
+#define com_android_internal_telephony_cdma_sms_SmsDataCoding_JNI_CDMA_SMS_FAILURE 1L
+#undef com_android_internal_telephony_cdma_sms_SmsDataCoding_JNI_CDMA_SMS_DATA_LEN_OUT_OF_RANGE
+#define com_android_internal_telephony_cdma_sms_SmsDataCoding_JNI_CDMA_SMS_DATA_LEN_OUT_OF_RANGE 2L
+#undef com_android_internal_telephony_cdma_sms_SmsDataCoding_JNI_CDMA_SMS_CLASS_UNKNOWN
+#define com_android_internal_telephony_cdma_sms_SmsDataCoding_JNI_CDMA_SMS_CLASS_UNKNOWN 3L
+#undef com_android_internal_telephony_cdma_sms_SmsDataCoding_JNI_CDMA_SMS_FIELD_ID_UNKNOWN
+#define com_android_internal_telephony_cdma_sms_SmsDataCoding_JNI_CDMA_SMS_FIELD_ID_UNKNOWN 4L
+#undef com_android_internal_telephony_cdma_sms_SmsDataCoding_JNI_CDMA_SMS_OUT_OF_MEMORY
+#define com_android_internal_telephony_cdma_sms_SmsDataCoding_JNI_CDMA_SMS_OUT_OF_MEMORY 5L
+/*
+ * Class:     com_android_internal_telephony_cdma_sms_SmsDataCoding
+ * Method:    nativeCdmaSmsConstructClientBD
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsConstructClientBD
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     com_android_internal_telephony_cdma_sms_SmsDataCoding
+ * Method:    nativeCdmaSmsDestructClientBD
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsDestructClientBD
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     com_android_internal_telephony_cdma_sms_SmsDataCoding
+ * Method:    nativeCdmaSmsSetBearerDataPrimitives
+ * Signature: (Lcom/android/internal/telephony/cdma/sms/BearerData;)I
+ */
+JNIEXPORT jint JNICALL Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsSetBearerDataPrimitives
+  (JNIEnv *, jobject, jobject);
+
+/*
+ * Class:     com_android_internal_telephony_cdma_sms_SmsDataCoding
+ * Method:    nativeCdmaSmsGetBearerDataPrimitives
+ * Signature: (Lcom/android/internal/telephony/cdma/sms/BearerData;)I
+ */
+JNIEXPORT jint JNICALL Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsGetBearerDataPrimitives
+  (JNIEnv *, jobject, jobject);
+
+/*
+ * Class:     com_android_internal_telephony_cdma_sms_SmsDataCoding
+ * Method:    nativeCdmaSmsSetUserData
+ * Signature: (Lcom/android/internal/telephony/cdma/sms/UserData;)I
+ */
+JNIEXPORT jint JNICALL Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsSetUserData
+  (JNIEnv *, jobject, jobject);
+
+/*
+ * Class:     com_android_internal_telephony_cdma_sms_SmsDataCoding
+ * Method:    nativeCdmaSmsGetUserData
+ * Signature: (Lcom/android/internal/telephony/cdma/sms/UserData;)I
+ */
+JNIEXPORT jint JNICALL Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsGetUserData
+  (JNIEnv *, jobject, jobject);
+
+/*
+ * Class:     com_android_internal_telephony_cdma_sms_SmsDataCoding
+ * Method:    nativeCdmaSmsSetUserDataHeader
+ * Signature: (I[BII)I
+ */
+JNIEXPORT jint JNICALL Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsSetUserDataHeader
+  (JNIEnv *, jobject, jint, jbyteArray, jint, jint);
+
+/*
+ * Class:     com_android_internal_telephony_cdma_sms_SmsDataCoding
+ * Method:    nativeCdmaSmsGetUserDataHeader
+ * Signature: ()[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsGetUserDataHeader
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     com_android_internal_telephony_cdma_sms_SmsDataCoding
+ * Method:    nativeCdmaSmsSetSmsAddress
+ * Signature: (Lcom/android/internal/telephony/cdma/sms/CdmaSmsAddress;)I
+ */
+JNIEXPORT jint JNICALL Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsSetSmsAddress
+  (JNIEnv *, jobject, jobject);
+
+/*
+ * Class:     com_android_internal_telephony_cdma_sms_SmsDataCoding
+ * Method:    nativeCdmaSmsGetSmsAddress
+ * Signature: (Lcom/android/internal/telephony/cdma/sms/CdmaSmsAddress;)I
+ */
+JNIEXPORT jint JNICALL Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsGetSmsAddress
+  (JNIEnv *, jobject, jobject);
+
+/*
+ * Class:     com_android_internal_telephony_cdma_sms_SmsDataCoding
+ * Method:    nativeCdmaSmsEncodeSms
+ * Signature: ()[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsEncodeSms
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     com_android_internal_telephony_cdma_sms_SmsDataCoding
+ * Method:    nativeCdmaSmsDecodeSms
+ * Signature: ([B)I
+ */
+JNIEXPORT jint JNICALL Java_com_android_internal_telephony_cdma_sms_SmsDataCoding_nativeCdmaSmsDecodeSms
+  (JNIEnv *, jobject, jbyteArray);
+
+/**
+ * CDMA SMS return value defines
+ */
+#define JNI_SUCCESS \
+com_android_internal_telephony_cdma_sms_SmsDataCoding_JNI_CDMA_SMS_SUCCESS  /**< Successful operation */
+#define JNI_FAILURE \
+com_android_internal_telephony_cdma_sms_SmsDataCoding_JNI_CDMA_SMS_FAILURE  /**< General failure */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/tests/AndroidTests/src/com/android/unit_tests/SMSTest.java b/tests/AndroidTests/src/com/android/unit_tests/SMSTest.java
index ce0b53d..360352b 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/SMSTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/SMSTest.java
@@ -16,10 +16,10 @@
 
 package com.android.unit_tests;
 
-import com.android.internal.telephony.gsm.GsmAlphabet;
-import com.android.internal.telephony.gsm.SmsHeader;
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.SmsHeader;
+import com.android.internal.telephony.gsm.SmsMessage;
 import com.android.internal.util.HexDump;
-import android.telephony.gsm.SmsMessage;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
diff --git a/tests/CoreTests/com/android/internal/telephony/gsm/AdnRecordTest.java b/tests/CoreTests/com/android/internal/telephony/AdnRecordTest.java
similarity index 83%
rename from tests/CoreTests/com/android/internal/telephony/gsm/AdnRecordTest.java
rename to tests/CoreTests/com/android/internal/telephony/AdnRecordTest.java
index 6cafdf0..8a4a285 100644
--- a/tests/CoreTests/com/android/internal/telephony/gsm/AdnRecordTest.java
+++ b/tests/CoreTests/com/android/internal/telephony/AdnRecordTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 import junit.framework.TestCase;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -32,7 +32,7 @@
         // Typical record
         // 
         adn = new AdnRecord(
-                SimUtils.hexStringToBytes("566F696365204D61696C07918150367742F3FFFFFFFFFFFF"));
+                IccUtils.hexStringToBytes("566F696365204D61696C07918150367742F3FFFFFFFFFFFF"));
 
         assertEquals("Voice Mail", adn.getAlphaTag());
         assertEquals("+18056377243", adn.getNumber());
@@ -42,7 +42,7 @@
         // Empty records, empty strings
         // 
         adn = new AdnRecord(
-                SimUtils.hexStringToBytes("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"));
+                IccUtils.hexStringToBytes("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"));
 
         assertEquals("", adn.getAlphaTag());
         assertEquals("", adn.getNumber());
@@ -51,7 +51,7 @@
         //
         // Record too short
         // 
-        adn = new AdnRecord(SimUtils.hexStringToBytes( "FF"));
+        adn = new AdnRecord(IccUtils.hexStringToBytes( "FF"));
 
         assertEquals("", adn.getAlphaTag());
         assertEquals("", adn.getNumber());
@@ -61,7 +61,7 @@
         // TOA = 0xff ("control string")
         // 
         adn = new AdnRecord(
-                SimUtils.hexStringToBytes("566F696365204D61696C07FF8150367742F3FFFFFFFFFFFF"));
+                IccUtils.hexStringToBytes("566F696365204D61696C07FF8150367742F3FFFFFFFFFFFF"));
 
         assertEquals("Voice Mail", adn.getAlphaTag());
         assertEquals("18056377243", adn.getNumber());
@@ -71,7 +71,7 @@
         // TOA = 0x81 (unknown)
         // 
         adn = new AdnRecord(
-                SimUtils.hexStringToBytes("566F696365204D61696C07818150367742F3FFFFFFFFFFFF"));
+                IccUtils.hexStringToBytes("566F696365204D61696C07818150367742F3FFFFFFFFFFFF"));
 
         assertEquals("Voice Mail", adn.getAlphaTag());
         assertEquals("18056377243", adn.getNumber());
@@ -81,7 +81,7 @@
         // Number Length is too long
         // 
         adn = new AdnRecord(
-                SimUtils.hexStringToBytes("566F696365204D61696C0F918150367742F3FFFFFFFFFFFF"));
+                IccUtils.hexStringToBytes("566F696365204D61696C0F918150367742F3FFFFFFFFFFFF"));
 
         assertEquals("Voice Mail", adn.getAlphaTag());
         assertEquals("", adn.getNumber());
@@ -91,7 +91,7 @@
         // Number Length is zero (invalid)
         // 
         adn = new AdnRecord(
-                SimUtils.hexStringToBytes("566F696365204D61696C00918150367742F3FFFFFFFFFFFF"));
+                IccUtils.hexStringToBytes("566F696365204D61696C00918150367742F3FFFFFFFFFFFF"));
 
         assertEquals("Voice Mail", adn.getAlphaTag());
         assertEquals("", adn.getNumber());
@@ -101,7 +101,7 @@
         // Number Length is 2, first number byte is FF, TOA is international
         // 
         adn = new AdnRecord(
-                SimUtils.hexStringToBytes("566F696365204D61696C0291FF50367742F3FFFFFFFFFFFF"));
+                IccUtils.hexStringToBytes("566F696365204D61696C0291FF50367742F3FFFFFFFFFFFF"));
 
         assertEquals("Voice Mail", adn.getAlphaTag());
         assertEquals("", adn.getNumber());
@@ -111,7 +111,7 @@
         // Number Length is 2, first number digit is valid, TOA is international
         // 
         adn = new AdnRecord(
-                SimUtils.hexStringToBytes("566F696365204D61696C0291F150367742F3FFFFFFFFFFFF"));
+                IccUtils.hexStringToBytes("566F696365204D61696C0291F150367742F3FFFFFFFFFFFF"));
 
         assertEquals("Voice Mail", adn.getAlphaTag());
         assertEquals("+1", adn.getNumber());
@@ -121,7 +121,7 @@
         // An extended record
         // 
         adn = new AdnRecord(
-                SimUtils.hexStringToBytes(
+                IccUtils.hexStringToBytes(
                         "4164676A6DFFFFFFFFFFFFFFFFFFFFFF0B918188551512C221436587FF01"));
 
         assertEquals("Adgjm", adn.getAlphaTag());
@@ -129,7 +129,7 @@
         assertFalse(adn.isEmpty());
         assertTrue(adn.hasExtendedRecord());
 
-        adn.appendExtRecord(SimUtils.hexStringToBytes("0206092143658709ffffffffff"));
+        adn.appendExtRecord(IccUtils.hexStringToBytes("0206092143658709ffffffffff"));
 
         assertEquals("Adgjm", adn.getAlphaTag());
         assertEquals("+18885551212,12345678901234567890", adn.getNumber());
@@ -139,7 +139,7 @@
         // An extended record with an invalid extension
         // 
         adn = new AdnRecord(
-                SimUtils.hexStringToBytes(
+                IccUtils.hexStringToBytes(
                         "4164676A6DFFFFFFFFFFFFFFFFFFFFFF0B918188551512C221436587FF01"));
 
         assertEquals("Adgjm", adn.getAlphaTag());
@@ -147,7 +147,7 @@
         assertFalse(adn.isEmpty());
         assertTrue(adn.hasExtendedRecord());
 
-        adn.appendExtRecord(SimUtils.hexStringToBytes("0106092143658709ffffffffff"));
+        adn.appendExtRecord(IccUtils.hexStringToBytes("0106092143658709ffffffffff"));
 
         assertEquals("Adgjm", adn.getAlphaTag());
         assertEquals("+18885551212,12345678", adn.getNumber());
@@ -157,7 +157,7 @@
         // An extended record with an invalid extension
         // 
         adn = new AdnRecord(
-                SimUtils.hexStringToBytes(
+                IccUtils.hexStringToBytes(
                         "4164676A6DFFFFFFFFFFFFFFFFFFFFFF0B918188551512C221436587FF01"));
 
         assertEquals("Adgjm", adn.getAlphaTag());
@@ -165,7 +165,7 @@
         assertFalse(adn.isEmpty());
         assertTrue(adn.hasExtendedRecord());
 
-        adn.appendExtRecord(SimUtils.hexStringToBytes("020B092143658709ffffffffff"));
+        adn.appendExtRecord(IccUtils.hexStringToBytes("020B092143658709ffffffffff"));
 
         assertEquals("Adgjm", adn.getAlphaTag());
         assertEquals("+18885551212,12345678", adn.getNumber());
diff --git a/tests/CoreTests/com/android/internal/telephony/gsm/GsmAlphabetTest.java b/tests/CoreTests/com/android/internal/telephony/GsmAlphabetTest.java
similarity index 97%
rename from tests/CoreTests/com/android/internal/telephony/gsm/GsmAlphabetTest.java
rename to tests/CoreTests/com/android/internal/telephony/GsmAlphabetTest.java
index f36d96b..5df8991 100644
--- a/tests/CoreTests/com/android/internal/telephony/gsm/GsmAlphabetTest.java
+++ b/tests/CoreTests/com/android/internal/telephony/GsmAlphabetTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 import junit.framework.TestCase;
 
@@ -216,12 +216,12 @@
 
         byte unpacked[];
 
-        unpacked = SimUtils.hexStringToBytes("566F696365204D61696C");
+        unpacked = IccUtils.hexStringToBytes("566F696365204D61696C");
         assertEquals("Voice Mail",
                 GsmAlphabet.gsm8BitUnpackedToString(unpacked, 0, unpacked.length));
 
-        assertEquals(SimUtils.bytesToHexString(unpacked),
-                SimUtils.bytesToHexString(
+        assertEquals(IccUtils.bytesToHexString(unpacked),
+                IccUtils.bytesToHexString(
                         GsmAlphabet.stringToGsm8BitPacked("Voice Mail")));
 
         unpacked = GsmAlphabet.stringToGsm8BitPacked(sGsmExtendedChars);
diff --git a/tests/CoreTests/com/android/internal/telephony/gsm/SMSDispatcherTest.java b/tests/CoreTests/com/android/internal/telephony/SMSDispatcherTest.java
similarity index 92%
rename from tests/CoreTests/com/android/internal/telephony/gsm/SMSDispatcherTest.java
rename to tests/CoreTests/com/android/internal/telephony/SMSDispatcherTest.java
index 6db230f..5d5d1f9 100644
--- a/tests/CoreTests/com/android/internal/telephony/gsm/SMSDispatcherTest.java
+++ b/tests/CoreTests/com/android/internal/telephony/SMSDispatcherTest.java
@@ -14,15 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 import android.test.suitebuilder.annotation.MediumTest;
 import com.android.internal.telephony.TestPhoneNotifier;
+import com.android.internal.telephony.gsm.SmsMessage;
 import com.android.internal.telephony.test.SimulatedCommands;
 import com.android.internal.telephony.test.SimulatedRadioControl;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.Suppress;
-import android.telephony.gsm.SmsMessage;
 
 import java.util.Iterator;
 
@@ -37,24 +37,24 @@
         Iterator<SmsHeader.Element> elements;
 
         String[] lines = new String[2];
-
-        lines[0] = "+CMT: ,158";
+        
+        lines[0] = "+CMT: ,158";             
         lines[1] = "07914140279510F6440A8111110301003BF56080426101748A8C0B05040B"
                  + "8423F000035502010106276170706C69636174696F6E2F766E642E776170"
                  + "2E6D6D732D6D65737361676500AF848D0185B4848C8298524F347839776F"
                  + "7547514D4141424C3641414141536741415A4B554141414141008D908918"
                  + "802B31363530323438363137392F545950453D504C4D4E008A808E028000"
                  + "88058103093A8083687474703A2F2F36";
-
+             
         sms = SmsMessage.newFromCMT(lines);
         header = sms.getUserDataHeader();
         assertNotNull(header);
         assertNotNull(sms.getUserData());
-
+                    
         elements = header.getElements().iterator();
         assertNotNull(elements);
     }
-
+    
     @MediumTest
     public void testCMT2() throws Exception {
         SmsMessage sms;
@@ -62,7 +62,7 @@
         Iterator<SmsHeader.Element> elements;
 
         String[] lines = new String[2];
-
+        
 
         lines[0] = "+CMT: ,77";
         lines[1] = "07914140279510F6440A8111110301003BF56080426101848A3B0B05040B8423F"
@@ -74,7 +74,7 @@
         System.out.println("header = " + header);
         assertNotNull(header);
         assertNotNull(sms.getUserData());
-
+                    
         elements = header.getElements().iterator();
         assertNotNull(elements);
     }
@@ -89,7 +89,7 @@
                  + "b0986c46abd96eb89c6ec7ebf97ec0a070482c1a8fc8a472c96c3a9fd0a874"
                  + "4aad5aafd8ac76cbed7abfe0b0784c2e9bcfe8b47acd6ebbdff0b87c4eafdb"
                  + "eff8bc7ecfeffbffffffffffffffffffffffffffff";
-       byte[] data = SimUtils.hexStringToBytes(s);
+       byte[] data = IccUtils.hexStringToBytes(s);
 
        sms = SmsMessage.createFromEfRecord(1, data);
        assertNotNull(sms.getMessageBody());
diff --git a/tests/CoreTests/com/android/internal/telephony/gsm/SimPhoneBookTest.java b/tests/CoreTests/com/android/internal/telephony/SimPhoneBookTest.java
similarity index 78%
rename from tests/CoreTests/com/android/internal/telephony/gsm/SimPhoneBookTest.java
rename to tests/CoreTests/com/android/internal/telephony/SimPhoneBookTest.java
index db55bca..609e768 100644
--- a/tests/CoreTests/com/android/internal/telephony/gsm/SimPhoneBookTest.java
+++ b/tests/CoreTests/com/android/internal/telephony/SimPhoneBookTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 import android.os.ServiceManager;
 import android.test.suitebuilder.annotation.Suppress;
@@ -27,19 +27,19 @@
 public class SimPhoneBookTest extends TestCase {
 
     public void testBasic() throws Exception {
-        ISimPhoneBook simPhoneBook =
-                ISimPhoneBook.Stub.asInterface(ServiceManager.getService("simphonebook"));
+        IIccPhoneBook simPhoneBook =
+                IIccPhoneBook.Stub.asInterface(ServiceManager.getService("simphonebook"));
         assertNotNull(simPhoneBook);
 
-        int size[] = simPhoneBook.getAdnRecordsSize(SimConstants.EF_ADN);
+        int size[] = simPhoneBook.getAdnRecordsSize(IccConstants.EF_ADN);
         assertNotNull(size);
         assertEquals(3, size.length);
         assertEquals(size[0] * size[2], size[1]);
         assertTrue(size[2] >= 100);
 
-        List<AdnRecord> adnRecordList = simPhoneBook.getAdnRecordsInEf(SimConstants.EF_ADN);
+        List<AdnRecord> adnRecordList = simPhoneBook.getAdnRecordsInEf(IccConstants.EF_ADN);
         // do it twice cause the second time shall read from cache only
-        adnRecordList = simPhoneBook.getAdnRecordsInEf(SimConstants.EF_ADN);
+        adnRecordList = simPhoneBook.getAdnRecordsInEf(IccConstants.EF_ADN);
         assertNotNull(adnRecordList);
 
         // Test for phone book update
@@ -47,58 +47,58 @@
         AdnRecord originalAdn = null;
         // We need to maintain the state of the SIM before and after the test.
         // Since this test doesn't mock the SIM we try to get a valid ADN record,
-        // for 3 tries and if this fails, we bail out.
+        // for 3 tries and if this fails, we bail out. 
         for (adnIndex = 3 ; adnIndex >= 1; adnIndex--) {
             listIndex = adnIndex - 1; // listIndex is zero based.
             originalAdn = adnRecordList.get(listIndex);
             assertNotNull("Original Adn is Null.", originalAdn);
             assertNotNull("Original Adn alpha tag is null.", originalAdn.getAlphaTag());
             assertNotNull("Original Adn number is null.", originalAdn.getNumber());
-
-            if (originalAdn.getNumber().length() > 0 &&
-                originalAdn.getAlphaTag().length() > 0) {
+            
+            if (originalAdn.getNumber().length() > 0 &&  
+                originalAdn.getAlphaTag().length() > 0) {   
                 break;
             }
         }
         if (adnIndex == 0) return;
-
+        
         AdnRecord emptyAdn = new AdnRecord("", "");
         AdnRecord firstAdn = new AdnRecord("John", "4085550101");
         AdnRecord secondAdn = new AdnRecord("Andy", "6505550102");
         String pin2 = null;
 
         // udpate by index
-        boolean success = simPhoneBook.updateAdnRecordsInEfByIndex(SimConstants.EF_ADN,
+        boolean success = simPhoneBook.updateAdnRecordsInEfByIndex(IccConstants.EF_ADN,
                 firstAdn.getAlphaTag(), firstAdn.getNumber(), adnIndex, pin2);
-        adnRecordList = simPhoneBook.getAdnRecordsInEf(SimConstants.EF_ADN);
+        adnRecordList = simPhoneBook.getAdnRecordsInEf(IccConstants.EF_ADN);
          AdnRecord tmpAdn = adnRecordList.get(listIndex);
         assertTrue(success);
         assertTrue(firstAdn.isEqual(tmpAdn));
 
         // replace by search
-        success = simPhoneBook.updateAdnRecordsInEfBySearch(SimConstants.EF_ADN,
+        success = simPhoneBook.updateAdnRecordsInEfBySearch(IccConstants.EF_ADN,
                 firstAdn.getAlphaTag(), firstAdn.getNumber(),
                 secondAdn.getAlphaTag(), secondAdn.getNumber(), pin2);
-        adnRecordList = simPhoneBook.getAdnRecordsInEf(SimConstants.EF_ADN);
+        adnRecordList = simPhoneBook.getAdnRecordsInEf(IccConstants.EF_ADN);
         tmpAdn = adnRecordList.get(listIndex);
         assertTrue(success);
         assertFalse(firstAdn.isEqual(tmpAdn));
         assertTrue(secondAdn.isEqual(tmpAdn));
 
         // erase be search
-        success = simPhoneBook.updateAdnRecordsInEfBySearch(SimConstants.EF_ADN,
+        success = simPhoneBook.updateAdnRecordsInEfBySearch(IccConstants.EF_ADN,
                 secondAdn.getAlphaTag(), secondAdn.getNumber(),
                 emptyAdn.getAlphaTag(), emptyAdn.getNumber(), pin2);
-        adnRecordList = simPhoneBook.getAdnRecordsInEf(SimConstants.EF_ADN);
+        adnRecordList = simPhoneBook.getAdnRecordsInEf(IccConstants.EF_ADN);
         tmpAdn = adnRecordList.get(listIndex);
         assertTrue(success);
         assertTrue(tmpAdn.isEmpty());
 
         // restore the orginial adn
-        success = simPhoneBook.updateAdnRecordsInEfByIndex(SimConstants.EF_ADN,
+        success = simPhoneBook.updateAdnRecordsInEfByIndex(IccConstants.EF_ADN,
                 originalAdn.getAlphaTag(), originalAdn.getNumber(), adnIndex,
                 pin2);
-        adnRecordList = simPhoneBook.getAdnRecordsInEf(SimConstants.EF_ADN);
+        adnRecordList = simPhoneBook.getAdnRecordsInEf(IccConstants.EF_ADN);
         tmpAdn = adnRecordList.get(listIndex);
         assertTrue(success);
         assertTrue(originalAdn.isEqual(tmpAdn));
diff --git a/tests/CoreTests/com/android/internal/telephony/gsm/SimSmsTest.java b/tests/CoreTests/com/android/internal/telephony/SimSmsTest.java
similarity index 94%
rename from tests/CoreTests/com/android/internal/telephony/gsm/SimSmsTest.java
rename to tests/CoreTests/com/android/internal/telephony/SimSmsTest.java
index 6ced23d..1609680 100644
--- a/tests/CoreTests/com/android/internal/telephony/gsm/SimSmsTest.java
+++ b/tests/CoreTests/com/android/internal/telephony/SimSmsTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 import android.os.ServiceManager;
 import android.test.suitebuilder.annotation.MediumTest;
@@ -33,7 +33,7 @@
         ISms sms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
         assertNotNull(sms);
 
-        List<SmsRawData> records = sms.getAllMessagesFromSimEf();
+        List<SmsRawData> records = sms.getAllMessagesFromIccEf();
         assertNotNull(records);
         assertTrue(records.size() >= 0);
 
diff --git a/tests/CoreTests/com/android/internal/telephony/gsm/SimUtilsTest.java b/tests/CoreTests/com/android/internal/telephony/SimUtilsTest.java
similarity index 62%
rename from tests/CoreTests/com/android/internal/telephony/gsm/SimUtilsTest.java
rename to tests/CoreTests/com/android/internal/telephony/SimUtilsTest.java
index 3fbc8f5..e733af9 100644
--- a/tests/CoreTests/com/android/internal/telephony/gsm/SimUtilsTest.java
+++ b/tests/CoreTests/com/android/internal/telephony/SimUtilsTest.java
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.internal.telephony.gsm;
+package com.android.internal.telephony;
 
 import com.android.internal.telephony.gsm.SimTlv;
-import com.android.internal.telephony.gsm.SimUtils;
+import com.android.internal.telephony.IccUtils;
 import junit.framework.TestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
@@ -33,46 +33,46 @@
          */
 
         // An EF[ICCID] record
-        data = SimUtils.hexStringToBytes("981062400510444868f2");
-        assertEquals("8901260450014484862", SimUtils.bcdToString(data, 0, data.length));
+        data = IccUtils.hexStringToBytes("981062400510444868f2");
+        assertEquals("8901260450014484862", IccUtils.bcdToString(data, 0, data.length));
 
         // skip the first and last bytes
-        assertEquals("0126045001448486", SimUtils.bcdToString(data, 1, data.length - 2));
+        assertEquals("0126045001448486", IccUtils.bcdToString(data, 1, data.length - 2));
 
         // Stops on invalid BCD value
-        data = SimUtils.hexStringToBytes("98F062400510444868f2");
-        assertEquals("890", SimUtils.bcdToString(data, 0, data.length));
+        data = IccUtils.hexStringToBytes("98F062400510444868f2");
+        assertEquals("890", IccUtils.bcdToString(data, 0, data.length));
 
         /*
         * bcdByteToInt()
         */
 
-        assertEquals(98, SimUtils.bcdByteToInt((byte) 0x89));
+        assertEquals(98, IccUtils.bcdByteToInt((byte) 0x89));
 
         // Out of range is treated as 0
-        assertEquals(8, SimUtils.bcdByteToInt((byte) 0x8c));
+        assertEquals(8, IccUtils.bcdByteToInt((byte) 0x8c));
 
         /*
          * adnStringFieldToString()
          */
 
 
-        data = SimUtils.hexStringToBytes("00566f696365204d61696c07918150367742f3ffffffffffff");
+        data = IccUtils.hexStringToBytes("00566f696365204d61696c07918150367742f3ffffffffffff");
         // Again, skip prepended 0
         // (this is an EF[ADN] record)
-        assertEquals("Voice Mail", SimUtils.adnStringFieldToString(data, 1, data.length - 15));
+        assertEquals("Voice Mail", IccUtils.adnStringFieldToString(data, 1, data.length - 15));
 
-        data = SimUtils.hexStringToBytes("809673539A5764002F004DFFFFFFFFFF");
+        data = IccUtils.hexStringToBytes("809673539A5764002F004DFFFFFFFFFF");
         // (this is from an EF[ADN] record)
-        assertEquals("\u9673\u539A\u5764/M", SimUtils.adnStringFieldToString(data, 0, data.length));
+        assertEquals("\u9673\u539A\u5764/M", IccUtils.adnStringFieldToString(data, 0, data.length));
 
-        data = SimUtils.hexStringToBytes("810A01566fec6365204de0696cFFFFFF");
+        data = IccUtils.hexStringToBytes("810A01566fec6365204de0696cFFFFFF");
         // (this is made up to test since I don't have a real one)
-        assertEquals("Vo\u00ECce M\u00E0il", SimUtils.adnStringFieldToString(data, 0, data.length));
+        assertEquals("Vo\u00ECce M\u00E0il", IccUtils.adnStringFieldToString(data, 0, data.length));
 
-        data = SimUtils.hexStringToBytes("820505302D82d32d31");
+        data = IccUtils.hexStringToBytes("820505302D82d32d31");
         // Example from 3GPP TS 11.11 V18.1.3.0 annex B
-        assertEquals("-\u0532\u0583-1", SimUtils.adnStringFieldToString(data, 0, data.length));
+        assertEquals("-\u0532\u0583-1", IccUtils.adnStringFieldToString(data, 0, data.length));
     }
 
 }
diff --git a/tests/CoreTests/com/android/internal/telephony/TelephonyTests.java b/tests/CoreTests/com/android/internal/telephony/TelephonyTests.java
index eb2bd23..b4fb324 100644
--- a/tests/CoreTests/com/android/internal/telephony/TelephonyTests.java
+++ b/tests/CoreTests/com/android/internal/telephony/TelephonyTests.java
@@ -16,13 +16,13 @@
 
 package com.android.internal.telephony;
 
-import com.android.internal.telephony.gsm.AdnRecordTest;
+import com.android.internal.telephony.AdnRecordTest;
 import com.android.internal.telephony.gsm.GSMPhoneTest;
-import com.android.internal.telephony.gsm.GsmAlphabetTest;
-import com.android.internal.telephony.gsm.SMSDispatcherTest;
-import com.android.internal.telephony.gsm.SimPhoneBookTest;
-import com.android.internal.telephony.gsm.SimSmsTest;
-import com.android.internal.telephony.gsm.SimUtilsTest;
+import com.android.internal.telephony.GsmAlphabetTest;
+import com.android.internal.telephony.SMSDispatcherTest;
+import com.android.internal.telephony.SimPhoneBookTest;
+import com.android.internal.telephony.SimSmsTest;
+import com.android.internal.telephony.SimUtilsTest;
 
 import junit.framework.TestSuite;
 
diff --git a/tests/framework-tests/src/com/android/internal/policy/impl/LockPatternKeyguardViewTest.java b/tests/framework-tests/src/com/android/internal/policy/impl/LockPatternKeyguardViewTest.java
index 0368651..fd05fed 100644
--- a/tests/framework-tests/src/com/android/internal/policy/impl/LockPatternKeyguardViewTest.java
+++ b/tests/framework-tests/src/com/android/internal/policy/impl/LockPatternKeyguardViewTest.java
@@ -17,8 +17,7 @@
 package com.android.internal.policy.impl;
 
 import android.content.Context;
-
-import com.android.internal.telephony.SimCard;
+import com.android.internal.telephony.IccCard;
 import android.test.AndroidTestCase;
 import android.view.View;
 import android.view.KeyEvent;
@@ -39,7 +38,7 @@
 
     private static class MockUpdateMonitor extends KeyguardUpdateMonitor {
 
-        public SimCard.State simState = SimCard.State.READY;
+        public IccCard.State simState = IccCard.State.READY;
         public boolean inPortrait = false;
         public boolean keyboardOpen = false;
 
@@ -48,7 +47,7 @@
         }
 
         @Override
-        public SimCard.State getSimState() {
+        public IccCard.State getSimState() {
             return simState;
         }
 
@@ -339,7 +338,7 @@
 
     public void testMenuDoesntGoToUnlockScreenOnWakeWhenPukLocked() {
         // PUK locked
-        mUpdateMonitor.simState = SimCard.State.PUK_REQUIRED;
+        mUpdateMonitor.simState = IccCard.State.PUK_REQUIRED;
 
         // wake by menu
         mLPKV.wakeWhenReadyTq(KeyEvent.KEYCODE_MENU);