Merge "LayoutLib: fix clipping issues." into honeycomb
diff --git a/api/current.xml b/api/current.xml
index 112c147..610542d 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -85932,6 +85932,97 @@
 </parameter>
 </constructor>
 </class>
+<class name="SurfaceTexture"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="SurfaceTexture"
+ type="android.graphics.SurfaceTexture"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="texName" type="int">
+</parameter>
+</constructor>
+<method name="setOnFrameAvailableListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="l" type="android.graphics.SurfaceTexture.OnFrameAvailableListener">
+</parameter>
+</method>
+<method name="updateTexImage"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<interface name="SurfaceTexture.OnFrameAvailableListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onFrameAvailable"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="surfaceTexture" type="android.graphics.SurfaceTexture">
+</parameter>
+</method>
+</interface>
+<class name="SurfaceTexture.OutOfResourcesException"
+ extends="java.lang.Exception"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="SurfaceTexture.OutOfResourcesException"
+ type="android.graphics.SurfaceTexture.OutOfResourcesException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="SurfaceTexture.OutOfResourcesException"
+ type="android.graphics.SurfaceTexture.OutOfResourcesException"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</constructor>
+</class>
 <class name="SweepGradient"
  extends="android.graphics.Shader"
  abstract="false"
diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
index 80a80bd..21144f2 100644
--- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java
+++ b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
@@ -149,10 +149,6 @@
                     newState == BluetoothInputDevice.STATE_DISCONNECTED) {
                     sendMessage(TRANSITION_TO_STABLE);
                 }
-            } else if (action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)) {
-                Message msg = new Message();
-                msg.what = AUTO_CONNECT_PROFILES;
-                sendMessage(msg);
             } else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
                 // This is technically not needed, but we can get stuck sometimes.
                 // For example, if incoming A2DP fails, we are not informed by Bluez
diff --git a/core/java/android/database/sqlite/SQLiteCursor.java b/core/java/android/database/sqlite/SQLiteCursor.java
index 5a6c667..26a1440 100644
--- a/core/java/android/database/sqlite/SQLiteCursor.java
+++ b/core/java/android/database/sqlite/SQLiteCursor.java
@@ -407,15 +407,29 @@
                 mWindow.clear();
             }
             mPos = -1;
-            SQLiteDatabase db = mQuery.mDatabase.getDatabaseHandle(mQuery.mSql);
+            SQLiteDatabase db = null;
+            try {
+                db = mQuery.mDatabase.getDatabaseHandle(mQuery.mSql);
+            } catch (IllegalStateException e) {
+                // for backwards compatibility, just return false
+                return false;
+            }
             if (!db.equals(mQuery.mDatabase)) {
                 // since we need to use a different database connection handle,
                 // re-compile the query
-                db.lock();
+                try {
+                    db.lock();
+                } catch (IllegalStateException e) {
+                    // for backwards compatibility, just return false
+                    return false;
+                }
                 try {
                     // close the old mQuery object and open a new one
                     mQuery.close();
                     mQuery = new SQLiteQuery(db, mQuery);
+                } catch (IllegalStateException e) {
+                    // for backwards compatibility, just return false
+                    return false;
                 } finally {
                     db.unlock();
                 }
@@ -427,6 +441,9 @@
             queryThreadLock();
             try {
                 mQuery.requery();
+            } catch (IllegalStateException e) {
+                // for backwards compatibility, just return false
+                return false;
             } finally {
                 queryThreadUnlock();
             }
@@ -437,7 +454,12 @@
             Log.v(TAG, "--- Requery()ed cursor " + this + ": " + mQuery);
         }
 
