Merge "Adding framework support for resizable widgets"
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 751a8d3..f98d275 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -1077,6 +1077,8 @@
     }
 
     public synchronized boolean removeBondInternal(String address) {
+        // Unset the trusted device state and then unpair
+        setTrust(address, false);
         return removeDeviceNative(getObjectPathFromAddress(address));
     }
 
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index 13a911b..2d2165b 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -20,7 +20,6 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedList;
-import java.util.Map;
 
 import android.appwidget.AppWidgetManager;
 import android.content.Context;
@@ -33,8 +32,8 @@
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.view.ViewGroup;
 import android.view.View.MeasureSpec;
+import android.view.ViewGroup;
 
 import com.android.internal.widget.IRemoteViewsAdapterConnection;
 import com.android.internal.widget.IRemoteViewsFactory;
diff --git a/core/java/android/widget/RemoteViewsService.java b/core/java/android/widget/RemoteViewsService.java
index fb2c416..e0b08d4 100644
--- a/core/java/android/widget/RemoteViewsService.java
+++ b/core/java/android/widget/RemoteViewsService.java
@@ -21,8 +21,6 @@
 import android.app.Service;
 import android.content.Intent;
 import android.os.IBinder;
-import android.util.Log;
-import android.util.Pair;
 
 import com.android.internal.widget.IRemoteViewsFactory;
 
@@ -40,9 +38,9 @@
     // reclaimed), the references to the factories that are created need to be stored and used when
     // the service is restarted (in response to user input for example).  When the process is
     // destroyed, so is this static cache of RemoteViewsFactories.
-    private static final HashMap<Intent.FilterComparison, RemoteViewsFactory> mRemoteViewFactories =
+    private static final HashMap<Intent.FilterComparison, RemoteViewsFactory> sRemoteViewFactories =
             new HashMap<Intent.FilterComparison, RemoteViewsFactory>();
-    private final Object mLock = new Object();
+    private static final Object sLock = new Object();
 
     /**
      * An interface for an adapter between a remote collection view (ListView, GridView, etc) and
@@ -162,6 +160,16 @@
         public synchronized boolean hasStableIds() {
             return mFactory.hasStableIds();
         }
+        public void onDestroy(Intent intent) {
+            synchronized (sLock) {
+                Intent.FilterComparison fc = new Intent.FilterComparison(intent);
+                if (RemoteViewsService.sRemoteViewFactories.containsKey(fc)) {
+                    RemoteViewsFactory factory = RemoteViewsService.sRemoteViewFactories.get(fc);
+                    factory.onDestroy();
+                    RemoteViewsService.sRemoteViewFactories.remove(fc);
+                }
+            }
+        }
 
         private RemoteViewsFactory mFactory;
         private boolean mIsCreated;
@@ -169,17 +177,17 @@
 
     @Override
     public IBinder onBind(Intent intent) {
-        synchronized (mLock) {
+        synchronized (sLock) {
             Intent.FilterComparison fc = new Intent.FilterComparison(intent);
             RemoteViewsFactory factory = null;
             boolean isCreated = false;
-            if (!mRemoteViewFactories.containsKey(fc)) {
+            if (!sRemoteViewFactories.containsKey(fc)) {
                 factory = onGetViewFactory(intent);
-                mRemoteViewFactories.put(fc, factory);
+                sRemoteViewFactories.put(fc, factory);
                 factory.onCreate();
                 isCreated = false;
             } else {
-                factory = mRemoteViewFactories.get(fc);
+                factory = sRemoteViewFactories.get(fc);
                 isCreated = true;
             }
             return new RemoteViewsFactoryAdapter(factory, isCreated);
diff --git a/core/java/com/android/internal/widget/IRemoteViewsFactory.aidl b/core/java/com/android/internal/widget/IRemoteViewsFactory.aidl
index 60eca00..5857acb 100644
--- a/core/java/com/android/internal/widget/IRemoteViewsFactory.aidl
+++ b/core/java/com/android/internal/widget/IRemoteViewsFactory.aidl
@@ -16,11 +16,13 @@
 
 package com.android.internal.widget;
 
+import android.content.Intent;
 import android.widget.RemoteViews;
 
 /** {@hide} */
 interface IRemoteViewsFactory {
     void onDataSetChanged();
+    void onDestroy(in Intent intent);
     int getCount();
     RemoteViews getViewAt(int position);
     RemoteViews getLoadingView();
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index bd5305d..7a53874 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -31,8 +31,6 @@
 #include <binder/IPCThreadState.h>
 #include <utils/Log.h>
 #include <utils/SystemClock.h>
-#include <utils/List.h>
-#include <utils/KeyedVector.h>
 #include <cutils/logger.h>
 #include <binder/Parcel.h>
 #include <binder/ProcessState.h>
@@ -324,15 +322,25 @@
 class JavaBBinderHolder : public RefBase
 {
 public:
-    sp<JavaBBinder> get(JNIEnv* env, jobject obj)
+    JavaBBinderHolder(JNIEnv* env, jobject object)
+        : mObject(object)
+    {
+        LOGV("Creating JavaBBinderHolder for Object %p\n", object);
+    }
+    ~JavaBBinderHolder()
+    {
+        LOGV("Destroying JavaBBinderHolder for Object %p\n", mObject);
+    }
+
+    sp<JavaBBinder> get(JNIEnv* env)
     {
         AutoMutex _l(mLock);
         sp<JavaBBinder> b = mBinder.promote();
         if (b == NULL) {
-            b = new JavaBBinder(env, obj);
+            b = new JavaBBinder(env, mObject);
             mBinder = b;
             LOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%d\n",
-                 b.get(), b->getWeakRefs(), obj, b->getWeakRefs()->getWeakCount());
+                 b.get(), b->getWeakRefs(), mObject, b->getWeakRefs()->getWeakCount());
         }
 
         return b;
@@ -346,41 +354,20 @@
 
 private:
     Mutex           mLock;
+    jobject         mObject;
     wp<JavaBBinder> mBinder;
 };
 
 // ----------------------------------------------------------------------------
 
