Merge branch 'readonly-p4-donut' into donut
diff --git a/api/current.xml b/api/current.xml
index 26a416d..6704766 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -28346,6 +28346,28 @@
  visibility="public"
 >
 </field>
+<field name="ACTION_POWER_CONNECTED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.intent.action.ACTION_POWER_CONNECTED&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_POWER_DISCONNECTED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.intent.action.ACTION_POWER_DISCONNECTED&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="ACTION_PROVIDER_CHANGED"
  type="java.lang.String"
  transient="false"
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 849a37d..9b1f0f9 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -611,7 +611,7 @@
     private IBinder mToken;
     /*package*/ String mEmbeddedID;
     private Application mApplication;
-    private Intent mIntent;
+    /*package*/ Intent mIntent;
     private ComponentName mComponent;
     /*package*/ ActivityInfo mActivityInfo;
     /*package*/ ActivityThread mMainThread;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index d816193..09862d2 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1689,7 +1689,7 @@
 
                     r.packageInfo = getPackageInfoNoCheck(
                             r.activityInfo.applicationInfo);
-                    handleLaunchActivity(r);
+                    handleLaunchActivity(r, null);
                 } break;
                 case RELAUNCH_ACTIVITY: {
                     ActivityRecord r = (ActivityRecord)msg.obj;
@@ -2109,7 +2109,7 @@
                     + ", comp=" + name
                     + ", token=" + token);
         }
-        return performLaunchActivity(r);
+        return performLaunchActivity(r, null);
     }
 
     public final Activity getActivity(IBinder token) {
@@ -2159,7 +2159,7 @@
         queueOrSendMessage(H.CLEAN_UP_CONTEXT, cci);
     }
 
-    private final Activity performLaunchActivity(ActivityRecord r) {
+    private final Activity performLaunchActivity(ActivityRecord r, Intent customIntent) {
         // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
 
         ActivityInfo aInfo = r.activityInfo;
@@ -2219,6 +2219,9 @@
                         r.lastNonConfigurationInstance, r.lastNonConfigurationChildInstances,
                         config);
                 
+                if (customIntent != null) {
+                    activity.mIntent = customIntent;
+                }
                 r.lastNonConfigurationInstance = null;
                 r.lastNonConfigurationChildInstances = null;
                 activity.mStartedActivity = false;
@@ -2274,14 +2277,14 @@
         return activity;
     }
 
