Merge change 21653 into eclair

* changes:
  Remove global IO context and integrate it into the RS context.
diff --git a/api/current.xml b/api/current.xml
index 58c0bf8..461fc38 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -27032,6 +27032,21 @@
 <parameter name="selectionArgs" type="java.lang.String[]">
 </parameter>
 </method>
+<method name="getIsSyncable"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="account" type="android.accounts.Account">
+</parameter>
+<parameter name="authority" type="java.lang.String">
+</parameter>
+</method>
 <method name="getMasterSyncAutomatically"
  return="boolean"
  abstract="false"
@@ -27329,6 +27344,23 @@
 <parameter name="extras" type="android.os.Bundle">
 </parameter>
 </method>
+<method name="setIsSyncable"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="account" type="android.accounts.Account">
+</parameter>
+<parameter name="authority" type="java.lang.String">
+</parameter>
+<parameter name="syncable" type="int">
+</parameter>
+</method>
 <method name="setMasterSyncAutomatically"
  return="void"
  abstract="false"
@@ -35765,6 +35797,17 @@
  visibility="public"
 >
 </field>
+<field name="isUserFacing"
+ type="boolean"
+ transient="false"
+ volatile="false"
+ value="true"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <interface name="SyncStatusObserver"
  abstract="true"
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 98ed098..bf1a442 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -1012,6 +1012,31 @@
     }
 
     /**
+     * Check if this account/provider is syncable.
+     * @return >0 if it is syncable, 0 if not, and <0 if the state isn't known yet.
+     */
+    public static int getIsSyncable(Account account, String authority) {
+        try {
+            return getContentService().getIsSyncable(account, authority);
+        } catch (RemoteException e) {
+            throw new RuntimeException("the ContentService should always be reachable", e);
+        }
+    }
+
+    /**
+     * Set whether this account/provider is syncable.
+     * @param syncable >0 denotes syncable, 0 means not syncable, <0 means unknown
+     */
+    public static void setIsSyncable(Account account, String authority, int syncable) {
+        try {
+            getContentService().setIsSyncable(account, authority, syncable);
+        } catch (RemoteException e) {
+            // exception ignored; if this is thrown then it means the runtime is in the midst of
+            // being restarted
+        }
+    }
+
+    /**
      * Gets the master auto-sync setting that applies to all the providers and accounts.
      * If this is false then the per-provider auto-sync setting is ignored.
      *
diff --git a/core/java/android/content/ContentService.java b/core/java/android/content/ContentService.java
index 7a1ad2b..c4d8aaf 100644
--- a/core/java/android/content/ContentService.java
+++ b/core/java/android/content/ContentService.java
@@ -272,6 +272,37 @@
         }
     }
 
+    public int getIsSyncable(Account account, String providerName) {
+        mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
+                "no permission to read the sync settings");
+        long identityToken = clearCallingIdentity();
+        try {
+            SyncManager syncManager = getSyncManager();
+            if (syncManager != null) {
+                return syncManager.getSyncStorageEngine().getIsSyncable(
+                        account, providerName);
+            }
+        } finally {
+            restoreCallingIdentity(identityToken);
+        }
+        return -1;
+    }
+
+    public void setIsSyncable(Account account, String providerName, int syncable) {
+        mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
+                "no permission to write the sync settings");
+        long identityToken = clearCallingIdentity();
+        try {
+            SyncManager syncManager = getSyncManager();
+            if (syncManager != null) {
+                syncManager.getSyncStorageEngine().setIsSyncable(
+                        account, providerName, syncable);
+            }
+        } finally {
+            restoreCallingIdentity(identityToken);
+        }
+    }
+
     public boolean getMasterSyncAutomatically() {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
                 "no permission to read the sync settings");
diff --git a/core/java/android/content/IContentService.aidl b/core/java/android/content/IContentService.aidl
index 658a5bc..b0f14c1 100644
--- a/core/java/android/content/IContentService.aidl
+++ b/core/java/android/content/IContentService.aidl
@@ -54,6 +54,18 @@
      */
     void setSyncAutomatically(in Account account, String providerName, boolean sync);
 
+    /**
+     * Check if this account/provider is syncable.
+     * @return >0 if it is syncable, 0 if not, and <0 if the state isn't known yet.
+     */
+    int getIsSyncable(in Account account, String providerName);
+
+    /**
+     * Set whether this account/provider is syncable.
+     * @param syncable, >0 denotes syncable, 0 means not syncable, <0 means unknown
+     */
+    void setIsSyncable(in Account account, String providerName, int syncable);
+
     void setMasterSyncAutomatically(boolean flag);
 
     boolean getMasterSyncAutomatically();
diff --git a/core/java/android/content/SyncAdapterType.java b/core/java/android/content/SyncAdapterType.java
index 5a96003..d3f8230 100644
--- a/core/java/android/content/SyncAdapterType.java
+++ b/core/java/android/content/SyncAdapterType.java
@@ -27,6 +27,7 @@
 public class SyncAdapterType implements Parcelable {
     public final String authority;
     public final String accountType;
+    public final boolean isUserFacing = true; // TODO: implement logic to set this
 
     public SyncAdapterType(String authority, String accountType) {
         if (TextUtils.isEmpty(authority)) {
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index f256394..f50fd74 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -589,22 +589,21 @@
         // if the url was specified then replace the list of authorities with just this authority
         // or clear it if this authority isn't syncable
         if (requestedAuthority != null) {
-            final boolean isSyncable = syncableAuthorities.contains(requestedAuthority);
+            final boolean hasSyncAdapter = syncableAuthorities.contains(requestedAuthority);
             syncableAuthorities.clear();
-            if (isSyncable) syncableAuthorities.add(requestedAuthority);
+            if (hasSyncAdapter) syncableAuthorities.add(requestedAuthority);
         }
 
         for (String authority : syncableAuthorities) {
             for (Account account : accounts) {
+                boolean isSyncable = mSyncStorageEngine.getIsSyncable(account, authority) > 0;
+                if (!isSyncable) {
+                    continue;
+                }
                 if (mSyncAdapters.getServiceInfo(new SyncAdapterType(authority, account.type))
                         != null) {
                     scheduleSyncOperation(
                             new SyncOperation(account, source, authority, extras, delay));
-                    // TODO: remove this when Calendar supports multiple accounts. Until then
-                    // pretend that only the first account exists when syncing calendar.
-                    if ("calendar".equals(authority)) {
-                        break;
-                    }
                 }
             }
         }
@@ -1589,9 +1588,11 @@
                     final boolean syncAutomatically =
                             mSyncStorageEngine.getSyncAutomatically(op.account, op.authority)
                                     && mSyncStorageEngine.getMasterSyncAutomatically();
+                    boolean isSyncable =
+                            mSyncStorageEngine.getIsSyncable(op.account, op.authority) > 0;
                     boolean syncAllowed =
                             manualSync || (backgroundDataUsageAllowed && syncAutomatically);
-                    if (!syncAllowed) {
+                    if (!syncAllowed || !isSyncable) {
                         if (isLoggable) {
                             Log.v(TAG, "runStateIdle: sync off, dropping " + op);
                         }
diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java
index b3f9bbb..2647962 100644
--- a/core/java/android/content/SyncStorageEngine.java
+++ b/core/java/android/content/SyncStorageEngine.java
@@ -155,12 +155,15 @@
         final String authority;
         final int ident;
         boolean enabled;
+        int syncable;
 
         AuthorityInfo(Account account, String authority, int ident) {
             this.account = account;
             this.authority = authority;
             this.ident = ident;
             enabled = SYNC_ENABLED_DEFAULT;
+            // TODO: change the default to -1 when the syncadapters are changed to set this
+            syncable = 1;
         }
     }
     
@@ -392,6 +395,44 @@
         reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
     }
 
+    public int getIsSyncable(Account account, String providerName) {
+        synchronized (mAuthorities) {
+            if (account != null) {
+                AuthorityInfo authority = getAuthorityLocked(account, providerName,
+                        "getIsSyncable");
+                if (authority == null) {
+                    return -1;
+                }
+                return authority.syncable;
+            }
+
+            int i = mAuthorities.size();
+            while (i > 0) {
+                i--;
+                AuthorityInfo authority = mAuthorities.get(i);
+                if (authority.authority.equals(providerName)) {
+                    return authority.syncable;
+                }
+            }
+            return -1;
+        }
+    }
+
+    public void setIsSyncable(Account account, String providerName, int syncable) {
+        int oldState;
+        synchronized (mAuthorities) {
+            AuthorityInfo authority = getOrCreateAuthorityLocked(account, providerName, -1, false);
+            oldState = authority.syncable;
+            authority.syncable = syncable;
+            writeAccountInfoLocked();
+        }
+
+        if (oldState <= 0 && syncable > 0) {
+            mContext.getContentResolver().requestSync(account, providerName, new Bundle());
+        }
+        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
+    }
+
     public void setMasterSyncAutomatically(boolean flag) {
         boolean old;
         synchronized (mAuthorities) {
@@ -1064,10 +1105,12 @@
                                         null, "authority");
                                 String enabled = parser.getAttributeValue(
                                         null, "enabled");
-                                AuthorityInfo authority = mAuthorities.get(id); 
+                                String syncable = parser.getAttributeValue(null, "syncable");
+                                AuthorityInfo authority = mAuthorities.get(id);
                                 if (DEBUG_FILE) Log.v(TAG, "Adding authority: account="
                                         + accountName + " auth=" + authorityName
-                                        + " enabled=" + enabled);
+                                        + " enabled=" + enabled
+                                        + " syncable=" + syncable);
                                 if (authority == null) {
                                     if (DEBUG_FILE) Log.v(TAG, "Creating entry");
                                     authority = getOrCreateAuthorityLocked(
@@ -1077,10 +1120,19 @@
                                 if (authority != null) {
                                     authority.enabled = enabled == null
                                             || Boolean.parseBoolean(enabled);
+                                    if ("unknown".equals(syncable)) {
+                                        authority.syncable = -1;
+                                    } else {
+                                        authority.syncable =
+                                                (syncable == null || Boolean.parseBoolean(enabled))
+                                                        ? 1
+                                                        : 0;
+                                    }
                                 } else {
                                     Log.w(TAG, "Failure adding authority: account="
                                             + accountName + " auth=" + authorityName
-                                            + " enabled=" + enabled);
+                                            + " enabled=" + enabled
+                                            + " syncable=" + syncable);
                                 }
                             }
                         }
@@ -1133,6 +1185,11 @@
                 if (!authority.enabled) {
                     out.attribute(null, "enabled", "false");
                 }
+                if (authority.syncable < 0) {
+                    out.attribute(null, "syncable", "unknown");
+                } else if (authority.syncable == 0) {
+                    out.attribute(null, "syncable", "false");
+                }
                 out.endTag(null, "authority");
             }
             
@@ -1268,6 +1325,7 @@
                         AuthorityInfo authority = mAuthorities.get(i);
                         if (authority.authority.equals(provider)) {
                             authority.enabled = value == null || Boolean.parseBoolean(value);
+                            authority.syncable = 1;
                         }
                     }
                 }
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index 6b00900..da1115d 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -49,7 +49,6 @@
 
     private String mApnType;
     private boolean mEnabled;