-// Per-IBinder death recipient bookkeeping.  This is how we reconcile local jobject
-// death recipient references passed in through JNI with the permanent corresponding
-// JavaDeathRecipient objects.
-
-class JavaDeathRecipient;
-
-class DeathRecipientList : public RefBase {
-    List< sp<JavaDeathRecipient> > mList;
-    Mutex mLock;
-
-public:
-    ~DeathRecipientList();
-
-    void add(const sp<JavaDeathRecipient>& recipient);
-    void remove(const sp<JavaDeathRecipient>& recipient);
-    sp<JavaDeathRecipient> find(jobject recipient);
-};
-
-// ----------------------------------------------------------------------------
-
 class JavaDeathRecipient : public IBinder::DeathRecipient
 {
 public:
-    JavaDeathRecipient(JNIEnv* env, jobject object, sp<DeathRecipientList>& list)
-        : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)), mList(list)
+    JavaDeathRecipient(JNIEnv* env, jobject object)
+        : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)),
+          mHoldsRef(true)
     {
-        // These objects manage their own lifetimes so are responsible for final bookkeeping.
-        // The list holds a strong reference to this object.
-        mList->add(this);
-
+        incStrong(this);
         android_atomic_inc(&gNumDeathRefs);
         incRefsCreated(env);
     }
@@ -404,12 +391,16 @@
 
     void clearReference()
     {
-        mList->remove(this);
-    }
-
-    bool matches(jobject obj) {
-        JNIEnv* env = javavm_to_jnienv(mVM);
-        return env->IsSameObject(obj, mObject);
+        bool release = false;
+        mLock.lock();
+        if (mHoldsRef) {
+            mHoldsRef = false;
+            release = true;
+        }
+        mLock.unlock();
+        if (release) {
+            decStrong(this);
+        }
     }
 
 protected:
@@ -424,57 +415,12 @@
 private:
     JavaVM* const   mVM;
     jobject const   mObject;
-    sp<DeathRecipientList> mList;
+    Mutex           mLock;
+    bool            mHoldsRef;
 };
 
 // ----------------------------------------------------------------------------
 