-        boolean result = super.requery();
+        boolean result = false;
+        try {
+            result = super.requery();
+        } catch (IllegalStateException e) {
+            // for backwards compatibility, just return false
+        }
         if (Config.LOGV) {
             long timeEnd = System.currentTimeMillis();
             Log.v(TAG, "requery (" + (timeEnd - timeStart) + " ms): " + mDriver.toString());
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 58fadb9..5138442 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -129,6 +129,16 @@
     private int[] mTmpPointerIds;
     private MotionEvent.PointerCoords[] mTmpPointerCoords;
 
+    // For debugging only.  You can see these in hierarchyviewer.
+    @ViewDebug.ExportedProperty(category = "events")
+    private long mLastTouchDownTime;
+    @ViewDebug.ExportedProperty(category = "events")
+    private int mLastTouchDownIndex = -1;
+    @ViewDebug.ExportedProperty(category = "events")
+    private float mLastTouchDownX;
+    @ViewDebug.ExportedProperty(category = "events")
+    private float mLastTouchDownY;
+
     /**
      * Internal flags.
      *
@@ -1157,6 +1167,10 @@
                         resetCancelNextUpFlag(child);
                         if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)) {
                             // Child wants to receive touch within its bounds.
+                            mLastTouchDownTime = ev.getDownTime();
+                            mLastTouchDownIndex = i;
+                            mLastTouchDownX = ev.getX();
+                            mLastTouchDownY = ev.getY();
                             newTouchTarget = addTouchTarget(child, idBitsToAssign);
                             alreadyDispatchedToNewTouchTarget = true;
                             break;
@@ -2805,6 +2819,9 @@
             }
             children[index] = child;
             mChildrenCount++;
+            if (mLastTouchDownIndex >= index) {
+                mLastTouchDownIndex++;
+            }
         } else {
             throw new IndexOutOfBoundsException("index=" + index + " count=" + count);
         }
@@ -2825,6 +2842,12 @@
         } else {
             throw new IndexOutOfBoundsException();
         }
+        if (mLastTouchDownIndex == index) {
+            mLastTouchDownTime = 0;
+            mLastTouchDownIndex = -1;
+        } else if (mLastTouchDownIndex > index) {
+            mLastTouchDownIndex--;
+        }
     }
 
     // This method also sets the children's mParent to null
diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java
index 96c1ed3..f927fae 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuView.java
@@ -47,9 +47,7 @@
     private boolean mReserveOverflow;
     private OverflowMenuButton mOverflowButton;
     private MenuPopupHelper mOverflowPopup;
-    
-    private float mButtonPaddingLeft;
-    private float mButtonPaddingRight;
+
     private float mDividerPadding;
     
     private Drawable mDivider;
@@ -94,16 +92,9 @@
                 Configuration.SCREENLAYOUT_SIZE_XLARGE;
         
         TypedArray a = context.obtainStyledAttributes(com.android.internal.R.styleable.Theme);
-        final int buttonStyle = a.getResourceId(
-                com.android.internal.R.styleable.Theme_actionButtonStyle, 0);
         mDivider = a.getDrawable(com.android.internal.R.styleable.Theme_dividerVertical);
         a.recycle();
         
-        a = context.obtainStyledAttributes(buttonStyle, com.android.internal.R.styleable.View);
-        mButtonPaddingLeft = a.getDimension(com.android.internal.R.styleable.View_paddingLeft, 0);
-        mButtonPaddingRight = a.getDimension(com.android.internal.R.styleable.View_paddingRight, 0);
-        a.recycle();
-        
         mDividerPadding = DIVIDER_PADDING * res.getDisplayMetrics().density;
 
         setBaselineAligned(false);
@@ -295,10 +286,7 @@
     }
 
     private LayoutParams makeActionViewLayoutParams(View view) {
-        LayoutParams params = generateLayoutParams(view.getLayoutParams());
-        params.leftMargin = (int) mButtonPaddingLeft;
-        params.rightMargin = (int) mButtonPaddingRight;
-        return params;
+        return generateLayoutParams(view.getLayoutParams());
     }
 
     private class OverflowMenuButton extends ImageButton {
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 241bc3e..c635b39 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -111,6 +111,7 @@
 	android/graphics/Rasterizer.cpp \
 	android/graphics/Region.cpp \
 	android/graphics/Shader.cpp \
+	android/graphics/SurfaceTexture.cpp \
 	android/graphics/TextLayout.cpp \
 	android/graphics/Typeface.cpp \
 	android/graphics/Utils.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index b6e4119..d28bdc9 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -111,6 +111,7 @@
 extern int register_android_graphics_Picture(JNIEnv*);
 extern int register_android_graphics_PorterDuff(JNIEnv* env);
 extern int register_android_graphics_Rasterizer(JNIEnv* env);
+extern int register_android_graphics_SurfaceTexture(JNIEnv* env);
 extern int register_android_graphics_Xfermode(JNIEnv* env);
 extern int register_android_graphics_PixelFormat(JNIEnv* env);
 extern int register_com_android_internal_graphics_NativeUtils(JNIEnv *env);
@@ -1235,6 +1236,7 @@
     REG_JNI(register_android_graphics_Rasterizer),
     REG_JNI(register_android_graphics_Region),
     REG_JNI(register_android_graphics_Shader),
+    REG_JNI(register_android_graphics_SurfaceTexture),
     REG_JNI(register_android_graphics_Typeface),
     REG_JNI(register_android_graphics_Xfermode),
     REG_JNI(register_android_graphics_YuvImage),
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
new file mode 100644
index 0000000..2645045
--- /dev/null
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "SurfaceTexture"
+
+#include <stdio.h>
+
+#include <gui/SurfaceTexture.h>
+
+#include <android_runtime/AndroidRuntime.h>
+
+#include <utils/Log.h>
+#include <utils/misc.h>
+
+#include "android/graphics/GraphicsJNI.h"
+#include "jni.h"
+
+// ----------------------------------------------------------------------------
+
+namespace android {
+
+static const char* const OutOfResourcesException =
+    "android/graphics/SurfaceTexture$OutOfResourcesException";
+
+struct st_t {
+    jfieldID surfaceTexture;
+};
+static st_t st;
+
+// ----------------------------------------------------------------------------
+
+static void setSurfaceTexture(JNIEnv* env, jobject clazz,
+        const sp<SurfaceTexture>& surfaceTexture)
+{
+    SurfaceTexture* const p =
+        (SurfaceTexture*)env->GetIntField(clazz, st.surfaceTexture);
+    if (surfaceTexture.get()) {
+        surfaceTexture->incStrong(clazz);
+    }
+    if (p) {
+        p->decStrong(clazz);
+    }
+    env->SetIntField(clazz, st.surfaceTexture, (int)surfaceTexture.get());
+}
+
+sp<SurfaceTexture> getSurfaceTexture(JNIEnv* env, jobject clazz)
+{
+    sp<SurfaceTexture> surfaceTexture(
+        (SurfaceTexture*)env->GetIntField(clazz, st.surfaceTexture));
+    return surfaceTexture;
+}
+
+// ----------------------------------------------------------------------------
+
+static void SurfaceTexture_init(JNIEnv* env, jobject clazz, jint texName)
+{
+    sp<SurfaceTexture> surfaceTexture(new SurfaceTexture(texName));
+
+    if (surfaceTexture == 0) {
+        doThrow(env, OutOfResourcesException);
+        return;
+    }
+    setSurfaceTexture(env, clazz, surfaceTexture);
+}
+
+static void SurfaceTexture_updateTexImage(JNIEnv* env, jobject clazz)
+{
+    sp<SurfaceTexture> surfaceTexture(getSurfaceTexture(env, clazz));
+    surfaceTexture->updateTexImage();
+}
+
+// ----------------------------------------------------------------------------
+
+const char* const kSurfaceTextureClassPathName = "android/graphics/SurfaceTexture";
+static void nativeClassInit(JNIEnv* env, jclass clazz);
+
+static JNINativeMethod gSurfaceTextureMethods[] = {
+    {"nativeClassInit",     "()V",  (void*)nativeClassInit },
+    {"init",                "(I)V", (void*)SurfaceTexture_init },
+    {"updateTexImage",      "()V",  (void*)SurfaceTexture_updateTexImage },
+};
+
+static void nativeClassInit(JNIEnv* env, jclass clazz)
+{
+    st.surfaceTexture = env->GetFieldID(clazz,
+            ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID, "I");
+}
+
+int register_android_graphics_SurfaceTexture(JNIEnv* env)
+{
+    int err = 0;
+    err = AndroidRuntime::registerNativeMethods(env, kSurfaceTextureClassPathName,
+            gSurfaceTextureMethods, NELEM(gSurfaceTextureMethods));
+    return err;
+}
+
+} // namespace android
diff --git a/core/res/res/layout/action_menu_item_layout.xml b/core/res/res/layout/action_menu_item_layout.xml
index 94fcc2f..e502b1e 100644
--- a/core/res/res/layout/action_menu_item_layout.xml
+++ b/core/res/res/layout/action_menu_item_layout.xml
@@ -29,7 +29,11 @@
                  android:layout_height="wrap_content"
                  android:layout_gravity="center"
                  android:visibility="gone"
-                 style="?attr/actionButtonStyle" />
+                 android:paddingLeft="4dip"
+                 android:paddingRight="4dip"
+                 android:minHeight="56dip"
+                 android:scaleType="center"
+                 android:background="@null" />
     <Button android:id="@+id/textButton"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 470fb36..ec5ef83 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1030,7 +1030,7 @@
     </style>
 
     <style name="Widget.ActionButton">
-        <item name="android:background">@null</item>
+        <item name="android:background">?android:attr/selectableItemBackground</item>
         <item name="android:paddingLeft">16dip</item>
         <item name="android:paddingRight">16dip</item>
     </style>
@@ -1651,8 +1651,8 @@
     </style>
 
     <style name="Widget.Holo.ActionButton" parent="Widget.ActionButton">
-        <item name="android:paddingLeft">4dip</item>
-        <item name="android:paddingRight">4dip</item>
+        <item name="android:paddingLeft">16dip</item>
+        <item name="android:paddingRight">16dip</item>
         <item name="android:minHeight">56dip</item>
         <item name="android:scaleType">center</item>
     </style>
@@ -1981,7 +1981,6 @@
 
     <style name="Widget.Holo.Light.ActionButton.Overflow">
         <item name="android:src">@android:drawable/ic_menu_moreoverflow_holo_light</item>
-        <item name="android:background">?android:attr/selectableItemBackground</item>
         <item name="android:paddingLeft">16dip</item>
         <item name="android:paddingRight">16dip</item>
     </style>
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
new file mode 100644
index 0000000..883c4eb
--- /dev/null
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+/**
+ * Captures frames from an image stream as an OpenGL ES texture.
+ *
+ * <p>The image stream may come from either video playback or camera preview.  A SurfaceTexture may
+ * be used in place of a SurfaceHolder when specifying the output destination of a MediaPlayer or
+ * Camera object.  This will cause all the frames from that image stream to be sent to the
+ * SurfaceTexture object rather than to the device's display.  When {@link #updateTexImage} is
+ * called, the contents of the texture object specified when the SurfaceTexture was created is
+ * updated to contain the most recent image from the image stream.  This may cause some frames of
+ * the stream to be skipped.
+ *
+ * <p>The texture object uses the GL_TEXTURE_EXTERNAL_OES texture target, which is defined by the
+ * OES_EGL_image_external OpenGL ES extension.  This limits how the texture may be used.
+ */
+public class SurfaceTexture {
+
+    @SuppressWarnings("unused")
+    private int mSurfaceTexture;
+
+    /**
+     * Callback interface for being notified that a new stream frame is available.
+     */
+    public interface OnFrameAvailableListener {
+        void onFrameAvailable(SurfaceTexture surfaceTexture);
+    }
+
+    /**
+     * Exception thrown when a surface couldn't be created or resized
+     */
+    public static class OutOfResourcesException extends Exception {
+        public OutOfResourcesException() {
+        }
+        public OutOfResourcesException(String name) {
+            super(name);
+        }
+    }
+
+    /**
+     * Construct a new SurfaceTexture to stream images to a given OpenGL texture.
+     *
+     * @param texName the OpenGL texture object name (e.g. generated via glGenTextures)
+     */
+    public SurfaceTexture(int texName) {
+        init(texName);
+    }
+
+    /**
+     * Register a callback to be invoked when a new image frame becomes available to the
+     * SurfaceTexture.  Note that this callback may be called on an arbitrary thread, so it is not
+     * safe to call {@link #updateTexImage} without first binding the OpenGL ES context to the
+     * thread invoking the callback.
+     */
+    public void setOnFrameAvailableListener(OnFrameAvailableListener l) {
+        // TODO: Implement this!
+    }
+
+    /**
+     * Update the texture image to the most recent frame from the image stream.  This may only be
+     * called while the OpenGL ES context that owns the texture is bound to the thread.  It will
+     * implicitly bind its texture to the GL_TEXTURE_EXTERNAL_OES texture target.
+     */
+    public native void updateTexImage();
+
+    private native void init(int texName);
+
+    /*
+     * We use a class initializer to allow the native code to cache some
+     * field offsets.
+     */
+    private static native void nativeClassInit();
+    static { nativeClassInit(); }
+}
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index a3e7fc7..5979be6 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -229,7 +229,7 @@
                 bufferRemaining);
 
         if (n < 0) {
-            return err;
+            return n;
         }
 
         if (n == 0) {
@@ -340,6 +340,7 @@
 void LiveSession::onDownloadNext() {
     size_t bandwidthIndex = getBandwidthIndex();
 
+rinse_repeat:
     int64_t nowUs = ALooper::GetNowUs();
 
     if (mLastPlaylistFetchTimeUs < 0
@@ -437,6 +438,18 @@
 
     if (mSeqNumber < firstSeqNumberInPlaylist
             || mSeqNumber > lastSeqNumberInPlaylist) {
+        if (mSeqNumber < firstSeqNumberInPlaylist
+                && mPrevBandwidthIndex != (ssize_t)bandwidthIndex) {
+            // Go back to the previous bandwidth.
+
+            LOGI("new bandwidth does not have the sequence number "
+                 "we're looking for, switching back to previous bandwidth");
+
+            mLastPlaylistFetchTimeUs = -1;
+            bandwidthIndex = mPrevBandwidthIndex;
+            goto rinse_repeat;
+        }
+
         if (!mPlaylist->isComplete()
                 && mSeqNumber > lastSeqNumberInPlaylist
                 && mNumRetries < kMaxNumRetries) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 5374957b..3a7bd90 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -78,6 +78,8 @@
 
         mWindowManager = IWindowManager.Stub.asInterface(
                 ServiceManager.getService(Context.WINDOW_SERVICE));
+
+        setClickable(true);
     }
 
     public boolean onTouchEvent(MotionEvent ev) {
diff --git a/services/java/com/android/server/AccessibilityManagerService.java b/services/java/com/android/server/AccessibilityManagerService.java
index 77b6dd0..393beda 100644
--- a/services/java/com/android/server/AccessibilityManagerService.java
+++ b/services/java/com/android/server/AccessibilityManagerService.java
@@ -532,11 +532,8 @@
 
         for (int i = 0, count = services.size(); i < count; i++) {
             Service service = services.get(i);
-
             service.unbind();
-            mComponentNameToServiceMap.remove(service.mComponentName);
         }
-        services.clear();
     }
 
     /**
@@ -588,15 +585,18 @@
             Service service = componentNameToServiceMap.get(componentName);
 
             if (isEnabled) {
-                if (enabledServices.contains(componentName) && service == null) {
-                    new Service(componentName).bind();
-                } else if (!enabledServices.contains(componentName) && service != null) {
-                    // clean up done in Service#onServiceDisconnected
-                    service.unbind();
+                if (enabledServices.contains(componentName)) {
+                    if (service == null) {
+                        service = new Service(componentName);
+                    }
+                    service.bind();
+                } else if (!enabledServices.contains(componentName)) {
+                    if (service != null) {
+                        service.unbind();
+                    }
                 }
             } else {
                 if (service != null) {
-                    // clean up done in Service#onServiceDisconnected
                     service.unbind();
                 }
             }
@@ -679,6 +679,8 @@
         public void unbind() {
             if (mService != null) {
                 mContext.unbindService(this);
+                mComponentNameToServiceMap.remove(mComponentName);
+                mServices.remove(this);
             }
         }
 
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 3b47bce..b1eead2 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -1132,11 +1132,13 @@
         }
     }
 
-    // returns null if no failover available
+    // returns null if no failover available, otherwise returns the highest
+    // priority network we're trying
     private NetworkStateTracker tryFailover(int prevNetType) {
         /*
-         * If this is a default network, check if other defaults are available
-         * or active
+         * If this is a default network, check if other defaults are available.
+         * Try to reconnect on all available and let them hash it out when
+         * more than one connects.
          */
         NetworkStateTracker newNet = null;
         if (mNetAttributes[prevNetType].isDefault()) {
@@ -1149,54 +1151,30 @@
             for (int checkType=0; checkType <= ConnectivityManager.MAX_NETWORK_TYPE; checkType++) {
                 if (checkType == prevNetType) continue;
                 if (mNetAttributes[checkType] == null) continue;
-                if (mNetAttributes[checkType].isDefault()) {
-                    /* TODO - if we have multiple nets we could use
-                     * we may want to put more thought into which we choose
-                     */
-                    if (checkType == mNetworkPreference) {
-                        newType = checkType;
-                        break;
-                    }
-                    if (mNetAttributes[checkType].mPriority > newPriority) {
-                        newType = checkType;
-                        newPriority = mNetAttributes[newType].mPriority;
-                    }
-                }
-            }
+                if (!mNetAttributes[checkType].isDefault()) continue;
+                if (!mNetTrackers[checkType].isAvailable()) continue;
 
-            if (newType != -1) {
-                newNet = mNetTrackers[newType];
-                /**
-                 * See if the other network is available to fail over to.
-                 * If is not available, we enable it anyway, so that it
-                 * will be able to connect when it does become available,
-                 * but we report a total loss of connectivity rather than
-                 * report that we are attempting to fail over.
-                 */
-                if (newNet.isAvailable()) {
-                    NetworkInfo switchTo = newNet.getNetworkInfo();
-                    switchTo.setFailover(true);
-                    if (!switchTo.isConnectedOrConnecting() ||
-                            newNet.isTeardownRequested()) {
-                        newNet.reconnect();
-                    }
-                    if (DBG) {
-                        if (switchTo.isConnected()) {
-                            log("Switching to already connected " + switchTo.getTypeName());
-                        } else {
-                            log("Attempting to switch to " + switchTo.getTypeName());
-                        }
-                    }
-                } else {
-                    newNet.reconnect();
-                    newNet = null; // not officially avail..  try anyway, but
-                                   // report no failover
+                NetworkStateTracker tracker = mNetTrackers[checkType];
+                NetworkInfo info = tracker.getNetworkInfo();
+                if (!info.isConnectedOrConnecting() ||
+                        tracker.isTeardownRequested()) {
+                    info.setFailover(true);
+                    tracker.reconnect();
                 }
-            } else {
-                loge("Network failover failing.");
+                if (DBG) log("Attempting to switch to " + info.getTypeName());
+
+                // figure out if this is the highest priority network
+                // so we send an appropriate return value
+                if (checkType == mNetworkPreference) {
+                    newType = checkType;
+                }
+                if (mNetAttributes[checkType].mPriority > newPriority &&
+                        newType != mNetworkPreference) {
+                    newType = checkType;
+                    newPriority = mNetAttributes[newType].mPriority;
+                }
             }
         }
-
         return newNet;
     }
 
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index c60613c..c14988c 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -18,7 +18,7 @@
     package="com.android.test.hwui">
 
     <uses-permission android:name="android.permission.INTERNET" />
-    <uses-sdk android:minSdkVersion="Froyo" />
+    <uses-sdk android:minSdkVersion="Honeycomb" />
     
     <application
         android:label="HwUi"