-    private boolean mTeardownRequested;
 
     /**
      * Create a new MobileDataStateTracker
@@ -66,7 +65,6 @@
                 TelephonyManager.getDefault().getNetworkTypeName());
         mApnType = apnType;
         mPhoneService = null;
-        mTeardownRequested = false;
         if(netType == ConnectivityManager.TYPE_MOBILE) {
             mEnabled = true;
         } else {
@@ -81,7 +79,9 @@
                 "net.eth0.dns3",
                 "net.eth0.dns4",
                 "net.gprs.dns1",
-                "net.gprs.dns2"};
+                "net.gprs.dns2",
+                "net.ppp0.dns1",
+                "net.ppp0.dns2"};
 
     }
 
@@ -160,9 +160,9 @@
 
                     switch (state) {
                     case DISCONNECTED:
-                        if(mTeardownRequested) {
+                        if(isTeardownRequested()) {
                             mEnabled = false;
-                            mTeardownRequested = false;
+                            setTeardownRequested(false);
                         }
 
                         setDetailedState(DetailedState.DISCONNECTED, reason, apnName);
@@ -277,7 +277,7 @@
      */
     @Override
     public boolean teardown() {
-        mTeardownRequested = true;
+        setTeardownRequested(true);
         return (setEnableApn(mApnType, false) != Phone.APN_REQUEST_FAILED);
     }
 