-DeathRecipientList::~DeathRecipientList() {
-    AutoMutex _l(mLock);
-
-    // Should never happen -- the JavaDeathRecipient objects that have added themselves
-    // to the list are holding references on the list object.  Only when they are torn
-    // down can the list header be destroyed.
-    if (mList.size() > 0) {
-        LOGE("Retiring binder %p with extant death recipients\n", this);
-    }
-}
-
-void DeathRecipientList::add(const sp<JavaDeathRecipient>& recipient) {
-    AutoMutex _l(mLock);
-
-    mList.push_back(recipient);
-}
-
-void DeathRecipientList::remove(const sp<JavaDeathRecipient>& recipient) {
-    AutoMutex _l(mLock);
-
-    List< sp<JavaDeathRecipient> >::iterator iter;
-    for (iter = mList.begin(); iter != mList.end(); iter++) {
-        if (*iter == recipient) {
-            mList.erase(iter);
-            return;
-        }
-    }
-}
-
-sp<JavaDeathRecipient> DeathRecipientList::find(jobject recipient) {
-    AutoMutex _l(mLock);
-
-    List< sp<JavaDeathRecipient> >::iterator iter;
-    for (iter = mList.begin(); iter != mList.end(); iter++) {
-        if ((*iter)->matches(recipient)) {
-            return *iter;
-        }
-    }
-    return NULL;
-}
-
-static KeyedVector<IBinder*, sp<DeathRecipientList> > gDeathRecipientsByIBinder;
-static Mutex gDeathRecipientMapLock;
-
-// ----------------------------------------------------------------------------
-
 namespace android {
 
 static void proxy_cleanup(const void* id, void* obj, void* cleanupCookie)
@@ -544,7 +490,7 @@
     if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
         JavaBBinderHolder* jbh = (JavaBBinderHolder*)
             env->GetIntField(obj, gBinderOffsets.mObject);
-        return jbh != NULL ? jbh->get(env, obj) : NULL;
+        return jbh != NULL ? jbh->get(env) : NULL;
     }
 
     if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
@@ -675,26 +621,26 @@
     IPCThreadState::self()->flushCommands();
 }
 
-static void android_os_Binder_init(JNIEnv* env, jobject obj)
+static void android_os_Binder_init(JNIEnv* env, jobject clazz)
 {
-    JavaBBinderHolder* jbh = new JavaBBinderHolder();
+    JavaBBinderHolder* jbh = new JavaBBinderHolder(env, clazz);
     if (jbh == NULL) {
         jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
         return;
     }
-    LOGV("Java Binder %p: acquiring first ref on holder %p", obj, jbh);
-    jbh->incStrong((void*)android_os_Binder_init);
-    env->SetIntField(obj, gBinderOffsets.mObject, (int)jbh);
+    LOGV("Java Binder %p: acquiring first ref on holder %p", clazz, jbh);
+    jbh->incStrong(clazz);
+    env->SetIntField(clazz, gBinderOffsets.mObject, (int)jbh);
 }
 
-static void android_os_Binder_destroy(JNIEnv* env, jobject obj)
+static void android_os_Binder_destroy(JNIEnv* env, jobject clazz)
 {
     JavaBBinderHolder* jbh = (JavaBBinderHolder*)
-        env->GetIntField(obj, gBinderOffsets.mObject);
+        env->GetIntField(clazz, gBinderOffsets.mObject);
     if (jbh != NULL) {
-        env->SetIntField(obj, gBinderOffsets.mObject, 0);
-        LOGV("Java Binder %p: removing ref on holder %p", obj, jbh);
-        jbh->decStrong((void*)android_os_Binder_init);
+        env->SetIntField(clazz, gBinderOffsets.mObject, 0);
+        LOGV("Java Binder %p: removing ref on holder %p", clazz, jbh);
+        jbh->decStrong(clazz);
     } else {
         // Encountering an uninitialized binder is harmless.  All it means is that
         // the Binder was only partially initialized when its finalizer ran and called
@@ -702,7 +648,7 @@
         // For example, a Binder subclass constructor might have thrown an exception before
         // it could delegate to its superclass's constructor.  Consequently init() would
         // not have been called and the holder pointer would remain NULL.
-        LOGV("Java Binder %p: ignoring uninitialized binder", obj);
+        LOGV("Java Binder %p: ignoring uninitialized binder", clazz);
     }
 }
 