-    private final void handleLaunchActivity(ActivityRecord r) {
+    private final void handleLaunchActivity(ActivityRecord r, Intent customIntent) {
         // If we are getting ready to gc after going to the background, well
         // we are back active so skip it.
         unscheduleGcIdler();
 
         if (localLOGV) Log.v(
             TAG, "Handling launch of " + r);
-        Activity a = performLaunchActivity(r);
+        Activity a = performLaunchActivity(r, customIntent);
 
         if (a != null) {
             handleResumeActivity(r.token, false, r.isForward);
@@ -3243,6 +3246,7 @@
         }
         
         r.activity.mConfigChangeFlags |= configChanges;
+        Intent currentIntent = r.activity.mIntent;
         
         Bundle savedState = null;
         if (!r.paused) {
@@ -3275,7 +3279,7 @@
             r.state = savedState;
         }
         
-        handleLaunchActivity(r);
+        handleLaunchActivity(r, currentIntent);
     }
 
     private final void handleRequestThumbnail(IBinder token) {
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 99cf34c..e82a86c 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -508,6 +508,8 @@
  *     <li> {@link #ACTION_PACKAGE_DATA_CLEARED}
  *     <li> {@link #ACTION_UID_REMOVED}
  *     <li> {@link #ACTION_BATTERY_CHANGED}
+ *     <li> {@link #ACTION_POWER_CONNECTED}
+ *     <li> {@link #ACTION_POWER_DISCONNECTED} 
  * </ul>
  *
  * <h3>Standard Categories</h3>
@@ -1250,6 +1252,24 @@
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_BATTERY_LOW = "android.intent.action.BATTERY_LOW";
     /**
+     * Broadcast Action:  External power has been connected to the device.
+     * This is intended for applications that wish to register specifically to this notification.
+     * Unlike ACTION_BATTERY_CHANGED, applications will be woken for this and so do not have to
+     * stay active to receive this notification.  This action can be used to implement actions
+     * that wait until power is available to trigger.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_POWER_CONNECTED = "android.intent.action.ACTION_POWER_CONNECTED";
+    /**
+     * Broadcast Action:  External power has been removed from the device.
+     * This is intended for applications that wish to register specifically to this notification.
+     * Unlike ACTION_BATTERY_CHANGED, applications will be woken for this and so do not have to
+     * stay active to receive this notification.  This action can be used to implement actions
+     * that wait until power is available to trigger. 
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_POWER_DISCONNECTED = "android.intent.action.ACTION_POWER_DISCONNECTED";    
+    /**
      * Broadcast Action:  Indicates low memory condition on the device
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index ed7c056..1064fb6 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -354,9 +354,10 @@
 
     /**
      * Tells the phone sub-system that the caller wants to
-     * begin using the named feature. The only supported feature at
-     * this time is {@code Phone.FEATURE_ENABLE_MMS}, which allows an application
-     * to specify that it wants to send and/or receive MMS data.
+     * begin using the named feature. The only supported features at
+     * this time are {@code Phone.FEATURE_ENABLE_MMS}, which allows an application
+     * to specify that it wants to send and/or receive MMS data, and
+     * {@code Phone.FEATURE_ENABLE_SUPL}, which is used for Assisted GPS.
      * @param feature the name of the feature to be used
      * @param callingPid the process ID of the process that is issuing this request
      * @param callingUid the user ID of the process that is issuing this request
@@ -376,6 +377,8 @@
         if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
             mLastCallingPid = callingPid;
             return setEnableApn(Phone.APN_TYPE_MMS, true);
+        } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
+            return setEnableApn(Phone.APN_TYPE_SUPL, true);
         } else {
             return -1;
         }
@@ -396,6 +399,8 @@
     public int stopUsingNetworkFeature(String feature, int callingPid, int callingUid) {
         if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
             return setEnableApn(Phone.APN_TYPE_MMS, false);
+        } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
+            return setEnableApn(Phone.APN_TYPE_SUPL, false);
         } else {
             return -1;
         }
diff --git a/core/java/android/net/Proxy.java b/core/java/android/net/Proxy.java
index 9f07c0a..66eefb2 100644
--- a/core/java/android/net/Proxy.java
+++ b/core/java/android/net/Proxy.java
@@ -30,6 +30,9 @@
  */
 final public class Proxy {
 
+    // Set to true to enable extra debugging.
+    static final private boolean DEBUG = false;
+
     static final public String PROXY_CHANGE_ACTION =
         "android.intent.action.PROXY_CHANGE";
 
@@ -49,7 +52,7 @@
         if (host != null) {
             int i = host.indexOf(':');
             if (i == -1) {
-                if (android.util.Config.DEBUG) {
+                if (DEBUG) {
                     Assert.assertTrue(host.length() == 0);
                 }
                 return null;
@@ -73,12 +76,12 @@
         if (host != null) {
             int i = host.indexOf(':');
             if (i == -1) {
-                if (android.util.Config.DEBUG) {
+                if (DEBUG) {
                     Assert.assertTrue(host.length() == 0);
                 }
                 return -1;
             }
-            if (android.util.Config.DEBUG) {
+            if (DEBUG) {
                 Assert.assertTrue(i < host.length());
             }
             return Integer.parseInt(host.substring(i+1));
diff --git a/core/java/android/provider/Gmail.java b/core/java/android/provider/Gmail.java
index cc03968..c4b29ae 100644
--- a/core/java/android/provider/Gmail.java
+++ b/core/java/android/provider/Gmail.java
@@ -38,7 +38,6 @@
 import android.text.TextUtils.SimpleStringSplitter;
 import android.text.style.CharacterStyle;
 import android.text.util.Regex;
-import android.util.Config;
 import android.util.Log;
 
 import java.io.UnsupportedEncodingException;
@@ -61,6 +60,9 @@
  * @hide
  */
 public final class Gmail {
+    // Set to true to enable extra debugging.
+    private static final boolean DEBUG = false;
+
     public static final String GMAIL_AUTH_SERVICE = "mail";
     // These constants come from google3/java/com/google/caribou/backend/MailLabel.java.
     public static final String LABEL_SENT = "^f";
@@ -1195,7 +1197,7 @@
 
         @Override
         public void onChange(boolean selfChange) {
-            if (Config.DEBUG) {
+            if (DEBUG) {
                 Log.d(TAG, "MailCursor is notifying " + mObservers.size() + " observers");
             }
             for (MailCursorObserver o: mObservers) {
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index a6ed922..29dc2ea52 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -24,7 +24,6 @@
 import android.graphics.RectF;
 import android.graphics.Path;
 import com.android.internal.util.ArrayUtils;
-import android.util.Config;
 
 import junit.framework.Assert;
 import android.text.style.*;
@@ -39,6 +38,8 @@
  * For text that will not change, use a {@link StaticLayout}.
  */
 public abstract class Layout {
+    private static final boolean DEBUG = false;
+
     /* package */ static final EmojiFactory EMOJI_FACTORY =
         EmojiFactory.newAvailableInstance();
     /* package */ static final int MIN_EMOJI, MAX_EMOJI;
@@ -330,7 +331,7 @@
             boolean hasTab = getLineContainsTab(i);
             if (directions == DIRS_ALL_LEFT_TO_RIGHT &&
                     !spannedText && !hasTab) {
-                if (Config.DEBUG) {
+                if (DEBUG) {
                     Assert.assertTrue(dir == DIR_LEFT_TO_RIGHT);
                     Assert.assertNotNull(c);
                 }
@@ -797,7 +798,7 @@
     }
     
     private int getLineVisibleEnd(int line, int start, int end) {
-        if (Config.DEBUG) {
+        if (DEBUG) {
             Assert.assertTrue(getLineStart(line) == start && getLineStart(line+1) == end);
         }
 
@@ -1340,7 +1341,7 @@
         char[] buf;
         if (!hasTabs) {
             if (directions == DIRS_ALL_LEFT_TO_RIGHT) {
-                if (Config.DEBUG) {
+                if (DEBUG) {
                     Assert.assertTrue(DIR_LEFT_TO_RIGHT == dir);
                 }
                 Styled.drawText(canvas, text, start, end, dir, false, x, top, y, bottom, paint, workPaint, false);
diff --git a/core/java/android/util/DebugUtils.java b/core/java/android/util/DebugUtils.java
index 1c5d669..56f389c 100644
--- a/core/java/android/util/DebugUtils.java
+++ b/core/java/android/util/DebugUtils.java
@@ -43,8 +43,8 @@
      *
      * <p>This class is useful for debugging and logging purpose:</p>
      * <pre>
-     * if (Config.DEBUG) {
-     *   if (DebugUtils.isObjectSelected(childView) && Config.LOGV) {
+     * if (DEBUG) {
+     *   if (DebugUtils.isObjectSelected(childView) && LOGV_ENABLED) {
      *     Log.v(TAG, "Object " + childView + " logged!");
      *   }
      * }
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 5401a6e..ba3f78c 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -24,7 +24,6 @@
 import android.net.http.SslCertificate;
 import android.os.Handler;
 import android.os.Message;
-import android.util.Config;
 import android.util.Log;
 import android.util.TypedValue;
 
@@ -120,7 +119,7 @@
         mDatabase = WebViewDatabase.getInstance(context);
         mWebViewCore = w;
 
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "BrowserFrame constructor: this=" + this);
         }
     }
@@ -331,7 +330,7 @@
         switch (msg.what) {
             case FRAME_COMPLETED: {
                 if (mSettings.getSavePassword() && hasPasswordField()) {
-                    if (Config.DEBUG) {
+                    if (WebView.DEBUG) {
                         Assert.assertNotNull(mCallbackProxy.getBackForwardList()
                                 .getCurrentItem());
                     }
@@ -480,7 +479,7 @@
             }
             if (mSettings.getSavePassword() && hasPasswordField()) {
                 try {
-                    if (Config.DEBUG) {
+                    if (WebView.DEBUG) {
                         Assert.assertNotNull(mCallbackProxy.getBackForwardList()
                                 .getCurrentItem());
                     }
@@ -528,7 +527,7 @@
         // is this resource the main-frame top-level page?
         boolean isMainFramePage = mIsMainFrame;
 
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "startLoadingResource: url=" + url + ", method="
                     + method + ", postData=" + postData + ", isHighPriority="
                     + isHighPriority + ", isMainFramePage=" + isMainFramePage);
diff --git a/core/java/android/webkit/CacheManager.java b/core/java/android/webkit/CacheManager.java
index 4528b73..7897435 100644
--- a/core/java/android/webkit/CacheManager.java
+++ b/core/java/android/webkit/CacheManager.java
@@ -19,7 +19,6 @@
 import android.content.Context;
 import android.net.http.Headers;
 import android.os.FileUtils;
-import android.util.Config;
 import android.util.Log;
 import java.io.File;
 import java.io.FileInputStream;
@@ -322,7 +321,7 @@
             }
         }
 
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "getCacheFile for url " + url);
         }
 
@@ -416,7 +415,7 @@
 
         mDataBase.addCache(url, cacheRet);
 
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "saveCacheFile for url " + url);
         }
     }
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index 0f9f29c..5f8acc8 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -30,7 +30,6 @@
 import android.os.Message;
 import android.os.SystemClock;
 import android.provider.Browser;
-import android.util.Config;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
@@ -822,7 +821,7 @@
             String password, Message resumeMsg) {
         // resumeMsg should be null at this point because we want to create it
         // within the CallbackProxy.
-        if (Config.DEBUG) {
+        if (WebView.DEBUG) {
             junit.framework.Assert.assertNull(resumeMsg);
         }
         resumeMsg = obtainMessage(NOTIFY);
diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java
index d90a2fd..c0c6775 100644
--- a/core/java/android/webkit/CookieManager.java
+++ b/core/java/android/webkit/CookieManager.java
@@ -18,7 +18,6 @@
 
 import android.net.ParseException;
 import android.net.WebAddress;
-import android.util.Config;
 import android.util.Log;
 
 import java.util.ArrayList;
@@ -263,7 +262,7 @@
         if (!mAcceptCookie || uri == null) {
             return;
         }
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "setCookie: uri: " + uri + " value: " + value);
         }
 
@@ -428,12 +427,12 @@
             }
         }
         if (ret.length() > 0) {
-            if (Config.LOGV) {
+            if (WebView.LOGV_ENABLED) {
                 Log.v(LOGTAG, "getCookie: uri: " + uri + " value: " + ret);
             }
             return ret.toString();
         } else {
-            if (Config.LOGV) {
+            if (WebView.LOGV_ENABLED) {
                 Log.v(LOGTAG, "getCookie: uri: " + uri
                         + " But can't find cookie.");
             }
@@ -589,7 +588,7 @@
             Iterator<ArrayList<Cookie>> listIter = cookieLists.iterator();
             while (listIter.hasNext() && count < MAX_RAM_COOKIES_COUNT) {
                 ArrayList<Cookie> list = listIter.next();
-                if (Config.DEBUG) {
+                if (WebView.DEBUG) {
                     Iterator<Cookie> iter = list.iterator();
                     while (iter.hasNext() && count < MAX_RAM_COOKIES_COUNT) {
                         Cookie cookie = iter.next();
@@ -609,7 +608,7 @@
 
         ArrayList<Cookie> retlist = new ArrayList<Cookie>();
         if (mapSize >= MAX_RAM_DOMAIN_COUNT || count >= MAX_RAM_COOKIES_COUNT) {
-            if (Config.DEBUG) {
+            if (WebView.DEBUG) {
                 Log.v(LOGTAG, count + " cookies used " + byteCount
                         + " bytes with " + mapSize + " domains");
             }
@@ -617,7 +616,7 @@
             int toGo = mapSize / 10 + 1;
             while (toGo-- > 0){
                 String domain = domains[toGo].toString();
-                if (Config.LOGV) {
+                if (WebView.LOGV_ENABLED) {
                     Log.v(LOGTAG, "delete domain: " + domain
                             + " from RAM cache");
                 }
diff --git a/core/java/android/webkit/CookieSyncManager.java b/core/java/android/webkit/CookieSyncManager.java
index f2511d8..8d66529 100644
--- a/core/java/android/webkit/CookieSyncManager.java
+++ b/core/java/android/webkit/CookieSyncManager.java
@@ -17,7 +17,6 @@
 package android.webkit;
 
 import android.content.Context;
-import android.util.Config;
 import android.util.Log;
 import android.webkit.CookieManager.Cookie;
 
@@ -162,7 +161,7 @@
     }
 
     protected void syncFromRamToFlash() {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "CookieSyncManager::syncFromRamToFlash STARTS");
         }
 
@@ -179,7 +178,7 @@
                 CookieManager.getInstance().deleteLRUDomain();
         syncFromRamToFlash(lruList);
 
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "CookieSyncManager::syncFromRamToFlash DONE");
         }
     }
diff --git a/core/java/android/webkit/FrameLoader.java b/core/java/android/webkit/FrameLoader.java
index 42d03f0..6f1b160 100644
--- a/core/java/android/webkit/FrameLoader.java
+++ b/core/java/android/webkit/FrameLoader.java
@@ -18,7 +18,6 @@
 
 import android.net.http.EventHandler;
 import android.net.http.RequestHandle;
-import android.util.Config;
 import android.util.Log;
 import android.webkit.CacheManager.CacheResult;
 
@@ -121,7 +120,7 @@
         } else if (handleLocalFile(url, mListener, mSettings)) {
             return true;
         }
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "FrameLoader.executeLoad: url protocol not supported:"
                     + mListener.url());
         }
@@ -181,7 +180,7 @@
             return true;
         }
 
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "FrameLoader: http " + mMethod + " load for: "
                     + mListener.url());
         }
@@ -212,7 +211,7 @@
      * setup a load from the byte stream in a CacheResult.
      */
     private void startCacheLoad(CacheResult result) {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "FrameLoader: loading from cache: "
                   + mListener.url());
         }
@@ -286,7 +285,7 @@
             // of it's state. If it is not in the cache, then go to the 
             // network.
             case WebSettings.LOAD_CACHE_ELSE_NETWORK: {
-                if (Config.LOGV) {
+                if (WebView.LOGV_ENABLED) {
                     Log.v(LOGTAG, "FrameLoader: checking cache: "
                             + mListener.url());
                 }
diff --git a/core/java/android/webkit/JWebCoreJavaBridge.java b/core/java/android/webkit/JWebCoreJavaBridge.java
index a0049ac..2a84683 100644
--- a/core/java/android/webkit/JWebCoreJavaBridge.java
+++ b/core/java/android/webkit/JWebCoreJavaBridge.java
@@ -18,7 +18,6 @@
 
 import android.os.Handler;
 import android.os.Message;
-import android.util.Config;
 import android.util.Log;
 
 final class JWebCoreJavaBridge extends Handler {
@@ -156,7 +155,7 @@
      * @param timemillis The relative time when the timer should fire
      */
     private void setSharedTimer(long timemillis) {
-        if (Config.LOGV) Log.v(LOGTAG, "setSharedTimer " + timemillis);
+        if (WebView.LOGV_ENABLED) Log.v(LOGTAG, "setSharedTimer " + timemillis);
 
         if (timemillis <= 0) {
             // we don't accumulate the sharedTimer unless it is a delayed
@@ -180,7 +179,7 @@
      * Stop the shared timer.
      */
     private void stopSharedTimer() {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "stopSharedTimer removing all timers");
         }
         removeMessages(TIMER_MESSAGE);
diff --git a/core/java/android/webkit/LoadListener.java b/core/java/android/webkit/LoadListener.java
index c64200cd..d583eb1 100644
--- a/core/java/android/webkit/LoadListener.java
+++ b/core/java/android/webkit/LoadListener.java
@@ -29,7 +29,6 @@
 
 import android.os.Handler;
 import android.os.Message;
-import android.util.Config;
 import android.util.Log;
 import android.webkit.CacheManager.CacheResult;
 
@@ -134,7 +133,7 @@
 
     LoadListener(Context context, BrowserFrame frame, String url,
             int nativeLoader, boolean synchronous, boolean isMainPageLoader) {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "LoadListener constructor url=" + url);
         }
         mContext = context;
@@ -285,7 +284,7 @@
      * directly
      */
     public void headers(Headers headers) {
-        if (Config.LOGV) Log.v(LOGTAG, "LoadListener.headers");
+        if (WebView.LOGV_ENABLED) Log.v(LOGTAG, "LoadListener.headers");
         sendMessageInternal(obtainMessage(MSG_CONTENT_HEADERS, headers));
     }
 
@@ -432,7 +431,7 @@
      */
     public void status(int majorVersion, int minorVersion,
             int code, /* Status-Code value */ String reasonPhrase) {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "LoadListener: from: " + mUrl
                     + " major: " + majorVersion
                     + " minor: " + minorVersion
@@ -489,7 +488,7 @@
      * directly
      */
     public void error(int id, String description) {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "LoadListener.error url:" +
                     url() + " id:" + id + " description:" + description);
         }
@@ -517,7 +516,7 @@
      * mDataBuilder is a thread-safe structure.
      */
     public void data(byte[] data, int length) {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "LoadListener.data(): url: " + url());
         }
 
@@ -555,7 +554,7 @@
      * directly
      */
     public void endData() {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "LoadListener.endData(): url: " + url());
         }
         sendMessageInternal(obtainMessage(MSG_CONTENT_FINISHED));
@@ -608,7 +607,7 @@
                 // before calling it.
                 if (mCacheLoader != null) {
                     mCacheLoader.load();
-                    if (Config.LOGV) {
+                    if (WebView.LOGV_ENABLED) {
                         Log.v(LOGTAG, "LoadListener cache load url=" + url());
                     }
                     return;
@@ -658,7 +657,7 @@
                     CacheManager.HEADER_KEY_IFNONEMATCH) &&
                     !headers.containsKey(
                             CacheManager.HEADER_KEY_IFMODIFIEDSINCE)) {
-                if (Config.LOGV) {
+                if (WebView.LOGV_ENABLED) {
                     Log.v(LOGTAG, "FrameLoader: HTTP URL in cache " +
                             "and usable: " + url());
                 }
@@ -677,7 +676,7 @@
      * directly
      */
     public void handleSslErrorRequest(SslError error) {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG,
                     "LoadListener.handleSslErrorRequest(): url:" + url() +
                     " primary error: " + error.getPrimaryError() +
@@ -743,7 +742,7 @@
      * are null, cancel the request.
      */
     void handleAuthResponse(String username, String password) {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "LoadListener.handleAuthResponse: url: " + mUrl
                     + " username: " + username
                     + " password: " + password);
@@ -840,7 +839,7 @@
     }
 
     void attachRequestHandle(RequestHandle requestHandle) {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "LoadListener.attachRequestHandle(): " +
                     "requestHandle: " +  requestHandle);
         }
@@ -848,7 +847,7 @@
     }
 
     void detachRequestHandle() {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "LoadListener.detachRequestHandle(): " +
                     "requestHandle: " + mRequestHandle);
         }
@@ -887,7 +886,7 @@
      */
     static boolean willLoadFromCache(String url) {
         boolean inCache = CacheManager.getCacheFile(url, null) != null;
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "willLoadFromCache: " + url + " in cache: " + 
                     inCache);
         }
@@ -1057,7 +1056,7 @@
      * EventHandler's method call.
      */
     public void cancel() {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             if (mRequestHandle == null) {
                 Log.v(LOGTAG, "LoadListener.cancel(): no requestHandle");
             } else {
@@ -1189,7 +1188,7 @@
             tearDown();
         }
 
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "LoadListener.onRedirect(): redirect to: " +
                     redirectTo);
         }
@@ -1203,7 +1202,7 @@
             Pattern.compile("^((?:[xX]-)?[a-zA-Z\\*]+/[\\w\\+\\*-]+[\\.[\\w\\+-]+]*)$");
 
     private void parseContentTypeHeader(String contentType) {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "LoadListener.parseContentTypeHeader: " +
                     "contentType: " + contentType);
         }
@@ -1390,7 +1389,7 @@
      */
     private String guessMimeTypeFromExtension() {
         // PENDING: need to normalize url
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "guessMimeTypeFromExtension: mURL = " + mUrl);
         }
 
@@ -1425,7 +1424,7 @@
      * Cycle through our messages for synchronous loads.
      */
     /* package */ void loadSynchronousMessages() {
-        if (Config.DEBUG && !mSynchronous) {
+        if (WebView.DEBUG && !mSynchronous) {
             throw new AssertionError();
         }
         // Note: this can be called twice if it is a synchronous network load,
diff --git a/core/java/android/webkit/Network.java b/core/java/android/webkit/Network.java
index 6fa0775..c9b80ce 100644
--- a/core/java/android/webkit/Network.java
+++ b/core/java/android/webkit/Network.java
@@ -20,7 +20,6 @@
 import android.net.http.*;
 import android.os.*;
 import android.util.Log;
-import android.util.Config;
 
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
@@ -133,7 +132,7 @@
      * XXX: Must be created in the same thread as WebCore!!!!!
      */
     private Network(Context context) {
-        if (Config.DEBUG) {
+        if (WebView.DEBUG) {
             Assert.assertTrue(Thread.currentThread().
                     getName().equals(WebViewCore.THREAD_NAME));
         }
@@ -233,7 +232,7 @@
      * connecting through the proxy.
      */
     public synchronized void setProxyUsername(String proxyUsername) {
-        if (Config.DEBUG) {
+        if (WebView.DEBUG) {
             Assert.assertTrue(isValidProxySet());
         }
 
@@ -253,7 +252,7 @@
      * connecting through the proxy.
      */
     public synchronized void setProxyPassword(String proxyPassword) {
-        if (Config.DEBUG) {
+        if (WebView.DEBUG) {
             Assert.assertTrue(isValidProxySet());
         }
 
@@ -267,7 +266,7 @@
      * @return True iff succeeds.
      */
     public boolean saveState(Bundle outState) {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "Network.saveState()");
         }
 
@@ -281,7 +280,7 @@
      * @return True iff succeeds.
      */
     public boolean restoreState(Bundle inState) {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "Network.restoreState()");
         }
 
@@ -301,7 +300,7 @@
      * @param loader The loader that resulted in SSL errors.
      */
     public void handleSslErrorRequest(LoadListener loader) {
-        if (Config.DEBUG) Assert.assertNotNull(loader);
+        if (WebView.DEBUG) Assert.assertNotNull(loader);
         if (loader != null) {
             mSslErrorHandler.handleSslErrorRequest(loader);
         }
@@ -314,7 +313,7 @@
      * authentication request.
      */
     public void handleAuthRequest(LoadListener loader) {
-        if (Config.DEBUG) Assert.assertNotNull(loader);
+        if (WebView.DEBUG) Assert.assertNotNull(loader);
         if (loader != null) {
             mHttpAuthHandler.handleAuthRequest(loader);
         }
diff --git a/core/java/android/webkit/SslErrorHandler.java b/core/java/android/webkit/SslErrorHandler.java
index 2e2fa12..5f84bbe 100644
--- a/core/java/android/webkit/SslErrorHandler.java
+++ b/core/java/android/webkit/SslErrorHandler.java
@@ -22,7 +22,6 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
-import android.util.Config;
 import android.util.Log;
 
 import java.util.LinkedList;
@@ -121,7 +120,7 @@
      * Handles SSL error(s) on the way up to the user.
      */
     /* package */ synchronized void handleSslErrorRequest(LoadListener loader) {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "SslErrorHandler.handleSslErrorRequest(): " +
                   "url=" + loader.url());
         }
@@ -158,14 +157,14 @@
 
             SslError error = loader.sslError();
 
-            if (Config.DEBUG) {
+            if (WebView.DEBUG) {
                 Assert.assertNotNull(error);
             }
 
             int primary = error.getPrimaryError();
             String host = loader.host();
 
-            if (Config.DEBUG) {
+            if (WebView.DEBUG) {
                 Assert.assertTrue(host != null && primary != 0);
             }
 
@@ -206,11 +205,11 @@
      */
     /* package */ synchronized void handleSslErrorResponse(boolean proceed) {
         LoadListener loader = mLoaderQueue.poll();
-        if (Config.DEBUG) {
+        if (WebView.DEBUG) {
             Assert.assertNotNull(loader);
         }
 
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "SslErrorHandler.handleSslErrorResponse():"
                   + " proceed: " + proceed
                   + " url:" + loader.url());
@@ -222,7 +221,7 @@
                 int primary = loader.sslError().getPrimaryError();
                 String host = loader.host();
 
-                if (Config.DEBUG) {
+                if (WebView.DEBUG) {
                     Assert.assertTrue(host != null && primary != 0);
                 }
                 boolean hasKey = mSslPrefTable.containsKey(host);
diff --git a/core/java/android/webkit/StreamLoader.java b/core/java/android/webkit/StreamLoader.java
index 9098307..705157c 100644
--- a/core/java/android/webkit/StreamLoader.java
+++ b/core/java/android/webkit/StreamLoader.java
@@ -20,7 +20,6 @@
 import android.net.http.Headers;
 import android.os.Handler;
 import android.os.Message;
-import android.util.Config;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -114,7 +113,7 @@
      * @see android.os.Handler#handleMessage(android.os.Message)
      */
     public void handleMessage(Message msg) {
-        if (Config.DEBUG && mHandler.isSynchronous()) {
+        if (WebView.DEBUG && mHandler.isSynchronous()) {
             throw new AssertionError();
         }
         switch(msg.what) {
diff --git a/core/java/android/webkit/URLUtil.java b/core/java/android/webkit/URLUtil.java
index 0e8144e..d6ac3e9 100644
--- a/core/java/android/webkit/URLUtil.java
+++ b/core/java/android/webkit/URLUtil.java
@@ -23,7 +23,6 @@
 import android.net.Uri;
 import android.net.ParseException;
 import android.net.WebAddress;
-import android.util.Config;
 import android.util.Log;
 
 public final class URLUtil {
@@ -62,7 +61,7 @@
             webAddress = new WebAddress(inUrl);
         } catch (ParseException ex) {
 
-            if (Config.LOGV) {
+            if (WebView.LOGV_ENABLED) {
                 Log.v(LOGTAG, "smartUrlFilter: failed to parse url = " + inUrl);
             }
             return retVal;
diff --git a/core/java/android/webkit/WebBackForwardList.java b/core/java/android/webkit/WebBackForwardList.java
index 9dea5ec..ffd6a11 100644
--- a/core/java/android/webkit/WebBackForwardList.java
+++ b/core/java/android/webkit/WebBackForwardList.java
@@ -16,7 +16,6 @@
 
 package android.webkit;
 
-import android.util.Config;
 import java.io.Serializable;
 import java.util.ArrayList;
 
@@ -138,7 +137,7 @@
         // when removing the first item, we can assert that the index is 0.
         // This lets us change the current index without having to query the
         // native BackForwardList.
-        if (Config.DEBUG && (index != 0)) {
+        if (WebView.DEBUG && (index != 0)) {
             throw new AssertionError();
         }
         final WebHistoryItem h = mArray.remove(index);
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 025e6bb..105eacd 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -1097,7 +1097,7 @@
     /*package*/
     synchronized void syncSettingsAndCreateHandler(BrowserFrame frame) {
         mBrowserFrame = frame;
-        if (android.util.Config.DEBUG) {
+        if (WebView.DEBUG) {
             junit.framework.Assert.assertTrue(frame.mNativeFrame != 0);
         }
         nativeSync(frame.mNativeFrame);
diff --git a/core/java/android/webkit/WebSyncManager.java b/core/java/android/webkit/WebSyncManager.java
index e6e9994..ded17ed 100644
--- a/core/java/android/webkit/WebSyncManager.java
+++ b/core/java/android/webkit/WebSyncManager.java
@@ -21,7 +21,6 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.Process;
-import android.util.Config;
 import android.util.Log;
 
 abstract class WebSyncManager implements Runnable {
@@ -48,7 +47,7 @@
         @Override
         public void handleMessage(Message msg) {
             if (msg.what == SYNC_MESSAGE) {
-                if (Config.LOGV) {
+                if (WebView.LOGV_ENABLED) {
                     Log.v(LOGTAG, "*** WebSyncManager sync ***");
                 }
                 syncFromRamToFlash();
@@ -95,7 +94,7 @@
      * sync() forces sync manager to sync now
      */
     public void sync() {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "*** WebSyncManager sync ***");
         }
         if (mHandler == null) {
@@ -110,7 +109,7 @@
      * resetSync() resets sync manager's timer
      */
     public void resetSync() {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "*** WebSyncManager resetSync ***");
         }
         if (mHandler == null) {
@@ -125,7 +124,7 @@
      * startSync() requests sync manager to start sync
      */
     public void startSync() {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "***  WebSyncManager startSync ***, Ref count:" + 
                     mStartSyncRefCount);
         }
@@ -143,7 +142,7 @@
      * the queue to break the sync loop
      */
     public void stopSync() {
-        if (Config.LOGV) {
+        if (WebView.LOGV_ENABLED) {
             Log.v(LOGTAG, "*** WebSyncManager stopSync ***, Ref count:" + 
                     mStartSyncRefCount);
         }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index a5846ed..a926355 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -42,7 +42,6 @@
 import android.text.Selection;
 import android.text.Spannable;
 import android.util.AttributeSet;
-import android.util.Config;
 import android.util.EventLog;
 import android.util.Log;
 import android.view.Gravity;
@@ -110,7 +109,7 @@
     // keep debugging parameters near the top of the file
     static final String LOGTAG = "webview";
     static final boolean DEBUG = false;
-    static final boolean LOGV_ENABLED = DEBUG ? Config.LOGD : Config.LOGV;
+    static final boolean LOGV_ENABLED = DEBUG;
 
     private class ExtendedZoomControls extends FrameLayout {
         public ExtendedZoomControls(Context context, AttributeSet attrs) {
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 72b30f6..58d8ae7 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -29,7 +29,6 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.Process;
-import android.util.Config;
 import android.util.Log;
 import android.util.SparseBooleanArray;
 import android.view.KeyEvent;
@@ -43,7 +42,7 @@
 
     private static final String LOGTAG = "webcore";
     static final boolean DEBUG = false;
-    static final boolean LOGV_ENABLED = DEBUG ? Config.LOGD : Config.LOGV;
+    static final boolean LOGV_ENABLED = DEBUG;
 
     static {
         // Load libwebcore during static initialization. This happens in the
diff --git a/core/java/android/webkit/gears/AndroidWifiDataProvider.java b/core/java/android/webkit/gears/AndroidWifiDataProvider.java
index 7379f59..d2850b06 100644
--- a/core/java/android/webkit/gears/AndroidWifiDataProvider.java
+++ b/core/java/android/webkit/gears/AndroidWifiDataProvider.java
@@ -33,7 +33,6 @@
 import android.net.wifi.WifiManager;
 import android.os.Handler;
 import android.os.Looper;
-import android.util.Config;
 import android.util.Log;
 import android.webkit.WebView;
 import java.util.List;
@@ -48,6 +47,11 @@
    */
   private static final String TAG = "Gears-J-WifiProvider";
   /**
+   * Flag for guarding Log.v() calls.
+   * Set to true to enable extra debug logging.
+   */
+  private static final boolean LOGV_ENABLED = false;
+  /**
    * Our Wifi manager instance.
    */
   private WifiManager mWifiManager;
@@ -104,7 +108,7 @@
    */
   public void shutdown() {
     mContext.unregisterReceiver(this);
-    if (Config.LOGV) {
+    if (LOGV_ENABLED) {
       Log.v(TAG, "Wifi provider closed.");
     }
   }
@@ -118,7 +122,7 @@
   public void onReceive(Context context, Intent intent) {
     if (intent.getAction().equals(
             mWifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
-      if (Config.LOGV) {
+      if (LOGV_ENABLED) {
         Log.v(TAG, "Wifi scan resulst available");
       }
       onUpdateAvailable(mWifiManager.getScanResults(), mNativeObject);
diff --git a/core/java/android/webkit/gears/ApacheHttpRequestAndroid.java b/core/java/android/webkit/gears/ApacheHttpRequestAndroid.java
index 529e666..74d27ed 100644
--- a/core/java/android/webkit/gears/ApacheHttpRequestAndroid.java
+++ b/core/java/android/webkit/gears/ApacheHttpRequestAndroid.java
@@ -29,7 +29,6 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.util.Config;
 import android.util.Log;
 import android.webkit.CacheManager;
 import android.webkit.CacheManager.CacheResult;
@@ -88,6 +87,8 @@
 public final class ApacheHttpRequestAndroid {
     /** Debug logging tag. */
     private static final String LOG_TAG = "Gears-J";
+    /** Flag for guarding Log.v() calls. */
+    private static final boolean LOGV_ENABLED = false;
     /** HTTP response header line endings are CR-LF style. */
     private static final String HTTP_LINE_ENDING = "\r\n";
     /** Safe MIME type to use whenever it isn't specified. */
@@ -173,18 +174,18 @@
         public void run() {
             boolean problem = false;
             try {
-                if (Config.LOGV) {
+                if (LOGV_ENABLED) {
                     Log.i(LOG_TAG, "REQUEST : " + mMethod.getRequestLine());
                 }
                 mResponse = mClient.execute(mMethod);
                 if (mResponse != null) {
-                    if (Config.LOGV) {
+                    if (LOGV_ENABLED) {
                         Log.i(LOG_TAG, "response (status line): "
                               + mResponse.getStatusLine());
                     }
                     mResponseLine = "" + mResponse.getStatusLine();
                 } else {
-                    if (Config.LOGV) {
+                    if (LOGV_ENABLED) {
                         Log.i(LOG_TAG, "problem, response == null");
                     }
                     problem = true;
@@ -198,7 +199,7 @@
             }
 
             if (!problem) {
-                if (Config.LOGV) {
+                if (LOGV_ENABLED) {
                     Log.i(LOG_TAG, "Request complete ("
                           + mMethod.getRequestLine() + ")");
                 }
@@ -206,7 +207,7 @@
                 mConnectionFailedLock.lock();
                 mConnectionFailed = true;
                 mConnectionFailedLock.unlock();
-                if (Config.LOGV) {
+                if (LOGV_ENABLED) {
                     Log.i(LOG_TAG, "Request FAILED ("
                           + mMethod.getRequestLine() + ")");
                 }
@@ -233,7 +234,7 @@
                 try {
                     wait();
                 } catch (InterruptedException e) {
-                    if (Config.LOGV) {
+                    if (LOGV_ENABLED) {
                         Log.i(LOG_TAG, "InterruptedException while putting " +
                             "a DataPacket in the Buffer: " + e);
                     }
@@ -248,7 +249,7 @@
                 try {
                     wait();
                 } catch (InterruptedException e) {
-                    if (Config.LOGV) {
+                    if (LOGV_ENABLED) {
                       Log.i(LOG_TAG, "InterruptedException while getting " +
                           "a DataPacket in the Buffer: " + e);
                     }
@@ -271,7 +272,7 @@
                 try {
                     wait();
                 } catch (InterruptedException e) {
-                    if (Config.LOGV) {
+                    if (LOGV_ENABLED) {
                         Log.i(LOG_TAG, "InterruptedException while waiting " +
                             "until a DataPacket is consumed: " + e);
                     }
@@ -285,7 +286,7 @@
                 try {
                     wait();
                 } catch (InterruptedException e) {
-                    if (Config.LOGV) {
+                    if (LOGV_ENABLED) {
                         Log.i(LOG_TAG, "InterruptedException while indicating "
                               + "that the DataPacket has been consumed: " + e);
                     }
@@ -373,14 +374,14 @@
                 mSignal.packetConsumed();
                 mConnectionFailedLock.lock();
                 if (mConnectionFailed) {
-                    if (Config.LOGV) {
+                    if (LOGV_ENABLED) {
                         Log.i(LOG_TAG, "stopping loop on error");
                     }
                     finished = true;
                 }
                 mConnectionFailedLock.unlock();
             }
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "flushing the outputstream...");
             }
             mOutputStream.flush();
@@ -399,7 +400,7 @@
         private void write(DataPacket packet) {
             try {
                 if (mOutputStream == null) {
-                    if (Config.LOGV) {
+                    if (LOGV_ENABLED) {
                         Log.i(LOG_TAG, "NO OUTPUT STREAM !!!");
                     }
                     return;
@@ -407,7 +408,7 @@
                 mOutputStream.write(packet.getBytes(), 0, packet.getLength());
                 mOutputStream.flush();
             } catch (IOException e) {
-                if (Config.LOGV) {
+                if (LOGV_ENABLED) {
                     Log.i(LOG_TAG, "exc: " + e);
                 }
                 mConnectionFailedLock.lock();
@@ -423,7 +424,7 @@
                     mStreamingReady.await();
                 }
             } catch (InterruptedException e) {
-                if (Config.LOGV) {
+                if (LOGV_ENABLED) {
                     Log.i(LOG_TAG, "InterruptedException in "
                           + "StreamEntity::isReady() : ", e);
                 }
@@ -468,7 +469,7 @@
      *                  False on failure.
      */
     public synchronized boolean open(String method, String url) {
-        if (Config.LOGV) {
+        if (LOGV_ENABLED) {
             Log.i(LOG_TAG, "open " + method + " " + url);
         }
         // Create the client
@@ -502,7 +503,7 @@
         } else if ("DELETE".equalsIgnoreCase(method)) {
             mMethod = new HttpDelete(url);
         } else {
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "Method " + method + " not supported");
             }
             return false;
@@ -549,7 +550,7 @@
      * (unless already finished)
      */
     private void waitUntilConnectionFinished() {
-        if (Config.LOGV) {
+        if (LOGV_ENABLED) {
             Log.i(LOG_TAG, "waitUntilConnectionFinished("
                   + mConnectionFinished + ")");
         }
@@ -558,11 +559,11 @@
                 try {
                     mHttpThread.join();
                     mConnectionFinished = true;
-                    if (Config.LOGV) {
+                    if (LOGV_ENABLED) {
                         Log.i(LOG_TAG, "http thread joined");
                     }
                 } catch (InterruptedException e) {
-                    if (Config.LOGV) {
+                    if (LOGV_ENABLED) {
                         Log.i(LOG_TAG, "interrupted: " + e);
                     }
                 }
@@ -596,7 +597,7 @@
         Header[] headers = mResponse.getAllHeaders();
         for (int i = 0; i < headers.length; i++) {
             Header header = headers[i];
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "header " + header.getName()
                       + " -> " + header.getValue());
             }
@@ -615,7 +616,7 @@
      */
     public synchronized void setRequestHeader(String name, String value) {
         String[] mapValue = { name, value };
-        if (Config.LOGV) {
+        if (LOGV_ENABLED) {
             Log.i(LOG_TAG, "setRequestHeader: " + name + " => " + value);
         }
         if (name.equalsIgnoreCase(KEY_CONTENT_LENGTH)) {
@@ -647,7 +648,7 @@
         while (it.hasNext()) {
             // Set the key case-sensitive.
             String[] entry = it.next();
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "apply header " + entry[HEADERS_MAP_INDEX_KEY] +
                     " => " + entry[HEADERS_MAP_INDEX_VALUE]);
             }
@@ -671,7 +672,7 @@
                 return null;
             }
         } else {
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "getResponseHeader() called but "
                       + "response not received");
             }
@@ -687,7 +688,7 @@
      */
     public synchronized String getAllResponseHeaders() {
         if (mResponseHeaders == null) {
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "getAllResponseHeaders() called but "
                       + "response not received");
             }
@@ -715,7 +716,7 @@
      * @param value The associated value.
      */
     private void setResponseHeader(String name, String value) {
-        if (Config.LOGV) {
+        if (LOGV_ENABLED) {
             Log.i(LOG_TAG, "Set response header " + name + ": " + value);
         }
         String mapValue[] = { name, value };
@@ -766,7 +767,7 @@
         UrlInterceptHandlerGears.ServiceResponse serviceResponse =
             handler.getServiceResponse(url, mRequestHeaders);
         if (serviceResponse == null) {
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "No response in LocalServer");
             }
             return false;
@@ -776,7 +777,7 @@
         mBodyInputStream = serviceResponse.getInputStream();
         mResponseLine = serviceResponse.getStatusLine();
         mResponseHeaders = serviceResponse.getResponseHeaders();
-        if (Config.LOGV) {
+        if (LOGV_ENABLED) {
             Log.i(LOG_TAG, "Got response from LocalServer: " + mResponseLine);
         }
         return true;
@@ -803,19 +804,19 @@
         CacheResult mCacheResult =
             CacheManager.getCacheFile(url, cacheRequestHeaders);
         if (mCacheResult == null) {
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "No CacheResult for " + url);
             }
             return false;
         }
-        if (Config.LOGV) {
+        if (LOGV_ENABLED) {
             Log.i(LOG_TAG, "Got CacheResult from browser cache");
         }
         // Check for expiry. -1 is "never", otherwise milliseconds since 1970.
         // Can be compared to System.currentTimeMillis().
         long expires = mCacheResult.getExpires();
         if (expires >= 0 && System.currentTimeMillis() >= expires) {
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "CacheResult expired "
                     + (System.currentTimeMillis() - expires)
                     + " milliseconds ago");
@@ -827,7 +828,7 @@
         mBodyInputStream = mCacheResult.getInputStream();
         if (mBodyInputStream == null) {
             // Cache result may have gone away.
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "No mBodyInputStream for CacheResult " + url);
             }
             return false;
@@ -855,7 +856,7 @@
         }
         // Synthesize the response line.
         mResponseLine = "HTTP/1.1 " + statusCode + " " + statusMessage;
-        if (Config.LOGV) {
+        if (LOGV_ENABLED) {
             Log.i(LOG_TAG, "Synthesized " + mResponseLine);
         }
         // Synthesize the returned headers from cache.
@@ -914,7 +915,7 @@
      */
     public synchronized boolean createCacheResult(
         String url, int responseCode, String mimeType, String encoding) {
-        if (Config.LOGV) {
+        if (LOGV_ENABLED) {
             Log.i(LOG_TAG, "Making cache entry for " + url);
         }
         // Take the headers and parse them into a format needed by
@@ -935,14 +936,14 @@
         mCacheResult = CacheManager.createCacheFile(
             url, responseCode, cacheHeaders, mimeType, true);
         if (mCacheResult != null) {
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "Saving into cache");
             }
             mCacheResult.setEncoding(encoding);
             mCacheResultUrl = url;
             return true;
         } else {
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "Couldn't create mCacheResult");
             }
             return false;
@@ -960,7 +961,7 @@
      */
     public synchronized boolean appendCacheResult(byte[] data, int bytes) {
         if (mCacheResult == null) {
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "appendCacheResult() called without a "
                       + "CacheResult initialized");
             }
@@ -969,7 +970,7 @@
         try {
             mCacheResult.getOutputStream().write(data, 0, bytes);
         } catch (IOException ex) {
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "Got IOException writing cache data: " + ex);
             }
             return false;
@@ -984,14 +985,14 @@
      */
     public synchronized boolean saveCacheResult() {
         if (mCacheResult == null || mCacheResultUrl == null) {
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "Tried to save cache result but "
                       + "createCacheResult not called");
             }
             return false;
         }
 
-        if (Config.LOGV) {
+        if (LOGV_ENABLED) {
             Log.i(LOG_TAG, "Saving cache result");
         }
         CacheManager.saveCacheFile(mCacheResultUrl, mCacheResult);
@@ -1006,7 +1007,7 @@
      * ability to receive a null packet for sendPostData().
      */
     public synchronized void abort() {
-        if (Config.LOGV) {
+        if (LOGV_ENABLED) {
             Log.i(LOG_TAG, "ABORT CALLED");
         }
         if (mMethod != null) {
@@ -1019,7 +1020,7 @@
      * thread to complete.
      */
     public synchronized void interrupt() {
-        if (Config.LOGV) {
+        if (LOGV_ENABLED) {
             Log.i(LOG_TAG, "INTERRUPT CALLED");
         }
         mConnectionFailedLock.lock();
@@ -1053,7 +1054,7 @@
                     mBodyInputStream = entity.getContent();
                 }
             } catch (IOException inputException) {
-                if (Config.LOGV) {
+                if (LOGV_ENABLED) {
                     Log.i(LOG_TAG, "Failed to connect InputStream: "
                           + inputException);
                 }
@@ -1062,7 +1063,7 @@
             }
             if (mBodyInputStream == null) {
                 // No error stream either. Treat as a 0 byte response.
-                if (Config.LOGV) {
+                if (LOGV_ENABLED) {
                     Log.i(LOG_TAG, "No InputStream");
                 }
                 return 0; // EOF.
@@ -1081,7 +1082,7 @@
             }
         } catch (IOException e) {
             // An abort() interrupts us by calling close() on our stream.
-            if (Config.LOGV) {
+            if (LOGV_ENABLED) {
                 Log.i(LOG_TAG, "Got IOException in mBodyInputStream.read(): ", e);
             }
             ret = -1;
diff --git a/core/java/com/android/internal/app/IUsageStats.aidl b/core/java/com/android/internal/app/IUsageStats.aidl
index 6b053d5..1ea7409 100755
--- a/core/java/com/android/internal/app/IUsageStats.aidl
+++ b/core/java/com/android/internal/app/IUsageStats.aidl
@@ -22,6 +22,7 @@
 interface IUsageStats {
     void noteResumeComponent(in ComponentName componentName);
     void notePauseComponent(in ComponentName componentName);
+    void noteLaunchTime(in ComponentName componentName, int millis);
     PkgUsageStats getPkgUsageStats(in ComponentName componentName);
     PkgUsageStats[] getAllPkgUsageStats();
 }
diff --git a/core/java/com/android/internal/util/BitwiseInputStream.java b/core/java/com/android/internal/util/BitwiseInputStream.java
new file mode 100644
index 0000000..5da3bc6
--- /dev/null
+++ b/core/java/com/android/internal/util/BitwiseInputStream.java
@@ -0,0 +1,116 @@
+/*
+ * 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.util;
+
+/**
+ * An object that provides bitwise incremental read access to a byte array.
+ *
+ * This is useful, for example, when accessing a series of fields that
+ * may not be aligned on byte boundaries.
+ *
+ * NOTE -- This class is not threadsafe.
+ */
+public class BitwiseInputStream {
+
+    // The byte array being read from.
+    private byte[] mBuf;
+
+    // The current position offset, in bits, from the msb in byte 0.
+    private int mPos;
+
+    // The last valid bit offset.
+    private int mEnd;
+
+    /**
+     * An exception to report access problems.
+     */
+    public static class AccessException extends Exception {
+        public AccessException(String s) {
+            super("BitwiseInputStream access failed: " + s);
+        }
+    }
+
+    /**
+     * Create object from byte array.
+     *
+     * @param buf a byte array containing data
+     */
+    public BitwiseInputStream(byte buf[]) {
+        mBuf = buf;
+        mEnd = buf.length * 8;
+        mPos = 0;
+    }
+
+    /**
+     * Return the number of bit still available for reading.
+     */
+    public int available() {
+        return mEnd - mPos;
+    }
+
+    /**
+     * Read some data and increment the current position.
+     *
+     * @param bits the amount of data to read (gte 0, lte 8)
+     *
+     * @return byte of read data (possibly partially filled, from lsb)
+     */
+    public byte read(int bits) throws AccessException {
+        int index = mPos / 8;
+        int offset = 16 - (mPos % 8) - bits;
+        if ((bits < 0) || (bits > 8) || ((mPos + bits) > mEnd)) {
+            throw new AccessException("illegal read " +
+                "(pos " + mPos + ", end " + mEnd + ", bits " + bits + ")");
+        }
+        int data = (mBuf[index] & 0xFF) << 8;
+        if (offset < 8) data |= (mBuf[index + 1] & 0xFF);
+        data >>>= offset;
+        data &= (-1 >>> (32 - bits));
+        mPos += bits;
+        return (byte)data;
+    }
+
+    /**
+     * Read data in bulk into a byte array and increment the current position.
+     *
+     * @param bits the amount of data to read
+     *
+     * @return newly allocated byte array of read data
+     */
+    public byte[] readByteArray(int bits) throws AccessException {
+        int bytes = (bits / 8) + ((bits % 8) > 0 ? 1 : 0);
+        byte[] arr = new byte[bytes];
+        for (int i = 0; i < bytes; i++) {
+            int increment = Math.min(8, bits - (i * 8));
+            arr[i] = (byte)(read(increment) << (8 - increment));
+        }
+        return arr;
+    }
+
+    /**
+     * Increment the current position and ignore contained data.
+     *
+     * @param bits the amount by which to increment the position
+     */
+    public void skip(int bits) throws AccessException {
+        if ((mPos + bits) > mEnd) {
+            throw new AccessException("illegal skip " +
+                "(pos " + mPos + ", end " + mEnd + ", bits " + bits + ")");
+        }
+        mPos += bits;
+    }
+}
diff --git a/core/java/com/android/internal/util/BitwiseOutputStream.java b/core/java/com/android/internal/util/BitwiseOutputStream.java
new file mode 100644
index 0000000..5941bf3
--- /dev/null
+++ b/core/java/com/android/internal/util/BitwiseOutputStream.java
@@ -0,0 +1,126 @@
+/*
+ * 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.util;
+
+/**
+ * An object that rovides bitwise incremental write access to a byte array.
+ *
+ * This is useful, for example, when writing a series of fields that
+ * may not be aligned on byte boundaries.
+ *
+ * NOTE -- This class is not threadsafe.
+ */
+public class BitwiseOutputStream {
+
+    // The byte array being written to, which will be grown as needed.
+    private byte[] mBuf;
+
+    // The current position offset, in bits, from the msb in byte 0.
+    private int mPos;
+
+    // The last bit offset, given the current buf length.
+    private int mEnd;
+
+    /**
+     * An exception to report access problems.
+     */
+    public static class AccessException extends Exception {
+        public AccessException(String s) {
+            super("BitwiseOutputStream access failed: " + s);
+        }
+    }
+
+    /**
+     * Create object from hint at desired size.
+     *
+     * @param startingLength initial internal byte array length in bytes
+     */
+    public BitwiseOutputStream(int startingLength) {
+        mBuf = new byte[startingLength];
+        mEnd = startingLength * 8;
+        mPos = 0;
+    }
+
+    /**
+     * Return byte array containing accumulated data, sized to just fit.
+     *
+     * @return newly allocated byte array
+     */
+    public byte[] toByteArray() {
+        int len = (mPos / 8) + ((mPos % 8) > 0 ? 1 : 0);
+        byte[] newBuf = new byte[len];
+        System.arraycopy(mBuf, 0, newBuf, 0, len);
+        return newBuf;
+    }
+
+    /**
+     * Allocate a new internal buffer, if needed.
+     *
+     * @param bits additional bits to be accommodated
+     */
+    private void possExpand(int bits) {
+        if ((mPos + bits) < mEnd) return;
+        byte[] newBuf = new byte[((mPos + bits) * 2) / 8];
+        System.arraycopy(mBuf, 0, newBuf, 0, mEnd / 8);
+        mBuf = newBuf;
+    }
+
+    /**
+     * Write some data and increment the current position.
+     *
+     * @param bits the amount of data to write (gte 0, lte 8)
+     * @param data to write, will be masked to expose only bits param from lsb
+     */
+    public void write(int bits, int data) throws AccessException {
+        if ((bits < 0) || (bits > 8)) {
+            throw new AccessException("illegal write (" + bits + " bits)");
+        }
+        possExpand(bits);
+        data &= (-1 >>> (32 - bits));
+        int index = mPos / 8;
+        int offset = 16 - (mPos % 8) - bits;
+        data <<= offset;
+        mPos += bits;
+        mBuf[index] |= (data >>> 8);
+        if (offset < 8) mBuf[index + 1] |= (data & 0xFF);
+    }
+
+    /**
+     * Write data in bulk from a byte array and increment the current position.
+     *
+     * @param bits the amount of data to write
+     * @param arr the byte array containing data to be written
+     */
+    public void writeByteArray(int bits, byte[] arr) throws AccessException {
+        for (int i = 0; i < arr.length; i++) {
+            int increment = Math.min(8, bits - (i * 8));
+            if (increment > 0) {
+                write(increment, (byte)(arr[i] >>> (8 - increment)));
+            }
+        }
+    }
+
+    /**
+     * Increment the current position, implicitly writing zeros.
+     *
+     * @param bits the amount by which to increment the position
+     */
+    public void skip(int bits) {
+        possExpand(bits);
+        mPos += bits;
+    }
+}
diff --git a/core/jni/android_location_GpsLocationProvider.cpp b/core/jni/android_location_GpsLocationProvider.cpp
index f0b35e9..bbde8d5 100644
--- a/core/jni/android_location_GpsLocationProvider.cpp
+++ b/core/jni/android_location_GpsLocationProvider.cpp
@@ -31,6 +31,7 @@
 static jmethodID method_reportLocation;
 static jmethodID method_reportStatus;
 static jmethodID method_reportSvStatus;
+static jmethodID method_reportSuplStatus;
 static jmethodID method_xtraDownloadRequest;
 
 static const GpsInterface* sGpsInterface = NULL;
@@ -41,19 +42,22 @@
 static GpsLocation  sGpsLocation;
 static GpsStatus    sGpsStatus;
 static GpsSvStatus  sGpsSvStatus;
+static GpsSuplStatus    sGpsSuplStatus;
 
 // a copy of the data shared by android_location_GpsLocationProvider_wait_for_event
 // and android_location_GpsLocationProvider_read_status
 static GpsLocation  sGpsLocationCopy;
 static GpsStatus    sGpsStatusCopy;
 static GpsSvStatus  sGpsSvStatusCopy;
+static GpsSuplStatus    sGpsSuplStatusCopy;
 
 enum CallbackType {
     kLocation = 1,
     kStatus = 2,
     kSvStatus = 4,
-    kXtraDownloadRequest = 8,
-    kDisableRequest = 16,
+    kSuplStatus = 8,
+    kXtraDownloadRequest = 16,
+    kDisableRequest = 32,
 }; 
 static int sPendingCallbacks;
 
@@ -92,6 +96,17 @@
     pthread_mutex_unlock(&sEventMutex);
 }
 
+static void supl_status_callback(GpsSuplStatus* supl_status)
+{
+    pthread_mutex_lock(&sEventMutex);
+
+    sPendingCallbacks |= kSuplStatus;
+    memcpy(&sGpsSuplStatus, supl_status, sizeof(GpsSuplStatus));
+
+    pthread_cond_signal(&sEventCond);
+    pthread_mutex_unlock(&sEventMutex);
+}
+
 GpsCallbacks sGpsCallbacks = {
     location_callback,
     status_callback,
@@ -111,11 +126,15 @@
     download_request_callback,
 };
 
+GpsSuplCallbacks sGpsSuplCallbacks = {
+    supl_status_callback,
+};
 
 static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
     method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V");
     method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
     method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V");
+    method_reportSuplStatus = env->GetMethodID(clazz, "reportSuplStatus", "(I)V");
     method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
 }
 
@@ -129,7 +148,13 @@
 {
     if (!sGpsInterface)
         sGpsInterface = gps_get_interface();
-    return (sGpsInterface && sGpsInterface->init(&sGpsCallbacks) == 0);
+    if (!sGpsInterface || sGpsInterface->init(&sGpsCallbacks) != 0)
+        return false;
+
+    if (!sGpsSuplInterface)
+        sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE);
+    if (sGpsSuplInterface)
+        sGpsSuplInterface->init(&sGpsSuplCallbacks);
 }
 
 static void android_location_GpsLocationProvider_disable(JNIEnv* env, jobject obj)
@@ -186,6 +211,7 @@
     memcpy(&sGpsLocationCopy, &sGpsLocation, sizeof(sGpsLocationCopy));
     memcpy(&sGpsStatusCopy, &sGpsStatus, sizeof(sGpsStatusCopy));
     memcpy(&sGpsSvStatusCopy, &sGpsSvStatus, sizeof(sGpsSvStatusCopy));
+    memcpy(&sGpsSuplStatusCopy, &sGpsSuplStatus, sizeof(sGpsSuplStatusCopy));
     pthread_mutex_unlock(&sEventMutex);   
 
     if (pendingCallbacks & kLocation) { 
@@ -201,6 +227,9 @@
     if (pendingCallbacks & kSvStatus) {
         env->CallVoidMethod(obj, method_reportSvStatus);
     }
+    if (pendingCallbacks & kSuplStatus) {
+        env->CallVoidMethod(obj, method_reportSuplStatus, sGpsSuplStatusCopy.status);
+    }  
     if (pendingCallbacks & kXtraDownloadRequest) {    
         env->CallVoidMethod(obj, method_xtraDownloadRequest);
     }
@@ -269,18 +298,7 @@
     env->ReleaseByteArrayElements(data, bytes, 0);
 }
 
-static void android_location_GpsLocationProvider_set_supl_server(JNIEnv* env, jobject obj,
-        jint addr, jint port)
-{
-    if (!sGpsSuplInterface) {
-        sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE);
-    }
-    if (sGpsSuplInterface) {
-        sGpsSuplInterface->set_server(addr, port);
-    }
-}
-
-static void android_location_GpsLocationProvider_set_supl_apn(JNIEnv* env, jobject obj, jstring apn)
+static void android_location_GpsLocationProvider_supl_data_conn_open(JNIEnv* env, jobject obj, jstring apn)
 {
     if (!sGpsSuplInterface) {
         sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE);
@@ -291,11 +309,42 @@
             return;
         }
         const char *apnStr = env->GetStringUTFChars(apn, NULL);
-        sGpsSuplInterface->set_apn(apnStr);
+        sGpsSuplInterface->data_conn_open(apnStr);
         env->ReleaseStringUTFChars(apn, apnStr);
     }
 }
 
+static void android_location_GpsLocationProvider_supl_data_conn_closed(JNIEnv* env, jobject obj)
+{
+    if (!sGpsSuplInterface) {
+        sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE);
+    }
+    if (sGpsSuplInterface) {
+        sGpsSuplInterface->data_conn_closed();
+    }
+}
+
+static void android_location_GpsLocationProvider_supl_data_conn_failed(JNIEnv* env, jobject obj)
+{
+    if (!sGpsSuplInterface) {
+        sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE);
+    }
+    if (sGpsSuplInterface) {
+        sGpsSuplInterface->data_conn_failed();
+    }
+}
+
+static void android_location_GpsLocationProvider_set_supl_server(JNIEnv* env, jobject obj,
+        jint addr, jint port)
+{
+    if (!sGpsSuplInterface) {
+        sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE);
+    }
+    if (sGpsSuplInterface) {
+        sGpsSuplInterface->set_server(addr, port);
+    }
+}
+
 static JNINativeMethod sMethods[] = {
      /* name, signature, funcPtr */
     {"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native},
@@ -312,8 +361,10 @@
 	{"native_inject_time", "(JJI)V", (void*)android_location_GpsLocationProvider_inject_time},
 	{"native_supports_xtra", "()Z", (void*)android_location_GpsLocationProvider_supports_xtra},
 	{"native_inject_xtra_data", "([BI)V", (void*)android_location_GpsLocationProvider_inject_xtra_data},
+ 	{"native_supl_data_conn_open", "(Ljava/lang/String;)V", (void*)android_location_GpsLocationProvider_supl_data_conn_open},
+ 	{"native_supl_data_conn_closed", "()V", (void*)android_location_GpsLocationProvider_supl_data_conn_closed},
+ 	{"native_supl_data_conn_failed", "()V", (void*)android_location_GpsLocationProvider_supl_data_conn_failed},
  	{"native_set_supl_server", "(II)V", (void*)android_location_GpsLocationProvider_set_supl_server},
- 	{"native_set_supl_apn", "(Ljava/lang/String;)V", (void*)android_location_GpsLocationProvider_set_supl_apn},
 };
 
 int register_android_location_GpsLocationProvider(JNIEnv* env)
diff --git a/location/java/com/android/internal/location/GpsLocationProvider.java b/location/java/com/android/internal/location/GpsLocationProvider.java
index 8a33574..d56594e 100644
--- a/location/java/com/android/internal/location/GpsLocationProvider.java
+++ b/location/java/com/android/internal/location/GpsLocationProvider.java
@@ -28,6 +28,7 @@
 import android.location.LocationManager;
 import android.location.LocationProvider;
 import android.location.LocationProviderImpl;
+import android.net.ConnectivityManager;
 import android.net.SntpClient;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -99,6 +100,14 @@
     private static final int GPS_STATUS_ENGINE_ON = 3;
     private static final int GPS_STATUS_ENGINE_OFF = 4;
 
+    // these need to match GpsSuplStatusValue defines in gps.h
+    /** SUPL status event values. */
+    private static final int GPS_REQUEST_SUPL_DATA_CONN = 1;
+    private static final int GPS_RELEASE_SUPL_DATA_CONN = 2;
+    private static final int GPS_SUPL_DATA_CONNECTED = 3;
+    private static final int GPS_SUPL_DATA_CONN_DONE = 4;
+    private static final int GPS_SUPL_DATA_CONN_FAILED = 5;
+
     // these need to match GpsLocationFlags enum in gps.h
     private static final int LOCATION_INVALID = 0;
     private static final int LOCATION_HAS_LAT_LONG = 1;
@@ -122,6 +131,11 @@
     private static final int GPS_DELETE_CELLDB_INFO = 0x8000;
     private static final int GPS_DELETE_ALL = 0xFFFF;
 
+    // for mSuplDataConnectionState
+    private static final int SUPL_DATA_CONNECTION_CLOSED = 0;
+    private static final int SUPL_DATA_CONNECTION_OPENING = 1;
+    private static final int SUPL_DATA_CONNECTION_OPEN = 2;
+
     private static final String PROPERTIES_FILE = "/etc/gps.conf";
 
     private int mLocationFlags = LOCATION_INVALID;
@@ -176,6 +190,9 @@
     private String mSuplHost;
     private int mSuplPort;
     private boolean mSetSuplServer;
+    private String mSuplApn;
+    private int mSuplDataConnectionState;
+    private ConnectivityManager mConnMgr;
 
     // how often to request NTP time, in milliseconds
     // current setting 4 hours
@@ -199,9 +216,11 @@
                     Log.d(TAG, "state: " + state +  " apnName: " + apnName + " reason: " + reason);
                 }
                 if ("CONNECTED".equals(state)) {
-                    native_set_supl_apn(apnName);
-                } else {
-                    native_set_supl_apn("");
+                    mSuplApn = apnName;
+                    if (mSuplDataConnectionState == SUPL_DATA_CONNECTION_OPENING) {
+                        native_supl_data_conn_open(mSuplApn);
+                        mSuplDataConnectionState = SUPL_DATA_CONNECTION_OPEN;
+                    }
                 }
             }
         }
@@ -220,6 +239,8 @@
         intentFilter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
         context.registerReceiver(receiver, intentFilter);
 
+        mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
+
         mProperties = new Properties();
         try {
             File file = new File(PROPERTIES_FILE);
@@ -782,7 +803,44 @@
             updateStatus(TEMPORARILY_UNAVAILABLE, mSvCount);
         }
     }
-    
+
+    /**
+     * called from native code to update SUPL status
+     */
+    private void reportSuplStatus(int status) {
+        switch (status) {
+            case GPS_REQUEST_SUPL_DATA_CONN:
+                 int result = mConnMgr.startUsingNetworkFeature(
+                        ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
+                if (result == Phone.APN_ALREADY_ACTIVE) {
+                    native_supl_data_conn_open(mSuplApn);
+                    mSuplDataConnectionState = SUPL_DATA_CONNECTION_OPEN;
+                } else if (result == Phone.APN_REQUEST_STARTED) {
+                    mSuplDataConnectionState = SUPL_DATA_CONNECTION_OPENING;
+                } else {
+                    native_supl_data_conn_failed();
+                }
+                break;
+            case GPS_RELEASE_SUPL_DATA_CONN:
+                if (mSuplDataConnectionState != SUPL_DATA_CONNECTION_CLOSED) {
+                    mConnMgr.stopUsingNetworkFeature(
+                            ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
+                    native_supl_data_conn_closed();
+                    mSuplDataConnectionState = SUPL_DATA_CONNECTION_CLOSED;
+                }
+                break;
+            case GPS_SUPL_DATA_CONNECTED:
+                // Log.d(TAG, "GPS_SUPL_DATA_CONNECTED");
+                break;
+            case GPS_SUPL_DATA_CONN_DONE:
+                // Log.d(TAG, "GPS_SUPL_DATA_CONN_DONE");
+                break;
+            case GPS_SUPL_DATA_CONN_FAILED:
+                // Log.d(TAG, "GPS_SUPL_DATA_CONN_FAILED");
+                break;
+        }
+    }
+
     private void xtraDownloadRequest() {
         if (Config.LOGD) Log.d(TAG, "xtraDownloadRequest");
         if (mNetworkThread != null) {
@@ -1002,6 +1060,8 @@
     private native void native_inject_xtra_data(byte[] data, int length);
 
     // SUPL Support    
+    private native void native_supl_data_conn_open(String apn);
+    private native void native_supl_data_conn_closed();
+    private native void native_supl_data_conn_failed();
     private native void native_set_supl_server(int addr, int port);
-    private native void native_set_supl_apn(String apn);
 }
diff --git a/opengl/tools/glgen/src/.gitignore b/opengl/tools/glgen/src/.gitignore
new file mode 100644
index 0000000..6b468b6
--- /dev/null
+++ b/opengl/tools/glgen/src/.gitignore
@@ -0,0 +1 @@
+*.class
diff --git a/opengl/tools/glgen/src/CFunc.java b/opengl/tools/glgen/src/CFunc.java
index 0794f41..a89e1c5 100644
--- a/opengl/tools/glgen/src/CFunc.java
+++ b/opengl/tools/glgen/src/CFunc.java
@@ -1,155 +1,156 @@
-

-import java.util.*;

-

-public class CFunc {

-

-    String original;

-

-    CType ftype;

-    String fname;

-

-    List<String> argNames = new ArrayList<String>();

-    List<CType> argTypes = new ArrayList<CType>();

-

-    boolean hasPointerArg = false;

-    boolean hasTypedPointerArg = false;

-

-    public CFunc(String original) {

-        this.original = original;

-    }

-

-    public String getOriginal() {

-        return original;

-    }

-

-    public void setName(String fname) {

-        this.fname = fname;

-    }

-

-    public String getName() {

-        return fname;

-    }

-

-    public void setType(CType ftype) {

-        this.ftype = ftype;

-    }

-

-    public CType getType() {

-        return ftype;

-    }

-

-    public void addArgument(String argName, CType argType) {

-        argNames.add(argName);

-        argTypes.add(argType);

-

-        if (argType.isPointer()) {

-            hasPointerArg = true;

-        }

-        if (argType.isTypedPointer()) {

-            hasTypedPointerArg = true;

-        }

-    }

-

-    public int getNumArgs() {

-        return argNames.size();

-    }

-

-    public int getArgIndex(String name) {

-        int len = argNames.size();

-        for (int i = 0; i < len; i++) {

-            if (name.equals(argNames.get(i))) {

-                return i;

-            }

-        }

-        return -1;

-    }

-

-    public String getArgName(int index) {

-        return argNames.get(index);

-    }

-

-    public CType getArgType(int index) {

-        return argTypes.get(index);

-    }

-

-    public boolean hasPointerArg() {

-        return hasPointerArg;

-    }

-

-    public boolean hasTypedPointerArg() {

-        return hasTypedPointerArg;

-    }

-

-    public String toString() {

-        String s =  "Function " + fname + " returns " + ftype + ": ";

-        for (int i = 0; i < argNames.size(); i++) {

-            if (i > 0) {

-                s += ", ";

-            }

-            s += argTypes.get(i) + " " + argNames.get(i);

-        }

-        return s;

-    }

-

-    public static CFunc parseCFunc(String s) {

-        CFunc cfunc = new CFunc(s);

-        String[] tokens = s.split("\\s");

-

-        int i = 0;

-        CType ftype = new CType();

-        String ftypeName = tokens[i++];

-        if (ftypeName.equals("const")) {

-            ftype.setIsConst(true);

-            ftypeName = tokens[i++];

-        }

-        ftype.setBaseType(ftypeName);

-

-        String fname = tokens[i++];

-        if (fname.equals("*")) {

-            ftype.setIsPointer(true);

-            fname = tokens[i++];

-        }

-	

-        cfunc.setName(fname);

-        cfunc.setType(ftype);

-	

-        while (i < tokens.length) {

-            String tok = tokens[i++];

-	    

-            if (tok.equals("(")) {

-                continue;

-            }

-            if (tok.equals(")")) {

-                break;

-            }

-

-            CType argType = new CType();

-	    

-            String argTypeName = tok;

-            String argName = "";

-	    

-            if (argTypeName.equals("const")) {

-                argType.setIsConst(true);

-                argTypeName = tokens[i++];

-            }

-            argType.setBaseType(argTypeName);

-

-            if (argTypeName.equals("void")) {

-                break;

-            }

-	    

-            argName = tokens[i++];

-            if (argName.startsWith("*")) {

-                argType.setIsPointer(true);

-                argName = argName.substring(1, argName.length());

-            }

-            if (argName.endsWith(",")) {

-                argName = argName.substring(0, argName.length() - 1);

-            }

-	    

-            cfunc.addArgument(argName, argType);

-        }

-

-        return cfunc;

-    }

-}

+
+import java.util.*;
+
+public class CFunc {
+
+    String original;
+
+    CType ftype;
+    String fname;
+
+    List<String> argNames = new ArrayList<String>();
+    List<CType> argTypes = new ArrayList<CType>();
+
+    boolean hasPointerArg = false;
+    boolean hasTypedPointerArg = false;
+
+    public CFunc(String original) {
+        this.original = original;
+    }
+
+    public String getOriginal() {
+        return original;
+    }
+
+    public void setName(String fname) {
+        this.fname = fname;
+    }
+
+    public String getName() {
+        return fname;
+    }
+
+    public void setType(CType ftype) {
+        this.ftype = ftype;
+    }
+
+    public CType getType() {
+        return ftype;
+    }
+
+    public void addArgument(String argName, CType argType) {
+        argNames.add(argName);
+        argTypes.add(argType);
+
+        if (argType.isPointer()) {
+            hasPointerArg = true;
+        }
+        if (argType.isTypedPointer()) {
+            hasTypedPointerArg = true;
+        }
+    }
+
+    public int getNumArgs() {
+        return argNames.size();
+    }
+
+    public int getArgIndex(String name) {
+        int len = argNames.size();
+        for (int i = 0; i < len; i++) {
+            if (name.equals(argNames.get(i))) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    public String getArgName(int index) {
+        return argNames.get(index);
+    }
+
+    public CType getArgType(int index) {
+        return argTypes.get(index);
+    }
+
+    public boolean hasPointerArg() {
+        return hasPointerArg;
+    }
+
+    public boolean hasTypedPointerArg() {
+        return hasTypedPointerArg;
+    }
+
+    @Override
+    public String toString() {
+        String s =  "Function " + fname + " returns " + ftype + ": ";
+        for (int i = 0; i < argNames.size(); i++) {
+            if (i > 0) {
+                s += ", ";
+            }
+            s += argTypes.get(i) + " " + argNames.get(i);
+        }
+        return s;
+    }
+
+    public static CFunc parseCFunc(String s) {
+        CFunc cfunc = new CFunc(s);
+        String[] tokens = s.split("\\s");
+
+        int i = 0;
+        CType ftype = new CType();
+        String ftypeName = tokens[i++];
+        if (ftypeName.equals("const")) {
+            ftype.setIsConst(true);
+            ftypeName = tokens[i++];
+        }
+        ftype.setBaseType(ftypeName);
+
+        String fname = tokens[i++];
+        if (fname.equals("*")) {
+            ftype.setIsPointer(true);
+            fname = tokens[i++];
+        }
+
+        cfunc.setName(fname);
+        cfunc.setType(ftype);
+
+        while (i < tokens.length) {
+            String tok = tokens[i++];
+
+            if (tok.equals("(")) {
+                continue;
+            }
+            if (tok.equals(")")) {
+                break;
+            }
+
+            CType argType = new CType();
+
+            String argTypeName = tok;
+            String argName = "";
+
+            if (argTypeName.equals("const")) {
+                argType.setIsConst(true);
+                argTypeName = tokens[i++];
+            }
+            argType.setBaseType(argTypeName);
+
+            if (argTypeName.equals("void")) {
+                break;
+            }
+
+            argName = tokens[i++];
+            if (argName.startsWith("*")) {
+                argType.setIsPointer(true);
+                argName = argName.substring(1, argName.length());
+            }
+            if (argName.endsWith(",")) {
+                argName = argName.substring(0, argName.length() - 1);
+            }
+
+            cfunc.addArgument(argName, argType);
+        }
+
+        return cfunc;
+    }
+}
diff --git a/opengl/tools/glgen/src/CType.java b/opengl/tools/glgen/src/CType.java
index 331ec62..826c90d 100644
--- a/opengl/tools/glgen/src/CType.java
+++ b/opengl/tools/glgen/src/CType.java
@@ -1,85 +1,88 @@
-

-public class CType {

-

-    String baseType;

-    boolean isConst;

-    boolean isPointer;

-

-    public CType() {

-    }

-

-    public CType(String baseType) {

-	setBaseType(baseType);

-    }

-

-    public CType(String baseType, boolean isConst, boolean isPointer) {

-	setBaseType(baseType);

-	setIsConst(isConst);

-	setIsPointer(isPointer);

-    }

-

-    public String getDeclaration() {

-	return baseType + (isPointer ? " *" : "");

-    }

-    

-    public void setIsConst(boolean isConst) {

-	this.isConst = isConst;

-    }

-

-    public boolean isConst() {

-	return isConst;

-    }

-

-    public void setIsPointer(boolean isPointer) {

-	this.isPointer = isPointer;

-    }

-

-    public boolean isPointer() {

-	return isPointer;

-    }

-

-    boolean isVoid() {

-	String baseType = getBaseType();

-	return baseType.equals("GLvoid") ||

-	    baseType.equals("void");

-    }

-

-    public boolean isTypedPointer() {

-	return isPointer() && !isVoid();

-    }

-

-    public void setBaseType(String baseType) {

-	this.baseType = baseType;

-    }

-

-    public String getBaseType() {

-	return baseType;

-    }

-

-    public String toString() {

-	String s = "";

-	if (isConst()) {

-	    s += "const ";

-	}

-	s += baseType;

-	if (isPointer()) {

-	    s += "*";

-	}

-

-	return s;

-    }

-

-    public int hashCode() {

-	return baseType.hashCode() ^ (isPointer ? 2 : 0) ^ (isConst ? 1 : 0);

-    }

-

-    public boolean equals(Object o) {

-	if (o != null && o instanceof CType) {

-	    CType c = (CType)o;

-	    return baseType.equals(c.baseType) &&

-		isPointer() == c.isPointer() &&

-		isConst() == c.isConst();

-	}

-	return false;

-    }

-}

+
+public class CType {
+
+    String baseType;
+    boolean isConst;
+    boolean isPointer;
+
+    public CType() {
+    }
+
+    public CType(String baseType) {
+    setBaseType(baseType);
+    }
+
+    public CType(String baseType, boolean isConst, boolean isPointer) {
+    setBaseType(baseType);
+    setIsConst(isConst);
+    setIsPointer(isPointer);
+    }
+
+    public String getDeclaration() {
+    return baseType + (isPointer ? " *" : "");
+    }
+
+    public void setIsConst(boolean isConst) {
+    this.isConst = isConst;
+    }
+
+    public boolean isConst() {
+    return isConst;
+    }
+
+    public void setIsPointer(boolean isPointer) {
+    this.isPointer = isPointer;
+    }
+
+    public boolean isPointer() {
+    return isPointer;
+    }
+
+    boolean isVoid() {
+    String baseType = getBaseType();
+    return baseType.equals("GLvoid") ||
+        baseType.equals("void");
+    }
+
+    public boolean isTypedPointer() {
+    return isPointer() && !isVoid();
+    }
+
+    public void setBaseType(String baseType) {
+    this.baseType = baseType;
+    }
+
+    public String getBaseType() {
+    return baseType;
+    }
+
+    @Override
+    public String toString() {
+    String s = "";
+    if (isConst()) {
+        s += "const ";
+    }
+    s += baseType;
+    if (isPointer()) {
+        s += "*";
+    }
+
+    return s;
+    }
+
+    @Override
+    public int hashCode() {
+    return baseType.hashCode() ^ (isPointer ? 2 : 0) ^ (isConst ? 1 : 0);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+    if (o != null && o instanceof CType) {
+        CType c = (CType)o;
+        return baseType.equals(c.baseType) &&
+        isPointer() == c.isPointer() &&
+        isConst() == c.isConst();
+    }
+    return false;
+    }
+}
diff --git a/opengl/tools/glgen/src/CodeEmitter.java b/opengl/tools/glgen/src/CodeEmitter.java
index 3e9b90a..ebb9727 100644
--- a/opengl/tools/glgen/src/CodeEmitter.java
+++ b/opengl/tools/glgen/src/CodeEmitter.java
@@ -1,8 +1,8 @@
-

-public interface CodeEmitter {

-

-    void setVersion(int version, boolean ext, boolean pack);

-    void emitCode(CFunc cfunc, String original);

-    void addNativeRegistration(String fname);

-    void emitNativeRegistration();

-}

+
+public interface CodeEmitter {
+
+    void setVersion(int version, boolean ext, boolean pack);
+    void emitCode(CFunc cfunc, String original);
+    void addNativeRegistration(String fname);
+    void emitNativeRegistration();
+}
diff --git a/opengl/tools/glgen/src/GenerateGL.java b/opengl/tools/glgen/src/GenerateGL.java
index 657ee6e..afe1bb6 100644
--- a/opengl/tools/glgen/src/GenerateGL.java
+++ b/opengl/tools/glgen/src/GenerateGL.java
@@ -1,164 +1,168 @@
-

-import java.io.*;

-import java.util.*;

-

-public class GenerateGL {

-

-    static void copy(String filename, PrintStream out) throws IOException {

-        BufferedReader br = new BufferedReader(new FileReader(filename));

-        String s;

-        while ((s = br.readLine()) != null) {

-            out.println(s);

-        }

-    }

-

-    private static void emit(int version, boolean ext, boolean pack,

-                             CodeEmitter emitter,

-                             BufferedReader specReader,

-                             PrintStream glStream,

-                             PrintStream glImplStream,

-                             PrintStream cStream) throws Exception {

-        String s = null;

-        int counter = 0;

-        while ((s = specReader.readLine()) != null) {

-            if (s.trim().startsWith("//")) {

-                continue;

-            }

-

-            CFunc cfunc = CFunc.parseCFunc(s);

-

-            String fname = cfunc.getName();

-            File f = new File("stubs/" + fname +

-                              ".java-1" + version + "-if");

-            if (f.exists()) {

-                System.out.println("Special-casing function " + fname);

-                copy("stubs/" + fname +

-                     ".java-1" + version + "-if", glStream);

-                copy("stubs/" + fname + ".java-impl", glImplStream);

-                copy("stubs/" + fname + ".cpp", cStream);

-

-                // Register native function names

-                // This should be improved to require fewer discrete files

-                String filename = "stubs/" + fname + ".nativeReg";

-                BufferedReader br =

-                    new BufferedReader(new FileReader(filename));

-                String nfunc;

-                while ((nfunc = br.readLine()) != null) {

-                    emitter.addNativeRegistration(nfunc);

-                }

-            } else {

-                emitter.setVersion(version, ext, pack);

-                emitter.emitCode(cfunc, s);

-            }

-        }

-    }

-

-    public static void main(String[] args) throws Exception {

-        String classPathName = "com/google/android/gles_jni/GLImpl";

-        boolean useContextPointer = true;

-

-        int aidx = 0;

-        while (args[aidx].charAt(0) == '-') {

-            switch (args[aidx].charAt(1)) {

-            case 'c':

-                useContextPointer = false;

-                break;

-

-            default:

-                System.err.println("Unknown flag: " + args[aidx]);

-                System.exit(1);

-            }

-

-            aidx++;

-        }

-

-        System.out.println("useContextPointer = " + useContextPointer);

-

-        BufferedReader spec10Reader =

-            new BufferedReader(new FileReader(args[aidx++]));

-        BufferedReader spec10ExtReader =

-            new BufferedReader(new FileReader(args[aidx++]));

-        BufferedReader spec11Reader =

-            new BufferedReader(new FileReader(args[aidx++]));

-        BufferedReader spec11ExtReader =

-            new BufferedReader(new FileReader(args[aidx++]));

-        BufferedReader spec11ExtPackReader =

-            new BufferedReader(new FileReader(args[aidx++]));

-        BufferedReader checksReader =

-            new BufferedReader(new FileReader(args[aidx++]));

-

-        String gl10Filename = "javax/microedition/khronos/opengles/GL10.java";

-        String gl10ExtFilename =

-            "javax/microedition/khronos/opengles/GL10Ext.java";

-        String gl11Filename = "javax/microedition/khronos/opengles/GL11.java";

-        String gl11ExtFilename =

-            "javax/microedition/khronos/opengles/GL11Ext.java";

-        String gl11ExtPackFilename =

-            "javax/microedition/khronos/opengles/GL11ExtensionPack.java";

-        String glImplFilename = "com/google/android/gles_jni/GLImpl.java";

-        String cFilename = "com_google_android_gles_jni_GLImpl.cpp";

-

-        PrintStream gl10Stream =

-            new PrintStream(new FileOutputStream("out/" + gl10Filename));

-        PrintStream gl10ExtStream =

-            new PrintStream(new FileOutputStream("out/" + gl10ExtFilename));

-        PrintStream gl11Stream =

-            new PrintStream(new FileOutputStream("out/" + gl11Filename));

-        PrintStream gl11ExtStream =

-            new PrintStream(new FileOutputStream("out/" + gl11ExtFilename));

-        PrintStream gl11ExtPackStream =

-            new PrintStream(new FileOutputStream("out/" + gl11ExtPackFilename));

-        PrintStream glImplStream =

-            new PrintStream(new FileOutputStream("out/" + glImplFilename));

-        PrintStream cStream =

-            new PrintStream(new FileOutputStream("out/" + cFilename));

-

-        ParameterChecker checker = new ParameterChecker(checksReader);

-

-        CodeEmitter emitter =

-            new JniCodeEmitter(classPathName,

-                               checker,

-                               gl10Stream, gl10ExtStream,

-                               gl11Stream, gl11ExtStream, gl11ExtPackStream,

-                               glImplStream, cStream,

-                               useContextPointer);

-

-        gl10Stream.println("/* //device/java/android/" + gl10Filename);

-        gl10ExtStream.println("/* //device/java/android/" + gl10ExtFilename);

-        gl11Stream.println("/* //device/java/android/" + gl11Filename);

-        gl11ExtStream.println("/* //device/java/android/" + gl11ExtFilename);

-        gl11ExtPackStream.println("/* //device/java/android/" +

-            gl11ExtPackFilename);

-        glImplStream.println("/* //device/java/android/" + glImplFilename);

-        cStream.println("/* //device/libs/android_runtime/" + cFilename);

-

-        copy("stubs/GL10Header.java-if", gl10Stream);

-        copy("stubs/GL10ExtHeader.java-if", gl10ExtStream);

-        copy("stubs/GL11Header.java-if", gl11Stream);

-        copy("stubs/GL11ExtHeader.java-if", gl11ExtStream);

-        copy("stubs/GL11ExtensionPackHeader.java-if", gl11ExtPackStream);

-        copy("stubs/GLImplHeader.java-impl", glImplStream);

-        copy("stubs/GLCHeader.cpp", cStream);

-

-        emit(0, false, false,

-             emitter, spec10Reader, gl10Stream, glImplStream, cStream);

-        emit(0, true, false,

-             emitter, spec10ExtReader, gl10ExtStream, glImplStream, cStream);

-        emit(1, false, false,

-             emitter, spec11Reader, gl11Stream, glImplStream, cStream);

-        emit(1, true, false,

-             emitter, spec11ExtReader, gl11ExtStream, glImplStream, cStream);

-        emit(1, true, true,

-             emitter, spec11ExtPackReader, gl11ExtPackStream, glImplStream,

-             cStream);

-

-        emitter.emitNativeRegistration();

-

-        gl10Stream.println("}");

-        gl10ExtStream.println("}");

-        gl11Stream.println("}");

-        gl11ExtStream.println("}");

-        gl11ExtPackStream.println("}");

-        glImplStream.println("}");

-    }

-}

+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintStream;
+
+public class GenerateGL {
+
+    static void copy(String filename, PrintStream out) throws IOException {
+        BufferedReader br = new BufferedReader(new FileReader(filename));
+        String s;
+        while ((s = br.readLine()) != null) {
+            out.println(s);
+        }
+    }
+
+    private static void emit(int version, boolean ext, boolean pack,
+                             CodeEmitter emitter,
+                             BufferedReader specReader,
+                             PrintStream glStream,
+                             PrintStream glImplStream,
+                             PrintStream cStream) throws Exception {
+        String s = null;
+        int counter = 0;
+        while ((s = specReader.readLine()) != null) {
+            if (s.trim().startsWith("//")) {
+                continue;
+            }
+
+            CFunc cfunc = CFunc.parseCFunc(s);
+
+            String fname = cfunc.getName();
+            File f = new File("stubs/" + fname +
+                              ".java-1" + version + "-if");
+            if (f.exists()) {
+                System.out.println("Special-casing function " + fname);
+                copy("stubs/" + fname +
+                     ".java-1" + version + "-if", glStream);
+                copy("stubs/" + fname + ".java-impl", glImplStream);
+                copy("stubs/" + fname + ".cpp", cStream);
+
+                // Register native function names
+                // This should be improved to require fewer discrete files
+                String filename = "stubs/" + fname + ".nativeReg";
+                BufferedReader br =
+                    new BufferedReader(new FileReader(filename));
+                String nfunc;
+                while ((nfunc = br.readLine()) != null) {
+                    emitter.addNativeRegistration(nfunc);
+                }
+            } else {
+                emitter.setVersion(version, ext, pack);
+                emitter.emitCode(cfunc, s);
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        String classPathName = "com/google/android/gles_jni/GLImpl";
+        boolean useContextPointer = true;
+
+        int aidx = 0;
+        while (args[aidx].charAt(0) == '-') {
+            switch (args[aidx].charAt(1)) {
+            case 'c':
+                useContextPointer = false;
+                break;
+
+            default:
+                System.err.println("Unknown flag: " + args[aidx]);
+                System.exit(1);
+            }
+
+            aidx++;
+        }
+
+        System.out.println("useContextPointer = " + useContextPointer);
+
+        BufferedReader spec10Reader =
+            new BufferedReader(new FileReader(args[aidx++]));
+        BufferedReader spec10ExtReader =
+            new BufferedReader(new FileReader(args[aidx++]));
+        BufferedReader spec11Reader =
+            new BufferedReader(new FileReader(args[aidx++]));
+        BufferedReader spec11ExtReader =
+            new BufferedReader(new FileReader(args[aidx++]));
+        BufferedReader spec11ExtPackReader =
+            new BufferedReader(new FileReader(args[aidx++]));
+        BufferedReader checksReader =
+            new BufferedReader(new FileReader(args[aidx++]));
+
+        String gl10Filename = "javax/microedition/khronos/opengles/GL10.java";
+        String gl10ExtFilename =
+            "javax/microedition/khronos/opengles/GL10Ext.java";
+        String gl11Filename = "javax/microedition/khronos/opengles/GL11.java";
+        String gl11ExtFilename =
+            "javax/microedition/khronos/opengles/GL11Ext.java";
+        String gl11ExtPackFilename =
+            "javax/microedition/khronos/opengles/GL11ExtensionPack.java";
+        String glImplFilename = "com/google/android/gles_jni/GLImpl.java";
+        String cFilename = "com_google_android_gles_jni_GLImpl.cpp";
+
+        PrintStream gl10Stream =
+            new PrintStream(new FileOutputStream("out/" + gl10Filename));
+        PrintStream gl10ExtStream =
+            new PrintStream(new FileOutputStream("out/" + gl10ExtFilename));
+        PrintStream gl11Stream =
+            new PrintStream(new FileOutputStream("out/" + gl11Filename));
+        PrintStream gl11ExtStream =
+            new PrintStream(new FileOutputStream("out/" + gl11ExtFilename));
+        PrintStream gl11ExtPackStream =
+            new PrintStream(new FileOutputStream("out/" + gl11ExtPackFilename));
+        PrintStream glImplStream =
+            new PrintStream(new FileOutputStream("out/" + glImplFilename));
+        PrintStream cStream =
+            new PrintStream(new FileOutputStream("out/" + cFilename));
+
+        ParameterChecker checker = new ParameterChecker(checksReader);
+
+        CodeEmitter emitter =
+            new JniCodeEmitter(classPathName,
+                               checker,
+                               gl10Stream, gl10ExtStream,
+                               gl11Stream, gl11ExtStream, gl11ExtPackStream,
+                               glImplStream, cStream,
+                               useContextPointer);
+
+        gl10Stream.println("/* //device/java/android/" + gl10Filename);
+        gl10ExtStream.println("/* //device/java/android/" + gl10ExtFilename);
+        gl11Stream.println("/* //device/java/android/" + gl11Filename);
+        gl11ExtStream.println("/* //device/java/android/" + gl11ExtFilename);
+        gl11ExtPackStream.println("/* //device/java/android/" +
+            gl11ExtPackFilename);
+        glImplStream.println("/* //device/java/android/" + glImplFilename);
+        cStream.println("/* //device/libs/android_runtime/" + cFilename);
+
+        copy("stubs/GL10Header.java-if", gl10Stream);
+        copy("stubs/GL10ExtHeader.java-if", gl10ExtStream);
+        copy("stubs/GL11Header.java-if", gl11Stream);
+        copy("stubs/GL11ExtHeader.java-if", gl11ExtStream);
+        copy("stubs/GL11ExtensionPackHeader.java-if", gl11ExtPackStream);
+        copy("stubs/GLImplHeader.java-impl", glImplStream);
+        copy("stubs/GLCHeader.cpp", cStream);
+
+        emit(0, false, false,
+             emitter, spec10Reader, gl10Stream, glImplStream, cStream);
+        emit(0, true, false,
+             emitter, spec10ExtReader, gl10ExtStream, glImplStream, cStream);
+        emit(1, false, false,
+             emitter, spec11Reader, gl11Stream, glImplStream, cStream);
+        emit(1, true, false,
+             emitter, spec11ExtReader, gl11ExtStream, glImplStream, cStream);
+        emit(1, true, true,
+             emitter, spec11ExtPackReader, gl11ExtPackStream, glImplStream,
+             cStream);
+
+        emitter.emitNativeRegistration();
+
+        gl10Stream.println("}");
+        gl10ExtStream.println("}");
+        gl11Stream.println("}");
+        gl11ExtStream.println("}");
+        gl11ExtPackStream.println("}");
+        glImplStream.println("}");
+    }
+}
diff --git a/opengl/tools/glgen/src/JFunc.java b/opengl/tools/glgen/src/JFunc.java
index 42d466c..68f717c 100644
--- a/opengl/tools/glgen/src/JFunc.java
+++ b/opengl/tools/glgen/src/JFunc.java
@@ -1,148 +1,149 @@
-

-import java.util.ArrayList;

-import java.util.List;

-

-public class JFunc {

-

-    String className = "com.google.android.gles_jni.GL11Impl";

-

-    CFunc cfunc;

-    JType ftype;

-    String fname;

-

-    List<String> argNames = new ArrayList<String>();

-    List<JType> argTypes = new ArrayList<JType>();

-    List<Integer> argCIndices = new ArrayList<Integer>();

-

-    boolean hasBufferArg = false;

-    boolean hasTypedBufferArg = false;

-    ArrayList<String> bufferArgNames = new ArrayList<String>();

-

-    public JFunc(CFunc cfunc) {

-        this.cfunc = cfunc;

-    }

-

-    public CFunc getCFunc() {

-        return cfunc;

-    }

-

-    public void setName(String fname) {

-        this.fname = fname;

-    }

-

-    public String getName() {

-        return fname;

-    }

-

-    public void setType(JType ftype) {

-        this.ftype = ftype;

-    }

-

-    public JType getType() {

-        return ftype;

-    }

-

-    public void setClassName(String className) {

-        this.className = className;

-    }

-

-    public String getClassName() {

-        return className;

-    }

-    

-    public boolean hasBufferArg() {

-        return hasBufferArg;

-    }

-

-    public boolean hasTypedBufferArg() {

-        return hasTypedBufferArg;

-    }

-

-    public String getBufferArgName(int index) {

-        return bufferArgNames.get(index);

-    }

-

-    public void addArgument(String argName, JType argType, int cindex) {

-        argNames.add(argName);

-        argTypes.add(argType);

-        argCIndices.add(new Integer(cindex));

-

-        if (argType.isBuffer()) {

-            hasBufferArg = true;

-            bufferArgNames.add(argName);

-        }

-        if (argType.isTypedBuffer()) {

-            hasTypedBufferArg = true;

-            bufferArgNames.add(argName);

-        }

-    }

-

-    public int getNumArgs() {

-        return argNames.size();

-    }

-

-    public int getArgIndex(String name) {

-        int len = argNames.size();

-        for (int i = 0; i < len; i++) {

-            if (name.equals(argNames.get(i))) {

-                return i;

-            }

-        }

-        return -1;

-    }

-

-    public String getArgName(int index) {

-        return argNames.get(index);

-    }

-

-    public JType getArgType(int index) {

-        return argTypes.get(index);

-    }

-

-    public int getArgCIndex(int index) {

-        return argCIndices.get(index).intValue();

-    }

-

-    public static JFunc convert(CFunc cfunc, boolean useArray) {

-        JFunc jfunc = new JFunc(cfunc);

-        jfunc.setName(cfunc.getName());

-        jfunc.setType(JType.convert(cfunc.getType(), false));

-	

-        int numArgs = cfunc.getNumArgs();

-        int numOffsets = 0;

-        for (int i = 0; i < numArgs; i++) {

-            CType cArgType = cfunc.getArgType(i);

-            if (cArgType.isTypedPointer() && useArray) {

-                ++numOffsets;

-            }

-        }

-

-        for (int i = 0; i < numArgs; i++) {

-            String cArgName = cfunc.getArgName(i);

-            CType cArgType = cfunc.getArgType(i);

-

-            jfunc.addArgument(cArgName, JType.convert(cArgType, useArray), i);

-            if (cArgType.isTypedPointer() && useArray) {

-                if (numOffsets > 1) {

-                    jfunc.addArgument(cArgName + "Offset", new JType("int"), i);

-                } else {

-                    jfunc.addArgument("offset", new JType("int"), i);

-                }

-            }

-        }

-

-        return jfunc;

-    }

-

-    public String toString() {

-        String s =  "Function " + fname + " returns " + ftype + ": ";

-        for (int i = 0; i < argNames.size(); i++) {

-            if (i > 0) {

-                s += ", ";

-            }

-            s += argTypes.get(i) + " " + argNames.get(i);

-        }

-        return s;

-    }

-

-}

+
+import java.util.ArrayList;
+import java.util.List;
+
+public class JFunc {
+
+    String className = "com.google.android.gles_jni.GL11Impl";
+
+    CFunc cfunc;
+    JType ftype;
+    String fname;
+
+    List<String> argNames = new ArrayList<String>();
+    List<JType> argTypes = new ArrayList<JType>();
+    List<Integer> argCIndices = new ArrayList<Integer>();
+
+    boolean hasBufferArg = false;
+    boolean hasTypedBufferArg = false;
+    ArrayList<String> bufferArgNames = new ArrayList<String>();
+
+    public JFunc(CFunc cfunc) {
+        this.cfunc = cfunc;
+    }
+
+    public CFunc getCFunc() {
+        return cfunc;
+    }
+
+    public void setName(String fname) {
+        this.fname = fname;
+    }
+
+    public String getName() {
+        return fname;
+    }
+
+    public void setType(JType ftype) {
+        this.ftype = ftype;
+    }
+
+    public JType getType() {
+        return ftype;
+    }
+
+    public void setClassName(String className) {
+        this.className = className;
+    }
+
+    public String getClassName() {
+        return className;
+    }
+
+    public boolean hasBufferArg() {
+        return hasBufferArg;
+    }
+
+    public boolean hasTypedBufferArg() {
+        return hasTypedBufferArg;
+    }
+
+    public String getBufferArgName(int index) {
+        return bufferArgNames.get(index);
+    }
+
+    public void addArgument(String argName, JType argType, int cindex) {
+        argNames.add(argName);
+        argTypes.add(argType);
+        argCIndices.add(new Integer(cindex));
+
+        if (argType.isBuffer()) {
+            hasBufferArg = true;
+            bufferArgNames.add(argName);
+        }
+        if (argType.isTypedBuffer()) {
+            hasTypedBufferArg = true;
+            bufferArgNames.add(argName);
+        }
+    }
+
+    public int getNumArgs() {
+        return argNames.size();
+    }
+
+    public int getArgIndex(String name) {
+        int len = argNames.size();
+        for (int i = 0; i < len; i++) {
+            if (name.equals(argNames.get(i))) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    public String getArgName(int index) {
+        return argNames.get(index);
+    }
+
+    public JType getArgType(int index) {
+        return argTypes.get(index);
+    }
+
+    public int getArgCIndex(int index) {
+        return argCIndices.get(index).intValue();
+    }
+
+    public static JFunc convert(CFunc cfunc, boolean useArray) {
+        JFunc jfunc = new JFunc(cfunc);
+        jfunc.setName(cfunc.getName());
+        jfunc.setType(JType.convert(cfunc.getType(), false));
+
+        int numArgs = cfunc.getNumArgs();
+        int numOffsets = 0;
+        for (int i = 0; i < numArgs; i++) {
+            CType cArgType = cfunc.getArgType(i);
+            if (cArgType.isTypedPointer() && useArray) {
+                ++numOffsets;
+            }
+        }
+
+        for (int i = 0; i < numArgs; i++) {
+            String cArgName = cfunc.getArgName(i);
+            CType cArgType = cfunc.getArgType(i);
+
+            jfunc.addArgument(cArgName, JType.convert(cArgType, useArray), i);
+            if (cArgType.isTypedPointer() && useArray) {
+                if (numOffsets > 1) {
+                    jfunc.addArgument(cArgName + "Offset", new JType("int"), i);
+                } else {
+                    jfunc.addArgument("offset", new JType("int"), i);
+                }
+            }
+        }
+
+        return jfunc;
+    }
+
+    @Override
+    public String toString() {
+        String s =  "Function " + fname + " returns " + ftype + ": ";
+        for (int i = 0; i < argNames.size(); i++) {
+            if (i > 0) {
+                s += ", ";
+            }
+            s += argTypes.get(i) + " " + argNames.get(i);
+        }
+        return s;
+    }
+
+}
diff --git a/opengl/tools/glgen/src/JType.java b/opengl/tools/glgen/src/JType.java
index a16d440..5ad0e54 100644
--- a/opengl/tools/glgen/src/JType.java
+++ b/opengl/tools/glgen/src/JType.java
@@ -1,139 +1,140 @@
-

-import java.util.HashMap;

-

-public class JType {

-    

-    String baseType;

-    boolean isArray;

-    boolean isClass;

-

-    static HashMap<CType,JType> typeMapping = new HashMap<CType,JType>();

-    static HashMap<CType,JType> arrayTypeMapping = new HashMap<CType,JType>();

-

-    static {

-	// Primitive types

-	typeMapping.put(new CType("GLbitfield"), new JType("int"));

-	typeMapping.put(new CType("GLboolean"), new JType("boolean"));

-	typeMapping.put(new CType("GLclampf"), new JType("float"));

-	typeMapping.put(new CType("GLclampx"), new JType("int"));

-	typeMapping.put(new CType("GLenum"), new JType("int"));

-	typeMapping.put(new CType("GLfloat"), new JType("float"));

-	typeMapping.put(new CType("GLfixed"), new JType("int"));

-	typeMapping.put(new CType("GLint"), new JType("int"));

-	typeMapping.put(new CType("GLintptr"), new JType("int"));

-	typeMapping.put(new CType("GLshort"), new JType("short"));

-	typeMapping.put(new CType("GLsizei"), new JType("int"));

-	typeMapping.put(new CType("GLsizeiptr"), new JType("int"));

-	typeMapping.put(new CType("GLubyte"), new JType("byte"));

-	typeMapping.put(new CType("GLuint"), new JType("int"));

-	typeMapping.put(new CType("void"), new JType("void"));

-	typeMapping.put(new CType("GLubyte", true, true), new JType("String"));

-

-	// Untyped pointers map to untyped Buffers

-	typeMapping.put(new CType("GLvoid", true, true),

-			new JType("java.nio.Buffer", true, false));

-	typeMapping.put(new CType("GLvoid", false, true),

-			new JType("java.nio.Buffer", true, false));

-	typeMapping.put(new CType("void", false, true),

-			new JType("java.nio.Buffer", true, false));

-

-	// Typed pointers map to typed Buffers

-	typeMapping.put(new CType("GLboolean", false, true),

-			new JType("java.nio.IntBuffer", true, false));

-	typeMapping.put(new CType("GLfixed", false, true),

-			new JType("java.nio.IntBuffer", true, false));

-	typeMapping.put(new CType("GLfixed", true, true),

-			new JType("java.nio.IntBuffer", true, false));

-	typeMapping.put(new CType("GLfloat", false, true),

-			new JType("java.nio.FloatBuffer", true, false));

-	typeMapping.put(new CType("GLfloat", true, true),

-			new JType("java.nio.FloatBuffer", true, false));

-	typeMapping.put(new CType("GLint", false, true),

-			new JType("java.nio.IntBuffer", true, false));

-	typeMapping.put(new CType("GLint", true, true),

-			new JType("java.nio.IntBuffer", true, false));

-	typeMapping.put(new CType("GLuint", false, true),

-			new JType("java.nio.IntBuffer", true, false));

-	typeMapping.put(new CType("GLuint", true, true),

-			new JType("java.nio.IntBuffer", true, false));

-	typeMapping.put(new CType("GLshort", true, true),

-			new JType("java.nio.ShortBuffer", true, false));

-

-	// Typed pointers map to arrays + offsets

-	arrayTypeMapping.put(new CType("GLboolean", false, true),

-			     new JType("boolean", false, true));

-	arrayTypeMapping.put(new CType("GLfixed", true, true), new JType("int", false, true));

-	arrayTypeMapping.put(new CType("GLfixed", false, true), new JType("int", false, true));

-	arrayTypeMapping.put(new CType("GLfloat", false, true), new JType("float", false, true));

-	arrayTypeMapping.put(new CType("GLfloat", true, true), new JType("float", false, true));

-	arrayTypeMapping.put(new CType("GLint", false, true), new JType("int", false, true));

-	arrayTypeMapping.put(new CType("GLint", true, true), new JType("int", false, true));

-	arrayTypeMapping.put(new CType("GLshort", true, true), new JType("short", false, true));

-	arrayTypeMapping.put(new CType("GLuint", false, true), new JType("int", false, true));

-	arrayTypeMapping.put(new CType("GLuint", true, true), new JType("int", false, true));

-	arrayTypeMapping.put(new CType("GLintptr"), new JType("int", false, true));

-	arrayTypeMapping.put(new CType("GLsizeiptr"), new JType("int", false, true));

-    }

-

-    public JType() {

-    }

-

-    public JType(String primitiveTypeName) {

-	this.baseType = primitiveTypeName;

-	this.isClass = false;

-	this.isArray = false;

-    }

-

-    public JType(String primitiveTypeName, boolean isClass, boolean isArray) {

-	this.baseType = primitiveTypeName;

-	this.isClass = isClass;

-	this.isArray = isArray;

-    }

-

-    public String getBaseType() {

-	return baseType;

-    }

-

-    public String toString() {

-	return baseType + (isArray ? "[]" : "");

-    }

-

-    public boolean isArray() {

-	return isArray;

-    }

-

-    public boolean isClass() {

-	return isClass;

-    }

-

-    public boolean isPrimitive() {

-	return !isClass() && !isArray();

-    }

-

-    public boolean isVoid() {

-	return baseType.equals("void");

-    }

-

-    public boolean isBuffer() {

-	return baseType.indexOf("Buffer") != -1;

-    }

-

-    public boolean isTypedBuffer() {

-	return !baseType.equals("java.nio.Buffer") &&

-	    (baseType.indexOf("Buffer") != -1);

-    }

-

-    public static JType convert(CType ctype, boolean useArray) {

- 	JType javaType = null;

- 	if (useArray) {

- 	    javaType = arrayTypeMapping.get(ctype);

- 	}

- 	if (javaType == null) {

- 	    javaType = typeMapping.get(ctype);

- 	}

- 	if (javaType == null) {

- 	    throw new RuntimeException("Unsupported C type: " + ctype);

- 	}

- 	return javaType;

-    }

-}

+
+import java.util.HashMap;
+
+public class JType {
+
+    String baseType;
+    boolean isArray;
+    boolean isClass;
+
+    static HashMap<CType,JType> typeMapping = new HashMap<CType,JType>();
+    static HashMap<CType,JType> arrayTypeMapping = new HashMap<CType,JType>();
+
+    static {
+    // Primitive types
+    typeMapping.put(new CType("GLbitfield"), new JType("int"));
+    typeMapping.put(new CType("GLboolean"), new JType("boolean"));
+    typeMapping.put(new CType("GLclampf"), new JType("float"));
+    typeMapping.put(new CType("GLclampx"), new JType("int"));
+    typeMapping.put(new CType("GLenum"), new JType("int"));
+    typeMapping.put(new CType("GLfloat"), new JType("float"));
+    typeMapping.put(new CType("GLfixed"), new JType("int"));
+    typeMapping.put(new CType("GLint"), new JType("int"));
+    typeMapping.put(new CType("GLintptr"), new JType("int"));
+    typeMapping.put(new CType("GLshort"), new JType("short"));
+    typeMapping.put(new CType("GLsizei"), new JType("int"));
+    typeMapping.put(new CType("GLsizeiptr"), new JType("int"));
+    typeMapping.put(new CType("GLubyte"), new JType("byte"));
+    typeMapping.put(new CType("GLuint"), new JType("int"));
+    typeMapping.put(new CType("void"), new JType("void"));
+    typeMapping.put(new CType("GLubyte", true, true), new JType("String"));
+
+    // Untyped pointers map to untyped Buffers
+    typeMapping.put(new CType("GLvoid", true, true),
+            new JType("java.nio.Buffer", true, false));
+    typeMapping.put(new CType("GLvoid", false, true),
+            new JType("java.nio.Buffer", true, false));
+    typeMapping.put(new CType("void", false, true),
+            new JType("java.nio.Buffer", true, false));
+
+    // Typed pointers map to typed Buffers
+    typeMapping.put(new CType("GLboolean", false, true),
+            new JType("java.nio.IntBuffer", true, false));
+    typeMapping.put(new CType("GLfixed", false, true),
+            new JType("java.nio.IntBuffer", true, false));
+    typeMapping.put(new CType("GLfixed", true, true),
+            new JType("java.nio.IntBuffer", true, false));
+    typeMapping.put(new CType("GLfloat", false, true),
+            new JType("java.nio.FloatBuffer", true, false));
+    typeMapping.put(new CType("GLfloat", true, true),
+            new JType("java.nio.FloatBuffer", true, false));
+    typeMapping.put(new CType("GLint", false, true),
+            new JType("java.nio.IntBuffer", true, false));
+    typeMapping.put(new CType("GLint", true, true),
+            new JType("java.nio.IntBuffer", true, false));
+    typeMapping.put(new CType("GLuint", false, true),
+            new JType("java.nio.IntBuffer", true, false));
+    typeMapping.put(new CType("GLuint", true, true),
+            new JType("java.nio.IntBuffer", true, false));
+    typeMapping.put(new CType("GLshort", true, true),
+            new JType("java.nio.ShortBuffer", true, false));
+
+    // Typed pointers map to arrays + offsets
+    arrayTypeMapping.put(new CType("GLboolean", false, true),
+                 new JType("boolean", false, true));
+    arrayTypeMapping.put(new CType("GLfixed", true, true), new JType("int", false, true));
+    arrayTypeMapping.put(new CType("GLfixed", false, true), new JType("int", false, true));
+    arrayTypeMapping.put(new CType("GLfloat", false, true), new JType("float", false, true));
+    arrayTypeMapping.put(new CType("GLfloat", true, true), new JType("float", false, true));
+    arrayTypeMapping.put(new CType("GLint", false, true), new JType("int", false, true));
+    arrayTypeMapping.put(new CType("GLint", true, true), new JType("int", false, true));
+    arrayTypeMapping.put(new CType("GLshort", true, true), new JType("short", false, true));
+    arrayTypeMapping.put(new CType("GLuint", false, true), new JType("int", false, true));
+    arrayTypeMapping.put(new CType("GLuint", true, true), new JType("int", false, true));
+    arrayTypeMapping.put(new CType("GLintptr"), new JType("int", false, true));
+    arrayTypeMapping.put(new CType("GLsizeiptr"), new JType("int", false, true));
+    }
+
+    public JType() {
+    }
+
+    public JType(String primitiveTypeName) {
+    this.baseType = primitiveTypeName;
+    this.isClass = false;
+    this.isArray = false;
+    }
+
+    public JType(String primitiveTypeName, boolean isClass, boolean isArray) {
+    this.baseType = primitiveTypeName;
+    this.isClass = isClass;
+    this.isArray = isArray;
+    }
+
+    public String getBaseType() {
+    return baseType;
+    }
+
+    @Override
+    public String toString() {
+    return baseType + (isArray ? "[]" : "");
+    }
+
+    public boolean isArray() {
+    return isArray;
+    }
+
+    public boolean isClass() {
+    return isClass;
+    }
+
+    public boolean isPrimitive() {
+    return !isClass() && !isArray();
+    }
+
+    public boolean isVoid() {
+    return baseType.equals("void");
+    }
+
+    public boolean isBuffer() {
+    return baseType.indexOf("Buffer") != -1;
+    }
+
+    public boolean isTypedBuffer() {
+    return !baseType.equals("java.nio.Buffer") &&
+        (baseType.indexOf("Buffer") != -1);
+    }
+
+    public static JType convert(CType ctype, boolean useArray) {
+     JType javaType = null;
+     if (useArray) {
+         javaType = arrayTypeMapping.get(ctype);
+     }
+     if (javaType == null) {
+         javaType = typeMapping.get(ctype);
+     }
+     if (javaType == null) {
+         throw new RuntimeException("Unsupported C type: " + ctype);
+     }
+     return javaType;
+    }
+}
diff --git a/opengl/tools/glgen/src/JniCodeEmitter.java b/opengl/tools/glgen/src/JniCodeEmitter.java
index 33b9a3e..2a8bcbb8 100644
--- a/opengl/tools/glgen/src/JniCodeEmitter.java
+++ b/opengl/tools/glgen/src/JniCodeEmitter.java
@@ -1,6 +1,4 @@
 import java.io.PrintStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -24,7 +22,7 @@
     boolean mUseContextPointer = true;
 
     String mClassPathName;
-    
+
     ParameterChecker mChecker;
     PrintStream mJava10InterfaceStream;
     PrintStream mJava10ExtInterfaceStream;
@@ -47,7 +45,7 @@
     /**
      * @param java10InterfaceStream the PrintStream to which to emit the Java interface for GL 1.0 functions
      * @param java10ExtInterfaceStream the PrintStream to which to emit the Java interface for GL 1.0 extension functions
-     * @param java11InterfaceStream the PrintStream to which to emit the Java interface for GL 1.1 functions 
+     * @param java11InterfaceStream the PrintStream to which to emit the Java interface for GL 1.1 functions
      * @param java11ExtInterfaceStream the PrintStream to which to emit the Java interface for GL 1.1 Extension functions
      * @param java11ExtPackInterfaceStream the PrintStream to which to emit the Java interface for GL 1.1 Extension Pack functions
      * @param javaImplStream the PrintStream to which to emit the Java implementation
@@ -93,7 +91,7 @@
         JFunc jfunc;
         String signature;
         boolean duplicate;
-        
+
         if (cfunc.hasTypedPointerArg()) {
             jfunc = JFunc.convert(cfunc, true);
 
@@ -152,7 +150,7 @@
     public void emitJavaCode(JFunc jfunc, PrintStream out) {
         emitFunction(jfunc, out, false, false);
     }
-    
+
     void emitFunctionCall(JFunc jfunc, PrintStream out, String iii, boolean grabArray ) {
         boolean isVoid = jfunc.getType().isVoid();
         boolean isPointerFunc = jfunc.getName().endsWith("Pointer") &&
@@ -167,7 +165,7 @@
                     jfunc.getName() +
                     (isPointerFunc ? "Bounds" : "" ) +
                     "(");
-	
+
         int numArgs = jfunc.getNumArgs();
         for (int i = 0; i < numArgs; i++) {
             String argName = jfunc.getArgName(i);
@@ -177,7 +175,7 @@
                 String typeName = argType.getBaseType();
                 typeName = typeName.substring(9, typeName.length() - 6);
                 out.println(iii + indent + "get" + typeName + "Array(" + argName + "),");
-                out.print(iii + indent + "getOffset(" + argName + ")"); 
+                out.print(iii + indent + "getOffset(" + argName + ")");
             } else {
                 out.print(iii + indent + argName);
             }
@@ -192,7 +190,7 @@
                 out.println(",");
             }
         }
-	
+
         out.println(iii + ");");
     }
 
@@ -220,7 +218,7 @@
                     (mUseCPlusPlus ? "" : "_env, ") +
                     "IAEClass, " +
                     "\"" +
-                    (isBuffer ? 
+                    (isBuffer ?
                      "remaining()" : "length - " + offset) +
                     " < needed\");");
         out.println(iii + indent + "goto exit;");
@@ -345,21 +343,21 @@
                     if (emitExceptionCheck) {
                         out.println(iii + indent + "_exception = 1;");
                     }
-		    String exceptionClassName = "IAEClass";
-		    // If the "check" keyword was of the form
-		    // "check_<class name>", use the class name in the
-		    // exception to be thrown
-		    int underscore = checks[index].indexOf('_');
-		    if (underscore >= 0) {
-			exceptionClassName = checks[index].substring(underscore + 1) + "Class";
-		    }
+            String exceptionClassName = "IAEClass";
+            // If the "check" keyword was of the form
+            // "check_<class name>", use the class name in the
+            // exception to be thrown
+            int underscore = checks[index].indexOf('_');
+            if (underscore >= 0) {
+            exceptionClassName = checks[index].substring(underscore + 1) + "Class";
+            }
                     out.println(iii + indent +
                                 (mUseCPlusPlus ? "_env" : "(*_env)") +
                                 "->ThrowNew(" +
                                 (mUseCPlusPlus ? "" : "_env, ") +
-				exceptionClassName + ", " +
+                exceptionClassName + ", " +
                                 "\"" +
-                                (isBuffer ? 
+                                (isBuffer ?
                                  "remaining()" : "length - " + offset) +
                                 " < " + checks[index + 2] +
                                 "\");");
@@ -367,7 +365,7 @@
                     out.println(iii + indent + "goto exit;");
                     needsExit = true;
                     out.println(iii + "}");
-                
+
                     index += 3;
                 } else if (checks[index].equals("ifcheck")) {
                     String[] matches = checks[index + 4].split(",");
@@ -379,7 +377,7 @@
                                     checks[index + 3] +
                                     ") {");
                     }
-                    
+
                     for (int i = 0; i < matches.length; i++) {
                         out.println("#if defined(" + matches[i] + ")");
                         out.println(iii +
@@ -394,7 +392,7 @@
                                 ";");
                     out.println(iii +
                                 "        break;");
-                
+
                     lastWasIfcheck = true;
                     index += 5;
                 } else if (checks[index].equals("return")) {
@@ -439,7 +437,7 @@
 
         return false;
     }
-    
+
     /**
      * Emit a function in several variants:
      *
@@ -478,12 +476,12 @@
                         jfunc.getName() +
                         "(");
         }
-	
+
         int numArgs = jfunc.getNumArgs();
         for (int i = 0; i < numArgs; i++) {
             String argName = jfunc.getArgName(i);
             JType argType = jfunc.getArgType(i);
-	    
+
             out.print(indent + indent + argType + " " + argName);
             if (i == numArgs - 1) {
                 if (isPointerFunc && nativeDecl) {
@@ -568,7 +566,7 @@
         } else if (jType.isArray()) {
             jniName = "[";
         }
-	
+
         String baseType = jType.getBaseType();
         if (baseType.equals("int")) {
             jniName += "I";
@@ -604,7 +602,7 @@
             return "jobject";
         }
     }
-    
+
     String getJniMangledName(String name) {
         name = name.replaceAll("_", "_1");
         name = name.replaceAll(";", "_2");
@@ -614,7 +612,7 @@
 
     public void emitJniCode(JFunc jfunc, PrintStream out) {
         CFunc cfunc = jfunc.getCFunc();
-	
+
         // Emit comment identifying original C function
         //
         // Example:
@@ -658,13 +656,13 @@
         }
 
         // Append signature to function name
-        String sig = getJniMangledName(signature).replace('.', '_');        
+        String sig = getJniMangledName(signature).replace('.', '_');
         out.print("__" + sig);
         outName += "__" + sig;
-	
+
         signature = signature.replace('.', '/');
         rsignature = rsignature.replace('.', '/');
-	
+
         out.println();
         if (rsignature.length() == 0) {
             rsignature = "V";
@@ -718,7 +716,7 @@
             out.print(", jint remaining");
         }
         out.println(") {");
-	
+
         int numArrays = 0;
         int numBuffers = 0;
         for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
@@ -740,7 +738,7 @@
         // Example:
         //
         // android::gl::ogles_context_t *ctx;
-        // 
+        //
         // jint _exception;
         // GLenum _returnValue;
         //
@@ -827,7 +825,7 @@
                 out.println(indent +
                             decl +
                             (decl.endsWith("*") ? "" : " ") +
-                            jfunc.getArgName(idx) + 
+                            jfunc.getArgName(idx) +
                             " = (" + decl + ") 0;");
             }
 
@@ -843,7 +841,7 @@
             for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
                 int idx = nonPrimitiveArgs.get(i).intValue();
                 int cIndex = jfunc.getArgCIndex(idx);
-		
+
                 String cname = cfunc.getArgName(cIndex);
                 offset = numArrays <= 1 ? "offset" :
                     cname + "Offset";
@@ -852,7 +850,7 @@
 
                 if (jfunc.getArgType(idx).isArray()) {
                     out.println(indent +
-                                "if (!" + 
+                                "if (!" +
                                 cname +
                                 "_ref) {");
                     if (emitExceptionCheck) {
@@ -884,7 +882,7 @@
                     out.println(indent + "}");
 
                     out.println(indent + remaining + " = " +
-                                    (mUseCPlusPlus ? "_env" : "(*_env)") + 
+                                    (mUseCPlusPlus ? "_env" : "(*_env)") +
                                     "->GetArrayLength(" +
                                     (mUseCPlusPlus ? "" : "_env, ") +
                                     cname + "_ref) - " + offset + ";");
@@ -901,7 +899,7 @@
                     out.println(indent + "    " +
                                 (mUseCPlusPlus ? "_env" : "(*_env)") +
                                 "->GetPrimitiveArrayCritical(" +
-                                (mUseCPlusPlus ? "" : "_env, ") + 
+                                (mUseCPlusPlus ? "" : "_env, ") +
                                 jfunc.getArgName(idx) +
                                 "_ref, (jboolean *)0);");
                     out.println(indent +
@@ -917,7 +915,7 @@
                         out.println(indent + "if (" + cname + "_buf) {");
                         out.print(indent);
                     }
-                    
+
                     out.println(indent +
                                 cname +
                                 " = (" +
@@ -950,10 +948,10 @@
                 name.substring(1, name.length());
             out.print("ctx->procs.");
         }
-        
+
         out.print(name + (isPointerFunc ? "Bounds" : "") + "(");
 
-        numArgs = cfunc.getNumArgs();    
+        numArgs = cfunc.getNumArgs();
         if (numArgs == 0) {
             if (mUseContextPointer) {
                 out.println("ctx);");
@@ -1006,7 +1004,7 @@
 
                 int cIndex = jfunc.getArgCIndex(idx);
                 if (jfunc.getArgType(idx).isArray()) {
-		    
+
                     // If the argument is 'const', GL will not write to it.
                     // In this case, we can use the 'JNI_ABORT' flag to avoid
                     // the need to write back to the Java array
@@ -1015,7 +1013,7 @@
                     out.println(indent + indent +
                                 (mUseCPlusPlus ? "_env" : "(*_env)") +
                                 "->ReleasePrimitiveArrayCritical(" +
-                                (mUseCPlusPlus ? "" : "_env, ") + 
+                                (mUseCPlusPlus ? "" : "_env, ") +
                                 jfunc.getArgName(idx) + "_ref, " +
                                 cfunc.getArgName(cIndex) +
                                 "_base,");
@@ -1070,7 +1068,7 @@
 
         mCStream.println("};");
         mCStream.println();
-    
+
 
         mCStream.println("int register_com_google_android_gles_jni_GLImpl(JNIEnv *_env)");
         mCStream.println("{");
diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java
index 7cd6b17..90d8c9d 100644
--- a/services/java/com/android/server/BatteryService.java
+++ b/services/java/com/android/server/BatteryService.java
@@ -84,7 +84,7 @@
     private static final int CRITICAL_BATTERY_LEVEL = 4; 
 
     private static final int DUMP_MAX_LENGTH = 24 * 1024;
-    private static final String[] DUMPSYS_ARGS = new String[] { "-c", "-u" };
+    private static final String[] DUMPSYS_ARGS = new String[] { "--checkin", "-u" };
     private static final String BATTERY_STATS_SERVICE_NAME = "batteryinfo";
     
     private static final String DUMPSYS_DATA_PATH = "/data/system/";
@@ -247,6 +247,20 @@
                 logOutlier = true;
             }
             
+            // Separate broadcast is sent for power connected / not connected
+            // since the standard intent will not wake any applications and some
+            // applications may want to have smart behavior based on this.
+            if (mPlugType != 0 && mLastPlugType == 0) {
+                Intent intent = new Intent(Intent.ACTION_POWER_CONNECTED);
+                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+                mContext.sendBroadcast(intent);
+            }
+            else if (mPlugType == 0 && mLastPlugType != 0) {
+                Intent intent = new Intent(Intent.ACTION_POWER_DISCONNECTED);
+                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+                mContext.sendBroadcast(intent);
+            }
+            
             mLastBatteryStatus = mBatteryStatus;
             mLastBatteryHealth = mBatteryHealth;
             mLastBatteryPresent = mBatteryPresent;
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 0b1ddc8..b0fcb1c 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -77,7 +77,6 @@
 import android.os.SystemProperties;
 import android.os.TokenWatcher;
 import android.provider.Settings;
-import android.util.Config;
 import android.util.EventLog;
 import android.util.Log;
 import android.util.SparseIntArray;
@@ -137,7 +136,7 @@
     
     static final boolean PROFILE_ORIENTATION = false;
     static final boolean BLUR = true;
-    static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
+    static final boolean localLOGV = DEBUG;
     
     static final int LOG_WM_NO_SURFACE_MEMORY = 31000;
     
@@ -2023,7 +2022,7 @@
             wtoken.appFullscreen = fullscreen;
             wtoken.requestedOrientation = requestedOrientation;
             mAppTokens.add(addPos, wtoken);
-            if (Config.LOGV) Log.v(TAG, "Adding new app token: " + wtoken);
+            if (localLOGV) Log.v(TAG, "Adding new app token: " + wtoken);
             mTokenMap.put(token.asBinder(), wtoken);
             mTokenList.add(wtoken);
             
@@ -4801,14 +4800,11 @@
                     mPaused = true;
                 } else {
                     if (mLastWin == null) {
-                        if (Config.LOGI) Log.i(
-                            TAG, "Key dispatching not paused: no last window.");
+                        Log.i(TAG, "Key dispatching not paused: no last window.");
                     } else if (mFinished) {
-                        if (Config.LOGI) Log.i(
-                            TAG, "Key dispatching not paused: finished last key.");
+                        Log.i(TAG, "Key dispatching not paused: finished last key.");
                     } else {
-                        if (Config.LOGI) Log.i(
-                            TAG, "Key dispatching not paused: window in higher layer.");
+                        Log.i(TAG, "Key dispatching not paused: window in higher layer.");
                     }
                 }
                 */
@@ -7423,7 +7419,7 @@
     private boolean mInLayout = false;
     private final void performLayoutAndPlaceSurfacesLocked() {
         if (mInLayout) {
-            if (Config.DEBUG) {
+            if (DEBUG) {
                 throw new RuntimeException("Recursive call!");
             }
             Log.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout");
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index d676c00..a3c23d3 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -682,6 +682,11 @@
     HashMap<String, IBinder> mAppBindArgs;
 
     /**
+     * Temporary to avoid allocations.  Protected by main lock.
+     */
+    final StringBuilder mStringBuilder = new StringBuilder(256);
+    
+    /**
      * Used to control how we initialize the service.
      */
     boolean mStartRunning = false;
@@ -778,6 +783,8 @@
     long mLastCpuTime = 0;
     long mLastWriteTime = 0;
 
+    long mInitialStartTime = 0;
+    
     /**
      * Set to true after the system has finished booting.
      */
@@ -1270,7 +1277,7 @@
         mBatteryStatsService.getActiveStatistics().writeLocked();
         
         mUsageStatsService = new UsageStatsService( new File(
-                systemDir, "usagestats.bin").toString());
+                systemDir, "usagestats").toString());
 
         mConfiguration.makeDefault();
         mProcessStats.init();
@@ -1635,6 +1642,11 @@
         
         if (r.startTime == 0) {
             r.startTime = SystemClock.uptimeMillis();
+            if (mInitialStartTime == 0) {
+                mInitialStartTime = r.startTime;
+            }
+        } else if (mInitialStartTime == 0) {
+            mInitialStartTime = SystemClock.uptimeMillis();
         }
         
         if (app != null && app.thread != null) {
@@ -1785,7 +1797,8 @@
                 Watchdog.getInstance().processStarted(app, app.processName, pid);
             }
             
-            StringBuilder buf = new StringBuilder(128);
+            StringBuilder buf = mStringBuilder;
+            buf.setLength(0);
             buf.append("Start proc ");
             buf.append(app.processName);
             buf.append(" for ");
@@ -2813,7 +2826,6 @@
         HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
                 intent, resolvedType, aInfo, mConfiguration,
                 resultRecord, resultWho, requestCode, componentSpecified);
-        r.startTime = SystemClock.uptimeMillis();
 
         HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
                 != 0 ? r : null;
@@ -4095,7 +4107,8 @@
             }
         }
 
-        StringBuilder info = new StringBuilder();
+        StringBuilder info = mStringBuilder;
+        info.setLength(0);
         info.append("ANR (application not responding) in process: ");
         info.append(app.processName);
         if (annotation != null) {
@@ -4517,7 +4530,7 @@
             }
         } else if (mStartingProcesses.size() > 0) {
             app = mStartingProcesses.remove(0);
-            app.pid = pid;
+            app.setPid(pid);
         } else {
             app = null;
         }
@@ -7877,24 +7890,24 @@
                 return;
             }
             pw.println("Activities in Current Activity Manager State:");
-            dumpHistoryList(pw, mHistory, "  ", "History");
+            dumpHistoryList(pw, mHistory, "  ", "History", true);
             pw.println(" ");
             pw.println("  Running activities (most recent first):");
-            dumpHistoryList(pw, mLRUActivities, "  ", "Running");
+            dumpHistoryList(pw, mLRUActivities, "  ", "Running", false);
             if (mWaitingVisibleActivities.size() > 0) {
                 pw.println(" ");
                 pw.println("  Activities waiting for another to become visible:");
-                dumpHistoryList(pw, mWaitingVisibleActivities, "  ", "Waiting");
+                dumpHistoryList(pw, mWaitingVisibleActivities, "  ", "Waiting", false);
             }
             if (mStoppingActivities.size() > 0) {
                 pw.println(" ");
                 pw.println("  Activities waiting to stop:");
-                dumpHistoryList(pw, mStoppingActivities, "  ", "Stopping");
+                dumpHistoryList(pw, mStoppingActivities, "  ", "Stopping", false);
             }
             if (mFinishingActivities.size() > 0) {
                 pw.println(" ");
                 pw.println("  Activities waiting to finish:");
-                dumpHistoryList(pw, mFinishingActivities, "  ", "Finishing");
+                dumpHistoryList(pw, mFinishingActivities, "  ", "Finishing", false);
             }
 
             pw.println(" ");
@@ -7931,8 +7944,8 @@
                         needSep = true;
                     }
                     ProcessRecord r = procs.valueAt(ia);
-                    pw.println((r.persistent ? "  *PERSISTENT* Process [" : "  Process [")
-                            + r.processName + "] UID " + procs.keyAt(ia));
+                    pw.print(r.persistent ? "  *PERSISTENT* Process [" : "  Process [");
+                    pw.print(r.processName); pw.print("] UID "); pw.println(procs.keyAt(ia));
                     r.dump(pw, "    ");
                     if (r.persistent) {
                         numPers++;
@@ -8360,16 +8373,29 @@
     }
 
     private static final void dumpHistoryList(PrintWriter pw, List list,
-            String prefix, String label) {
+            String prefix, String label, boolean complete) {
         TaskRecord lastTask = null;
         for (int i=list.size()-1; i>=0; i--) {
             HistoryRecord r = (HistoryRecord)list.get(i);
             if (lastTask != r.task) {
                 lastTask = r.task;
-                lastTask.dump(pw, prefix + "  ");
+                if (complete || !r.inHistory) {
+                    lastTask.dump(pw, prefix + "  ");
+                } else {
+                    pw.print(prefix);
+                    pw.print("  ");
+                    pw.println(lastTask);
+                }
             }
-            pw.println(prefix + "    " + label + " #" + i + ":");
-            r.dump(pw, prefix + "      ");
+            if (complete || !r.inHistory) {
+                pw.print(prefix); pw.print("    "); pw.print(label);
+                        pw.print(" #"); pw.print(i); pw.println(":");
+                r.dump(pw, prefix + "      ");
+            } else {
+                pw.print(prefix); pw.print("    "); pw.print(label);
+                        pw.print(" #"); pw.print(i); pw.print(": ");
+                        pw.println(r);
+            }
         }
     }
 
@@ -8401,7 +8427,7 @@
 
     private static final void dumpApplicationMemoryUsage(FileDescriptor fd,
             PrintWriter pw, List list, String prefix, String[] args) {
-        final boolean isCheckinRequest = scanArgs(args, "-c");
+        final boolean isCheckinRequest = scanArgs(args, "--checkin");
         long uptime = SystemClock.uptimeMillis();
         long realtime = SystemClock.elapsedRealtime();
         
@@ -8738,7 +8764,7 @@
                 mPidsSelfLocked.remove(app.pid);
                 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
             }
-            app.pid = 0;
+            app.setPid(0);
         }
     }
 
diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java
index c5907af..e265f43 100644
--- a/services/java/com/android/server/am/BatteryStatsService.java
+++ b/services/java/com/android/server/am/BatteryStatsService.java
@@ -295,7 +295,7 @@
             boolean isCheckin = false;
             if (args != null) {
                 for (String arg : args) {
-                    if ("-c".equals(arg)) {
+                    if ("--checkin".equals(arg)) {
                         isCheckin = true;
                         break;
                     }
diff --git a/services/java/com/android/server/am/ConnectionRecord.java b/services/java/com/android/server/am/ConnectionRecord.java
index 41a783f..b4c7df1 100644
--- a/services/java/com/android/server/am/ConnectionRecord.java
+++ b/services/java/com/android/server/am/ConnectionRecord.java
@@ -28,7 +28,8 @@
     final HistoryRecord activity;   // If non-null, the owning activity.
     final IServiceConnection conn;  // The client connection.
     final int flags;                // Binding options.
-
+    String stringName;              // Caching of toString.
+    
     void dump(PrintWriter pw, String prefix) {
         pw.println(prefix + this);
         pw.println(prefix + "binding=" + binding);
@@ -46,9 +47,17 @@
     }
 
     public String toString() {
-        return "ConnectionRecord{"
-            + Integer.toHexString(System.identityHashCode(this))
-            + " " + binding.service.shortName
-            + ":@" + Integer.toHexString(System.identityHashCode(conn.asBinder())) + "}";
+        if (stringName != null) {
+            return stringName;
+        }
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("ConnectionRecord{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(' ');
+        sb.append(binding.service.shortName);
+        sb.append(":@");
+        sb.append(Integer.toHexString(System.identityHashCode(conn.asBinder())));
+        sb.append('}');
+        return stringName = sb.toString();
     }
 }
diff --git a/services/java/com/android/server/am/ContentProviderRecord.java b/services/java/com/android/server/am/ContentProviderRecord.java
index 9f37c14..2b9e006 100644
--- a/services/java/com/android/server/am/ContentProviderRecord.java
+++ b/services/java/com/android/server/am/ContentProviderRecord.java
@@ -32,7 +32,8 @@
     int externals;     // number of non-framework processes supported by this provider
     ProcessRecord app; // if non-null, hosting application
     ProcessRecord launchingApp; // if non-null, waiting for this app to be launched.
-
+    String stringName;
+    
     public ContentProviderRecord(ProviderInfo _info, ApplicationInfo ai) {
         super(_info);
         uid = ai.uid;
@@ -69,8 +70,15 @@
     }
 
     public String toString() {
-        return "ContentProviderRecord{"
-            + Integer.toHexString(System.identityHashCode(this))
-            + " " + info.name + "}";
+        if (stringName != null) {
+            return stringName;
+        }
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("ContentProviderRecord{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(' ');
+        sb.append(info.name);
+        sb.append('}');
+        return stringName = sb.toString();
     }
 }
diff --git a/services/java/com/android/server/am/HistoryRecord.java b/services/java/com/android/server/am/HistoryRecord.java
index 0f62471..a2fd62b 100644
--- a/services/java/com/android/server/am/HistoryRecord.java
+++ b/services/java/com/android/server/am/HistoryRecord.java
@@ -100,46 +100,74 @@
     boolean hasBeenLaunched;// has this activity ever been launched?
     boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.
 
+    String stringName;      // for caching of toString().
+    
     void dump(PrintWriter pw, String prefix) {
-        pw.println(prefix + this);
-        pw.println(prefix + "packageName=" + packageName
-              + " processName=" + processName);
-        pw.println(prefix + "launchedFromUid=" + launchedFromUid
-                + " app=" + app);
-        pw.println(prefix + intent);
-        pw.println(prefix + "frontOfTask=" + frontOfTask + " task=" + task);
-        pw.println(prefix + "taskAffinity=" + taskAffinity);
-        pw.println(prefix + "realActivity=" + realActivity);
-        pw.println(prefix + "dir=" + baseDir + " res=" + resDir + " data=" + dataDir);
-        pw.println(prefix + "labelRes=0x" + Integer.toHexString(labelRes)
-                + " icon=0x" + Integer.toHexString(icon)
-                + " theme=0x" + Integer.toHexString(theme));
-        pw.println(prefix + "stateNotNeeded=" + stateNotNeeded
-                + " componentSpecified=" + componentSpecified
-                + " isHomeActivity=" + isHomeActivity);
-        pw.println(prefix + "configuration=" + configuration);
-        pw.println(prefix + "resultTo=" + resultTo
-              + " resultWho=" + resultWho + " resultCode=" + requestCode);
-        pw.println(prefix + "results=" + results);
-        pw.println(prefix + "pendingResults=" + pendingResults);
-        pw.println(prefix + "readUriPermissions=" + readUriPermissions);
-        pw.println(prefix + "writeUriPermissions=" + writeUriPermissions);
-        pw.println(prefix + "launchFailed=" + launchFailed
-              + " haveState=" + haveState + " icicle=" + icicle);
-        pw.println(prefix + "state=" + state
-              + " stopped=" + stopped + " finishing=" + finishing);
-        pw.println(prefix + "keysPaused=" + keysPaused
-              + " inHistory=" + inHistory + " persistent=" + persistent
-              + " launchMode=" + launchMode);
-        pw.println(prefix + "fullscreen=" + fullscreen
-              + " visible=" + visible
-              + " frozenBeforeDestroy=" + frozenBeforeDestroy
-              + " thumbnailNeeded=" + thumbnailNeeded + " idle=" + idle);
-        pw.println(prefix + "waitingVisible=" + waitingVisible
-              + " nowVisible=" + nowVisible);
-        pw.println(prefix + "configDestroy=" + configDestroy
-                + " configChangeFlags=" + Integer.toHexString(configChangeFlags));
-        pw.println(prefix + "connections=" + connections);
+        pw.print(prefix); pw.println(this);
+        pw.print(prefix); pw.print("packageName="); pw.print(packageName);
+                pw.print(" processName="); pw.println(processName);
+        pw.print(prefix); pw.print("launchedFromUid="); pw.print(launchedFromUid);
+                pw.print(" app="); pw.println(app);
+        pw.print(prefix); pw.println(intent);
+        pw.print(prefix); pw.print("frontOfTask="); pw.print(frontOfTask);
+                pw.print(" task="); pw.println(task);
+        pw.print(prefix); pw.print("taskAffinity="); pw.println(taskAffinity);
+        pw.print(prefix); pw.print("realActivity="); pw.println(realActivity);
+        pw.print(prefix); pw.print("dir="); pw.print(baseDir);
+                pw.print(" res="); pw.print(resDir);
+                pw.print(" data="); pw.println(dataDir);
+        pw.print(prefix); pw.print("labelRes=0x");
+                pw.print(Integer.toHexString(labelRes));
+                pw.print(" icon=0x"); pw.print(Integer.toHexString(icon));
+                pw.print(" theme=0x"); pw.println(Integer.toHexString(theme));
+        pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded);
+                pw.print(" componentSpecified="); pw.print(componentSpecified);
+                pw.print(" isHomeActivity="); pw.println(isHomeActivity);
+        pw.print(prefix); pw.print("configuration="); pw.println(configuration);
+        if (resultTo != null || resultWho != null) {
+            pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
+                    pw.print(" resultWho="); pw.print(resultWho);
+                    pw.print(" resultCode="); pw.println(requestCode);
+        }
+        if (results != null) {
+            pw.print(prefix); pw.print("results="); pw.println(results);
+        }
+        if (pendingResults != null) {
+            pw.print(prefix); pw.print("pendingResults="); pw.println(pendingResults);
+        }
+        if (readUriPermissions != null) {
+            pw.print(prefix); pw.print("readUriPermissions="); pw.println(readUriPermissions);
+        }
+        if (writeUriPermissions != null) {
+            pw.print(prefix); pw.print("writeUriPermissions="); pw.println(writeUriPermissions);
+        }
+        pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed);
+                pw.print(" haveState="); pw.print(haveState);
+                pw.print(" icicle="); pw.println(icicle);
+        pw.print(prefix); pw.print("state="); pw.print(state);
+                pw.print(" stopped="); pw.print(stopped);
+                pw.print(" finishing="); pw.println(finishing);
+        pw.print(prefix); pw.print("keysPaused="); pw.print(keysPaused);
+                pw.print(" inHistory="); pw.print(inHistory);
+                pw.print(" persistent="); pw.print(persistent);
+                pw.print(" launchMode="); pw.println(launchMode);
+        pw.print(prefix); pw.print("fullscreen="); pw.print(fullscreen);
+                pw.print(" visible="); pw.print(visible);
+                pw.print(" frozenBeforeDestroy="); pw.print(frozenBeforeDestroy);
+                pw.print(" thumbnailNeeded="); pw.print(thumbnailNeeded);
+                pw.print(" idle="); pw.println(idle);
+        if (waitingVisible || nowVisible) {
+            pw.print(prefix); pw.print("waitingVisible="); pw.print(waitingVisible);
+                    pw.print(" nowVisible="); pw.println(nowVisible);
+        }
+        if (configDestroy || configChangeFlags != 0) {
+            pw.print(prefix); pw.print("configDestroy="); pw.print(configDestroy);
+                    pw.print(" configChangeFlags=");
+                    pw.println(Integer.toHexString(configChangeFlags));
+        }
+        if (connections != null) {
+            pw.print(prefix); pw.print("connections="); pw.println(connections);
+        }
     }
 
     HistoryRecord(ActivityManagerService _service, ProcessRecord _caller,
@@ -335,15 +363,31 @@
     
     public void windowsVisible() {
         synchronized(service) {
-            if (ActivityManagerService.SHOW_ACTIVITY_START_TIME
-                    && startTime != 0) {
-                long time = SystemClock.uptimeMillis() - startTime;
-                EventLog.writeEvent(ActivityManagerService.LOG_ACTIVITY_LAUNCH_TIME,
-                        System.identityHashCode(this), shortComponentName, time);
-                Log.i(ActivityManagerService.TAG, "Displayed activity "
-                        + shortComponentName
-                        + ": " + time + " ms");
+            if (startTime != 0) {
+                final long curTime = SystemClock.uptimeMillis();
+                final long thisTime = curTime - startTime;
+                final long totalTime = service.mInitialStartTime != 0
+                        ? (curTime - service.mInitialStartTime) : thisTime;
+                if (ActivityManagerService.SHOW_ACTIVITY_START_TIME) {
+                    EventLog.writeEvent(ActivityManagerService.LOG_ACTIVITY_LAUNCH_TIME,
+                            System.identityHashCode(this), shortComponentName,
+                            thisTime, totalTime);
+                    StringBuilder sb = service.mStringBuilder;
+                    sb.setLength(0);
+                    sb.append("Displayed activity ");
+                    sb.append(shortComponentName);
+                    sb.append(": ");
+                    sb.append(thisTime);
+                    sb.append(" ms (total ");
+                    sb.append(totalTime);
+                    sb.append(" ms)");
+                    Log.i(ActivityManagerService.TAG, sb.toString());
+                }
+                if (totalTime > 0) {
+                    service.mUsageStatsService.noteLaunchTime(realActivity, (int)totalTime);
+                }
                 startTime = 0;
+                service.mInitialStartTime = 0;
             }
             if (ActivityManagerService.DEBUG_SWITCH) Log.v(
                     ActivityManagerService.TAG, "windowsVisible(): " + this);
@@ -453,8 +497,15 @@
     
     
     public String toString() {
-        return "HistoryRecord{"
-            + Integer.toHexString(System.identityHashCode(this))
-            + " " + intent.getComponent().toShortString() + "}";
+        if (stringName != null) {
+            return stringName;
+        }
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("HistoryRecord{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(' ');
+        sb.append(intent.getComponent().toShortString());
+        sb.append('}');
+        return stringName = sb.toString();
     }
 }
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index a1320df..d2667e7 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -98,44 +98,82 @@
     boolean waitedForDebugger;  // has process show wait for debugger dialog?
     Dialog waitDialog;          // current wait for debugger dialog
     
+    String stringName;          // caching of toString() result.
+    
     // These reports are generated & stored when an app gets into an error condition.
     // They will be "null" when all is OK.
     ActivityManager.ProcessErrorStateInfo crashingReport;
     ActivityManager.ProcessErrorStateInfo notRespondingReport;
 
     void dump(PrintWriter pw, String prefix) {
-        pw.println(prefix + this);
-        pw.println(prefix + "class=" + info.className);
-        pw.println(prefix+"manageSpaceActivityName="+info.manageSpaceActivityName);
-        pw.println(prefix + "dir=" + info.sourceDir + " publicDir=" + info.publicSourceDir 
-              + " data=" + info.dataDir);
-        pw.println(prefix + "packageList=" + pkgList);
-        pw.println(prefix + "instrumentationClass=" + instrumentationClass
-              + " instrumentationProfileFile=" + instrumentationProfileFile);
-        pw.println(prefix + "instrumentationArguments=" + instrumentationArguments);
-        pw.println(prefix + "thread=" + thread + " curReceiver=" + curReceiver);
-        pw.println(prefix + "pid=" + pid + " starting=" + starting
-                + " lastPss=" + lastPss);
-        pw.println(prefix + "maxAdj=" + maxAdj + " hiddenAdj=" + hiddenAdj
-                + " curRawAdj=" + curRawAdj + " setRawAdj=" + setRawAdj
-                + " curAdj=" + curAdj + " setAdj=" + setAdj);
-        pw.println(prefix + "isForeground=" + isForeground
-                + " setIsForeground=" + setIsForeground
-                + " foregroundServices=" + foregroundServices
-                + " forcingToForeground=" + forcingToForeground);
-        pw.println(prefix + "persistent=" + persistent + " removed=" + removed
-                + " persistentActivities=" + persistentActivities);
-        pw.println(prefix + "debugging=" + debugging
-                + " crashing=" + crashing + " " + crashDialog
-                + " notResponding=" + notResponding + " " + anrDialog
-                + " bad=" + bad);
-        pw.println(prefix + "activities=" + activities);
-        pw.println(prefix + "services=" + services);
-        pw.println(prefix + "executingServices=" + executingServices);
-        pw.println(prefix + "connections=" + connections);
-        pw.println(prefix + "pubProviders=" + pubProviders);
-        pw.println(prefix + "conProviders=" + conProviders);
-        pw.println(prefix + "receivers=" + receivers);
+        pw.print(prefix); pw.println(this);
+        if (info.className != null) {
+            pw.print(prefix); pw.print("class="); pw.println(info.className);
+        }
+        if (info.manageSpaceActivityName != null) {
+            pw.print(prefix); pw.print("manageSpaceActivityName=");
+            pw.println(info.manageSpaceActivityName);
+        }
+        pw.print(prefix); pw.print("dir="); pw.print(info.sourceDir);
+                pw.print(" publicDir="); pw.print(info.publicSourceDir);
+                pw.print(" data="); pw.println(info.dataDir);
+        pw.print(prefix); pw.print("packageList="); pw.println(pkgList);
+        if (instrumentationClass != null || instrumentationProfileFile != null
+                || instrumentationArguments != null) {
+            pw.print(prefix); pw.print("instrumentationClass=");
+                    pw.print(instrumentationClass);
+                    pw.print(" instrumentationProfileFile=");
+                    pw.println(instrumentationProfileFile);
+            pw.print(prefix); pw.print("instrumentationArguments=");
+                    pw.println(instrumentationArguments);
+        }
+        pw.print(prefix); pw.print("thread="); pw.print(thread);
+                pw.print(" curReceiver="); pw.println(curReceiver);
+        pw.print(prefix); pw.print("pid="); pw.print(pid); pw.print(" starting=");
+                pw.print(starting); pw.print(" lastPss="); pw.println(lastPss);
+        pw.print(prefix); pw.print("oom: max="); pw.print(maxAdj);
+                pw.print(" hidden="); pw.print(hiddenAdj);
+                pw.print(" curRaw="); pw.print(curRawAdj);
+                pw.print(" setRaw="); pw.print(setRawAdj);
+                pw.print(" cur="); pw.print(curAdj);
+                pw.print(" set="); pw.println(setAdj);
+        pw.print(prefix); pw.print("isForeground="); pw.print(isForeground);
+                pw.print(" setIsForeground="); pw.print(setIsForeground);
+                pw.print(" foregroundServices="); pw.print(foregroundServices);
+                pw.print(" forcingToForeground="); pw.println(forcingToForeground);
+        pw.print(prefix); pw.print("persistent="); pw.print(persistent);
+                pw.print(" removed="); pw.print(removed);
+                pw.print(" persistentActivities="); pw.println(persistentActivities);
+        if (debugging || crashing || crashDialog != null || notResponding
+                || anrDialog != null || bad) {
+            pw.print(prefix); pw.print("debugging="); pw.print(debugging);
+                    pw.print(" crashing="); pw.print(crashing);
+                    pw.print(" "); pw.print(crashDialog);
+                    pw.print(" notResponding="); pw.print(notResponding);
+                    pw.print(" " ); pw.print(anrDialog);
+                    pw.print(" bad="); pw.println(bad);
+        }
+        if (activities.size() > 0) {
+            pw.print(prefix); pw.print("activities="); pw.println(activities);
+        }
+        if (services.size() > 0) {
+            pw.print(prefix); pw.print("services="); pw.println(services);
+        }
+        if (executingServices.size() > 0) {
+            pw.print(prefix); pw.print("executingServices="); pw.println(executingServices);
+        }
+        if (connections.size() > 0) {
+            pw.print(prefix); pw.print("connections="); pw.println(connections);
+        }
+        if (pubProviders.size() > 0) {
+            pw.print(prefix); pw.print("pubProviders="); pw.println(pubProviders);
+        }
+        if (conProviders.size() > 0) {
+            pw.print(prefix); pw.print("conProviders="); pw.println(conProviders);
+        }
+        if (receivers.size() > 0) {
+            pw.print(prefix); pw.print("receivers="); pw.println(receivers);
+        }
     }
     
     ProcessRecord(BatteryStatsImpl.Uid.Proc _batteryStats, IApplicationThread _thread,
@@ -154,6 +192,11 @@
         persistentActivities = 0;
     }
 
+    public void setPid(int _pid) {
+        pid = _pid;
+        stringName = null;
+    }
+    
     /**
      * This method returns true if any of the activities within the process record are interesting
      * to the user. See HistoryRecord.isInterestingToUserLocked()
@@ -188,9 +231,20 @@
     }
     
     public String toString() {
-        return "ProcessRecord{"
-            + Integer.toHexString(System.identityHashCode(this))
-            + " " + pid + ":" + processName + "/" + info.uid + "}";
+        if (stringName != null) {
+            return stringName;
+        }
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("ProcessRecord{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(' ');
+        sb.append(pid);
+        sb.append(':');
+        sb.append(processName);
+        sb.append('/');
+        sb.append(info.uid);
+        sb.append('}');
+        return stringName = sb.toString();
     }
     
     /*
diff --git a/services/java/com/android/server/am/ReceiverList.java b/services/java/com/android/server/am/ReceiverList.java
index 6ac527b..b8bf30c 100644
--- a/services/java/com/android/server/am/ReceiverList.java
+++ b/services/java/com/android/server/am/ReceiverList.java
@@ -39,6 +39,8 @@
     BroadcastRecord curBroadcast = null;
     boolean linkedToDeath = false;
 
+    String stringName;
+    
     ReceiverList(ActivityManagerService _owner, ProcessRecord _app,
             int _pid, int _uid, IIntentReceiver _receiver) {
         owner = _owner;
@@ -82,11 +84,21 @@
     }
     
     public String toString() {
-        return "ReceiverList{"
-            + Integer.toHexString(System.identityHashCode(this))
-            + " " + pid + " " + (app != null ? app.processName : "(unknown name)")
-            + "/" + uid + " client "
-            + Integer.toHexString(System.identityHashCode(receiver.asBinder()))
-            + "}";
+        if (stringName != null) {
+            return stringName;
+        }
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("ReceiverList{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(' ');
+        sb.append(pid);
+        sb.append(' ');
+        sb.append((app != null ? app.processName : "(unknown name)"));
+        sb.append('/');
+        sb.append(uid);
+        sb.append(" client ");
+        sb.append(Integer.toHexString(System.identityHashCode(receiver.asBinder())));
+        sb.append('}');
+        return stringName = sb.toString();
     }
 }
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index 4b90600..a8fc761 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -77,6 +77,8 @@
     long restartTime;       // time of last restart.
     long nextRestartTime;   // time when restartDelay will expire.
 
+    String stringName;      // caching of toString
+    
     void dump(PrintWriter pw, String prefix) {
         pw.println(prefix + this);
         pw.println(prefix + "intent=" + intent.getIntent());
@@ -159,8 +161,15 @@
     }
     
     public String toString() {
-        return "ServiceRecord{"
-            + Integer.toHexString(System.identityHashCode(this))
-            + " " + shortName + "}";
+        if (stringName != null) {
+            return stringName;
+        }
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("ServiceRecord{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(' ');
+        sb.append(shortName);
+        sb.append('}');
+        return stringName = sb.toString();
     }
 }
diff --git a/services/java/com/android/server/am/UsageStatsService.java b/services/java/com/android/server/am/UsageStatsService.java
index 3922f39..b6f9158 100755
--- a/services/java/com/android/server/am/UsageStatsService.java
+++ b/services/java/com/android/server/am/UsageStatsService.java
@@ -37,11 +37,11 @@
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Collections;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TimeZone;
 
 /**
  * This service collects the statistics associated with usage
@@ -53,6 +53,23 @@
     public static final String SERVICE_NAME = "usagestats";
     private static final boolean localLOGV = false;
     private static final String TAG = "UsageStats";
+    
+    // Current on-disk Parcel version
+    private static final int VERSION = 1004;
+
+    private static final int CHECKIN_VERSION = 3;
+    
+    private static final String FILE_PREFIX = "usage-";
+    
+    private static final int FILE_WRITE_INTERVAL = 30*60*1000; //ms
+    
+    private static final int MAX_NUM_FILES = 5;
+    
+    private static final int NUM_LAUNCH_TIME_BINS = 10;
+    private static final int[] LAUNCH_TIME_BINS = {
+        250, 500, 750, 1000, 1500, 2000, 3000, 4000, 5000
+    };
+    
     static IUsageStats sService;
     private Context mContext;
     // structure used to maintain statistics since the last checkin.
@@ -66,16 +83,48 @@
     // Order of locks is mFileLock followed by mStatsLock to avoid deadlocks
     private String mResumedPkg;
     private File mFile;
+    private String mFileLeaf;
     //private File mBackupFile;
-    private long mLastWriteRealTime;
-    private int _FILE_WRITE_INTERVAL = 30*60*1000; //ms
-    private static final String _PREFIX_DELIMIT=".";
-    private String mFilePrefix;
+    private long mLastWriteElapsedTime;
+    private File mDir;
     private Calendar mCal;
-    private static final int  _MAX_NUM_FILES = 10;
-    private long mLastTime;
+    private int mLastWriteDay;
+    
+    static class TimeStats {
+        int[] times = new int[NUM_LAUNCH_TIME_BINS];
+        
+        TimeStats() {
+        }
+        
+        void add(int val) {
+            final int[] bins = LAUNCH_TIME_BINS;
+            for (int i=0; i<NUM_LAUNCH_TIME_BINS-1; i++) {
+                if (val < bins[i]) {
+                    times[i]++;
+                    return;
+                }
+            }
+            times[NUM_LAUNCH_TIME_BINS-1]++;
+        }
+        
+        TimeStats(Parcel in) {
+            final int[] localTimes = times;
+            for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) {
+                localTimes[i] = in.readInt();
+            }
+        }
+        
+        void writeToParcel(Parcel out) {
+            final int[] localTimes = times;
+            for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) {
+                out.writeInt(localTimes[i]);
+            }
+        }
+    }
     
     private class PkgUsageStatsExtended {
+        final HashMap<String, TimeStats> mLaunchTimes
+                = new HashMap<String, TimeStats>();
         int mLaunchCount;
         long mUsageTime;
         long mPausedTime;
@@ -85,44 +134,106 @@
             mLaunchCount = 0;
             mUsageTime = 0;
         }
+        
+        PkgUsageStatsExtended(Parcel in) {
+            mLaunchCount = in.readInt();
+            mUsageTime = in.readLong();
+            if (localLOGV) Log.v(TAG, "Launch count: " + mLaunchCount
+                    + ", Usage time:" + mUsageTime);
+            
+            final int N = in.readInt();
+            if (localLOGV) Log.v(TAG, "Reading comps: " + N);
+            for (int i=0; i<N; i++) {
+                String comp = in.readString();
+                if (localLOGV) Log.v(TAG, "Component: " + comp);
+                TimeStats times = new TimeStats(in);
+                mLaunchTimes.put(comp, times);
+            }
+        }
+        
         void updateResume() {
             mLaunchCount ++;
             mResumedTime = SystemClock.elapsedRealtime();
         }
+        
         void updatePause() {
             mPausedTime =  SystemClock.elapsedRealtime();
             mUsageTime += (mPausedTime - mResumedTime);
         }
+        
+        void addLaunchTime(String comp, int millis) {
+            TimeStats times = mLaunchTimes.get(comp);
+            if (times == null) {
+                times = new TimeStats();
+                mLaunchTimes.put(comp, times);
+            }
+            times.add(millis);
+        }
+        
+        void writeToParcel(Parcel out) {
+            out.writeInt(mLaunchCount);
+            out.writeLong(mUsageTime);
+            final int N = mLaunchTimes.size();
+            out.writeInt(N);
+            if (N > 0) {
+                for (Map.Entry<String, TimeStats> ent : mLaunchTimes.entrySet()) {
+                    out.writeString(ent.getKey());
+                    TimeStats times = ent.getValue();
+                    times.writeToParcel(out);
+                }
+            }
+        }
+        
         void clear() {
+            mLaunchTimes.clear();
             mLaunchCount = 0;
             mUsageTime = 0;
         }
     }
     
-    UsageStatsService(String fileName) {
+    UsageStatsService(String dir) {
         mStats = new HashMap<String, PkgUsageStatsExtended>();
         mStatsLock = new Object();
         mFileLock = new Object();
-        mFilePrefix = fileName;
-        mCal = Calendar.getInstance();
+        mDir = new File(dir);
+        mCal = Calendar.getInstance(TimeZone.getTimeZone("GMT+0"));
+        
+        mDir.mkdir();
+        
+        // Remove any old usage files from previous versions.
+        File parentDir = mDir.getParentFile();
+        String fList[] = parentDir.list();
+        if (fList != null) {
+            String prefix = mDir.getName() + ".";
+            int i = fList.length;
+            while (i > 0) {
+                i--;
+                if (fList[i].startsWith(prefix)) {
+                    Log.i(TAG, "Deleting old usage file: " + fList[i]);
+                    (new File(parentDir, fList[i])).delete();
+                }
+            }
+        }
+        
         // Update current stats which are binned by date
-        String uFileName = getCurrentDateStr(mFilePrefix);
-        mFile = new File(uFileName);
+        mFileLeaf = getCurrentDateStr(FILE_PREFIX);
+        mFile = new File(mDir, mFileLeaf);
         readStatsFromFile();
-        mLastWriteRealTime = SystemClock.elapsedRealtime();
-        mLastTime = new Date().getTime();
+        mLastWriteElapsedTime = SystemClock.elapsedRealtime();
+        // mCal was set by getCurrentDateStr(), want to use that same time.
+        mLastWriteDay = mCal.get(Calendar.DAY_OF_YEAR);
     }
 
     /*
      * Utility method to convert date into string.
      */
     private String getCurrentDateStr(String prefix) {
-        mCal.setTime(new Date());
+        mCal.setTimeInMillis(System.currentTimeMillis());
         StringBuilder sb = new StringBuilder();
         if (prefix != null) {
             sb.append(prefix);
-            sb.append(".");
         }
+        sb.append(mCal.get(Calendar.YEAR));
         int mm = mCal.get(Calendar.MONTH) - Calendar.JANUARY +1;
         if (mm < 10) {
             sb.append("0");
@@ -133,7 +244,6 @@
             sb.append("0");
         }
         sb.append(dd);
-        sb.append(mCal.get(Calendar.YEAR));
         return sb.toString();
     }
     
@@ -166,11 +276,20 @@
     
     private void readStatsFLOCK(File file) throws IOException {
         Parcel in = getParcelForFile(file);
-        while (in.dataAvail() > 0) {
+        int vers = in.readInt();
+        if (vers != VERSION) {
+            Log.w(TAG, "Usage stats version changed; dropping");
+            return;
+        }
+        int N = in.readInt();
+        while (N > 0) {
+            N--;
             String pkgName = in.readString();
-            PkgUsageStatsExtended pus = new PkgUsageStatsExtended();
-            pus.mLaunchCount = in.readInt();
-            pus.mUsageTime = in.readLong();
+            if (pkgName == null) {
+                break;
+            }
+            if (localLOGV) Log.v(TAG, "Reading package #" + N + ": " + pkgName);
+            PkgUsageStatsExtended pus = new PkgUsageStatsExtended(in);
             synchronized (mStatsLock) {
                 mStats.put(pkgName, pus);
             }
@@ -178,27 +297,18 @@
     }
 
     private ArrayList<String> getUsageStatsFileListFLOCK() {
-        File dir = getUsageFilesDir();
-        if (dir == null) {
-            Log.w(TAG, "Couldnt find writable directory for usage stats file");
-            return null;
-        }
         // Check if there are too many files in the system and delete older files
-        String fList[] = dir.list();
+        String fList[] = mDir.list();
         if (fList == null) {
             return null;
         }
-        File pre = new File(mFilePrefix);
-        String filePrefix = pre.getName();
-        // file name followed by dot
-        int prefixLen = filePrefix.length()+1;
         ArrayList<String> fileList = new ArrayList<String>();
         for (String file : fList) {
-            int index = file.indexOf(filePrefix);
-            if (index == -1) {
+            if (!file.startsWith(FILE_PREFIX)) {
                 continue;
             }
             if (file.endsWith(".bak")) {
+                (new File(mDir, file)).delete();
                 continue;
             }
             fileList.add(file);
@@ -206,20 +316,7 @@
         return fileList;
     }
     
-    private File getUsageFilesDir() {
-        if (mFilePrefix == null) {
-            return null;
-        }
-        File pre = new File(mFilePrefix);
-        return new File(pre.getParent());
-    }
-    
     private void checkFileLimitFLOCK() {
-        File dir = getUsageFilesDir();
-        if (dir == null) {
-            Log.w(TAG, "Couldnt find writable directory for usage stats file");
-            return;
-        }
         // Get all usage stats output files
         ArrayList<String> fileList = getUsageStatsFileListFLOCK();
         if (fileList == null) {
@@ -227,49 +324,54 @@
             return;
         }
         int count = fileList.size();
-        if (count <= _MAX_NUM_FILES) {
+        if (count <= MAX_NUM_FILES) {
             return;
         }
         // Sort files
         Collections.sort(fileList);
-        count -= _MAX_NUM_FILES;
+        count -= MAX_NUM_FILES;
         // Delete older files
         for (int i = 0; i < count; i++) {
             String fileName = fileList.get(i);
-            File file = new File(dir, fileName);
-            Log.i(TAG, "Deleting file : "+fileName);
+            File file = new File(mDir, fileName);
+            Log.i(TAG, "Deleting usage file : " + fileName);
             file.delete();
         }
     }
     
-    private void writeStatsToFile() {
+    private void writeStatsToFile(boolean force) {
         synchronized (mFileLock) {
-            long currTime = new Date().getTime();
-            boolean dayChanged =  ((currTime - mLastTime) >= (24*60*60*1000));
-            long currRealTime = SystemClock.elapsedRealtime();
-            if (((currRealTime-mLastWriteRealTime) < _FILE_WRITE_INTERVAL) &&
-                    (!dayChanged)) {
-                // wait till the next update
-                return;
+            mCal.setTimeInMillis(System.currentTimeMillis());
+            final int curDay = mCal.get(Calendar.DAY_OF_YEAR);
+            // Determine if the day changed...  note that this will be wrong
+            // if the year has changed but we are in the same day of year...
+            // we can probably live with this.
+            final boolean dayChanged =  curDay != mLastWriteDay;
+            long currElapsedTime = SystemClock.elapsedRealtime();
+            if (!force) {
+                if (((currElapsedTime-mLastWriteElapsedTime) < FILE_WRITE_INTERVAL) &&
+                        (!dayChanged)) {
+                    // wait till the next update
+                    return;
+                }
             }
             // Get the most recent file
-            String todayStr = getCurrentDateStr(mFilePrefix);
+            mFileLeaf = getCurrentDateStr(FILE_PREFIX);
             // Copy current file to back up
             File backupFile =  new File(mFile.getPath() + ".bak");
             mFile.renameTo(backupFile);
             try {
-                checkFileLimitFLOCK();
-                mFile.createNewFile();
                 // Write mStats to file
                 writeStatsFLOCK();
-                mLastWriteRealTime = currRealTime;
-                mLastTime = currTime;
+                mLastWriteElapsedTime = currElapsedTime;
                 if (dayChanged) {
+                    mLastWriteDay = curDay;
                     // clear stats
                     synchronized (mStats) {
                         mStats.clear();
                     }
-                    mFile = new File(todayStr);
+                    mFile = new File(mDir, mFileLeaf);
+                    checkFileLimitFLOCK();
                 }
                 // Delete the backup file
                 if (backupFile != null) {
@@ -278,6 +380,7 @@
             } catch (IOException e) {
                 Log.w(TAG, "Failed writing stats to file:" + mFile);
                 if (backupFile != null) {
+                    mFile.delete();
                     backupFile.renameTo(mFile);
                 }
             }
@@ -286,22 +389,26 @@
 
     private void writeStatsFLOCK() throws IOException {
         FileOutputStream stream = new FileOutputStream(mFile);
-        Parcel out = Parcel.obtain();
-        writeStatsToParcelFLOCK(out);
-        stream.write(out.marshall());
-        out.recycle();
-        stream.flush();
-        stream.close();
+        try {
+            Parcel out = Parcel.obtain();
+            writeStatsToParcelFLOCK(out);
+            stream.write(out.marshall());
+            out.recycle();
+            stream.flush();
+        } finally {
+            stream.close();
+        }
     }
 
     private void writeStatsToParcelFLOCK(Parcel out) {
         synchronized (mStatsLock) {
+            out.writeInt(VERSION);
             Set<String> keys = mStats.keySet();
+            out.writeInt(keys.size());
             for (String key : keys) {
                 PkgUsageStatsExtended pus = mStats.get(key);
                 out.writeString(key);
-                out.writeInt(pus.mLaunchCount);
-                out.writeLong(pus.mUsageTime);
+                pus.writeToParcel(out);
             }
         }
     }
@@ -355,6 +462,10 @@
             return;
         }
         if (localLOGV) Log.i(TAG, "paused component:"+pkgName);
+        
+        // Persist current data to file if needed.
+        writeStatsToFile(false);
+        
         synchronized (mStatsLock) {
             PkgUsageStatsExtended pus = mStats.get(pkgName);
             if (pus == null) {
@@ -364,8 +475,25 @@
             }
             pus.updatePause();
         }
-        // Persist data to file
-        writeStatsToFile();
+    }
+    
+    public void noteLaunchTime(ComponentName componentName, int millis) {
+        enforceCallingPermission();
+        String pkgName;
+        if ((componentName == null) ||
+                ((pkgName = componentName.getPackageName()) == null)) {
+            return;
+        }
+        
+        // Persist current data to file if needed.
+        writeStatsToFile(false);
+        
+        synchronized (mStatsLock) {
+            PkgUsageStatsExtended pus = mStats.get(pkgName);
+            if (pus != null) {
+                pus.addLaunchTime(componentName.getClassName(), millis);
+            }
+        }
     }
     
     public void enforceCallingPermission() {
@@ -432,27 +560,25 @@
         }
     }
     
-    private void collectDumpInfoFLOCK(PrintWriter pw, String[] args) {
+    private void collectDumpInfoFLOCK(PrintWriter pw, boolean isCompactOutput,
+            boolean deleteAfterPrint) {
         List<String> fileList = getUsageStatsFileListFLOCK();
         if (fileList == null) {
             return;
         }
-        final boolean isCheckinRequest = scanArgs(args, "-c");
         Collections.sort(fileList);
-        File usageFile = new File(mFilePrefix);
-        String dirName = usageFile.getParent();
-        File dir = new File(dirName);
-        String filePrefix = usageFile.getName();
-        // file name followed by dot
-        int prefixLen = filePrefix.length()+1;
-        String todayStr = getCurrentDateStr(null);
         for (String file : fileList) {
-            File dFile = new File(dir, file);
-            String dateStr = file.substring(prefixLen);
+            if (deleteAfterPrint && file.equalsIgnoreCase(mFileLeaf)) {
+                // In this mode we don't print the current day's stats, since
+                // they are incomplete.
+                continue;
+            }
+            File dFile = new File(mDir, file);
+            String dateStr = file.substring(FILE_PREFIX.length());
             try {
                 Parcel in = getParcelForFile(dFile);
-                collectDumpInfoFromParcelFLOCK(in, pw, dateStr, isCheckinRequest);
-                if (isCheckinRequest && !todayStr.equalsIgnoreCase(dateStr)) {
+                collectDumpInfoFromParcelFLOCK(in, pw, dateStr, isCompactOutput);
+                if (deleteAfterPrint) {
                     // Delete old file after collecting info only for checkin requests
                     dFile.delete();
                 }
@@ -466,40 +592,101 @@
     }
     
     private void collectDumpInfoFromParcelFLOCK(Parcel in, PrintWriter pw,
-            String date, boolean isCheckinRequest) {
-        StringBuilder sb = new StringBuilder();
-        sb.append("Date:");
-        sb.append(date);
-        boolean first = true;
-        while (in.dataAvail() > 0) {
-            String pkgName = in.readString();
-            int launchCount = in.readInt();
-            long usageTime = in.readLong();
-            if (isCheckinRequest) {
-                if (!first) {
-                    sb.append(",");
-                }
-                sb.append(pkgName);
-                sb.append(",");
-                sb.append(launchCount);
-                sb.append(",");
-                sb.append(usageTime);
-                sb.append("ms");
-            } else {
-                if (first) {
-                    sb.append("\n");
-                }
-                sb.append("pkg=");
-                sb.append(pkgName);
-                sb.append(", launchCount=");
-                sb.append(launchCount);
-                sb.append(", usageTime=");
-                sb.append(usageTime);
-                sb.append(" ms\n");
-            }
-            first = false;
+            String date, boolean isCompactOutput) {
+        StringBuilder sb = new StringBuilder(512);
+        if (isCompactOutput) {
+            sb.append("D:");
+            sb.append(CHECKIN_VERSION);
+            sb.append(',');
+        } else {
+            sb.append("Date: ");
         }
-        pw.write(sb.toString());
+        
+        sb.append(date);
+        
+        int vers = in.readInt();
+        if (vers != VERSION) {
+            sb.append(" (old data version)");
+            pw.println(sb.toString());
+            return;
+        }
+        
+        pw.println(sb.toString());
+        int N = in.readInt();
+        
+        while (N > 0) {
+            N--;
+            String pkgName = in.readString();
+            if (pkgName == null) {
+                break;
+            }
+            sb.setLength(0);
+            PkgUsageStatsExtended pus = new PkgUsageStatsExtended(in);
+            if (isCompactOutput) {
+                sb.append("P:");
+                sb.append(pkgName);
+                sb.append(",");
+                sb.append(pus.mLaunchCount);
+                sb.append(",");
+                sb.append(pus.mUsageTime);
+                sb.append('\n');
+                final int NC = pus.mLaunchTimes.size();
+                if (NC > 0) {
+                    for (Map.Entry<String, TimeStats> ent : pus.mLaunchTimes.entrySet()) {
+                        sb.append("A:");
+                        sb.append(ent.getKey());
+                        TimeStats times = ent.getValue();
+                        for (int i=0; i<NUM_LAUNCH_TIME_BINS; i++) {
+                            sb.append(",");
+                            sb.append(times.times[i]);
+                        }
+                        sb.append('\n');
+                    }
+                }
+                
+            } else {
+                sb.append("  ");
+                sb.append(pkgName);
+                sb.append(": ");
+                sb.append(pus.mLaunchCount);
+                sb.append(" times, ");
+                sb.append(pus.mUsageTime);
+                sb.append(" ms");
+                sb.append('\n');
+                final int NC = pus.mLaunchTimes.size();
+                if (NC > 0) {
+                    for (Map.Entry<String, TimeStats> ent : pus.mLaunchTimes.entrySet()) {
+                        sb.append("    ");
+                        sb.append(ent.getKey());
+                        TimeStats times = ent.getValue();
+                        int lastBin = 0;
+                        boolean first = true;
+                        for (int i=0; i<NUM_LAUNCH_TIME_BINS-1; i++) {
+                            if (times.times[i] != 0) {
+                                sb.append(first ? ": " : ", ");
+                                sb.append(lastBin);
+                                sb.append('-');
+                                sb.append(LAUNCH_TIME_BINS[i]);
+                                sb.append('=');
+                                sb.append(times.times[i]);
+                                first = false;
+                            }
+                            lastBin = LAUNCH_TIME_BINS[i];
+                        }
+                        if (times.times[NUM_LAUNCH_TIME_BINS-1] != 0) {
+                            sb.append(first ? ": " : ", ");
+                            sb.append(">=");
+                            sb.append(lastBin);
+                            sb.append('=');
+                            sb.append(times.times[NUM_LAUNCH_TIME_BINS-1]);
+                        }
+                        sb.append('\n');
+                    }
+                }
+            }
+            
+            pw.write(sb.toString());
+        }
     }
     
     /**
@@ -524,8 +711,19 @@
      * The data persisted to file is parsed and the stats are computed. 
      */
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        final boolean isCheckinRequest = scanArgs(args, "--checkin");
+        final boolean isCompactOutput = isCheckinRequest || scanArgs(args, "-c");
+        final boolean deleteAfterPrint = isCheckinRequest || scanArgs(args, "-d");
+        
+        // Make sure the current stats are written to the file.  This
+        // doesn't need to be done if we are deleting files after printing,
+        // since it that case we won't print the current stats.
+        if (!deleteAfterPrint) {
+            writeStatsToFile(true);
+        }
+        
         synchronized (mFileLock) {
-            collectDumpInfoFLOCK(pw, args);
+            collectDumpInfoFLOCK(pw, isCompactOutput, deleteAfterPrint);
         }
     }
 
diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java
index ed90d32..3f210ca 100644
--- a/telephony/java/com/android/internal/telephony/Phone.java
+++ b/telephony/java/com/android/internal/telephony/Phone.java
@@ -113,9 +113,12 @@
     static final String APN_TYPE_DEFAULT = "default";
     /** APN type for MMS traffic */
     static final String APN_TYPE_MMS = "mms";
+    /** APN type for SUPL assisted GPS */
+    static final String APN_TYPE_SUPL = "supl";
 
     // "Features" accessible through the connectivity manager
     static final String FEATURE_ENABLE_MMS = "enableMMS";
+    static final String FEATURE_ENABLE_SUPL = "enableSUPL";
 
     /**
      * Return codes for <code>enableApnType()</code>
@@ -170,7 +173,7 @@
     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;
+    int PREFERRED_NT_MODE    = NT_MODE_GSM_ONLY;
 
 
     // Used for CDMA roaming mode
diff --git a/telephony/java/com/android/internal/telephony/PhoneFactory.java b/telephony/java/com/android/internal/telephony/PhoneFactory.java
index 3db0499..86e2f04 100644
--- a/telephony/java/com/android/internal/telephony/PhoneFactory.java
+++ b/telephony/java/com/android/internal/telephony/PhoneFactory.java
@@ -108,26 +108,23 @@
                 sCommandsInterface = new RIL(context, networkMode, cdmaSubscription);
 
                 switch(networkMode) {
+                    case RILConstants.NETWORK_MODE_CDMA:
+                    case RILConstants.NETWORK_MODE_CDMA_NO_EVDO:
+                    case RILConstants.NETWORK_MODE_EVDO_NO_CDMA:
+                    case RILConstants.NETWORK_MODE_GLOBAL:
+                        sProxyPhone = new PhoneProxy(new CDMAPhone(context,
+                                sCommandsInterface, sPhoneNotifier));
+                        Log.i(LOG_TAG, "Creating CDMAPhone");
+                        break;
                     case RILConstants.NETWORK_MODE_WCDMA_PREF:
                     case RILConstants.NETWORK_MODE_GSM_ONLY:
                     case RILConstants.NETWORK_MODE_WCDMA_ONLY:
                     case RILConstants.NETWORK_MODE_GSM_UMTS:
+                    default:
                         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;
             }
@@ -160,5 +157,3 @@
         }
     }
 }
-
-
diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java
index f5d3b32..636a223 100644
--- a/telephony/java/com/android/internal/telephony/RIL.java
+++ b/telephony/java/com/android/internal/telephony/RIL.java
@@ -565,22 +565,18 @@
         mNetworkMode = networkMode;
         //At startup mPhoneType is first set from networkMode
         switch(networkMode) {
+            case RILConstants.NETWORK_MODE_CDMA:
+            case RILConstants.NETWORK_MODE_CDMA_NO_EVDO:
+            case RILConstants.NETWORK_MODE_EVDO_NO_CDMA:
+            case RILConstants.NETWORK_MODE_GLOBAL:
+                mPhoneType = RILConstants.CDMA_PHONE;
+                break;
             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;
+                mPhoneType = RILConstants.GSM_PHONE;
         }
 
         PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 028aad7..9c63627 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -51,7 +51,7 @@
     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;
+    int PREFERRED_NETWORK_MODE      = NETWORK_MODE_GSM_ONLY;
 
     /* CDMA subscription source. See ril.h RIL_REQUEST_CDMA_SET_SUBSCRIPTION */
     int SUBSCRIPTION_FROM_RUIM      = 0; /* CDMA subscription from RUIM when available */
diff --git a/telephony/java/com/android/internal/telephony/SmsMessageBase.java b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
index 7c32451..1aad38d 100644
--- a/telephony/java/com/android/internal/telephony/SmsMessageBase.java
+++ b/telephony/java/com/android/internal/telephony/SmsMessageBase.java
@@ -20,20 +20,7 @@
 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.
@@ -385,4 +372,3 @@
     }
 
 }
-
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
old mode 100644
new mode 100755
index c139619..8ffb7ec
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -475,6 +475,11 @@
             // we report data connected
 
             ret = DataState.CONNECTED;
+        } else if (mSST == null) {
+            // Radio Technology Change is ongoning, dispose() and removeReferences() have
+            // already been called
+
+            ret = DataState.DISCONNECTED;
         } else if (mSST.getCurrentCdmaDataConnectionState()
                 == ServiceState.RADIO_TECHNOLOGY_UNKNOWN) {
             // If we're out of service, open TCP sockets may still work
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
index ed617ef..87e8b62 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -228,6 +228,9 @@
         Log.d(LOG_TAG, "Request to enableApnType("+type+")");
         if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
             return Phone.APN_ALREADY_ACTIVE;
+        } else if (TextUtils.equals(type, Phone.APN_TYPE_SUPL)) {
+            Log.w(LOG_TAG, "Phone.APN_TYPE_SUPL not enabled for CDMA");
+            return Phone.APN_REQUEST_FAILED;
         } else {
             return Phone.APN_REQUEST_FAILED;
         }
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index e4b474a..2f26bdc 100644
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -27,7 +27,6 @@
 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;
 
@@ -50,23 +49,6 @@
 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.
@@ -186,7 +168,7 @@
 
         // ignore subaddress
         p.readInt(); //p_cur->sSubAddress.subaddressType
-        p.readByte(); //p_cur->sSubAddress.odd
+        p.readInt(); //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++) {
@@ -309,15 +291,15 @@
             int septetCount = GsmAlphabet.countGsmSeptets(message, true);
             // User Data (and length)
 
-            uData.userData = message.getBytes();
+            uData.payload = message.getBytes();
 
-            if (uData.userData.length > MAX_USER_DATA_SEPTETS) {
+            if (uData.payload.length > MAX_USER_DATA_SEPTETS) {
                 // Message too long
                 return null;
             }
 
             // desired TP-Data-Coding-Scheme
-            uData.userDataEncoding = UserData.UD_ENCODING_GSM_7BIT_ALPHABET;
+            uData.msgEncoding = UserData.ENCODING_GSM_7BIT_ALPHABET;
 
             // paddingBits not needed for UD_ENCODING_GSM_7BIT_ALPHABET
 
@@ -341,15 +323,15 @@
                 return null;
             }
 
-            uData.userData = textPart;
+            uData.payload = textPart;
 
-            if (uData.userData.length > MAX_USER_DATA_BYTES) {
+            if (uData.payload.length > MAX_USER_DATA_BYTES) {
                 // Message too long
                 return null;
             }
 
             // TP-Data-Coding-Scheme
-            uData.userDataEncoding = UserData.UD_ENCODING_UNICODE_16;
+            uData.msgEncoding = UserData.ENCODING_UNICODE_16;
 
             // sms header
             if(headerData != null) {
@@ -425,8 +407,8 @@
 
         // TP-Data-Coding-Scheme
         // No class, 8 bit data
-        uData.userDataEncoding = UserData.UD_ENCODING_OCTET;
-        uData.userData = data;
+        uData.msgEncoding = UserData.ENCODING_OCTET;
+        uData.payload = data;
 
         byte[] msgData = sms.getEnvelope(destinationAddress, statusReportRequested, uData,
                 true, true);
@@ -619,21 +601,21 @@
      * Parses a SMS message from its BearerData stream. (mobile-terminated only)
      */
     protected void parseSms() {
-        mBearerData = SmsDataCoding.decodeCdmaSms(mEnvelope.bearerData);
-        messageRef = mBearerData.messageID;
+        mBearerData = BearerData.decode(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:
+        case BearerData.MESSAGE_TYPE_USER_ACK:
+        case BearerData.MESSAGE_TYPE_READ_ACK:
+        case BearerData.MESSAGE_TYPE_DELIVER:
             // Deliver (mobile-terminated only)
             parseSmsDeliver();
             break;
-        case MESSAGE_TYPE_DELIVERY_ACK:
+        case BearerData.MESSAGE_TYPE_DELIVERY_ACK:
             parseSmsDeliveryAck();
             break;
 
@@ -699,22 +681,22 @@
             return;
         }
 
-        encodingType = uData.userDataEncoding;
+        encodingType = uData.msgEncoding;
 
         // insert DCS-decoding here when type is supported by ril-library
 
-        userData = uData.userData;
+        userData = uData.payload;
         userDataHeader = uData.userDataHeader;
 
         switch (encodingType) {
-        case UD_ENCODING_GSM_7BIT_ALPHABET:
-        case UD_ENCODING_UNICODE_16:
+        case UserData.ENCODING_GSM_7BIT_ALPHABET:
+        case UserData.ENCODING_UNICODE_16:
             // user data was already decoded by wmsts-library
             messageBody = new String(userData);
             break;
 
         // data and unsupported encodings:
-        case UD_ENCODING_OCTET:
+        case UserData.ENCODING_OCTET:
         default:
             messageBody = null;
             break;
@@ -771,7 +753,7 @@
         if (useNewId) {
             setNextMessageId();
         }
-        mBearerData.messageID = nextMessageId;
+        mBearerData.messageId = nextMessageId;
 
         // Set the reply options (See C.S0015-B, v2.0, 4.5.11)
         if(statusReportRequested) {
@@ -795,7 +777,7 @@
         // ** encode BearerData **
         byte[] encodedBearerData = null;
         try {
-            encodedBearerData = SmsDataCoding.encodeCdmaSms(mBearerData);
+            encodedBearerData = BearerData.encode(mBearerData);
         } catch (Exception e) {
             Log.e(LOG_TAG, "doGetSubmitPdu: EncodeCdmaSMS function in JNI interface failed: "
                     + e.getMessage());
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
index fec9529..8e67387 100644
--- a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
@@ -16,7 +16,52 @@
 
 package com.android.internal.telephony.cdma.sms;
 
+import android.util.Log;
+
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.SmsHeader;
+import com.android.internal.telephony.cdma.sms.UserData;
+
+import com.android.internal.util.HexDump;
+import com.android.internal.util.BitwiseInputStream;
+import com.android.internal.util.BitwiseOutputStream;
+
+/**
+ * XXX
+ *
+ *
+ */
 public final class BearerData{
+    private final static String LOG_TAG = "SMS";
+
+    /**
+     * Bearer Data Subparameter Indentifiers
+     * (See 3GPP2 C.S0015-B, v2.0, table 4.5-1)
+     */
+    private final static byte SUBPARAM_MESSAGE_IDENTIFIER               = 0x00;
+    private final static byte SUBPARAM_USER_DATA                        = 0x01;
+    private final static byte SUBPARAM_USER_REPONSE_CODE                = 0x02;
+    private final static byte SUBPARAM_MESSAGE_CENTER_TIME_STAMP        = 0x03;
+    //private final static byte SUBPARAM_VALIDITY_PERIOD_ABSOLUTE         = 0x04;
+    //private final static byte SUBPARAM_VALIDITY_PERIOD_RELATIVE         = 0x05;
+    //private final static byte SUBPARAM_DEFERRED_DELIVERY_TIME_ABSOLUTE  = 0x06;
+    //private final static byte SUBPARAM_DEFERRED_DELIVERY_TIME_RELATIVE  = 0x07;
+    //private final static byte SUBPARAM_PRIORITY_INDICATOR               = 0x08;
+    //private final static byte SUBPARAM_PRIVACY_INDICATOR                = 0x09;
+    private final static byte SUBPARAM_REPLY_OPTION                     = 0x0A;
+    private final static byte SUBPARAM_NUMBER_OF_MESSAGES               = 0x0B;
+    //private final static byte SUBPARAM_ALERT_ON_MESSAGE_DELIVERY        = 0x0C;
+    //private final static byte SUBPARAM_LANGUAGE_INDICATOR               = 0x0D;
+    private final static byte SUBPARAM_CALLBACK_NUMBER                  = 0x0E;
+    //private final static byte SUBPARAM_MESSAGE_DISPLAY_MODE             = 0x0F;
+    //private final static byte SUBPARAM_MULTIPLE_ENCODING_USER_DATA      = 0x10;
+    //private final static byte SUBPARAM_MESSAGE_DEPOSIT_INDEX            = 0x11;
+    //private final static byte SUBPARAM_SERVICE_CATEGORY_PROGRAM_DATA    = 0x12;
+    //private final static byte SUBPARAM_SERVICE_CATEGORY_PROGRAM_RESULTS = 0x13;
+    private final static byte SUBPARAM_MESSAGE_STATUS                   = 0x14;
+    //private final static byte SUBPARAM_TP_FAILURE_CAUSE                 = 0x15;
+    //private final static byte SUBPARAM_ENHANCED_VMN                     = 0x16;
+    //private final static byte SUBPARAM_ENHANCED_VMN_ACK                 = 0x17;
 
     // For completeness the following fields are listed, though not used yet.
     /**
@@ -94,9 +139,6 @@
     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
@@ -109,7 +151,7 @@
      * (Special rules apply for WAP-messages.)
      * (See 3GPP2 C.S0015-B, v2, 4.5.1)
      */
-    public int messageID;
+    public int messageId;
 
     /**
      * 1-bit value that indicates whether a User Data Header is present.
@@ -188,5 +230,440 @@
      */
     public int messageStatus = STATUS_UNDEFINED;
 
-}
+    private static class CodingException extends Exception {
+        public CodingException(String s) {
+            super(s);
+        }
+    }
 
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("BearerData:\n");
+        builder.append("  messageType: " + messageType + "\n");
+        builder.append("  messageId: " + (int)messageId + "\n");
+        builder.append("  hasUserDataHeader: " + hasUserDataHeader + "\n");
+        builder.append("  timeStamp: " + timeStamp + "\n");
+        builder.append("  userAckReq: " + userAckReq + "\n");
+        builder.append("  deliveryAckReq: " + deliveryAckReq + "\n");
+        builder.append("  readAckReq: " + readAckReq + "\n");
+        builder.append("  reportReq: " + reportReq + "\n");
+        builder.append("  numberOfMessages: " + numberOfMessages + "\n");
+        builder.append("  callbackNumber: " + callbackNumber + "\n");
+        builder.append("  displayMode: " + displayMode + "\n");
+        builder.append("  errorClass: " + errorClass + "\n");
+        builder.append("  messageStatus: " + messageStatus + "\n");
+        builder.append("  userData: " + userData + "\n");
+        return builder.toString();
+    }
+
+    private static void encodeMessageId(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        outStream.write(8, 3);
+        outStream.write(4, bData.messageType);
+        outStream.write(8, bData.messageId >> 8);
+        outStream.write(8, bData.messageId);
+        outStream.write(1, bData.hasUserDataHeader ? 1 : 0);
+        outStream.skip(3);
+    }
+
+    private static void encodeUserData(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        int dataBits = (bData.userData.payload.length * 8) - bData.userData.paddingBits;
+        byte[] headerData = null;
+        if (bData.hasUserDataHeader) {
+            headerData = bData.userData.userDataHeader.toByteArray();
+            dataBits += headerData.length * 8;
+        }
+        int paramBits = dataBits + 13;
+        if ((bData.userData.msgEncoding == UserData.ENCODING_IS91_EXTENDED_PROTOCOL) ||
+            (bData.userData.msgEncoding == UserData.ENCODING_GSM_DCS)) {
+            paramBits += 8;
+        }
+        int paramBytes = (paramBits / 8) + ((paramBits % 8) > 0 ? 1 : 0);
+        int paddingBits = (paramBytes * 8) - paramBits;
+        outStream.write(8, paramBytes);
+        outStream.write(5, bData.userData.msgEncoding);
+        if ((bData.userData.msgEncoding == UserData.ENCODING_IS91_EXTENDED_PROTOCOL) ||
+            (bData.userData.msgEncoding == UserData.ENCODING_GSM_DCS)) {
+            outStream.write(8, bData.userData.msgType);
+        }
+        outStream.write(8, bData.userData.numFields);
+        if (headerData != null) outStream.writeByteArray(headerData.length * 8, headerData);
+        outStream.writeByteArray(dataBits, bData.userData.payload);
+        if (paddingBits > 0) outStream.write(paddingBits, 0);
+    }
+
+    private static void encodeReplyOption(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        outStream.write(8, 1);
+        outStream.write(1, bData.userAckReq     ? 1 : 0);
+        outStream.write(1, bData.deliveryAckReq ? 1 : 0);
+        outStream.write(1, bData.readAckReq     ? 1 : 0);
+        outStream.write(1, bData.reportReq      ? 1 : 0);
+        outStream.write(4, 0);
+    }
+
+    private static byte[] encodeDtmfSmsAddress(String address) {
+        int digits = address.length();
+        int dataBits = digits * 4;
+        int dataBytes = (dataBits / 8);
+        dataBytes += (dataBits % 8) > 0 ? 1 : 0;
+        byte[] rawData = new byte[dataBytes];
+        for (int i = 0; i < digits; i++) {
+            char c = address.charAt(i);
+            int val = 0;
+            if ((c >= '1') && (c <= '9')) val = c - '0';
+            else if (c == '0') val = 10;
+            else if (c == '*') val = 11;
+            else if (c == '#') val = 12;
+            else return null;
+            rawData[i / 2] |= val << (4 - ((i % 2) * 4));
+        }
+        return rawData;
+    }
+
+    private static void encodeCdmaSmsAddress(CdmaSmsAddress addr) throws CodingException {
+        if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
+            try {
+                addr.origBytes = addr.address.getBytes("US-ASCII");
+            } catch (java.io.UnsupportedEncodingException ex) {
+                throw new CodingException("invalid SMS address, cannot convert to ASCII");
+            }
+        } else {
+            addr.origBytes = encodeDtmfSmsAddress(addr.address);
+        }
+    }
+
+    private static void encodeCallbackNumber(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException, CodingException
+    {
+        CdmaSmsAddress addr = bData.callbackNumber;
+        encodeCdmaSmsAddress(addr);
+        int paramBits = 9;
+        int dataBits = 0;
+        if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
+            paramBits += 7;
+            dataBits = addr.numberOfDigits * 8;
+        } else {
+            dataBits = addr.numberOfDigits * 4;
+        }
+        paramBits += dataBits;
+        int paramBytes = (paramBits / 8) + ((paramBits % 8) > 0 ? 1 : 0);
+        int paddingBits = (paramBytes * 8) - paramBits;
+        outStream.write(8, paramBytes);
+        outStream.write(1, addr.digitMode);
+        if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
+            outStream.write(3, addr.ton);
+            outStream.write(4, addr.numberPlan);
+        }
+        outStream.write(8, addr.numberOfDigits);
+        outStream.writeByteArray(dataBits, addr.origBytes);
+        if (paddingBits > 0) outStream.write(paddingBits, 0);
+    }
+
+    private static void encodeMsgStatus(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        outStream.write(8, 1);
+        outStream.write(2, bData.errorClass);
+        outStream.write(6, bData.messageStatus);
+    }
+
+    private static void encodeMsgCount(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        outStream.write(8, 1);
+        outStream.write(8, bData.numberOfMessages);
+    }
+
+    private static void encodeMsgCenterTimeStamp(BearerData bData, BitwiseOutputStream outStream)
+        throws BitwiseOutputStream.AccessException
+    {
+        outStream.write(8, 6);
+        outStream.writeByteArray(6 * 8, bData.timeStamp);
+    }
+
+    /**
+     * Create serialized representation for BearerData object.
+     * (See 3GPP2 C.R1001-F, v1.0, section 4.5 for layout details)
+     *
+     * @param bearerData an instance of BearerData.
+     *
+     * @return data byta array of raw encoded SMS bearer data.
+     */
+    public static byte[] encode(BearerData bData) {
+        try {
+            BitwiseOutputStream outStream = new BitwiseOutputStream(200);
+            outStream.write(8, SUBPARAM_MESSAGE_IDENTIFIER);
+            encodeMessageId(bData, outStream);
+            if (bData.userData != null) {
+                outStream.write(8, SUBPARAM_USER_DATA);
+                encodeUserData(bData, outStream);
+            }
+            if (bData.callbackNumber != null) {
+                outStream.write(8, SUBPARAM_CALLBACK_NUMBER);
+                encodeCallbackNumber(bData, outStream);
+            }
+            if (bData.userAckReq || bData.deliveryAckReq || bData.readAckReq || bData.reportReq) {
+                outStream.write(8, SUBPARAM_REPLY_OPTION);
+                encodeReplyOption(bData, outStream);
+            }
+            if (bData.numberOfMessages != 0) {
+                outStream.write(8, SUBPARAM_NUMBER_OF_MESSAGES);
+                encodeMsgCount(bData, outStream);
+            }
+            if (bData.timeStamp != null) {
+                outStream.write(8, SUBPARAM_MESSAGE_CENTER_TIME_STAMP);
+                encodeMsgCenterTimeStamp(bData, outStream);
+            }
+            return outStream.toByteArray();
+        } catch (BitwiseOutputStream.AccessException ex) {
+            Log.e(LOG_TAG, "BearerData encode failed: " + ex);
+        } catch (CodingException ex) {
+            Log.e(LOG_TAG, "BearerData encode failed: " + ex);
+        }
+        return null;
+   }
+
+    private static void decodeMessageId(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException, CodingException
+    {
+        if (inStream.read(8) != 3) {
+            throw new CodingException("MESSAGE_IDENTIFIER subparam size incorrect");
+        }
+        bData.messageType = inStream.read(4);
+        bData.messageId = inStream.read(8) << 8;
+        bData.messageId |= inStream.read(8);
+        bData.hasUserDataHeader = (inStream.read(1) == 1);
+        inStream.skip(3);
+    }
+
+    private static void decodeUserData(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException
+    {
+        byte paramBytes = inStream.read(8);
+        bData.userData = new UserData();
+        bData.userData.msgEncoding = inStream.read(5);
+        bData.userData.msgType = 0;
+        int consumedBits = 5;
+        if ((bData.userData.msgEncoding == UserData.ENCODING_IS91_EXTENDED_PROTOCOL) ||
+            (bData.userData.msgEncoding == UserData.ENCODING_GSM_DCS)) {
+            bData.userData.msgType = inStream.read(8);
+            consumedBits += 8;
+        }
+        bData.userData.numFields = inStream.read(8);
+        consumedBits += 8;
+        int dataBits = (paramBytes * 8) - consumedBits;
+        bData.userData.payload = inStream.readByteArray(dataBits);
+    }
+
+    private static String decodePayloadStr(byte[] data, int offset, int numFields, String format)
+        throws CodingException
+    {
+        try {
+            return new String(data, offset, numFields, format);
+        } catch (java.io.UnsupportedEncodingException ex) {
+            throw new CodingException("invalid ASCII user data code");
+        }
+    }
+
+    private static void decodeUserDataPayload(UserData userData, boolean hasUserDataHeader)
+        throws CodingException
+    {
+        int offset = 0;
+        if (hasUserDataHeader) {
+            int UdhLen = userData.payload[0];
+            byte[] headerData = new byte[UdhLen];
+            System.arraycopy(userData.payload, 1, headerData, 0, UdhLen);
+            userData.userDataHeader = SmsHeader.parse(headerData);
+        }
+        switch (userData.msgEncoding) {
+        case UserData.ENCODING_GSM_7BIT_ALPHABET:
+            userData.payloadStr = GsmAlphabet.gsm7BitPackedToString(userData.payload,
+                                                                    offset, userData.numFields);
+            break;
+        case UserData.ENCODING_7BIT_ASCII:
+            userData.payloadStr = decodePayloadStr(userData.payload, offset,
+                                                   userData.numFields, "US-ASCII");
+            break;
+        case UserData.ENCODING_UNICODE_16:
+            userData.payloadStr = decodePayloadStr(userData.payload, offset,
+                                                   userData.numFields * 2, "UTF-16");
+            break;
+        default:
+            throw new CodingException("unsupported user data encoding ("
+                                      + userData.msgEncoding + ")");
+        }
+    }
+
+    private static void decodeReplyOption(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException, CodingException
+    {
+        byte paramBytes = inStream.read(8);
+        if (paramBytes != 1) {
+            throw new CodingException("REPLY_OPTION subparam size incorrect");
+        }
+        bData.userAckReq     = (inStream.read(1) == 1);
+        bData.deliveryAckReq = (inStream.read(1) == 1);
+        bData.readAckReq     = (inStream.read(1) == 1);
+        bData.reportReq      = (inStream.read(1) == 1);
+        inStream.skip(4);
+    }
+
+    private static void decodeMsgCount(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException, CodingException
+    {
+        if (inStream.read(8) != 1) {
+            throw new CodingException("NUMBER_OF_MESSAGES subparam size incorrect");
+        }
+        bData.numberOfMessages = inStream.read(8);
+    }
+
+    private static String decodeDtmfSmsAddress(byte[] rawData, int numFields)
+        throws CodingException
+    {
+        /* DTMF 4-bit digit encoding, defined in at
+         * 3GPP2 C.S005-D, v2.0, table 2.7.1.3.2.4-4 */
+        StringBuffer strBuf = new StringBuffer(numFields);
+        for (int i = 0; i < numFields; i++) {
+            int val = 0x0F & (rawData[i / 2] >>> (4 - ((i % 2) * 4)));
+            if ((val >= 1) && (val <= 9)) strBuf.append(Integer.toString(val, 10));
+            else if (val == 10) strBuf.append('0');
+            else if (val == 11) strBuf.append('*');
+            else if (val == 12) strBuf.append('#');
+            else throw new CodingException("invalid SMS address DTMF code (" + val + ")");
+        }
+        return strBuf.toString();
+    }
+
+    private static void decodeSmsAddress(CdmaSmsAddress addr) throws CodingException {
+        if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
+            try {
+                /* As specified in 3GPP2 C.S0015-B, v2, 4.5.15 -- actually
+                 * just 7-bit ASCII encoding, with the MSB being zero. */
+                addr.address = new String(addr.origBytes, 0, addr.origBytes.length, "US-ASCII");
+            } catch (java.io.UnsupportedEncodingException ex) {
+                throw new CodingException("invalid SMS address ASCII code");
+            }
+        } else {
+            addr.address = decodeDtmfSmsAddress(addr.origBytes, addr.numberOfDigits);
+        }
+    }
+
+    private static void decodeCallbackNumber(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException, CodingException
+    {
+        byte paramBytes = inStream.read(8);
+        CdmaSmsAddress addr = new CdmaSmsAddress();
+        addr.digitMode = inStream.read(1);
+        byte fieldBits = 4;
+        byte consumedBits = 1;
+        if (addr.digitMode == CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR) {
+            addr.ton = inStream.read(3);
+            addr.numberPlan = inStream.read(4);
+            fieldBits = 8;
+            consumedBits += 7;
+        }
+        addr.numberOfDigits = inStream.read(8);
+        consumedBits += 8;
+        int remainingBits = (paramBytes * 8) - consumedBits;
+        int dataBits = addr.numberOfDigits * fieldBits;
+        int paddingBits = remainingBits - dataBits;
+        if (remainingBits < dataBits) {
+            throw new CodingException("CALLBACK_NUMBER subparam encoding size error (" +
+                                      "remainingBits " + remainingBits + ", dataBits " +
+                                      dataBits + ", paddingBits " + paddingBits + ")");
+        }
+        addr.origBytes = inStream.readByteArray(dataBits);
+        inStream.skip(paddingBits);
+        decodeSmsAddress(addr);
+        bData.callbackNumber = addr;
+    }
+
+    private static void decodeMsgStatus(BearerData bData, BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException, CodingException
+    {
+        if (inStream.read(8) != 1) {
+            throw new CodingException("MESSAGE_STATUS subparam size incorrect");
+        }
+        bData.errorClass = inStream.read(2);
+        bData.messageStatus = inStream.read(6);
+    }
+
+    private static void decodeMsgCenterTimeStamp(BearerData bData,
+                                                 BitwiseInputStream inStream)
+        throws BitwiseInputStream.AccessException, CodingException
+    {
+        if (inStream.read(8) != 6) {
+            throw new CodingException("MESSAGE_CENTER_TIME_STAMP subparam size incorrect");
+        }
+        bData.timeStamp = inStream.readByteArray(6 * 8);
+    }
+
+    /**
+     * Create BearerData object from serialized representation.
+     * (See 3GPP2 C.R1001-F, v1.0, section 4.5 for layout details)
+     *
+     * @param smsData byte array of raw encoded SMS bearer data.
+     *
+     * @return an instance of BearerData.
+     */
+    public static BearerData decode(byte[] smsData) {
+        try {
+            BitwiseInputStream inStream = new BitwiseInputStream(smsData);
+            BearerData bData = new BearerData();
+            int foundSubparamMask = 0;
+            while (inStream.available() > 0) {
+                int subparamId = inStream.read(8);
+                int subparamIdBit = 1 << subparamId;
+                if ((foundSubparamMask & subparamIdBit) != 0) {
+                    throw new CodingException("illegal duplicate subparameter (" +
+                                              subparamId + ")");
+                }
+                foundSubparamMask |= subparamIdBit;
+                switch (subparamId) {
+                case SUBPARAM_MESSAGE_IDENTIFIER:
+                    decodeMessageId(bData, inStream);
+                    break;
+                case SUBPARAM_USER_DATA:
+                    decodeUserData(bData, inStream);
+                    break;
+                case SUBPARAM_REPLY_OPTION:
+                    decodeReplyOption(bData, inStream);
+                    break;
+                case SUBPARAM_NUMBER_OF_MESSAGES:
+                    decodeMsgCount(bData, inStream);
+                    break;
+                case SUBPARAM_CALLBACK_NUMBER:
+                    decodeCallbackNumber(bData, inStream);
+                    break;
+                case SUBPARAM_MESSAGE_STATUS:
+                    decodeMsgStatus(bData, inStream);
+                    break;
+                case SUBPARAM_MESSAGE_CENTER_TIME_STAMP:
+                    decodeMsgCenterTimeStamp(bData, inStream);
+                    break;
+                default:
+                    throw new CodingException("unsupported bearer data subparameter ("
+                                              + subparamId + ")");
+                }
+            }
+            if ((foundSubparamMask & (1 << SUBPARAM_MESSAGE_IDENTIFIER)) == 0) {
+                throw new CodingException("missing MESSAGE_IDENTIFIER subparam");
+            }
+            if (bData.userData != null) {
+                decodeUserDataPayload(bData.userData, bData.hasUserDataHeader);
+            }
+            return bData;
+        } catch (BitwiseInputStream.AccessException ex) {
+            Log.e(LOG_TAG, "BearerData decode failed: " + ex);
+        } catch (CodingException ex) {
+            Log.e(LOG_TAG, "BearerData decode failed: " + ex);
+        }
+        return null;
+    }
+}
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/CdmaSmsAddress.java b/telephony/java/com/android/internal/telephony/cdma/sms/CdmaSmsAddress.java
index 1643cab..440debb 100644
--- a/telephony/java/com/android/internal/telephony/cdma/sms/CdmaSmsAddress.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/CdmaSmsAddress.java
@@ -17,6 +17,7 @@
 package com.android.internal.telephony.cdma.sms;
 
 import com.android.internal.telephony.SmsAddress;
+import com.android.internal.util.HexDump;
 
 public class CdmaSmsAddress extends SmsAddress {
     /**
@@ -95,4 +96,18 @@
     public CdmaSmsAddress(){
     }
 
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("CdmaSmsAddress:\n");
+        builder.append("  digitMode: " + digitMode + "\n");
+        builder.append("  numberMode: " + numberMode + "\n");
+        builder.append("  numberPlan: " + numberPlan + "\n");
+        builder.append("  numberOfDigits: " + numberOfDigits + "\n");
+        builder.append("  ton: " + ton + "\n");
+        builder.append("  address: " + address + "\n");
+        builder.append("  origBytes: " + HexDump.toHexString(origBytes) + "\n");
+        return builder.toString();
+    }
+
 }
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/SmsDataCoding.java b/telephony/java/com/android/internal/telephony/cdma/sms/SmsDataCoding.java
deleted file mode 100644
index 6ba7463..0000000
--- a/telephony/java/com/android/internal/telephony/cdma/sms/SmsDataCoding.java
+++ /dev/null
@@ -1,371 +0,0 @@
-/*
- * 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/UserData.java b/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java
index e761469..bd6fbb4 100644
--- a/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/UserData.java
@@ -17,24 +17,25 @@
 package com.android.internal.telephony.cdma.sms;
 
 import com.android.internal.telephony.SmsHeader;
+import com.android.internal.util.HexDump;
 
 public class UserData{
 
     /**
-     * Supported user data encoding types
+     * 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;
+    public static final int ENCODING_OCTET                      = 0x00;
+    public static final int ENCODING_IS91_EXTENDED_PROTOCOL     = 0x01;
+    public static final int ENCODING_7BIT_ASCII                 = 0x02;
+    //public static final int ENCODING_IA5                        = 0x03;
+    public static final int ENCODING_UNICODE_16                 = 0x04;
+    //public static final int ENCODING_SHIFT_JIS                  = 0x05;
+    //public static final int ENCODING_KOREAN                     = 0x06;
+    //public static final int ENCODING_LATIN_HEBREW               = 0x07;
+    //public static final int ENCODING_LATIN                      = 0x08;
+    public static final int ENCODING_GSM_7BIT_ALPHABET          = 0x09;
+    public static final int ENCODING_GSM_DCS                    = 0x0A;
 
     /**
      * Contains the data header of the user data
@@ -44,20 +45,37 @@
     /**
      * Contains the data encoding type for the SMS message
      */
-    public int userDataEncoding;
+    public int msgEncoding;
 
-    // needed when encoding is IS91 or DCS (not supported yet):
-    //public int messageType;
+    // XXX needed when encoding is IS91 or DCS (not supported yet):
+    public int msgType;
 
     /**
      * Number of invalid bits in the last byte of data.
      */
     public int paddingBits;
 
+    public int numFields;
+
     /**
      * Contains the user data of a SMS message
      * (See 3GPP2 C.S0015-B, v2, 4.5.2)
      */
-    public byte[] userData;
+    public byte[] payload;
+    public String payloadStr;
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("UserData:\n");
+        builder.append("  msgEncoding: " + msgEncoding + "\n");
+        builder.append("  msgType: " + msgType + "\n");
+        builder.append("  paddingBits: " + paddingBits + "\n");
+        builder.append("  numFields: " + (int)numFields + "\n");
+        builder.append("  userDataHeader: " + userDataHeader + "\n");
+        builder.append("  payload: " + HexDump.toHexString(payload));
+        builder.append("  payloadStr: " + payloadStr);
+        return builder.toString();
+    }
 
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
old mode 100644
new mode 100755
index d1ae997..a2d3c5e
--- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -316,6 +316,11 @@
             // we report data connected
 
             ret = DataState.CONNECTED;
+        } else if (mSST == null) {
+            // Radio Technology Change is ongoning, dispose() and removeReferences() have
+            // already been called
+
+            ret = DataState.DISCONNECTED;
         } else if (mSST.getCurrentGprsState()
                 != ServiceState.STATE_IN_SERVICE) {
             // If we're out of service, open TCP sockets may still work
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index e2da7cb..1b07add 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -131,7 +131,8 @@
 
     private static int APN_DEFAULT_ID = 0;
     private static int APN_MMS_ID = 1;
-    private static int APN_NUM_TYPES = 2;
+    private static int APN_SUPL_ID = 2;
+    private static int APN_NUM_TYPES = 3;
 
     private boolean[] dataEnabled = new boolean[APN_NUM_TYPES];
 
@@ -322,8 +323,8 @@
 
     /**
      * Ensure that we are connected to an APN of the specified type.
-     * @param type the APN type (currently the only valid value
-     * is {@link Phone#APN_TYPE_MMS})
+     * @param type the APN type (currently the only valid values
+     * are {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL})
      * @return the result of the operation. Success is indicated by
      * a return value of either {@code Phone.APN_ALREADY_ACTIVE} or
      * {@code Phone.APN_REQUEST_STARTED}. In the latter case, a broadcast
@@ -331,9 +332,11 @@
      * the APN has been established.
      */
     protected int enableApnType(String type) {
-        if (!TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
+        if (!TextUtils.equals(type, Phone.APN_TYPE_MMS) &&
+                !TextUtils.equals(type, Phone.APN_TYPE_SUPL)) {
             return Phone.APN_REQUEST_FAILED;
         }
+
         // If already active, return
         Log.d(LOG_TAG, "enableApnType("+type+")");
         if (isApnTypeActive(type)) {
@@ -371,7 +374,8 @@
      */
     protected int disableApnType(String type) {
         Log.d(LOG_TAG, "disableApnType("+type+")");
-        if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
+        if (TextUtils.equals(type, Phone.APN_TYPE_MMS) ||
+                TextUtils.equals(type, Phone.APN_TYPE_SUPL)) {
             removeMessages(EVENT_RESTORE_DEFAULT_APN);
             setEnabled(type, false);
             if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
@@ -439,6 +443,8 @@
             return dataEnabled[APN_DEFAULT_ID];
         } else if (TextUtils.equals(apnType, Phone.APN_TYPE_MMS)) {
             return dataEnabled[APN_MMS_ID];
+        } else if (TextUtils.equals(apnType, Phone.APN_TYPE_SUPL)) {
+            return dataEnabled[APN_SUPL_ID];
         } else {
             return false;
         }
@@ -450,9 +456,12 @@
             dataEnabled[APN_DEFAULT_ID] = enable;
         } else if (TextUtils.equals(apnType, Phone.APN_TYPE_MMS)) {
             dataEnabled[APN_MMS_ID] = enable;
+        } else if (TextUtils.equals(apnType, Phone.APN_TYPE_SUPL)) {
+            dataEnabled[APN_SUPL_ID] = enable;
         }
         Log.d(LOG_TAG, "dataEnabled[DEFAULT_APN]=" + dataEnabled[APN_DEFAULT_ID] +
-                " dataEnabled[MMS_APN]=" + dataEnabled[APN_MMS_ID]);
+                " dataEnabled[MMS_APN]=" + dataEnabled[APN_MMS_ID] +
+                " dataEnabled[SUPL_APN]=" + dataEnabled[APN_SUPL_ID]);
     }
 
     /**
@@ -476,13 +485,14 @@
             return trySetupData(Phone.REASON_DATA_ENABLED);
         } else if (!enable) {
             setEnabled(Phone.APN_TYPE_DEFAULT, false);
-            // Don't tear down if there is an active APN and it handles MMS.
+            // Don't tear down if there is an active APN and it handles MMS or SUPL.
             // TODO: This isn't very general.
-            if (!isApnTypeActive(Phone.APN_TYPE_MMS) || !isEnabled(Phone.APN_TYPE_MMS)) {
-                cleanUpConnection(true, Phone.REASON_DATA_DISABLED);
-                return true;
+            if ((isApnTypeActive(Phone.APN_TYPE_MMS) && isEnabled(Phone.APN_TYPE_MMS)) ||
+                (isApnTypeActive(Phone.APN_TYPE_SUPL) && isEnabled(Phone.APN_TYPE_SUPL))) {
+                return false;
             }
-            return false;
+            cleanUpConnection(true, Phone.REASON_DATA_DISABLED);
+            return true;
         } else {
             // isEnabled && enable
             return true;
@@ -513,7 +523,7 @@
      * {@code true} otherwise.
      */
     public boolean getAnyDataEnabled() {
-        return dataEnabled[APN_DEFAULT_ID] || dataEnabled[APN_MMS_ID];
+        return dataEnabled[APN_DEFAULT_ID] || dataEnabled[APN_MMS_ID] || dataEnabled[APN_SUPL_ID];
     }
 
     /**
@@ -1316,7 +1326,7 @@
              * rather an app that inadvertantly fails to reset to the
              * default APN, or that dies before doing so.
              */
-            if (dataEnabled[APN_MMS_ID]) {
+            if (dataEnabled[APN_MMS_ID] || dataEnabled[APN_SUPL_ID]) {
                 removeMessages(EVENT_RESTORE_DEFAULT_APN);
                 sendMessageDelayed(obtainMessage(EVENT_RESTORE_DEFAULT_APN),
                         getRestoreDefaultApnDelay());
diff --git a/telephony/jni/cdmasms/Android.mk b/telephony/jni/cdmasms/Android.mk
deleted file mode 100644
index b0c96b4..0000000
--- a/telephony/jni/cdmasms/Android.mk
+++ /dev/null
@@ -1,24 +0,0 @@
-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
deleted file mode 100644
index 2a8e825..0000000
--- a/telephony/jni/cdmasms/cdma_sms_jni.cpp
+++ /dev/null
@@ -1,1300 +0,0 @@
-/*
- * 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
deleted file mode 100644
index 253c006..0000000
--- a/telephony/jni/cdmasms/cdma_sms_jni.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * 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/BitwiseStreamsTest.java b/tests/AndroidTests/src/com/android/unit_tests/BitwiseStreamsTest.java
new file mode 100644
index 0000000..2c9075c
--- /dev/null
+++ b/tests/AndroidTests/src/com/android/unit_tests/BitwiseStreamsTest.java
@@ -0,0 +1,88 @@
+/*
+ * 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.unit_tests;
+
+import com.android.internal.util.BitwiseInputStream;
+import com.android.internal.util.BitwiseOutputStream;
+import com.android.internal.util.HexDump;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+public class BitwiseStreamsTest extends AndroidTestCase {
+    private final static String LOG_TAG = "BitwiseStreamsTest";
+
+    @SmallTest
+    public void testOne() throws Exception {
+        int offset = 3;
+        byte[] inBuf = HexDump.hexStringToByteArray("FFDD");
+        BitwiseOutputStream outStream = new BitwiseOutputStream(30);
+        outStream.skip(offset);
+        for (int i = 0; i < inBuf.length; i++) outStream.write(8, inBuf[i]);
+        byte[] outBuf = outStream.toByteArray();
+        BitwiseInputStream inStream = new BitwiseInputStream(outBuf);
+        byte[] inBufDup = new byte[inBuf.length];
+        inStream.skip(offset);
+        for (int i = 0; i < inBufDup.length; i++) inBufDup[i] = inStream.read(8);
+        assertEquals(HexDump.toHexString(inBuf), HexDump.toHexString(inBufDup));
+    }
+
+    @SmallTest
+    public void testTwo() throws Exception {
+        int offset = 3;
+        byte[] inBuf = HexDump.hexStringToByteArray("11d4f29c0e9ad3c36e72584e064d9b53");
+        BitwiseOutputStream outStream = new BitwiseOutputStream(30);
+        outStream.skip(offset);
+        for (int i = 0; i < inBuf.length; i++) outStream.write(8, inBuf[i]);
+        BitwiseInputStream inStream = new BitwiseInputStream(outStream.toByteArray());
+        inStream.skip(offset);
+        byte[] inBufDup = new byte[inBuf.length];
+        for (int i = 0; i < inBufDup.length; i++) inBufDup[i] = inStream.read(8);
+        assertEquals(HexDump.toHexString(inBuf), HexDump.toHexString(inBufDup));
+    }
+
+    @SmallTest
+    public void testThree() throws Exception {
+        int offset = 4;
+        byte[] inBuf = HexDump.hexStringToByteArray("00031040900112488ea794e0");
+        BitwiseOutputStream outStream = new BitwiseOutputStream(30);
+        outStream.skip(offset);
+        for (int i = 0; i < inBuf.length; i++) outStream.write(8, inBuf[i]);
+        BitwiseInputStream inStream = new BitwiseInputStream(outStream.toByteArray());
+        inStream.skip(offset);
+        byte[] inBufDup = new byte[inBuf.length];
+        for (int i = 0; i < inBufDup.length; i++) inBufDup[i] = inStream.read(8);
+        assertEquals(HexDump.toHexString(inBuf), HexDump.toHexString(inBufDup));
+    }
+
+    @SmallTest
+    public void testFour() throws Exception {
+        int offset = 7;
+        byte[] inBuf = HexDump.hexStringToByteArray("00031040900112488ea794e0");
+        BitwiseOutputStream outStream = new BitwiseOutputStream(30);
+        outStream.skip(offset);
+        for (int i = 0; i < inBuf.length; i++) {
+            outStream.write(5, inBuf[i] >>> 3);
+            outStream.write(3, inBuf[i] & 0x07);
+        }
+        BitwiseInputStream inStream = new BitwiseInputStream(outStream.toByteArray());
+        inStream.skip(offset);
+        byte[] inBufDup = new byte[inBuf.length];
+        for (int i = 0; i < inBufDup.length; i++) inBufDup[i] = inStream.read(8);
+        assertEquals(HexDump.toHexString(inBuf), HexDump.toHexString(inBufDup));
+    }
+}
diff --git a/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java b/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java
new file mode 100644
index 0000000..723512c
--- /dev/null
+++ b/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java
@@ -0,0 +1,273 @@
+/*
+ * 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.unit_tests;
+
+import com.android.internal.telephony.GsmAlphabet;
+import com.android.internal.telephony.SmsHeader;
+import com.android.internal.telephony.cdma.sms.BearerData;
+import com.android.internal.telephony.cdma.sms.UserData;
+import com.android.internal.telephony.cdma.sms.CdmaSmsAddress;
+import com.android.internal.util.BitwiseInputStream;
+import com.android.internal.util.BitwiseOutputStream;
+import com.android.internal.util.HexDump;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.util.Iterator;
+
+import android.util.Log;
+
+public class CdmaSmsTest extends AndroidTestCase {
+    private final static String LOG_TAG = "Cdma_Sms_Test";
+
+    private static UserData makeUserData(String msg) {
+        UserData userData = new UserData();
+        byte[] payload;
+        try {
+            payload = GsmAlphabet.stringToGsm7BitPacked(msg);
+            userData.payload = new byte[payload.length - 1];
+            for (int i = 0; i < userData.payload.length; i++) userData.payload[i] = payload[i + 1];
+            userData.numFields = payload[0];
+            userData.paddingBits = (userData.payload.length * 8) - (userData.numFields * 7);
+            userData.paddingBits = 0; // XXX this is better, wtf?
+            userData.msgEncoding = UserData.ENCODING_GSM_7BIT_ALPHABET;
+        } catch (com.android.internal.telephony.EncodeException ex) {
+            assertEquals(1, 0);
+        }
+        return userData;
+    }
+
+    @SmallTest
+    public void testStandardSms() throws Exception {
+        String pdu = "00031040900112488ea794e074d69e1b7392c270326cde9e98";
+        BearerData bearerData = BearerData.decode(HexDump.hexStringToByteArray(pdu));
+        assertEquals("Test standard SMS", bearerData.userData.payloadStr);
+    }
+
+    @SmallTest
+    public void testStandardSmsFeedback() throws Exception {
+        BearerData bearerData = new BearerData();
+        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+        bearerData.messageId = 0;
+        bearerData.hasUserDataHeader = false;
+        String payloadStr = "Test standard SMS";
+        bearerData.userData = makeUserData(payloadStr);
+        byte []encodedSms = BearerData.encode(bearerData);
+        BearerData revBearerData = BearerData.decode(encodedSms);
+        assertEquals(BearerData.MESSAGE_TYPE_DELIVER, revBearerData.messageType);
+        assertEquals(0, revBearerData.messageId);
+        assertEquals(false, revBearerData.hasUserDataHeader);
+        assertEquals(UserData.ENCODING_GSM_7BIT_ALPHABET, revBearerData.userData.msgEncoding);
+        assertEquals(payloadStr.length(), revBearerData.userData.numFields);
+        assertEquals(payloadStr, revBearerData.userData.payloadStr);
+    }
+
+    @SmallTest
+    public void testAltUserDataFeedback() throws Exception {
+        try {
+            BearerData bearerData = new BearerData();
+            bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+            bearerData.messageId = 0;
+            bearerData.hasUserDataHeader = false;
+            UserData userData = new UserData();
+            String str1 = "test ascii user data encoding";
+            userData.payload = str1.getBytes("US-ASCII");
+            userData.numFields = str1.length();
+            userData.paddingBits = 0;
+            userData.msgEncoding = UserData.ENCODING_7BIT_ASCII;
+            bearerData.userData = userData;
+            byte []encodedSms = BearerData.encode(bearerData);
+            BearerData revBearerData = BearerData.decode(encodedSms);
+            assertEquals(str1, revBearerData.userData.payloadStr);
+            String str2 = "\u0160u\u1E5B\u0301r\u1ECFg\uD835\uDC1At\u00E9\u4E002\u3042";
+            userData.payload = str2.getBytes("UTF-16");
+            userData.numFields = str2.length() + 1;
+            userData.msgEncoding = UserData.ENCODING_UNICODE_16;
+            encodedSms = BearerData.encode(bearerData);
+            revBearerData = BearerData.decode(encodedSms);
+            assertEquals(str2, revBearerData.userData.payloadStr);
+        } catch (java.io.UnsupportedEncodingException ex) {
+            throw new RuntimeException("user data encoding error");
+        }
+    }
+
+    @SmallTest
+    public void testReplyOption() throws Exception {
+        String pdu1 = "0003104090011648b6a794e0705476bf77bceae934fe5f6d94d87450080a0180";
+        BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+        assertEquals("Test Acknowledgement 1", bd1.userData.payloadStr);
+        assertEquals(true, bd1.userAckReq);
+        assertEquals(false, bd1.deliveryAckReq);
+        assertEquals(false, bd1.readAckReq);
+        assertEquals(false, bd1.reportReq);
+        String pdu2 = "0003104090011648b6a794e0705476bf77bceae934fe5f6d94d87490080a0140";
+        BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
+        assertEquals("Test Acknowledgement 2", bd2.userData.payloadStr);
+        assertEquals(false, bd2.userAckReq);
+        assertEquals(true, bd2.deliveryAckReq);
+        assertEquals(false, bd2.readAckReq);
+        assertEquals(false, bd2.reportReq);
+        String pdu3 = "0003104090011648b6a794e0705476bf77bceae934fe5f6d94d874d0080a0120";
+        BearerData bd3 = BearerData.decode(HexDump.hexStringToByteArray(pdu3));
+        assertEquals("Test Acknowledgement 3", bd3.userData.payloadStr);
+        assertEquals(false, bd3.userAckReq);
+        assertEquals(false, bd3.deliveryAckReq);
+        assertEquals(true, bd3.readAckReq);
+        assertEquals(false, bd3.reportReq);
+        String pdu4 = "0003104090011648b6a794e0705476bf77bceae934fe5f6d94d87510080a0110";
+        BearerData bd4 = BearerData.decode(HexDump.hexStringToByteArray(pdu4));
+        assertEquals("Test Acknowledgement 4", bd4.userData.payloadStr);
+        assertEquals(false, bd4.userAckReq);
+        assertEquals(false, bd4.deliveryAckReq);
+        assertEquals(false, bd4.readAckReq);
+        assertEquals(true, bd4.reportReq);
+    }
+
+    @SmallTest
+    public void testReplyOptionFeedback() throws Exception {
+        BearerData bearerData = new BearerData();
+        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+        bearerData.messageId = 0;
+        bearerData.hasUserDataHeader = false;
+        bearerData.userData = makeUserData("test reply option");
+        bearerData.userAckReq = true;
+        byte []encodedSms = BearerData.encode(bearerData);
+        BearerData revBearerData = BearerData.decode(encodedSms);
+        assertEquals(true, revBearerData.userAckReq);
+        assertEquals(false, revBearerData.deliveryAckReq);
+        assertEquals(false, revBearerData.readAckReq);
+        assertEquals(false, revBearerData.reportReq);
+        bearerData.userAckReq = false;
+        bearerData.deliveryAckReq = true;
+        encodedSms = BearerData.encode(bearerData);
+        revBearerData = BearerData.decode(encodedSms);
+        assertEquals(false, revBearerData.userAckReq);
+        assertEquals(true, revBearerData.deliveryAckReq);
+        assertEquals(false, revBearerData.readAckReq);
+        assertEquals(false, revBearerData.reportReq);
+        bearerData.deliveryAckReq = false;
+        bearerData.readAckReq = true;
+        encodedSms = BearerData.encode(bearerData);
+        revBearerData = BearerData.decode(encodedSms);
+        assertEquals(false, revBearerData.userAckReq);
+        assertEquals(false, revBearerData.deliveryAckReq);
+        assertEquals(true, revBearerData.readAckReq);
+        assertEquals(false, revBearerData.reportReq);
+        bearerData.readAckReq = false;
+        bearerData.reportReq = true;
+        encodedSms = BearerData.encode(bearerData);
+        revBearerData = BearerData.decode(encodedSms);
+        assertEquals(false, revBearerData.userAckReq);
+        assertEquals(false, revBearerData.deliveryAckReq);
+        assertEquals(false, revBearerData.readAckReq);
+        assertEquals(true, revBearerData.reportReq);
+    }
+
+    @SmallTest
+    public void testNumberOfMessages() throws Exception {
+        String pdu1 = "000310409001124896a794e07595f69f199540ea759a0dc8e00b0163";
+        BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+        assertEquals("Test Voice mail 99", bd1.userData.payloadStr);
+        assertEquals(99, bd1.numberOfMessages);
+        String pdu2 = "00031040900113489ea794e07595f69f199540ea759a0988c0600b0164";
+        BearerData bd2 = BearerData.decode(HexDump.hexStringToByteArray(pdu2));
+        assertEquals("Test Voice mail 100", bd2.userData.payloadStr);
+        assertEquals(100, bd2.numberOfMessages);
+    }
+
+    @SmallTest
+    public void testNumberOfMessagesFeedback() throws Exception {
+        BearerData bearerData = new BearerData();
+        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+        bearerData.messageId = 0;
+        bearerData.hasUserDataHeader = false;
+        bearerData.userData = makeUserData("test message count");
+        bearerData.numberOfMessages = 27;
+        byte []encodedSms = BearerData.encode(bearerData);
+        BearerData revBearerData = BearerData.decode(encodedSms);
+        assertEquals(bearerData.numberOfMessages, revBearerData.numberOfMessages);
+    }
+
+    @SmallTest
+    public void testCallbackNum() throws Exception {
+        String pdu1 = "00031040900112488ea794e070d436cb638bc5e035ce2f97900e06910431323334";
+        BearerData bd1 = BearerData.decode(HexDump.hexStringToByteArray(pdu1));
+        assertEquals("Test Callback nbr", bd1.userData.payloadStr);
+        assertEquals(CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR, bd1.callbackNumber.digitMode);
+        assertEquals(CdmaSmsAddress.TON_INTERNATIONAL_OR_IP, bd1.callbackNumber.ton);
+        assertEquals(CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK, bd1.callbackNumber.numberMode);
+        assertEquals(CdmaSmsAddress.NUMBERING_PLAN_ISDN_TELEPHONY, bd1.callbackNumber.numberPlan);
+        assertEquals("1234", bd1.callbackNumber.address);
+    }
+
+    @SmallTest
+    public void testCallbackNumFeedback() throws Exception {
+        BearerData bearerData = new BearerData();
+        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+        bearerData.messageId = 0;
+        bearerData.hasUserDataHeader = false;
+        bearerData.userData = makeUserData("test callback number");
+        CdmaSmsAddress addr = new CdmaSmsAddress();
+        addr.digitMode = CdmaSmsAddress.DIGIT_MODE_8BIT_CHAR;
+        addr.ton = CdmaSmsAddress.TON_NATIONAL_OR_EMAIL;
+        addr.numberMode = CdmaSmsAddress.NUMBER_MODE_NOT_DATA_NETWORK;
+        addr.numberPlan = CdmaSmsAddress.NUMBERING_PLAN_UNKNOWN;
+        addr.address = "8005551212";
+        addr.numberOfDigits = (byte)addr.address.length();
+        bearerData.callbackNumber = addr;
+        byte []encodedSms = BearerData.encode(bearerData);
+        BearerData revBearerData = BearerData.decode(encodedSms);
+        CdmaSmsAddress revAddr = revBearerData.callbackNumber;
+        assertEquals(addr.digitMode, revAddr.digitMode);
+        assertEquals(addr.ton, revAddr.ton);
+        assertEquals(addr.numberMode, revAddr.numberMode);
+        assertEquals(addr.numberPlan, revAddr.numberPlan);
+        assertEquals(addr.numberOfDigits, revAddr.numberOfDigits);
+        assertEquals(addr.address, revAddr.address);
+        addr.address = "8*55#1012";
+        addr.numberOfDigits = (byte)addr.address.length();
+        addr.digitMode = CdmaSmsAddress.DIGIT_MODE_4BIT_DTMF;
+        encodedSms = BearerData.encode(bearerData);
+        revBearerData = BearerData.decode(encodedSms);
+        revAddr = revBearerData.callbackNumber;
+        assertEquals(addr.digitMode, revAddr.digitMode);
+        assertEquals(addr.numberOfDigits, revAddr.numberOfDigits);
+        assertEquals(addr.address, revAddr.address);
+    }
+
+    @SmallTest
+    public void testMsgCenterTimeStampFeedback() throws Exception {
+        BearerData bearerData = new BearerData();
+        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+        bearerData.messageId = 0;
+        bearerData.hasUserDataHeader = false;
+        bearerData.userData = makeUserData("test message center timestamp");
+        bearerData.timeStamp = HexDump.hexStringToByteArray("112233445566");
+        byte []encodedSms = BearerData.encode(bearerData);
+        BearerData revBearerData = BearerData.decode(encodedSms);
+        assertEquals(HexDump.toHexString(bearerData.timeStamp),
+                     HexDump.toHexString(revBearerData.timeStamp));
+    }
+
+    // XXX test messageId
+
+    // String pdu1 = "0003104090010d4866a794e07055965b91d040300c0100"; sid 12
+    // String pdu1 = "0003104090011748bea794e0731436ef3bd7c2e0352eef27a1c263fe58080d0101"; sid 13
+    // Log.d(LOG_TAG, "revBearerData -- " + revBearerData);
+
+}