@@ -286,7 +286,7 @@
      */
     public boolean reconnect() {
         mEnabled = true;
-        mTeardownRequested = false;
+        setTeardownRequested(false);
         mEnabled = (setEnableApn(mApnType, true) !=
                 Phone.APN_REQUEST_FAILED);
         return mEnabled;
diff --git a/core/java/android/text/BoringLayout.java b/core/java/android/text/BoringLayout.java
index 843754b..944f735 100644
--- a/core/java/android/text/BoringLayout.java
+++ b/core/java/android/text/BoringLayout.java
@@ -19,6 +19,7 @@
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Path;
+import android.text.style.ParagraphStyle;
 import android.util.FloatMath;
 
 /**
@@ -262,6 +263,14 @@
 
         TextUtils.recycle(temp);
 
+        if (boring && text instanceof Spanned) {
+            Spanned sp = (Spanned) text;
+            Object[] styles = sp.getSpans(0, text.length(), ParagraphStyle.class);
+            if (styles.length > 0) {
+                boring = false;
+            }
+        }
+
         if (boring) {
             Metrics fm = metrics;
             if (fm == null) {
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 7468aef..f49aab1 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -4689,19 +4689,20 @@
         mZoomCenterY = mLastTouchY;
         mInZoomOverview = !mInZoomOverview;
         mCallbackProxy.uiOnChangeViewingMode(mInZoomOverview);
-        if (mInZoomOverview) {
-            if (getSettings().getBuiltInZoomControls()) {
-                if (mZoomButtonsController.isVisible()) {
-                    mZoomButtonsController.setVisible(false);
-                }
-            } else {
-                if (mZoomControlRunnable != null) {
-                    mPrivateHandler.removeCallbacks(mZoomControlRunnable);
-                }
-                if (mZoomControls != null) {
-                    mZoomControls.hide();
-                }
+        // remove the zoom control after double tap
+        if (getSettings().getBuiltInZoomControls()) {
+            if (mZoomButtonsController.isVisible()) {
+                mZoomButtonsController.setVisible(false);
             }
+        } else {
+            if (mZoomControlRunnable != null) {
+                mPrivateHandler.removeCallbacks(mZoomControlRunnable);
+            }
+            if (mZoomControls != null) {
+                mZoomControls.hide();
+            }
+        }
+        if (mInZoomOverview) {
             zoomWithPreview((float) getViewWidth() / mZoomOverviewWidth);
         } else {
             // mLastTouchX and mLastTouchY are the point in the current viewport
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index b7e8f10..67721c9 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -546,6 +546,7 @@
 
     private void initAbsListView() {
         // Setting focusable in touch mode will set the focusable property to true
+        setClickable(true);
         setFocusableInTouchMode(true);
         setWillNotDraw(false);
         setAlwaysDrawnWithCacheEnabled(false);
@@ -1433,6 +1434,10 @@
      * this is a long press.
      */
     void keyPressed() {
+        if (!isEnabled() || !isClickable()) {
+            return;
+        }
+
         Drawable selector = mSelector;
         Rect selectorRect = mSelectorRect;
         if (selector != null && (isFocused() || touchModeDrawsInPressedState())
@@ -1450,8 +1455,8 @@
             Drawable d = selector.getCurrent();
             if (d != null && d instanceof TransitionDrawable) {
                 if (longClickable) {
-                    ((TransitionDrawable) d).startTransition(ViewConfiguration
-                            .getLongPressTimeout());
+                    ((TransitionDrawable) d).startTransition(
+                            ViewConfiguration.getLongPressTimeout());
                 } else {
                     ((TransitionDrawable) d).resetTransition();
                 }
@@ -1732,6 +1737,11 @@
     }
 
     @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        return false;
+    }
+
+    @Override
     public boolean onKeyUp(int keyCode, KeyEvent event) {
         switch (keyCode) {
         case KeyEvent.KEYCODE_DPAD_CENTER:
@@ -1739,8 +1749,7 @@
             if (!isEnabled()) {
                 return true;
             }
-            // Long clickable items don't necessarily have to be clickable
-            if (isClickable() && (event.getRepeatCount() == 0) && isPressed() &&
+            if (isClickable() && isPressed() &&
                     mSelectedPosition >= 0 && mAdapter != null &&
                     mSelectedPosition < mAdapter.getCount()) {
 
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 02a137d..993b7cb 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -1428,7 +1428,8 @@
                 throw new IllegalStateException("The content of the adapter has changed but "
                         + "ListView did not receive a notification. Make sure the content of "
                         + "your adapter is not modified from a background thread, but only "
-                        + "from the UI thread.");
+                        + "from the UI thread. [in ListView(" + getId() + ", " + getClass() 
+                        + ") with Adapter(" + mAdapter.getClass() + ")]");
             }
 
             setSelectedPositionInt(mNextSelectedPosition);
diff --git a/docs/html/guide/developing/tools/aidl.jd b/docs/html/guide/developing/tools/aidl.jd
index f370a80..abfa8b1 100644
--- a/docs/html/guide/developing/tools/aidl.jd
+++ b/docs/html/guide/developing/tools/aidl.jd
@@ -194,7 +194,6 @@
 <li>Make your class implement the {@link android.os.Parcelable} interface.</li>
 <li>Implement the method <code>public void writeToParcel(Parcel out)</code> that takes the
 current state of the object and writes it to a parcel.</li>
-<li>Implement the method <code>public void readFromParcel(Parcel in)</code> that reads the
 value in a parcel into your object.</li>
 <li>Add a static field called <code>CREATOR</code> to your class which is an object implementing
 the {@link android.os.Parcelable.Creator Parcelable.Creator} interface.</li>
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 33748ae..21b5e39 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -654,7 +654,7 @@
      * Create a drawable from an inputstream
      */
     public static Drawable createFromStream(InputStream is, String srcName) {
-        return createFromResourceStream(null, null, is, srcName);
+        return createFromResourceStream(null, null, is, srcName, null);
     }
 
     /**
@@ -663,7 +663,7 @@
      */
     public static Drawable createFromResourceStream(Resources res, TypedValue value,
             InputStream is, String srcName) {
-        return createFromResourceStream(res, value, is, srcName);
+        return createFromResourceStream(res, value, is, srcName, null);
     }
 
     /**
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index 58c2d9a..ba6c711 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -74,6 +74,7 @@
     status_t            writeInt64(int64_t val);
     status_t            writeFloat(float val);
     status_t            writeDouble(double val);
+    status_t            writeIntPtr(intptr_t val);
     status_t            writeCString(const char* str);
     status_t            writeString8(const String8& str);
     status_t            writeString16(const String16& str);
@@ -109,6 +110,8 @@
     status_t            readFloat(float *pArg) const;
     double              readDouble() const;
     status_t            readDouble(double *pArg) const;
+    intptr_t            readIntPtr() const;
+    status_t            readIntPtr(intptr_t *pArg) const;
 
     const char*         readCString() const;
     String8             readString8() const;
@@ -163,6 +166,14 @@
     void                initState();
     void                scanForFds() const;
                         
+    template<class T>
+    status_t            readAligned(T *pArg) const;
+
+    template<class T>   T readAligned() const;
+
+    template<class T>
+    status_t            writeAligned(T val);
+
     status_t            mError;
     uint8_t*            mData;
     size_t              mDataSize;
diff --git a/include/utils/Debug.h b/include/utils/Debug.h
index 21d04bd..d9ed32d 100644
--- a/include/utils/Debug.h
+++ b/include/utils/Debug.h
@@ -29,6 +29,8 @@
 #define COMPILE_TIME_ASSERT(_exp) \
     template class CompileTimeAssert< (_exp) >;
 #endif
+#define COMPILE_TIME_ASSERT_FUNCTION_SCOPE(_exp) \
+    CompileTimeAssert<( _exp )>();
 
 // ---------------------------------------------------------------------------
 
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 785a3c5..e397bce 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -562,54 +562,27 @@
 
 status_t Parcel::writeInt32(int32_t val)
 {
-    if ((mDataPos+sizeof(val)) <= mDataCapacity) {
-restart_write:
-        *reinterpret_cast<int32_t*>(mData+mDataPos) = val;
-        return finishWrite(sizeof(val));
-    }
-
-    status_t err = growData(sizeof(val));
-    if (err == NO_ERROR) goto restart_write;
-    return err;
+    return writeAligned(val);
 }
 
 status_t Parcel::writeInt64(int64_t val)
 {
-    if ((mDataPos+sizeof(val)) <= mDataCapacity) {
-restart_write:
-        *reinterpret_cast<int64_t*>(mData+mDataPos) = val;
-        return finishWrite(sizeof(val));
-    }
-
-    status_t err = growData(sizeof(val));
-    if (err == NO_ERROR) goto restart_write;
-    return err;
+    return writeAligned(val);
 }
 
 status_t Parcel::writeFloat(float val)
 {
-    if ((mDataPos+sizeof(val)) <= mDataCapacity) {
-restart_write:
-        *reinterpret_cast<float*>(mData+mDataPos) = val;
-        return finishWrite(sizeof(val));
-    }
-
-    status_t err = growData(sizeof(val));
-    if (err == NO_ERROR) goto restart_write;
-    return err;
+    return writeAligned(val);
 }
 
 status_t Parcel::writeDouble(double val)
 {
-    if ((mDataPos+sizeof(val)) <= mDataCapacity) {
-restart_write:
-        *reinterpret_cast<double*>(mData+mDataPos) = val;
-        return finishWrite(sizeof(val));
-    }
+    return writeAligned(val);
+}
 
-    status_t err = growData(sizeof(val));
-    if (err == NO_ERROR) goto restart_write;
-    return err;
+status_t Parcel::writeIntPtr(intptr_t val)
+{
+    return writeAligned(val);
 }
 
 status_t Parcel::writeCString(const char* str)
@@ -768,103 +741,98 @@
     return NULL;
 }
 
-status_t Parcel::readInt32(int32_t *pArg) const
-{
-    if ((mDataPos+sizeof(int32_t)) <= mDataSize) {
+template<class T>
+status_t Parcel::readAligned(T *pArg) const {
+    COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE(sizeof(T)) == sizeof(T));
+
+    if ((mDataPos+sizeof(T)) <= mDataSize) {
         const void* data = mData+mDataPos;
-        mDataPos += sizeof(int32_t);
-        *pArg =  *reinterpret_cast<const int32_t*>(data);
+        mDataPos += sizeof(T);
+        *pArg =  *reinterpret_cast<const T*>(data);
         return NO_ERROR;
     } else {
         return NOT_ENOUGH_DATA;
     }
 }
 
+template<class T>
+T Parcel::readAligned() const {
+    T result;
+    if (readAligned(&result) != NO_ERROR) {
+        result = 0;
+    }
+
+    return result;
+}
+
+template<class T>
+status_t Parcel::writeAligned(T val) {
+    COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE(sizeof(T)) == sizeof(T));
+
+    if ((mDataPos+sizeof(val)) <= mDataCapacity) {
+restart_write:
+        *reinterpret_cast<T*>(mData+mDataPos) = val;
+        return finishWrite(sizeof(val));
+    }
+
+    status_t err = growData(sizeof(val));
+    if (err == NO_ERROR) goto restart_write;
+    return err;
+}
+
+status_t Parcel::readInt32(int32_t *pArg) const
+{
+    return readAligned(pArg);
+}
+
 int32_t Parcel::readInt32() const
 {
-    if ((mDataPos+sizeof(int32_t)) <= mDataSize) {
-        const void* data = mData+mDataPos;
-        mDataPos += sizeof(int32_t);
-        LOGV("readInt32 Setting data pos of %p to %d\n", this, mDataPos);
-        return *reinterpret_cast<const int32_t*>(data);
-    }
-    return 0;
+    return readAligned<int32_t>();
 }
 
 
 status_t Parcel::readInt64(int64_t *pArg) const
 {
-    if ((mDataPos+sizeof(int64_t)) <= mDataSize) {
-        const void* data = mData+mDataPos;
-        mDataPos += sizeof(int64_t);
-        *pArg = *reinterpret_cast<const int64_t*>(data);
-        LOGV("readInt64 Setting data pos of %p to %d\n", this, mDataPos);
-        return NO_ERROR;
-    } else {
-        return NOT_ENOUGH_DATA;
-    }
+    return readAligned(pArg);
 }
 
 
 int64_t Parcel::readInt64() const
 {
-    if ((mDataPos+sizeof(int64_t)) <= mDataSize) {
-        const void* data = mData+mDataPos;
-        mDataPos += sizeof(int64_t);
-        LOGV("readInt64 Setting data pos of %p to %d\n", this, mDataPos);
-        return *reinterpret_cast<const int64_t*>(data);
-    }
-    return 0;
+    return readAligned<int64_t>();
 }
 
 status_t Parcel::readFloat(float *pArg) const
 {
-    if ((mDataPos+sizeof(float)) <= mDataSize) {
-        const void* data = mData+mDataPos;
-        mDataPos += sizeof(float);
-        LOGV("readFloat Setting data pos of %p to %d\n", this, mDataPos);
-        *pArg = *reinterpret_cast<const float*>(data);
-        return NO_ERROR;
-    } else {
-        return NOT_ENOUGH_DATA;
-    }
+    return readAligned(pArg);
 }
 
 
 float Parcel::readFloat() const
 {
-    if ((mDataPos+sizeof(float)) <= mDataSize) {
-        const void* data = mData+mDataPos;
-        mDataPos += sizeof(float);
-        LOGV("readFloat Setting data pos of %p to %d\n", this, mDataPos);
-        return *reinterpret_cast<const float*>(data);
-    }
-    return 0;
+    return readAligned<float>();
 }
 
 status_t Parcel::readDouble(double *pArg) const
 {
-    if ((mDataPos+sizeof(double)) <= mDataSize) {
-        const void* data = mData+mDataPos;
-        mDataPos += sizeof(double);
-        LOGV("readDouble Setting data pos of %p to %d\n", this, mDataPos);
-        *pArg = *reinterpret_cast<const double*>(data);
-        return NO_ERROR;
-    } else {
-        return NOT_ENOUGH_DATA;
-    }
+    return readAligned(pArg);
 }
 
 
 double Parcel::readDouble() const
 {
-    if ((mDataPos+sizeof(double)) <= mDataSize) {
-        const void* data = mData+mDataPos;
-        mDataPos += sizeof(double);
-        LOGV("readDouble Setting data pos of %p to %d\n", this, mDataPos);
-        return *reinterpret_cast<const double*>(data);
-    }
-    return 0;
+    return readAligned<double>();
+}
+
+status_t Parcel::readIntPtr(intptr_t *pArg) const
+{
+    return readAligned(pArg);
+}
+
+
+intptr_t Parcel::readIntPtr() const
+{
+    return readAligned<intptr_t>();
 }
 
 
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index ec3241c..10bebd0 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -45,16 +45,6 @@
             displayWidth, displayHeight);
 }
 
-static void *readVoidStar(const Parcel *parcel) {
-    // FIX if sizeof(void *) != sizeof(int32)
-    return (void *)parcel->readInt32();
-}
-
-static void writeVoidStar(void *x, Parcel *parcel) {
-    // FIX if sizeof(void *) != sizeof(int32)
-    parcel->writeInt32((int32_t)x);
-}
-
 class BpOMX : public BpInterface<IOMX> {
 public:
     BpOMX(const sp<IBinder> &impl)
@@ -86,7 +76,7 @@
 
         status_t err = reply.readInt32();
         if (err == OK) {
-            *node = readVoidStar(&reply);
+            *node = (void*)reply.readIntPtr();
         } else {
             *node = 0;
         }
@@ -97,7 +87,7 @@
     virtual status_t free_node(node_id node) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        writeVoidStar(node, &data);
+        data.writeIntPtr((intptr_t)node);
         remote()->transact(FREE_NODE, data, &reply);
 
         return reply.readInt32();
@@ -107,7 +97,7 @@
             node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        writeVoidStar(node, &data);
+        data.writeIntPtr((intptr_t)node);
         data.writeInt32(cmd);
         data.writeInt32(param);
         remote()->transact(SEND_COMMAND, data, &reply);
@@ -120,7 +110,7 @@
             void *params, size_t size) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        writeVoidStar(node, &data);
+        data.writeIntPtr((intptr_t)node);
         data.writeInt32(index);
         data.writeInt32(size);
         data.write(params, size);
@@ -141,7 +131,7 @@
             const void *params, size_t size) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        writeVoidStar(node, &data);
+        data.writeIntPtr((intptr_t)node);
         data.writeInt32(index);
         data.writeInt32(size);
         data.write(params, size);
@@ -155,7 +145,7 @@
             void *params, size_t size) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        writeVoidStar(node, &data);
+        data.writeIntPtr((intptr_t)node);
         data.writeInt32(index);
         data.writeInt32(size);
         data.write(params, size);
@@ -176,7 +166,7 @@
             const void *params, size_t size) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        writeVoidStar(node, &data);
+        data.writeIntPtr((intptr_t)node);
         data.writeInt32(index);
         data.writeInt32(size);
         data.write(params, size);
@@ -190,7 +180,7 @@
             buffer_id *buffer) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        writeVoidStar(node, &data);
+        data.writeIntPtr((intptr_t)node);
         data.writeInt32(port_index);
         data.writeStrongBinder(params->asBinder());
         remote()->transact(USE_BUFFER, data, &reply);
@@ -202,7 +192,7 @@
             return err;
         }
 
-        *buffer = readVoidStar(&reply);
+        *buffer = (void*)reply.readIntPtr();
 
         return err;
     }
@@ -212,7 +202,7 @@
             buffer_id *buffer) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        writeVoidStar(node, &data);
+        data.writeIntPtr((intptr_t)node);
         data.writeInt32(port_index);
         data.writeInt32(size);
         remote()->transact(ALLOC_BUFFER, data, &reply);
@@ -224,7 +214,7 @@
             return err;
         }
 
-        *buffer = readVoidStar(&reply);
+        *buffer = (void*)reply.readIntPtr();
 
         return err;
     }
@@ -234,7 +224,7 @@
             buffer_id *buffer) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        writeVoidStar(node, &data);
+        data.writeIntPtr((intptr_t)node);
         data.writeInt32(port_index);
         data.writeStrongBinder(params->asBinder());
         remote()->transact(ALLOC_BUFFER_WITH_BACKUP, data, &reply);
@@ -246,7 +236,7 @@
             return err;
         }
 
-        *buffer = readVoidStar(&reply);
+        *buffer = (void*)reply.readIntPtr();
 
         return err;
     }
@@ -255,9 +245,9 @@
             node_id node, OMX_U32 port_index, buffer_id buffer) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        writeVoidStar(node, &data);
+        data.writeIntPtr((intptr_t)node);
         data.writeInt32(port_index);
-        writeVoidStar(buffer, &data);
+        data.writeIntPtr((intptr_t)buffer);
         remote()->transact(FREE_BUFFER, data, &reply);
 
         return reply.readInt32();
@@ -267,7 +257,7 @@
             node_id node, const sp<IOMXObserver> &observer) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        writeVoidStar(node, &data);
+        data.writeIntPtr((intptr_t)node);
         data.writeStrongBinder(observer->asBinder());
         remote()->transact(OBSERVE_NODE, data, &reply);
 
@@ -277,8 +267,8 @@
     virtual void fill_buffer(node_id node, buffer_id buffer) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        writeVoidStar(node, &data);
-        writeVoidStar(buffer, &data);
+        data.writeIntPtr((intptr_t)node);
+        data.writeIntPtr((intptr_t)buffer);
         remote()->transact(FILL_BUFFER, data, &reply, IBinder::FLAG_ONEWAY);
     }
 
@@ -289,8 +279,8 @@
             OMX_U32 flags, OMX_TICKS timestamp) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        writeVoidStar(node, &data);
-        writeVoidStar(buffer, &data);
+        data.writeIntPtr((intptr_t)node);
+        data.writeIntPtr((intptr_t)buffer);
         data.writeInt32(range_offset);
         data.writeInt32(range_length);
         data.writeInt32(flags);
@@ -304,7 +294,7 @@
             OMX_INDEXTYPE *index) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
-        writeVoidStar(node, &data);
+        data.writeIntPtr((intptr_t)node);
         data.writeCString(parameter_name);
 
         remote()->transact(GET_EXTENSION_INDEX, data, &reply);
@@ -379,7 +369,7 @@
             status_t err = allocate_node(data.readCString(), &node);
             reply->writeInt32(err);
             if (err == OK) {
-                writeVoidStar(node, reply);
+                reply->writeIntPtr((intptr_t)node);
             }
                 
             return NO_ERROR;
@@ -389,7 +379,7 @@
         {
             CHECK_INTERFACE(IOMX, data, reply);
 
-            node_id node = readVoidStar(&data);
+            node_id node = (void*)data.readIntPtr();
 
             reply->writeInt32(free_node(node));
                 
@@ -400,7 +390,7 @@
         {
             CHECK_INTERFACE(IOMX, data, reply);
 
-            node_id node = readVoidStar(&data);
+            node_id node = (void*)data.readIntPtr();
 
             OMX_COMMANDTYPE cmd =
                 static_cast<OMX_COMMANDTYPE>(data.readInt32());
@@ -415,7 +405,7 @@
         {
             CHECK_INTERFACE(IOMX, data, reply);
 
-            node_id node = readVoidStar(&data);
+            node_id node = (void*)data.readIntPtr();
             OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
 
             size_t size = data.readInt32();
@@ -442,7 +432,7 @@
         {
             CHECK_INTERFACE(IOMX, data, reply);
 
-            node_id node = readVoidStar(&data);
+            node_id node = (void*)data.readIntPtr();
             OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
 
             size_t size = data.readInt32();
@@ -457,7 +447,7 @@
         {
             CHECK_INTERFACE(IOMX, data, reply);
 
-            node_id node = readVoidStar(&data);
+            node_id node = (void*)data.readIntPtr();
             OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
 
             size_t size = data.readInt32();
@@ -484,7 +474,7 @@
         {
             CHECK_INTERFACE(IOMX, data, reply);
 
-            node_id node = readVoidStar(&data);
+            node_id node = (void*)data.readIntPtr();
             OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
 
             size_t size = data.readInt32();
@@ -499,7 +489,7 @@
         {
             CHECK_INTERFACE(IOMX, data, reply);
 
-            node_id node = readVoidStar(&data);
+            node_id node = (void*)data.readIntPtr();
             OMX_U32 port_index = data.readInt32();
             sp<IMemory> params =
                 interface_cast<IMemory>(data.readStrongBinder());
@@ -509,7 +499,7 @@
             reply->writeInt32(err);
 
             if (err == OK) {
-                writeVoidStar(buffer, reply);
+                reply->writeIntPtr((intptr_t)buffer);
             }
 
             return NO_ERROR;
@@ -519,7 +509,7 @@
         {
             CHECK_INTERFACE(IOMX, data, reply);
 
-            node_id node = readVoidStar(&data);
+            node_id node = (void*)data.readIntPtr();
             OMX_U32 port_index = data.readInt32();
             size_t size = data.readInt32();
 
@@ -528,7 +518,7 @@
             reply->writeInt32(err);
 
             if (err == OK) {
-                writeVoidStar(buffer, reply);
+                reply->writeIntPtr((intptr_t)buffer);
             }
 
             return NO_ERROR;
@@ -538,7 +528,7 @@
         {
             CHECK_INTERFACE(IOMX, data, reply);
 
-            node_id node = readVoidStar(&data);
+            node_id node = (void*)data.readIntPtr();
             OMX_U32 port_index = data.readInt32();
             sp<IMemory> params =
                 interface_cast<IMemory>(data.readStrongBinder());
@@ -550,7 +540,7 @@
             reply->writeInt32(err);
 
             if (err == OK) {
-                writeVoidStar(buffer, reply);
+                reply->writeIntPtr((intptr_t)buffer);
             }
 
             return NO_ERROR;
@@ -560,9 +550,9 @@
         {
             CHECK_INTERFACE(IOMX, data, reply);
 
-            node_id node = readVoidStar(&data);
+            node_id node = (void*)data.readIntPtr();
             OMX_U32 port_index = data.readInt32();
-            buffer_id buffer = readVoidStar(&data);
+            buffer_id buffer = (void*)data.readIntPtr();
             reply->writeInt32(free_buffer(node, port_index, buffer));
 
             return NO_ERROR;
@@ -572,7 +562,7 @@
         {
             CHECK_INTERFACE(IOMX, data, reply);
 
-            node_id node = readVoidStar(&data);
+            node_id node = (void*)data.readIntPtr();
             sp<IOMXObserver> observer =
                 interface_cast<IOMXObserver>(data.readStrongBinder());
             reply->writeInt32(observe_node(node, observer));
@@ -584,8 +574,8 @@
         {
             CHECK_INTERFACE(IOMX, data, reply);
 
-            node_id node = readVoidStar(&data);
-            buffer_id buffer = readVoidStar(&data);
+            node_id node = (void*)data.readIntPtr();
+            buffer_id buffer = (void*)data.readIntPtr();
             fill_buffer(node, buffer);
 
             return NO_ERROR;
@@ -595,8 +585,8 @@
         {
             CHECK_INTERFACE(IOMX, data, reply);
 
-            node_id node = readVoidStar(&data);
-            buffer_id buffer = readVoidStar(&data);
+            node_id node = (void*)data.readIntPtr();
+            buffer_id buffer = (void*)data.readIntPtr();
             OMX_U32 range_offset = data.readInt32();
             OMX_U32 range_length = data.readInt32();
             OMX_U32 flags = data.readInt32();
@@ -613,7 +603,7 @@
         {
             CHECK_INTERFACE(IOMX, data, reply);
 
-            node_id node = readVoidStar(&data);
+            node_id node = (void*)data.readIntPtr();
             const char *parameter_name = data.readCString();
             
             OMX_INDEXTYPE index;
@@ -711,7 +701,7 @@
     virtual void render(IOMX::buffer_id buffer) {
         Parcel data, reply;
         data.writeInterfaceToken(IOMXRenderer::getInterfaceDescriptor());
-        writeVoidStar(buffer, &data);
+        data.writeIntPtr((intptr_t)buffer);
 
         // NOTE: Do NOT make this a ONE_WAY call, it must be synchronous
         // so that the caller knows when to recycle the buffer.
@@ -728,7 +718,7 @@
         {
             CHECK_INTERFACE(IOMXRenderer, data, reply);
 
-            IOMX::buffer_id buffer = readVoidStar(&data);
+            IOMX::buffer_id buffer = (void*)data.readIntPtr();
 
             render(buffer);
 
diff --git a/services/jni/com_android_server_BatteryService.cpp b/services/jni/com_android_server_BatteryService.cpp
index e4f001f..eb5c1d1 100644
--- a/services/jni/com_android_server_BatteryService.cpp
+++ b/services/jni/com_android_server_BatteryService.cpp
@@ -31,6 +31,7 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <unistd.h>
+#include <dirent.h>
 
 #if HAVE_ANDROID_OS
 #include <linux/ioctl.h>
@@ -38,15 +39,7 @@
 
 namespace android {
 
-#define AC_ONLINE_PATH "/sys/class/power_supply/ac/online"
-#define USB_ONLINE_PATH "/sys/class/power_supply/usb/online"
-#define BATTERY_STATUS_PATH "/sys/class/power_supply/battery/status"
-#define BATTERY_HEALTH_PATH "/sys/class/power_supply/battery/health"
-#define BATTERY_PRESENT_PATH "/sys/class/power_supply/battery/present"
-#define BATTERY_CAPACITY_PATH "/sys/class/power_supply/battery/capacity"
-#define BATTERY_VOLTAGE_PATH "/sys/class/power_supply/battery/batt_vol"
-#define BATTERY_TEMPERATURE_PATH "/sys/class/power_supply/battery/batt_temp"
-#define BATTERY_TECHNOLOGY_PATH "/sys/class/power_supply/battery/technology"
+#define POWER_SUPPLY_PATH "/sys/class/power_supply"
 
 struct FieldIds {
     // members
@@ -77,6 +70,19 @@
 };
 static BatteryManagerConstants gConstants;
 
+struct PowerSupplyPaths {
+    char* acOnlinePath;
+    char* usbOnlinePath;
+    char* batteryStatusPath;
+    char* batteryHealthPath;
+    char* batteryPresentPath;
+    char* batteryCapacityPath;
+    char* batteryVoltagePath;
+    char* batteryTemperaturePath;
+    char* batteryTechnologyPath;
+};
+static PowerSupplyPaths gPaths;
+
 static jint getBatteryStatus(const char* status)
 {
     switch (status[0]) {
@@ -173,27 +179,27 @@
 
 static void android_server_BatteryService_update(JNIEnv* env, jobject obj)
 {
-    setBooleanField(env, obj, AC_ONLINE_PATH, gFieldIds.mAcOnline);
-    setBooleanField(env, obj, USB_ONLINE_PATH, gFieldIds.mUsbOnline);
-    setBooleanField(env, obj, BATTERY_PRESENT_PATH, gFieldIds.mBatteryPresent);
+    setBooleanField(env, obj, gPaths.acOnlinePath, gFieldIds.mAcOnline);
+    setBooleanField(env, obj, gPaths.usbOnlinePath, gFieldIds.mUsbOnline);
+    setBooleanField(env, obj, gPaths.batteryPresentPath, gFieldIds.mBatteryPresent);
     
-    setIntField(env, obj, BATTERY_CAPACITY_PATH, gFieldIds.mBatteryLevel);
-    setIntField(env, obj, BATTERY_VOLTAGE_PATH, gFieldIds.mBatteryVoltage);
-    setIntField(env, obj, BATTERY_TEMPERATURE_PATH, gFieldIds.mBatteryTemperature);
+    setIntField(env, obj, gPaths.batteryCapacityPath, gFieldIds.mBatteryLevel);
+    setIntField(env, obj, gPaths.batteryVoltagePath, gFieldIds.mBatteryVoltage);
+    setIntField(env, obj, gPaths.batteryTemperaturePath, gFieldIds.mBatteryTemperature);
     
     const int SIZE = 128;
     char buf[SIZE];
     
-    if (readFromFile(BATTERY_STATUS_PATH, buf, SIZE) > 0)
+    if (readFromFile(gPaths.batteryStatusPath, buf, SIZE) > 0)
         env->SetIntField(obj, gFieldIds.mBatteryStatus, getBatteryStatus(buf));
     else
         env->SetIntField(obj, gFieldIds.mBatteryStatus,
                          gConstants.statusUnknown);
     
-    if (readFromFile(BATTERY_HEALTH_PATH, buf, SIZE) > 0)
+    if (readFromFile(gPaths.batteryHealthPath, buf, SIZE) > 0)
         env->SetIntField(obj, gFieldIds.mBatteryHealth, getBatteryHealth(buf));
 
-    if (readFromFile(BATTERY_TECHNOLOGY_PATH, buf, SIZE) > 0)
+    if (readFromFile(gPaths.batteryTechnologyPath, buf, SIZE) > 0)
         env->SetObjectField(obj, gFieldIds.mBatteryTechnology, env->NewStringUTF(buf));
 }
 
@@ -204,6 +210,51 @@
 
 int register_android_server_BatteryService(JNIEnv* env)
 {
+    char    path[PATH_MAX];
+    struct dirent* entry;
+
+    DIR* dir = opendir(POWER_SUPPLY_PATH);
+    if (dir == NULL) {
+        LOGE("Could not open %s\n", POWER_SUPPLY_PATH);
+        return -1;
+    }
+    while ((entry = readdir(dir))) {
+        char buf[20];
+        // Look for "type" file in each subdirectory
+        snprintf(path, sizeof(path), "%s/%s/type", POWER_SUPPLY_PATH, entry->d_name);
+        int length = readFromFile(path, buf, sizeof(buf));
+        if (length > 0) {
+            if (buf[length - 1] == '\n')
+                buf[length - 1] = 0;
+
+            if (strcmp(buf, "Mains") == 0) {
+                snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, entry->d_name);
+                gPaths.acOnlinePath = strdup(path);
+            }
+            else if (strcmp(buf, "USB") == 0) {
+                snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, entry->d_name);
+                gPaths.usbOnlinePath = strdup(path);
+            }
+            else if (strcmp(buf, "Battery") == 0) {
+                snprintf(path, sizeof(path), "%s/%s/status", POWER_SUPPLY_PATH, entry->d_name);
+                gPaths.batteryStatusPath = strdup(path);
+                snprintf(path, sizeof(path), "%s/%s/health", POWER_SUPPLY_PATH, entry->d_name);
+                gPaths.batteryHealthPath = strdup(path);
+                snprintf(path, sizeof(path), "%s/%s/present", POWER_SUPPLY_PATH, entry->d_name);
+                gPaths.batteryPresentPath = strdup(path);
+                snprintf(path, sizeof(path), "%s/%s/capacity", POWER_SUPPLY_PATH, entry->d_name);
+                gPaths.batteryCapacityPath = strdup(path);
+                snprintf(path, sizeof(path), "%s/%s/batt_vol", POWER_SUPPLY_PATH, entry->d_name);
+                gPaths.batteryVoltagePath = strdup(path);
+                snprintf(path, sizeof(path), "%s/%s/batt_temp", POWER_SUPPLY_PATH, entry->d_name);
+                gPaths.batteryTemperaturePath = strdup(path);
+                snprintf(path, sizeof(path), "%s/%s/technology", POWER_SUPPLY_PATH, entry->d_name);
+                gPaths.batteryTechnologyPath = strdup(path);
+            }
+        }
+    }
+    closedir(dir);
+
     jclass clazz = env->FindClass("com/android/server/BatteryService");
 
     if (clazz == NULL) {
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index fa0ffcd..29e89b5 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -24,14 +24,18 @@
 import android.os.RemoteException;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
+import android.text.TextUtils;
 import android.util.Log;
 
+import java.util.ArrayList;
+
 /**
  * {@hide}
  *
  */
 public abstract class DataConnectionTracker extends Handler {
-    private static final boolean DBG = true;
+    protected static final boolean DBG = true;
+    protected final String LOG_TAG = "DataConnectionTracker";
 
     /**
      * IDLE: ready to start data connection setup, default state
@@ -98,6 +102,20 @@
 
     //***** Constants
 
+    protected static final int APN_INVALID_ID = -1;
+    protected static final int APN_DEFAULT_ID = 0;
+    protected static final int APN_MMS_ID = 1;
+    protected static final int APN_SUPL_ID = 2;
+    protected static final int APN_DUN_ID = 3;
+    protected static final int APN_HIPRI_ID = 4;
+    protected static final int APN_NUM_TYPES = 5;
+
+    protected boolean[] dataEnabled = new boolean[APN_NUM_TYPES];
+    protected int enabledCount = 0;
+
+    /* Currently requested APN type */
+    protected String mRequestedApnType = Phone.APN_TYPE_DEFAULT;
+
     /** Retry configuration: A doubling of retry times from 5secs to 30minutes */
     protected static final String DEFAULT_DATA_RETRY_CONFIG = "default_randomization=2000,"
         + "5000,10000,20000,40000,80000:5000,160000:5000,"
@@ -167,6 +185,8 @@
         this.phone = phone;
     }
 
+    public abstract void dispose();
+
     public Activity getActivity() {
         return activity;
     }
@@ -301,24 +321,18 @@
      * @return {@code false} if data connectivity has been explicitly disabled,
      * {@code true} otherwise.
      */
-    public abstract boolean getDataEnabled();
+    public boolean getDataEnabled() {
+        return dataEnabled[APN_DEFAULT_ID];
+    }
 
     /**
      * Report on whether data connectivity is enabled
      * @return {@code false} if data connectivity has been explicitly disabled,
      * {@code true} otherwise.
      */
-    public abstract boolean getAnyDataEnabled();
-
-    /**
-     * Prevent mobile data connections from being established,
-     * or once again allow mobile data connections. If the state
-     * toggles, then either tear down or set up data, as
-     * appropriate to match the new state.
-     * @param enable indicates whether to enable ({@code true}) or disable ({@code false}) data
-     * @return {@code true} if the operation succeeded
-     */
-    public abstract boolean setDataEnabled(boolean enable);
+    public boolean getAnyDataEnabled() {
+        return (enabledCount != 0);
+    }
 
     protected abstract void startNetStatPoll();
 
@@ -327,4 +341,162 @@
     protected abstract void restartRadio();
 
     protected abstract void log(String s);
+
+    protected int apnTypeToId(String type) {
+        if (TextUtils.equals(type, Phone.APN_TYPE_DEFAULT)) {
+            return APN_DEFAULT_ID;
+        } else if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
+            return APN_MMS_ID;
+        } else if (TextUtils.equals(type, Phone.APN_TYPE_SUPL)) {
+            return APN_SUPL_ID;
+        } else if (TextUtils.equals(type, Phone.APN_TYPE_DUN)) {
+            return APN_DUN_ID;
+        } else if (TextUtils.equals(type, Phone.APN_TYPE_HIPRI)) {
+            return APN_HIPRI_ID;
+        } else {
+            return APN_INVALID_ID;
+        }
+    }
+
+    protected abstract boolean isApnTypeActive(String type);
+
+    protected abstract boolean isApnTypeAvailable(String type);
+
+    protected abstract String[] getActiveApnTypes();
+
+    protected abstract String getActiveApnString();
+
+    public abstract ArrayList<DataConnection> getAllDataConnections();
+
+    protected abstract String getInterfaceName(String apnType);
+
+    protected abstract String getIpAddress(String apnType);
+
+    protected abstract String getGateway(String apnType);
+
+    protected abstract String[] getDnsServers(String apnType);
+
+    protected abstract void setState(State s);
+
+    protected boolean isEnabled(int id) {
+        if (id != APN_INVALID_ID) {
+            return dataEnabled[id];
+        }
+        return false;
+    }
+
+    /**
+     * Ensure that we are connected to an APN of the specified type.
+     * @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
+     * will be sent by the ConnectivityManager when a connection to
+     * the APN has been established.
+     */
+    public int enableApnType(String type) {
+        int id = apnTypeToId(type);
+        if (id == APN_INVALID_ID) {
+            return Phone.APN_REQUEST_FAILED;
+        }
+
+        // If already active, return
+        if(DBG) Log.d(LOG_TAG, "enableApnType("+type+"), isApnTypeActive = "
+                + isApnTypeActive(type) + " and state = " + state);
+
+        if (isApnTypeActive(type)) {
+            if (state == State.INITING) return Phone.APN_REQUEST_STARTED;
+            else if (state == State.CONNECTED) return Phone.APN_ALREADY_ACTIVE;
+        }
+
+        if (!isApnTypeAvailable(type)) {
+            return Phone.APN_TYPE_NOT_AVAILABLE;
+        }
+
+        setEnabled(id, true);
+        mRequestedApnType = type;
+        sendMessage(obtainMessage(EVENT_ENABLE_NEW_APN));
+        return Phone.APN_REQUEST_STARTED;
+    }
+
+    /**
+     * The APN of the specified type is no longer needed. Ensure that if
+     * use of the default APN has not been explicitly disabled, we are connected
+     * to the default APN.
+     * @param type the APN type. The only valid values are currently
+     * {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL}.
+     * @return
+     */
+    public int disableApnType(String type) {
+        if (DBG) Log.d(LOG_TAG, "disableApnType("+type+")");
+        int id = apnTypeToId(type);
+        if (id == APN_INVALID_ID) {
+            return Phone.APN_REQUEST_FAILED;
+        }
+        if (isEnabled(id)) {
+            setEnabled(id, false);
+            if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
+                mRequestedApnType = Phone.APN_TYPE_DEFAULT;
+                if (dataEnabled[APN_DEFAULT_ID]) {
+                    return Phone.APN_ALREADY_ACTIVE;
+                } else {
+                    return Phone.APN_REQUEST_STARTED;
+                }
+            } else {
+                return Phone.APN_REQUEST_STARTED;
+            }
+        } else {
+            return Phone.APN_REQUEST_FAILED;
+        }
+    }
+
+    protected synchronized void setEnabled(int id, boolean enable) {
+        if (DBG) Log.d(LOG_TAG, "setEnabled(" + id + ", " + enable + ')');
+        if (dataEnabled[id] != enable) {
+            dataEnabled[id] = enable;
+
+            if (enable) {
+                enabledCount++;
+            } else {
+                enabledCount--;
+            }
+
+            if (enabledCount == 0) {
+                setPrivateDataEnabled(false);
+            } else if (enabledCount == 1) {
+                setPrivateDataEnabled(true);
+            }
+        }
+    }
+
+    /**
+     * Prevent mobile data connections from being established,
+     * or once again allow mobile data connections. If the state
+     * toggles, then either tear down or set up data, as
+     * appropriate to match the new state.
+     * <p>This operation only affects the default APN, and if the same APN is
+     * currently being used for MMS traffic, the teardown will not happen
+     * even when {@code enable} is {@code false}.</p>
+     * @param enable indicates whether to enable ({@code true}) or disable ({@code false}) data
+     * @return {@code true} if the operation succeeded
+     */
+    public boolean setDataEnabled(boolean enable) {
+        if (DBG) Log.d(LOG_TAG, "setDataEnabled("+enable+")");
+        setEnabled(APN_DEFAULT_ID, enable);
+        return true;
+    }
+
+    private void setPrivateDataEnabled(boolean enable) {
+        if (DBG) Log.d(LOG_TAG, "setPrivateDataEnabled("+enable+")");
+        if (enable) {
+            sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
+        } else {
+            Message msg = obtainMessage(EVENT_CLEAN_UP_CONNECTION);
+            msg.arg1 = 1; // tearDown is true
+            msg.obj = Phone.REASON_DATA_DISABLED;
+            sendMessage(msg);
+        }
+    }
+
 }
diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java
index b279527..6f4aef9 100644
--- a/telephony/java/com/android/internal/telephony/PhoneBase.java
+++ b/telephony/java/com/android/internal/telephony/PhoneBase.java
@@ -109,6 +109,7 @@
     public CommandsInterface mCM;
     protected IccFileHandler mIccFileHandler;
     boolean mDnsCheckDisabled = false;
+    public DataConnectionTracker mDataConnection;
 
     /**
      * Set a system property, unless we're in unit test mode
@@ -824,4 +825,71 @@
         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
          Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
      }
+
+    public String getInterfaceName(String apnType) {
+        return mDataConnection.getInterfaceName(apnType);
+    }
+
+    public String getIpAddress(String apnType) {
+        return mDataConnection.getIpAddress(apnType);
+    }
+
+    public boolean isDataConnectivityEnabled() {
+        return mDataConnection.getDataEnabled();
+    }
+
+    public String getGateway(String apnType) {
+        return mDataConnection.getGateway(apnType);
+    }
+
+    public String[] getDnsServers(String apnType) {
+        return mDataConnection.getDnsServers(apnType);
+    }
+
+    public String[] getActiveApnTypes() {
+        return mDataConnection.getActiveApnTypes();
+    }
+
+    public String getActiveApn() {
+        return mDataConnection.getActiveApnString();
+    }
+
+    public int enableApnType(String type) {
+        return mDataConnection.enableApnType(type);
+    }
+
+    public int disableApnType(String type) {
+        return mDataConnection.disableApnType(type);
+    }
+
+    /**
+     * simulateDataConnection
+     *
+     * simulates various data connection states. This messes with
+     * DataConnectionTracker's internal states, but doesn't actually change
+     * the underlying radio connection states.
+     *
+     * @param state Phone.DataState enum.
+     */
+    public void simulateDataConnection(Phone.DataState state) {
+        DataConnectionTracker.State dcState;
+
+        switch (state) {
+            case CONNECTED:
+                dcState = DataConnectionTracker.State.CONNECTED;
+                break;
+            case SUSPENDED:
+                dcState = DataConnectionTracker.State.CONNECTED;
+                break;
+            case DISCONNECTED:
+                dcState = DataConnectionTracker.State.FAILED;
+                break;
+            default:
+                dcState = DataConnectionTracker.State.CONNECTING;
+                break;
+        }
+
+        mDataConnection.setState(dcState);
+        notifyDataConnection(null);
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index 522fa1d..f0c0ea2 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -95,7 +95,6 @@
     CdmaCallTracker mCT;
     CdmaSMSDispatcher mSMS;
     CdmaServiceStateTracker mSST;
-    CdmaDataConnectionTracker mDataConnection;
     RuimFileHandler mRuimFileHandler;
     RuimRecords mRuimRecords;
     RuimCard mRuimCard;
@@ -369,42 +368,11 @@
         return mCT.backgroundCall;
     }
 
-    public String getGateway(String apnType) {
-        return mDataConnection.getGateway();
-    }
-
     public boolean handleInCallMmiCommands(String dialString) {
         Log.e(LOG_TAG, "method handleInCallMmiCommands is NOT supported in CDMA!");
         return false;
     }
 
-    public int enableApnType(String type) {
-        // This request is mainly used to enable MMS APN
-        // In CDMA there is no need to enable/disable a different APN for MMS
-        Log.d(LOG_TAG, "Request to enableApnType("+type+")");
-        if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
-            return Phone.APN_ALREADY_ACTIVE;
-        } else {
-            return Phone.APN_REQUEST_FAILED;
-        }
-    }
-
-    public int disableApnType(String type) {
-        // This request is mainly used to disable MMS APN
-        // In CDMA there is no need to enable/disable a different APN for MMS
-        Log.d(LOG_TAG, "Request to disableApnType("+type+")");
-        if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
-            return Phone.APN_REQUEST_STARTED;
-        } else {
-            return Phone.APN_REQUEST_FAILED;
-        }
-    }
-
-    public String getActiveApn() {
-        Log.d(LOG_TAG, "Request to getActiveApn()");
-        return null;
-    }
-
     public void
     setNetworkSelectionModeAutomatic(Message response) {
         Log.e(LOG_TAG, "method setNetworkSelectionModeAutomatic is NOT supported in CDMA!");
@@ -481,10 +449,6 @@
         return false;
     }
 