@@ -1027,25 +973,8 @@
     LOGV("linkToDeath: binder=%p recipient=%p\n", target, recipient);
 
     if (!target->localBinder()) {
-        sp<JavaDeathRecipient> jdr;
-
-        {
-            sp<DeathRecipientList> list;
-            AutoMutex _maplocker(gDeathRecipientMapLock);
-
-            ssize_t listIndex = gDeathRecipientsByIBinder.indexOfKey(target);
-            if (listIndex < 0) {
-                // Set up the death notice bookkeeping for this binder lazily
-                list = new DeathRecipientList;
-                gDeathRecipientsByIBinder.add(target, list);
-            } else {
-                list = gDeathRecipientsByIBinder.valueAt(listIndex);
-            }
-
-            jdr = new JavaDeathRecipient(env, recipient, list);
-        }
-
-        status_t err = target->linkToDeath(jdr, NULL, flags);
+        sp<JavaDeathRecipient> jdr = new JavaDeathRecipient(env, recipient);
+        status_t err = target->linkToDeath(jdr, recipient, flags);
         if (err != NO_ERROR) {
             // Failure adding the death recipient, so clear its reference
             // now.
@@ -1074,29 +1003,15 @@
     LOGV("unlinkToDeath: binder=%p recipient=%p\n", target, recipient);
 
     if (!target->localBinder()) {
-        status_t err = NAME_NOT_FOUND;
-        sp<JavaDeathRecipient> origJDR;
-        {
-            AutoMutex _maplocker(gDeathRecipientMapLock);
-            ssize_t listIndex = gDeathRecipientsByIBinder.indexOfKey(target);
-            if (listIndex >= 0) {
-                sp<DeathRecipientList> list = gDeathRecipientsByIBinder.valueAt(listIndex);
-                origJDR = list->find(recipient);
+        wp<IBinder::DeathRecipient> dr;
+        status_t err = target->unlinkToDeath(NULL, recipient, flags, &dr);
+        if (err == NO_ERROR && dr != NULL) {
+            sp<IBinder::DeathRecipient> sdr = dr.promote();
+            JavaDeathRecipient* jdr = static_cast<JavaDeathRecipient*>(sdr.get());
+            if (jdr != NULL) {
+                jdr->clearReference();
             }
         }
-        // If we found the matching recipient, proceed to unlink using that
-        if (origJDR != NULL) {
-            wp<IBinder::DeathRecipient> dr;
-            err = target->unlinkToDeath(origJDR, NULL, flags, &dr);
-            if (err == NO_ERROR && dr != NULL) {
-                sp<IBinder::DeathRecipient> sdr = dr.promote();
-                JavaDeathRecipient* jdr = static_cast<JavaDeathRecipient*>(sdr.get());
-                if (jdr != NULL) {
-                    jdr->clearReference();
-                }
-            }
-        }
-
         if (err == NO_ERROR || err == DEAD_OBJECT) {
             res = JNI_TRUE;
         } else {
@@ -1116,15 +1031,6 @@
     env->SetIntField(obj, gBinderProxyOffsets.mObject, 0);
     b->decStrong(obj);
     IPCThreadState::self()->flushCommands();
-
-    // tear down the death recipient bookkeeping
-    {
-        AutoMutex _maplocker(gDeathRecipientMapLock);
-        ssize_t listIndex = gDeathRecipientsByIBinder.indexOfKey(b);
-        if (listIndex >= 0) {
-            gDeathRecipientsByIBinder.removeItemsAt((size_t)listIndex);
-        }
-    }
 }
 
 // ----------------------------------------------------------------------------
diff --git a/include/binder/IBinder.h b/include/binder/IBinder.h
index 81b56c2..749a977 100644
--- a/include/binder/IBinder.h
+++ b/include/binder/IBinder.h
@@ -98,7 +98,7 @@
      * Register the @a recipient for a notification if this binder
      * goes away.  If this binder object unexpectedly goes away
      * (typically because its hosting process has been killed),
-     * then DeathRecipient::binderDied() will be called with a reference
+     * then DeathRecipient::binderDied() will be called with a referene
      * to this.
      *
      * The @a cookie is optional -- if non-NULL, it should be a
diff --git a/libs/rs/rsFont.cpp b/libs/rs/rsFont.cpp
index 8a5ab99..1c1bc98 100644
--- a/libs/rs/rsFont.cpp
+++ b/libs/rs/rsFont.cpp
@@ -20,6 +20,9 @@
 #include "rsFont.h"
 #include "rsProgramFragment.h"
 #include <cutils/properties.h>
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
 #include FT_BITMAP_H
 
 #include <GLES/gl.h>
@@ -208,7 +211,7 @@
             }
         }
 
-        penX += (cachedGlyph->mAdvance.x >> 6);
+        penX += (cachedGlyph->mAdvanceX >> 6);
 
         // If we were given a specific number of glyphs, decrement
         if (numGlyphs > 0) {
@@ -238,7 +241,8 @@
         return;
     }
 
-    glyph->mAdvance = mFace->glyph->advance;
+    glyph->mAdvanceX = mFace->glyph->advance.x;
+    glyph->mAdvanceY = mFace->glyph->advance.y;
     glyph->mBitmapLeft = mFace->glyph->bitmap_left;
     glyph->mBitmapTop = mFace->glyph->bitmap_top;
 
@@ -803,6 +807,22 @@
     }
 }
 
+bool FontState::CacheTextureLine::fitBitmap(FT_Bitmap_ *bitmap, uint32_t *retOriginX, uint32_t *retOriginY) {
+    if ((uint32_t)bitmap->rows > mMaxHeight) {
+        return false;
+    }
+
+    if (mCurrentCol + (uint32_t)bitmap->width < mMaxWidth) {
+        *retOriginX = mCurrentCol;
+        *retOriginY = mCurrentRow;
+        mCurrentCol += bitmap->width;
+        mDirty = true;
+       return true;
+    }
+
+    return false;
+}
+
 namespace android {
 namespace renderscript {
 
diff --git a/libs/rs/rsFont.h b/libs/rs/rsFont.h
index 4820999..91a5da9 100644
--- a/libs/rs/rsFont.h
+++ b/libs/rs/rsFont.h
@@ -23,8 +23,9 @@
 #include <utils/Vector.h>
 #include <utils/KeyedVector.h>
 
-#include <ft2build.h>
-#include FT_FREETYPE_H
+struct FT_LibraryRec_;
+struct FT_FaceRec_;
+struct FT_Bitmap_;
 
 // ---------------------------------------------------------------------------
 namespace android {
@@ -105,11 +106,12 @@
         float mBitmapMaxU;
         float mBitmapMaxV;
         // Minimize how much we call freetype
-        FT_UInt mGlyphIndex;
-        FT_Vector mAdvance;
+        int32_t mGlyphIndex;
+        int32_t mAdvanceX;
+        int32_t mAdvanceY;
         // Values below contain a glyph's origin in the bitmap
-        FT_Int mBitmapLeft;
-        FT_Int mBitmapTop;
+        int32_t mBitmapLeft;
+        int32_t mBitmapTop;
     };
 
     String8 mFontName;
@@ -120,7 +122,7 @@
     bool init(const char *name, float fontSize, uint32_t dpi, const void *data = NULL, uint32_t dataLen = 0);
 
     virtual void preDestroy() const;
-    FT_Face mFace;
+    FT_FaceRec_ *mFace;
     bool mInitialized;
     bool mHasKerning;
 
@@ -173,21 +175,7 @@
               mCurrentCol(currentCol), mDirty(false)  {
         }
 
-        bool fitBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY) {
-            if ((uint32_t)bitmap->rows > mMaxHeight) {
-                return false;
-            }
-
-            if (mCurrentCol + (uint32_t)bitmap->width < mMaxWidth) {
-                *retOriginX = mCurrentCol;
-                *retOriginY = mCurrentRow;
-                mCurrentCol += bitmap->width;
-                mDirty = true;
-               return true;
-            }
-
-            return false;
-        }
+        bool fitBitmap(FT_Bitmap_ *bitmap, uint32_t *retOriginX, uint32_t *retOriginY);
     };
 
     Vector<CacheTextureLine*> mCacheLines;
@@ -211,8 +199,8 @@
     float mWhiteThreshold;
 
     // Free type library, we only need one copy
-    FT_Library mLibrary;
-    FT_Library getLib();
+    FT_LibraryRec_ *mLibrary;
+    FT_LibraryRec_ *getLib();
     Vector<Font*> mActiveFonts;
 
     // Render state for the font
@@ -229,7 +217,7 @@
         return (uint8_t*)mTextTexture->getPtr();
     }
 