-    public String getInterfaceName(String apnType) {
-        return mDataConnection.getInterfaceName();
-    }
-
     public CellLocation getCellLocation() {
         return mSST.cellLoc;
     }
@@ -512,10 +476,6 @@
         return false;
     }
 
-    public boolean isDataConnectivityEnabled() {
-        return mDataConnection.getDataEnabled();
-    }
-
     public boolean isDataConnectivityPossible() {
         boolean noData = mDataConnection.getDataEnabled() &&
                 getDataConnectionState() == DataState.DISCONNECTED;
@@ -528,10 +488,6 @@
         Log.e(LOG_TAG, "setLine1Number: not possible in CDMA");
     }
 
-    public String[] getDnsServers(String apnType) {
-        return mDataConnection.getDnsServers();
-    }
-
     public IccCard getIccCard() {
         return mRuimCard;
     }
@@ -584,10 +540,6 @@
         mCT.unregisterForCallWaiting(h);
     }
 
-    public String getIpAddress(String apnType) {
-        return mDataConnection.getIpAddress();
-    }
-
     public void
     getNeighboringCids(Message response) {
         /*
@@ -701,14 +653,6 @@
         Log.e(LOG_TAG, "getAvailableNetworks: not possible in CDMA");
     }
 
-    public String[] getActiveApnTypes() {
-        String[] result;
-        Log.d(LOG_TAG, "Request to getActiveApn()");
-        result = new String[1];
-        result[0] = Phone.APN_TYPE_DEFAULT;
-        return result;
-    }
-
     public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, Message onComplete) {
         Log.e(LOG_TAG, "setOutgoingCallerIdDisplay: not possible in CDMA");
     }
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
index 8bae483..d02d33e 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -57,8 +57,7 @@
  * {@hide}
  */
 public final class CdmaDataConnectionTracker extends DataConnectionTracker {
-    private static final String LOG_TAG = "CDMA";
-    private static final boolean DBG = true;
+    protected final String LOG_TAG = "CDMA";
 
     private CDMAPhone mCdmaPhone;
 
@@ -77,12 +76,6 @@
     /** Currently active CdmaDataConnection */
     private CdmaDataConnection mActiveDataConnection;
 
-    /** Defined cdma connection profiles */
-    private static final int EXTERNAL_NETWORK_DEFAULT_ID = 0;
-    private static final int EXTERNAL_NETWORK_NUM_TYPES  = 1;
-
-    private boolean[] dataEnabled = new boolean[EXTERNAL_NETWORK_NUM_TYPES];
-
     /**
      * Pool size of CdmaDataConnection objects.
      */
@@ -101,6 +94,11 @@
      private static final int DATA_CONNECTION_ACTIVE_PH_LINK_DOWN = 1;
      private static final int DATA_CONNECTION_ACTIVE_PH_LINK_UP = 2;
 
+    private static final String[] mSupportedApnTypes = {
+            Phone.APN_TYPE_DEFAULT,
+            Phone.APN_TYPE_MMS,
+            Phone.APN_TYPE_HIPRI };
+
     // Possibly promoate to base class, the only difference is
     // the INTENT_RECONNECT_ALARM action is a different string.
     // Do consider technology changes if it is promoted.
@@ -182,9 +180,12 @@
         // and 2) whether the RIL will setup the baseband to auto-PS attach.
         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(phone.getContext());
 
-        dataEnabled[EXTERNAL_NETWORK_DEFAULT_ID] =
+        dataEnabled[APN_DEFAULT_ID] =
                 !sp.getBoolean(CDMAPhone.DATA_DISABLED_ON_BOOT_KEY, false);
-        noAutoAttach = !dataEnabled[EXTERNAL_NETWORK_DEFAULT_ID];
+        if (dataEnabled[APN_DEFAULT_ID]) {
+            enabledCount++;
+        }
+        noAutoAttach = !dataEnabled[APN_DEFAULT_ID];
 
         if (!mRetryMgr.configure(SystemProperties.get("ro.cdma.data_retry_config"))) {
             if (!mRetryMgr.configure(DEFAULT_DATA_RETRY_CONFIG)) {
@@ -219,7 +220,7 @@
         if(DBG) Log.d(LOG_TAG, "CdmaDataConnectionTracker finalized");
     }
 
-    void setState(State s) {
+    protected void setState(State s) {
         if (DBG) log ("setState: " + s);
         if (state != s) {
             if (s == State.INITING) { // request Data connection context
@@ -236,39 +237,33 @@
         state = s;
     }
 
-    public int enableApnType(String type) {
-        // This request is mainly used to enable MMS APN
-        // In CDMA there is no need to enable/disable a different APN for MMS
-        Log.d(LOG_TAG, "Request to enableApnType("+type+")");
-        if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
-            return Phone.APN_ALREADY_ACTIVE;
-        } else 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;
+    @Override
+    protected boolean isApnTypeActive(String type) {
+        return (isApnTypeAvailable(type) &&
+                mCdmaPhone.mSST.getCurrentCdmaDataConnectionState() ==
+                ServiceState.STATE_IN_SERVICE);
+    }
+
+    @Override
+    protected boolean isApnTypeAvailable(String type) {
+        for (String s : mSupportedApnTypes) {
+            if (TextUtils.equals(type, s)) {
+                return true;
+            }
         }
+        return false;
     }
 
-    public int disableApnType(String type) {
-        // This request is mainly used to disable MMS APN
-        // In CDMA there is no need to enable/disable a different APN for MMS
-        Log.d(LOG_TAG, "Request to disableApnType("+type+")");
-        if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
-            return Phone.APN_REQUEST_STARTED;
-        } else {
-            return Phone.APN_REQUEST_FAILED;
+    protected String[] getActiveApnTypes() {
+        if (mCdmaPhone.mSST.getCurrentCdmaDataConnectionState() ==
+                ServiceState.STATE_IN_SERVICE) {
+            return mSupportedApnTypes.clone();
         }
+        return new String[0];
     }
 
-    private boolean isEnabled(int cdmaDataProfile) {
-        return dataEnabled[cdmaDataProfile];
-    }
-
-    private void setEnabled(int cdmaDataProfile, boolean enable) {
-        Log.d(LOG_TAG, "setEnabled("  + cdmaDataProfile + ", " + enable + ')');
-        dataEnabled[cdmaDataProfile] = enable;
-        Log.d(LOG_TAG, "dataEnabled[DEFAULT_PROFILE]=" + dataEnabled[EXTERNAL_NETWORK_DEFAULT_ID]);
+    protected String getActiveApnString() {
+        return null;
     }
 
     /**
@@ -294,54 +289,6 @@
         return true;
     }
 
-    /**
-     * Prevent mobile data connections from being established,
-     * or once again allow mobile data connections. If the state
-     * toggles, then either tear down or set up data, as
-     * appropriate to match the new state.
-     * <p>This operation only affects the default connection
-     * @param enable indicates whether to enable ({@code true}) or disable ({@code false}) data
-     * @return {@code true} if the operation succeeded
-     */
-    public boolean setDataEnabled(boolean enable) {
-
-        boolean isEnabled = isEnabled(EXTERNAL_NETWORK_DEFAULT_ID);
-
-        Log.d(LOG_TAG, "setDataEnabled("+enable+") isEnabled=" + isEnabled);
-        if (!isEnabled && enable) {
-            setEnabled(EXTERNAL_NETWORK_DEFAULT_ID, true);
-            sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
-        } else if (!enable) {
-            setEnabled(EXTERNAL_NETWORK_DEFAULT_ID, false);
-            Message msg = obtainMessage(EVENT_CLEAN_UP_CONNECTION);
-            msg.arg1 = 1; // tearDown is true
-            msg.obj = Phone.REASON_DATA_DISABLED;
-            sendMessage(msg);
-        }
-        return true;
-    }
-
-    /**
-     * Report the current state of data connectivity (enabled or disabled)
-     * @return {@code false} if data connectivity has been explicitly disabled,
-     * {@code true} otherwise.
-     */
-    public boolean getDataEnabled() {
-        return dataEnabled[EXTERNAL_NETWORK_DEFAULT_ID];
-    }
-
-    /**
-     * Report on whether data connectivity is enabled
-     * @return {@code false} if data connectivity has been explicitly disabled,
-     * {@code true} otherwise.
-     */
-    public boolean getAnyDataEnabled() {
-        for (int i=0; i < EXTERNAL_NETWORK_NUM_TYPES; i++) {
-            if (isEnabled(i)) return true;
-        }
-        return false;
-    }
-
     private boolean isDataAllowed() {
         boolean roaming = phone.getServiceState().getRoaming();
         return getAnyDataEnabled() && (!roaming || getDataOnRoamingEnabled());
@@ -921,28 +868,28 @@
         }
     }
 
-    String getInterfaceName() {
+    protected String getInterfaceName(String apnType) {
         if (mActiveDataConnection != null) {
             return mActiveDataConnection.getInterface();
         }
         return null;
     }
 
-    protected String getIpAddress() {
+    protected String getIpAddress(String apnType) {
         if (mActiveDataConnection != null) {
             return mActiveDataConnection.getIpAddress();
         }
         return null;
     }
 
-    String getGateway() {
+    protected String getGateway(String apnType) {
         if (mActiveDataConnection != null) {
             return mActiveDataConnection.getGatewayAddress();
         }
         return null;
     }
 
-    protected String[] getDnsServers() {
+    protected String[] getDnsServers(String apnType) {
         if (mActiveDataConnection != null) {
             return mActiveDataConnection.getDnsServers();
         }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
index 94d4344..bb04a43 100755
--- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -102,7 +102,6 @@
     GsmCallTracker mCT;
     GsmServiceStateTracker mSST;
     GsmSMSDispatcher mSMS;
-    GsmDataConnectionTracker mDataConnection;
     SIMRecords mSIMRecords;
     SimCard mSimCard;
     StkService mStkService;
@@ -280,14 +279,6 @@
         return "GSM";
     }
 
-    public String[] getActiveApnTypes() {
-        return mDataConnection.getActiveApnTypes();
-    }
-
-    public String getActiveApn() {
-        return mDataConnection.getActiveApnString();
-    }
-
     public SignalStrength getSignalStrength() {
         return mSST.mSignalStrength;
     }
@@ -1145,38 +1136,10 @@
         return mDataConnection.setDataEnabled(true);
     }
 
-    public int enableApnType(String type) {
-        return mDataConnection.enableApnType(type);
-    }
-
-    public int disableApnType(String type) {
-        return mDataConnection.disableApnType(type);
-    }
-
     public boolean disableDataConnectivity() {
         return mDataConnection.setDataEnabled(false);
     }
 
-    public String getInterfaceName(String apnType) {
-        return mDataConnection.getInterfaceName(apnType);
-    }
-
-    public String getIpAddress(String apnType) {
-        return mDataConnection.getIpAddress(apnType);
-    }
-
-    public String getGateway(String apnType) {
-        return mDataConnection.getGateway(apnType);
-    }
-
-    public String[] getDnsServers(String apnType) {
-        return mDataConnection.getDnsServers(apnType);
-    }
-
-    public boolean isDataConnectivityEnabled() {
-        return mDataConnection.getDataEnabled();
-    }
-
     /**
      * The only circumstances under which we report that data connectivity is not
      * possible are
@@ -1543,36 +1506,6 @@
             }
         }
     }
-    /**
-     * simulateDataConnection
-     *
-     * simulates various data connection states. This messes with
-     * DataConnectionTracker's internal states, but doesn't actually change
-     * the underlying radio connection states.
-     *
-     * @param state Phone.DataState enum.
-     */
-    public void simulateDataConnection(Phone.DataState state) {
-        DataConnectionTracker.State dcState;
-
-        switch (state) {
-            case CONNECTED:
-                dcState = DataConnectionTracker.State.CONNECTED;
-                break;
-            case SUSPENDED:
-                dcState = DataConnectionTracker.State.CONNECTED;
-                break;
-            case DISCONNECTED:
-                dcState = DataConnectionTracker.State.FAILED;
-                break;
-            default:
-                dcState = DataConnectionTracker.State.CONNECTING;
-                break;
-        }
-
-        mDataConnection.setState(dcState);
-        notifyDataConnection(null);
-    }
 
     /**
      * Retrieves the PhoneSubInfo of the GSMPhone
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 34d3039..3aee26e 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -63,8 +63,7 @@
  * {@hide}
  */
 public final class GsmDataConnectionTracker extends DataConnectionTracker {
-    private static final String LOG_TAG = "GSM";
-    private static final boolean DBG = true;
+    protected final String LOG_TAG = "GSM";
 
     private GSMPhone mGsmPhone;
     /**
@@ -119,31 +118,17 @@
 
     private ApnSetting preferredApn = null;
 
+    /* Currently active APN */
+    protected ApnSetting mActiveApn;
+
     /**
      * pdpList holds all the PDP connection, i.e. IP Link in GPRS
      */
     private ArrayList<DataConnection> pdpList;
 
-    /** Currently requested APN type */
-    private String mRequestedApnType = Phone.APN_TYPE_DEFAULT;
-
-    /** Currently active APN */
-    private ApnSetting mActiveApn;
-
     /** Currently active PdpConnection */
     private PdpConnection mActivePdp;
 
-    private static int APN_INVALID_ID = -1;
-    private static int APN_DEFAULT_ID = 0;
-    private static int APN_MMS_ID = 1;
-    private static int APN_SUPL_ID = 2;
-    private static int APN_DUN_ID = 3;
-    private static int APN_HIPRI_ID = 4;
-    private static int APN_NUM_TYPES = 5;
-
-    private boolean[] dataEnabled = new boolean[APN_NUM_TYPES];
-    private int enabledCount = 0;
-
     /** Is packet service restricted by network */
     private boolean mIsPsRestricted = false;
 
@@ -293,7 +278,7 @@
         if(DBG) Log.d(LOG_TAG, "GsmDataConnectionTracker finalized");
     }
 
-    void setState(State s) {
+    protected void setState(State s) {
         if (DBG) log ("setState: " + s);
         if (state != s) {
             if (s == State.INITING) { // request PDP context
@@ -317,7 +302,7 @@
         }
     }
 
-    String[] getActiveApnTypes() {
+    public String[] getActiveApnTypes() {
         String[] result;
         if (mActiveApn != null) {
             result = mActiveApn.types;
@@ -336,87 +321,6 @@
         return result;
     }
 
-    protected int apnTypeToId(String type) {
-        if (TextUtils.equals(type, Phone.APN_TYPE_DEFAULT)) {
-            return APN_DEFAULT_ID;
-        } else if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
-            return APN_MMS_ID;
-        } else if (TextUtils.equals(type, Phone.APN_TYPE_SUPL)) {
-            return APN_SUPL_ID;
-        } else if (TextUtils.equals(type, Phone.APN_TYPE_DUN)) {
-            return APN_DUN_ID;
-        } else if (TextUtils.equals(type, Phone.APN_TYPE_HIPRI)) {
-            return APN_HIPRI_ID;
-        } else {
-            return APN_INVALID_ID;
-        }
-    }
-
-    /**
-     * Ensure that we are connected to an APN of the specified type.
-     * @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
-     * will be sent by the ConnectivityManager when a connection to
-     * the APN has been established.
-     */
-    protected int enableApnType(String type) {
-        int id = apnTypeToId(type);
-        if (id == APN_INVALID_ID) {
-            return Phone.APN_REQUEST_FAILED;
-        }
-
-        // If already active, return
-        if(DBG) Log.d(LOG_TAG, "enableApnType("+type+"), isApnTypeActive = "
-                + isApnTypeActive(type) + " and state = " + state);
-        if (isApnTypeActive(type)) {
-            if (state == State.INITING) return Phone.APN_REQUEST_STARTED;
-            else if (state == State.CONNECTED) return Phone.APN_ALREADY_ACTIVE;
-        }
-
-        if (!isApnTypeAvailable(type)) {
-            return Phone.APN_TYPE_NOT_AVAILABLE;
-        }
-
-        setEnabled(id, true);
-        mRequestedApnType = type;
-        sendMessage(obtainMessage(EVENT_ENABLE_NEW_APN));
-        return Phone.APN_REQUEST_STARTED;
-    }
-
-    /**
-     * The APN of the specified type is no longer needed. Ensure that if
-     * use of the default APN has not been explicitly disabled, we are connected
-     * to the default APN.
-     * @param type the APN type. The only valid values are currently
-     * {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL}.
-     * @return
-     */
-    protected int disableApnType(String type) {
-        if (DBG) Log.d(LOG_TAG, "disableApnType("+type+")");
-        int id = apnTypeToId(type);
-        if (id == APN_INVALID_ID) {
-            return Phone.APN_REQUEST_FAILED;
-        }
-        if (isEnabled(id)) {
-            setEnabled(id, false);
-            if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
-                mRequestedApnType = Phone.APN_TYPE_DEFAULT;
-                if (dataEnabled[APN_DEFAULT_ID]) {
-                    return Phone.APN_ALREADY_ACTIVE;
-                } else {
-                    return Phone.APN_REQUEST_STARTED;
-                }
-            } else {
-                return Phone.APN_REQUEST_STARTED;
-            }
-        } else {
-            return Phone.APN_REQUEST_FAILED;
-        }
-    }
-
     /**
      * The data connection is expected to be setup while device
      *  1. has sim card
@@ -439,12 +343,14 @@
         return true;
     }
 
-    private boolean isApnTypeActive(String type) {
-        // TODO: to support simultaneous, mActiveApn can be a List instead.
+    @Override
+    protected boolean isApnTypeActive(String type) {
+        // TODO: support simultaneous with List instead
         return mActiveApn != null && mActiveApn.canHandleType(type);
     }
 
-    private boolean isApnTypeAvailable(String type) {
+    @Override
+    protected boolean isApnTypeAvailable(String type) {
         if (allApns != null) {
             for (ApnSetting apn : allApns) {
                 if (apn.canHandleType(type)) {
@@ -455,80 +361,6 @@
         return false;
     }
 
-    private boolean isEnabled(int id) {
-        if (id != APN_INVALID_ID) {
-            return dataEnabled[id];
-        }
-        return false;
-    }
-
-    private void setEnabled(int id, boolean enable) {
-        if (DBG) Log.d(LOG_TAG, "setEnabled(" + id + ", " + enable + ')');
-        if (dataEnabled[id] != enable) {
-            dataEnabled[id] = enable;
-
-            if (enable) {
-                enabledCount++;
-            } else {
-                enabledCount--;
-            }
-
-            if (enabledCount == 0) {
-                setPrivateDataEnabled(false);
-            } else if (enabledCount == 1) {
-                setPrivateDataEnabled(true);
-            }
-        }
-    }
-
-    /**
-     * Prevent mobile data connections from being established,
-     * or once again allow mobile data connections. If the state
-     * toggles, then either tear down or set up data, as
-     * appropriate to match the new state.
-     * <p>This operation only affects the default APN, and if the same APN is
-     * currently being used for MMS traffic, the teardown will not happen
-     * even when {@code enable} is {@code false}.</p>
-     * @param enable indicates whether to enable ({@code true}) or disable ({@code false}) data
-     * @return {@code true} if the operation succeeded
-     */
-    public boolean setDataEnabled(boolean enable) {
-        if (DBG) Log.d(LOG_TAG, "setDataEnabled("+enable+")");
-        setEnabled(APN_DEFAULT_ID, enable);
-        return true;
-    }
-
-    private void setPrivateDataEnabled(boolean enable) {
-        if (DBG) Log.d(LOG_TAG, "setPrivateDataEnabled("+enable+")");
-        if (enable) {
-            sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
-        } else {
-            Message msg = obtainMessage(EVENT_CLEAN_UP_CONNECTION);
-            msg.arg1 = 1; // tearDown is true
-            msg.obj = Phone.REASON_DATA_DISABLED;
-            sendMessage(msg);
-        }
-    }
-
-    /**
-     * Report the current state of data connectivity (enabled or disabled) for
-     * the default APN.
-     * @return {@code false} if data connectivity has been explicitly disabled,
-     * {@code true} otherwise.
-     */
-    public boolean getDataEnabled() {
-        return dataEnabled[APN_DEFAULT_ID];
-    }
-
-    /**
-     * Report on whether data connectivity is enabled for any APN.
-     * @return {@code false} if data connectivity has been explicitly disabled,
-     * {@code true} otherwise.
-     */
-    public boolean getAnyDataEnabled() {
-        return (enabledCount != 0);
-    }
-
     /**
      * Formerly this method was ArrayList<PdpConnection> getAllPdps()
      */
@@ -744,7 +576,7 @@
         return true;
     }
 
-    String getInterfaceName(String apnType) {
+    protected String getInterfaceName(String apnType) {
         if (mActivePdp != null
                 && (apnType == null || mActiveApn.canHandleType(apnType))) {
             return mActivePdp.getInterface();
@@ -760,7 +592,7 @@
         return null;
     }
 
-    String getGateway(String apnType) {
+    public String getGateway(String apnType) {
         if (mActivePdp != null
                 && (apnType == null || mActiveApn.canHandleType(apnType))) {
             return mActivePdp.getGatewayAddress();
diff --git a/tests/backup/backup_stress_test.sh b/tests/backup/backup_stress_test.sh
new file mode 100755
index 0000000..8155507
--- /dev/null
+++ b/tests/backup/backup_stress_test.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+
+# Copyright (C) 2009 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+iterations=150
+failures=0
+i=0
+LOGDIR="$HOME/backup_tests"
+LOGFILE="$LOGDIR/backup_stress.`date +%s`.log"
+export BUGREPORT_DIR="$LOGDIR/bugreports"
+
+# make sure that we have a place to put logs and bugreports
+mkdir -p $LOGDIR $BUGREPORT_DIR
+
+echo "logfile is $LOGFILE"
+
+(while (sleep 10); do
+    failed=0
+    
+    echo
+    echo "Iteration $i at `date`"
+    echo
+
+    ./test_backup.sh "$@" 2>&1
+
+    sleep 10
+    echo "Restore at `date`"
+    echo
+
+    ./test_restore.sh "$@" 2>&1 || failed=1
+    
+    if [ "$failed" -ne 0 ]; then
+        failures=$(($failures+1))
+        # Long and verbose so it sticks out
+        echo "FAILED iteration $i of $iterations; $failures failures so far"
+        echo "FAILED iteration $i of $iterations; $failures failures so far" > /dev/stderr
+    else
+        printf "Iteration %d:\tPASS; remaining: %d\n" $i $(($iterations - $i - 1))
+        printf "Iteration %d:\tPASS; remaining: %d\n" $i $(($iterations - $i - 1)) > /dev/stderr
+    fi
+
+    echo "End $i at `date`"
+    
+    i=$(($i+1))
+    if [ $i -eq $iterations ]; then
+        echo "DONE: $iterations iterations with $failures failures."
+        echo "DONE: $iterations iterations with $failures failures." > /dev/stderr
+        [ "$failures" -eq 0 ] && exit 0
+        exit 1
+    fi
+done) > "$LOGFILE"
+
diff --git a/tests/backup/test_restore.sh b/tests/backup/test_restore.sh
index 4506c16..46b46e4 100755
--- a/tests/backup/test_restore.sh
+++ b/tests/backup/test_restore.sh
@@ -18,7 +18,7 @@
 #export DRY_RUN="echo"
 source test_backup_common.sh
 
-BUGREPORT_DIR="$HOME/backup/bugreports"
+[ -z "$BUGREPORT_DIR" ] && BUGREPORT_DIR="$HOME/backup/bugreports"
 
 function check_file
 {
@@ -107,3 +107,5 @@
 echo "Last 3 timestamps in 3.txt:"
 a shell cat /data/data/com.android.backuptest/files/3.txt | tail -n 3
 
+exit $need_bug
+