-    bool cacheBitmap(FT_Bitmap *bitmap, uint32_t *retOriginX, uint32_t *retOriginY);
+    bool cacheBitmap(FT_Bitmap_ *bitmap, uint32_t *retOriginX, uint32_t *retOriginY);
     const Type* getCacheTextureType() {
         return mTextTexture->getType();
     }
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index 445a4e4..e12926b 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -26,6 +26,8 @@
 #include <GLES/gl.h>
 #include <GLES/glext.h>
 
+#include <bcc/bcc.h>
+
 using namespace android;
 using namespace android::renderscript;
 
diff --git a/libs/rs/rsScriptC.h b/libs/rs/rsScriptC.h
index e794feb..2c74b5b 100644
--- a/libs/rs/rsScriptC.h
+++ b/libs/rs/rsScriptC.h
@@ -21,7 +21,7 @@
 
 #include "RenderScriptEnv.h"
 
-#include <bcc/bcc.h>
+struct BCCOpaqueScript;
 
 // ---------------------------------------------------------------------------
 namespace android {
@@ -50,7 +50,7 @@
 
     Program_t mProgram;
 
-    BCCScriptRef mBccScript;
+    BCCOpaqueScript *mBccScript;
 
     const Allocation *ptrToAllocation(const void *) const;
 
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index 550bb3d..afa8d69 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -22,7 +22,6 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -57,7 +56,6 @@
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
-import android.os.Handler;
 import android.os.IBinder;
 import android.os.Process;
 import android.os.RemoteException;
@@ -69,11 +67,13 @@
 import android.util.TypedValue;
 import android.util.Xml;
 import android.widget.RemoteViews;
+import android.widget.RemoteViewsService;
 
 import com.android.internal.appwidget.IAppWidgetHost;
 import com.android.internal.appwidget.IAppWidgetService;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.widget.IRemoteViewsAdapterConnection;
+import com.android.internal.widget.IRemoteViewsFactory;
 
 class AppWidgetService extends IAppWidgetService.Stub
 {
@@ -153,9 +153,12 @@
         }
     }
 
-    // Manages connections to RemoteViewsServices
+    // Manages active connections to RemoteViewsServices
     private final HashMap<Pair<Integer, FilterComparison>, ServiceConnection>
         mBoundRemoteViewsServices = new HashMap<Pair<Integer,FilterComparison>,ServiceConnection>();
+    // Manages persistent references to RemoteViewsServices from different App Widgets
+    private final HashMap<FilterComparison, HashSet<Integer>>
+        mRemoteViewsServicesAppWidgets = new HashMap<FilterComparison, HashSet<Integer>>();
 
     Context mContext;
     Locale mLocale;
@@ -429,6 +432,7 @@
         }
     }
 
+    // Binds to a specific RemoteViewsService
     public void bindRemoteViewsService(int appWidgetId, Intent intent, IBinder connection) {
         synchronized (mAppWidgetIds) {
             AppWidgetId id = lookupAppWidgetIdLocked(appWidgetId);
@@ -452,8 +456,8 @@
             // that first.  (This does not allow multiple connections to the same service under
             // the same key)
             ServiceConnectionProxy conn = null;
-            Pair<Integer, FilterComparison> key = Pair.create(appWidgetId,
-                    new FilterComparison(intent));
+            FilterComparison fc = new FilterComparison(intent);
+            Pair<Integer, FilterComparison> key = Pair.create(appWidgetId, fc);
             if (mBoundRemoteViewsServices.containsKey(key)) {
                 conn = (ServiceConnectionProxy) mBoundRemoteViewsServices.get(key);
                 conn.disconnect();
@@ -471,9 +475,15 @@
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
+
+            // Add it to the mapping of RemoteViewsService to appWidgetIds so that we can determine
+            // when we can call back to the RemoteViewsService later to destroy associated
+            // factories.
+            incrementAppWidgetServiceRefCount(appWidgetId, fc);
         }
     }
 
+    // Unbinds from a specific RemoteViewsService
     public void unbindRemoteViewsService(int appWidgetId, Intent intent) {
         synchronized (mAppWidgetIds) {
             // Unbind from the RemoteViewsService (which will trigger a callback to the bound
@@ -500,6 +510,7 @@
         }
     }
 
+    // Unbinds from a RemoteViewsService when we delete an app widget
     private void unbindAppWidgetRemoteViewsServicesLocked(AppWidgetId id) {
         int appWidgetId = id.appWidgetId;
         // Unbind all connections to Services bound to this AppWidgetId
@@ -515,6 +526,71 @@
                 it.remove();
             }
         }
+
+        // Check if we need to destroy any services (if no other app widgets are
+        // referencing the same service)
+        decrementAppWidgetServiceRefCount(appWidgetId);
+    }
+
+    // Destroys the cached factory on the RemoteViewsService's side related to the specified intent
+    private void destroyRemoteViewsService(final Intent intent) {
+        final ServiceConnection conn = new ServiceConnection() {
+            @Override
+            public void onServiceConnected(ComponentName name, IBinder service) {
+                final IRemoteViewsFactory cb =
+                    IRemoteViewsFactory.Stub.asInterface(service);
+                try {
+                    cb.onDestroy(intent);
+                } catch (RemoteException e) {
+                    e.printStackTrace();
+                }
+                mContext.unbindService(this);
+            }
+            @Override
+            public void onServiceDisconnected(android.content.ComponentName name) {
+                // Do nothing
+            }
+        };
+
+        // Bind to the service and remove the static intent->factory mapping in the
+        // RemoteViewsService.
+        final long token = Binder.clearCallingIdentity();
+        try {
+            mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    // Adds to the ref-count for a given RemoteViewsService intent
+    private void incrementAppWidgetServiceRefCount(int appWidgetId, FilterComparison fc) {
+        HashSet<Integer> appWidgetIds = null;
+        if (mRemoteViewsServicesAppWidgets.containsKey(fc)) {
+            appWidgetIds = mRemoteViewsServicesAppWidgets.get(fc);
+        } else {
+            appWidgetIds = new HashSet<Integer>();
+            mRemoteViewsServicesAppWidgets.put(fc, appWidgetIds);
+        }
+        appWidgetIds.add(appWidgetId);
+    }
+
+    // Subtracts from the ref-count for a given RemoteViewsService intent, prompting a delete if
+    // the ref-count reaches zero.
+    private void decrementAppWidgetServiceRefCount(int appWidgetId) {
+        Iterator<FilterComparison> it =
+            mRemoteViewsServicesAppWidgets.keySet().iterator();
+        while (it.hasNext()) {
+            final FilterComparison key = it.next();
+            final HashSet<Integer> ids = mRemoteViewsServicesAppWidgets.get(key);
+            if (ids.remove(appWidgetId)) {
+                // If we have removed the last app widget referencing this service, then we
+                // should destroy it and remove it from this set
+                if (ids.isEmpty()) {
+                    destroyRemoteViewsService(key.getIntent());
+                    it.remove();
+                }
+            }
+        }
     }
 
     public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) {
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 0fa97a3..c061a83 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -978,13 +978,11 @@
     }
 
     private void handleSetBackgroundData(boolean enabled) {
-        if (enabled != getBackgroundDataSetting()) {
-            Settings.Secure.putInt(mContext.getContentResolver(),
-                    Settings.Secure.BACKGROUND_DATA, enabled ? 1 : 0);
-            Intent broadcast = new Intent(
-                    ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
-            mContext.sendBroadcast(broadcast);
-        }
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                Settings.Secure.BACKGROUND_DATA, enabled ? 1 : 0);
+        Intent broadcast = new Intent(
+                ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
+        mContext.sendBroadcast(broadcast);
     }
 
     /**
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index 4decd1a..88fd678 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -1043,8 +1043,7 @@
 
     @LayoutlibDelegate
     /*package*/ static void native_drawText(int nativeCanvas, String text,
-                                               int start, int end, float x,
-                                               float y, int flags, int paint) {
+            int start, int end, float x, float y, int flags, int paint) {
         int count = end - start;
         char[] buffer = TemporaryBuffer.obtain(count);
         TextUtils.getChars(text, start, end, buffer, 0);
@@ -1060,7 +1059,7 @@
         char[] buffer = TemporaryBuffer.obtain(count);
         TextUtils.getChars(text, start, end, buffer, 0);
 
-        native_drawText(nativeCanvas, buffer, start, end, x, y, flags, paint);
+        native_drawText(nativeCanvas, buffer, 0, count, x, y, flags, paint);
     }
 
     @LayoutlibDelegate