Merge "Replace LruCache implementation for layoutlib."
diff --git a/core/java/android/text/MeasuredText.java b/core/java/android/text/MeasuredText.java
index 445aac63..bd9310c1 100644
--- a/core/java/android/text/MeasuredText.java
+++ b/core/java/android/text/MeasuredText.java
@@ -83,7 +83,7 @@
     }
 
     void setPos(int pos) {
-        mPos = pos;
+        mPos = pos - mTextStart;
     }
 
     /**
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 4de0b01..d0c393c 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -18,6 +18,7 @@
 
 import static android.view.accessibility.AccessibilityNodeInfo.INCLUDE_NOT_IMPORTANT_VIEWS;
 
+import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -64,6 +65,8 @@
 
     private final ArrayList<View> mTempArrayList = new ArrayList<View>();
 
+    private final Rect mTempRect = new Rect();
+
     public AccessibilityInteractionController(ViewRootImpl viewRootImpl) {
         Looper looper =  viewRootImpl.mHandler.getLooper();
         mMyLooperThreadId = looper.getThread().getId();
@@ -207,6 +210,7 @@
         } finally {
             try {
                 mViewRootImpl.mAttachInfo.mIncludeNotImportantViews = false;
+                applyApplicationScaleIfNeeded(infos);
                 callback.setFindAccessibilityNodeInfosResult(infos, interactionId);
                 infos.clear();
             } catch (RemoteException re) {
@@ -287,6 +291,7 @@
         } finally {
             try {
                 mViewRootImpl.mAttachInfo.mIncludeNotImportantViews = false;
+                applyApplicationScaleIfNeeded(info);
                 callback.setFindAccessibilityNodeInfoResult(info, interactionId);
             } catch (RemoteException re) {
                 /* ignore - the other side will time out */
@@ -396,6 +401,7 @@
         } finally {
             try {
                 mViewRootImpl.mAttachInfo.mIncludeNotImportantViews = false;
+                applyApplicationScaleIfNeeded(infos);
                 callback.setFindAccessibilityNodeInfosResult(infos, interactionId);
             } catch (RemoteException re) {
                 /* ignore - the other side will time out */
@@ -502,6 +508,7 @@
         } finally {
             try {
                 mViewRootImpl.mAttachInfo.mIncludeNotImportantViews = false;
+                applyApplicationScaleIfNeeded(focused);
                 callback.setFindAccessibilityNodeInfoResult(focused, interactionId);
             } catch (RemoteException re) {
                 /* ignore - the other side will time out */
@@ -582,6 +589,7 @@
         } finally {
             try {
                 mViewRootImpl.mAttachInfo.mIncludeNotImportantViews = false;
+                applyApplicationScaleIfNeeded(next);
                 callback.setFindAccessibilityNodeInfoResult(next, interactionId);
             } catch (RemoteException re) {
                 /* ignore - the other side will time out */
@@ -677,6 +685,39 @@
         return foundView;
     }
 
+    private void applyApplicationScaleIfNeeded(List<AccessibilityNodeInfo> infos) {
+        if (infos == null) {
+            return;
+        }
+        final float applicationScale = mViewRootImpl.mAttachInfo.mApplicationScale;
+        if (applicationScale != 1.0f) {
+            final int infoCount = infos.size();
+            for (int i = 0; i < infoCount; i++) {
+                AccessibilityNodeInfo info = infos.get(i);
+                applyApplicationScaleIfNeeded(info);
+            }
+        }
+    }
+
+    private void applyApplicationScaleIfNeeded(AccessibilityNodeInfo info) {
+        if (info == null) {
+            return;
+        }
+        final float applicationScale = mViewRootImpl.mAttachInfo.mApplicationScale;
+        if (applicationScale != 1.0f) {
+            Rect bounds = mTempRect;
+
+            info.getBoundsInParent(bounds);
+            bounds.scale(applicationScale);
+            info.setBoundsInParent(bounds);
+
+            info.getBoundsInScreen(bounds);
+            bounds.scale(applicationScale);
+            info.setBoundsInScreen(bounds);
+        }
+    }
+
+
     /**
      * This class encapsulates a prefetching strategy for the accessibility APIs for
      * querying window content. It is responsible to prefetch a batch of
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index c269ea3..7c2cbdf 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4697,14 +4697,11 @@
      */
     void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
         Rect bounds = mAttachInfo.mTmpInvalRect;
-        final float applicationScale = mAttachInfo.mApplicationScale;
 
         getDrawingRect(bounds);
-        bounds.scale(applicationScale);
         info.setBoundsInParent(bounds);
 
         getBoundsOnScreen(bounds);
-        bounds.scale(applicationScale);
         info.setBoundsInScreen(bounds);
 
         ViewParent parent = getParentForAccessibility();
@@ -5571,7 +5568,7 @@
         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
     })
     public int getResolvedLayoutDirection() {
-        // The layout diretion will be resolved only if needed
+        // The layout direction will be resolved only if needed
         if ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED) != LAYOUT_DIRECTION_RESOLVED) {
             resolveLayoutDirection();
         }
@@ -11099,9 +11096,13 @@
                     scrollBar.setParameters(computeVerticalScrollRange(),
                                             computeVerticalScrollOffset(),
                                             computeVerticalScrollExtent(), true);
-                    switch (mVerticalScrollbarPosition) {
+                    int verticalScrollbarPosition = mVerticalScrollbarPosition;
+                    if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
+                        verticalScrollbarPosition = isLayoutRtl() ?
+                                SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
+                    }
+                    switch (verticalScrollbarPosition) {
                         default:
-                        case SCROLLBAR_POSITION_DEFAULT:
                         case SCROLLBAR_POSITION_RIGHT:
                             left = scrollX + width - size - (mUserPaddingRight & inside);
                             break;
@@ -11272,15 +11273,18 @@
             // Set resolved depending on layout direction
             switch (getLayoutDirection()) {
                 case LAYOUT_DIRECTION_INHERIT:
-                    // If this is root view, no need to look at parent's layout dir.
-                    if (canResolveLayoutDirection()) {
-                        ViewGroup viewGroup = ((ViewGroup) mParent);
+                    // We cannot resolve yet. LTR is by default and let the resolution happen again
+                    // later to get the correct resolved value
+                    if (!canResolveLayoutDirection()) return;
 
-                        if (viewGroup.getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
-                            mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
-                        }
-                    } else {
-                        // Nothing to do, LTR by default
+                    ViewGroup viewGroup = ((ViewGroup) mParent);
+
+                    // We cannot resolve yet on the parent too. LTR is by default and let the
+                    // resolution happen again later
+                    if (!viewGroup.canResolveLayoutDirection()) return;
+
+                    if (viewGroup.getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
+                        mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
                     }
                     break;
                 case LAYOUT_DIRECTION_RTL:
@@ -14132,7 +14136,7 @@
                         ? 0 : getVerticalScrollbarWidth();
                 switch (mVerticalScrollbarPosition) {
                     case SCROLLBAR_POSITION_DEFAULT:
-                        if (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
+                        if (isLayoutRtl()) {
                             left += offset;
                         } else {
                             right += offset;
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index af5f474..4e6e2ce 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -5507,6 +5507,11 @@
          */
         static private final int DEFAULT_RELATIVE = Integer.MIN_VALUE;
 
+        private int initialLeftMargin;
+        private int initialRightMargin;
+
+        private int layoutDirection;
+
         /**
          * Creates a new set of layout parameters. The values are extracted from
          * the supplied attributes set and context.
@@ -5545,6 +5550,12 @@
                         R.styleable.ViewGroup_MarginLayout_layout_marginEnd, DEFAULT_RELATIVE);
             }
 
+            initialLeftMargin = leftMargin;
+            initialRightMargin = rightMargin;
+
+            // LTR by default
+            layoutDirection = View.LAYOUT_DIRECTION_LTR;
+
             a.recycle();
         }
 
@@ -5570,6 +5581,11 @@
             this.bottomMargin = source.bottomMargin;
             this.startMargin = source.startMargin;
             this.endMargin = source.endMargin;
+
+            this.initialLeftMargin = source.leftMargin;
+            this.initialRightMargin = source.rightMargin;
+
+            this.layoutDirection = source.layoutDirection;
         }
 
         /**
@@ -5599,6 +5615,8 @@
             topMargin = top;
             rightMargin = right;
             bottomMargin = bottom;
+            initialLeftMargin = left;
+            initialRightMargin = right;
         }
 
         /**
@@ -5624,6 +5642,8 @@
             topMargin = top;
             endMargin = end;
             bottomMargin = bottom;
+            initialLeftMargin = 0;
+            initialRightMargin = 0;
         }
 
         /**
@@ -5634,7 +5654,14 @@
          * @return the start margin in pixels.
          */
         public int getMarginStart() {
-            return startMargin;
+            if (startMargin != DEFAULT_RELATIVE) return startMargin;
+            switch(layoutDirection) {
+                case View.LAYOUT_DIRECTION_RTL:
+                    return rightMargin;
+                case View.LAYOUT_DIRECTION_LTR:
+                default:
+                    return leftMargin;
+            }
         }
 
         /**
@@ -5645,7 +5672,14 @@
          * @return the end margin in pixels.
          */
         public int getMarginEnd() {
-            return endMargin;
+            if (endMargin != DEFAULT_RELATIVE) return endMargin;
+            switch(layoutDirection) {
+                case View.LAYOUT_DIRECTION_RTL:
+                    return leftMargin;
+                case View.LAYOUT_DIRECTION_LTR:
+                default:
+                    return rightMargin;
+            }
         }
 
         /**
@@ -5666,15 +5700,19 @@
          */
         @Override
         public void onResolveLayoutDirection(int layoutDirection) {
+            this.layoutDirection = layoutDirection;
+
+            if (!isMarginRelative()) return;
+
             switch(layoutDirection) {
                 case View.LAYOUT_DIRECTION_RTL:
-                    leftMargin = (endMargin > DEFAULT_RELATIVE) ? endMargin : leftMargin;
-                    rightMargin = (startMargin > DEFAULT_RELATIVE) ? startMargin : rightMargin;
+                    leftMargin = (endMargin > DEFAULT_RELATIVE) ? endMargin : initialLeftMargin;
+                    rightMargin = (startMargin > DEFAULT_RELATIVE) ? startMargin : initialRightMargin;
                     break;
                 case View.LAYOUT_DIRECTION_LTR:
                 default:
-                    leftMargin = (startMargin > DEFAULT_RELATIVE) ? startMargin : leftMargin;
-                    rightMargin = (endMargin > DEFAULT_RELATIVE) ? endMargin : rightMargin;
+                    leftMargin = (startMargin > DEFAULT_RELATIVE) ? startMargin : initialLeftMargin;
+                    rightMargin = (endMargin > DEFAULT_RELATIVE) ? endMargin : initialRightMargin;
                     break;
             }
         }
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index 01c047b..e93db09 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -245,8 +245,8 @@
     }
 
    /**
-    * Tell the client that the quota has been reached for the Application Cache
-    * API and request a new quota. The client must respond by invoking the
+    * Notify the host application that the Application Cache has reached the
+    * maximum size. The client must respond by invoking the
     * {@link WebStorage.QuotaUpdater#updateQuota(long) updateQuota(long)}
     * method of the supplied {@link WebStorage.QuotaUpdater} instance. The
     * minimum value that can be set for the new quota is the current quota. The
@@ -255,7 +255,7 @@
     * @param requiredStorage The amount of storage required by the Application
     *                        Cache operation that triggered this notification,
     *                        in bytes.
-    * @param quota The quota, in bytes
+    * @param quota the current maximum Application Cache size, in bytes
     * @param quotaUpdater An instance of {@link WebStorage.QuotaUpdater} which
     *                     must be used to inform the WebView of the new quota.
     */
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index f2a041a..1a868d5 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -1005,8 +1005,11 @@
     }
 
     /**
-     * Sets the maximum size for the Application Caches content. The default is
-     * {@link Long#MAX_VALUE}.
+     * Sets the maximum size for the Application Cache content. The passed size
+     * will be rounded to the nearest value that the database can support, so
+     * this should be viewed as a guide, not a hard limit. Setting the
+     * size to a value less than current database size does not cause the
+     * database to be trimmed. The default size is {@link Long#MAX_VALUE}.
      *
      * @param appCacheMaxSize the maximum size in bytes
      */
diff --git a/core/java/android/webkit/WebStorage.java b/core/java/android/webkit/WebStorage.java
index 76674f4..1e955bd 100644
--- a/core/java/android/webkit/WebStorage.java
+++ b/core/java/android/webkit/WebStorage.java
@@ -23,17 +23,22 @@
  * {@link WebView}. It manages the Application Cache API, the Web SQL Database
  * API and the HTML5 Web Storage API.
  *
- * The Web SQL Database API provides storage which is private to a given
- * origin, where an origin comprises the host, scheme and port of a URI.
- * Similarly, use of the Application Cache API can be attributed to an origin.
- * This class provides access to the storage use and quotas for these APIs for
- * a given origin. Origins are represented using {@link WebStorage.Origin}.
+ * The Application Cache API provides a mechanism to create and maintain an
+ * application cache to power offline Web applications. Use of the Application
+ * Cache API can be attributed to an origin {@link WebStorage.Origin}, however
+ * it is not possible to set per-origin quotas. Note that there can be only
+ * one application cache per application.
+ *
+ * The Web SQL Database API provides storage which is private to a given origin.
+ * Similar to the Application Cache, use of the Web SQL Database can be attributed
+ * to an origin. It is also possible to set per-origin quotas.
  */
 public class WebStorage {
 
     /**
      * Encapsulates a callback function which is used to provide a new quota
-     * for a JavaScript storage API. See
+     * for a JavaScript storage API.
+     * See
      * {@link WebChromeClient#onExceededDatabaseQuota} and
      * {@link WebChromeClient#onReachedMaxAppCacheSize}.
      */
@@ -54,6 +59,7 @@
     /**
      * This class encapsulates information about the amount of storage
      * currently used by an origin for the JavaScript storage APIs.
+     * An origin comprises the host, scheme and port of a URI.
      * See {@link WebStorage} for details.
      */
     public static class Origin {
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 1875ced..40229af 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -443,7 +443,7 @@
     }
 
     /**
-     * Notify the browser that the origin has exceeded it's database quota.
+     * Notify the embedding application that the origin has exceeded it's database quota.
      * @param url The URL that caused the overflow.
      * @param databaseIdentifier The identifier of the database.
      * @param quota The current quota for the origin.
@@ -468,12 +468,15 @@
     }
 
     /**
-     * Notify the browser that the appcache has exceeded its max size.
+     * Notify the embedding application that the appcache has reached or exceeded its maximum
+     * allowed storage size.
+     *
      * @param requiredStorage is the amount of storage, in bytes, that would be
      * needed in order for the last appcache operation to succeed.
+     * @param maxSize maximum allowed Application Cache database size, in bytes.
      */
-    protected void reachedMaxAppCacheSize(long requiredStorage) {
-        mCallbackProxy.onReachedMaxAppCacheSize(requiredStorage, getUsedQuota(),
+    protected void reachedMaxAppCacheSize(long requiredStorage, long maxSize) {
+        mCallbackProxy.onReachedMaxAppCacheSize(requiredStorage, maxSize,
                 new WebStorage.QuotaUpdater() {
                     @Override
                     public void updateQuota(long newQuota) {
@@ -2117,8 +2120,8 @@
         return width;
     }
 
-    // Utility method for exceededDatabaseQuota and reachedMaxAppCacheSize
-    // callbacks. Computes the sum of database quota for all origins.
+    // Utility method for exceededDatabaseQuota callback. Computes the sum
+    // of WebSQL database quota for all origins.
     private long getUsedQuota() {
         WebStorageClassic webStorage = WebStorageClassic.getInstance();
         Collection<WebStorage.Origin> origins = webStorage.getOriginsSync();
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index 083a952..d2139af 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -181,10 +181,13 @@
     }
 
     public void setScrollbarPosition(int position) {
+        if (position == View.SCROLLBAR_POSITION_DEFAULT) {
+            position = mList.isLayoutRtl() ?
+                    View.SCROLLBAR_POSITION_LEFT : View.SCROLLBAR_POSITION_RIGHT;
+        }
         mPosition = position;
         switch (position) {
             default:
-            case View.SCROLLBAR_POSITION_DEFAULT:
             case View.SCROLLBAR_POSITION_RIGHT:
                 mOverlayDrawable = mOverlayDrawableRight;
                 break;
@@ -229,7 +232,6 @@
         final int viewWidth = mList.getWidth();
         // Bounds are always top right. Y coordinate get's translated during draw
         switch (mPosition) {
-            case View.SCROLLBAR_POSITION_DEFAULT:
             case View.SCROLLBAR_POSITION_RIGHT:
                 mThumbDrawable.setBounds(viewWidth - mThumbW, 0, viewWidth, mThumbH);
                 break;
@@ -327,7 +329,6 @@
             }
             int left = 0;
             switch (mPosition) {
-                case View.SCROLLBAR_POSITION_DEFAULT:
                 case View.SCROLLBAR_POSITION_RIGHT:
                     left = viewWidth - (mThumbW * alpha) / ScrollFade.ALPHA_MAX;
                     break;
@@ -360,7 +361,6 @@
                 int left = 0;
                 switch (mPosition) {
                     default:
-                    case View.SCROLLBAR_POSITION_DEFAULT:
                     case View.SCROLLBAR_POSITION_RIGHT:
                         left = Math.max(0,
                                 mThumbDrawable.getBounds().left - mThumbW - mOverlaySize);
@@ -410,7 +410,6 @@
         if (mThumbDrawable != null) {
             switch (mPosition) {
                 default:
-                case View.SCROLLBAR_POSITION_DEFAULT:
                 case View.SCROLLBAR_POSITION_RIGHT:
                     mThumbDrawable.setBounds(w - mThumbW, 0, w, mThumbH);
                     break;
@@ -820,7 +819,6 @@
         boolean inTrack = false;
         switch (mPosition) {
             default:
-            case View.SCROLLBAR_POSITION_DEFAULT:
             case View.SCROLLBAR_POSITION_RIGHT:
                 inTrack = x > mList.getWidth() - mThumbW;
                 break;
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index 2391898d..4e114d8 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -345,28 +345,42 @@
 
     void drawDividersHorizontal(Canvas canvas) {
         final int count = getVirtualChildCount();
+        final boolean isLayoutRtl = isLayoutRtl();
         for (int i = 0; i < count; i++) {
             final View child = getVirtualChildAt(i);
 
             if (child != null && child.getVisibility() != GONE) {
                 if (hasDividerBeforeChildAt(i)) {
                     final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-                    final int left = child.getLeft() - lp.leftMargin - mDividerWidth;
-                    drawVerticalDivider(canvas, left);
+                    final int position;
+                    if (isLayoutRtl) {
+                        position = child.getRight() + lp.rightMargin;
+                    } else {
+                        position = child.getLeft() - lp.leftMargin - mDividerWidth;
+                    }
+                    drawVerticalDivider(canvas, position);
                 }
             }
         }
 
         if (hasDividerBeforeChildAt(count)) {
             final View child = getVirtualChildAt(count - 1);
-            int right = 0;
+            int position;
             if (child == null) {
-                right = getWidth() - getPaddingRight() - mDividerWidth;
+                if (isLayoutRtl) {
+                    position = getPaddingLeft();
+                } else {
+                    position = getWidth() - getPaddingRight() - mDividerWidth;
+                }
             } else {
                 final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-                right = child.getRight() + lp.rightMargin;
+                if (isLayoutRtl) {
+                    position = child.getLeft() - lp.leftMargin - mDividerWidth;
+                } else {
+                    position = child.getRight() + lp.rightMargin;
+                }
             }
-            drawVerticalDivider(canvas, right);
+            drawVerticalDivider(canvas, position);
         }
     }
 
diff --git a/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java b/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java
index 4e60b75..421e247 100644
--- a/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java
+++ b/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java
@@ -214,8 +214,8 @@
                 mVibrationDuration);
         mFeedbackCount = a.getInt(R.styleable.GlowPadView_feedbackCount,
                 mFeedbackCount);
-        mHandleDrawable = new TargetDrawable(res,
-                a.peekValue(R.styleable.GlowPadView_handleDrawable).resourceId);
+        TypedValue handle = a.peekValue(R.styleable.GlowPadView_handleDrawable);
+        mHandleDrawable = new TargetDrawable(res, handle != null ? handle.resourceId : 0);
         mHandleDrawable.setState(TargetDrawable.STATE_INACTIVE);
         mOuterRing = new TargetDrawable(res,
                 getResourceId(a, R.styleable.GlowPadView_outerRingDrawable));
@@ -717,7 +717,7 @@
         startBackgroundAnimation(0, 0.0f);
         stopAndHideWaveAnimation();
         hideTargets(animate, false);
-        hideGlow(0, 0, 1.0f, null);
+        hideGlow(0, 0, 0.0f, null);
         Tweener.reset();
     }
 
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 416370e..69ef080 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -327,7 +327,18 @@
         const float sx = scaledWidth / float(decoded->width());
         const float sy = scaledHeight / float(decoded->height());
 
-        bitmap->setConfig(decoded->getConfig(), scaledWidth, scaledHeight);
+        SkBitmap::Config config = decoded->config();
+        switch (config) {
+            case SkBitmap::kNo_Config:
+            case SkBitmap::kIndex8_Config:
+            case SkBitmap::kRLE_Index8_Config:
+                config = SkBitmap::kARGB_8888_Config;
+                break;
+            default:
+                break;
+        }
+
+        bitmap->setConfig(config, scaledWidth, scaledHeight);
         bitmap->setIsOpaque(decoded->isOpaque());
         bitmap->allocPixels(&javaAllocator, NULL);
         bitmap->eraseColor(0);
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_down.png b/core/res/res/drawable-hdpi/ic_lockscreen_chevron_down.png
deleted file mode 100644
index bc718b5..0000000
--- a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_down.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_left.png b/core/res/res/drawable-hdpi/ic_lockscreen_chevron_left.png
deleted file mode 100644
index 0892c31..0000000
--- a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_left.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_right.png b/core/res/res/drawable-hdpi/ic_lockscreen_chevron_right.png
deleted file mode 100644
index 04cc0a2..0000000
--- a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_right.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_up.png b/core/res/res/drawable-hdpi/ic_lockscreen_chevron_up.png
deleted file mode 100644
index bb553b1..0000000
--- a/core/res/res/drawable-hdpi/ic_lockscreen_chevron_up.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_down.png b/core/res/res/drawable-mdpi/ic_lockscreen_chevron_down.png
deleted file mode 100644
index 308fe8a..0000000
--- a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_down.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_left.png b/core/res/res/drawable-mdpi/ic_lockscreen_chevron_left.png
deleted file mode 100644
index 9a25634..0000000
--- a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_left.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_right.png b/core/res/res/drawable-mdpi/ic_lockscreen_chevron_right.png
deleted file mode 100644
index 77240d0..0000000
--- a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_right.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_up.png b/core/res/res/drawable-mdpi/ic_lockscreen_chevron_up.png
deleted file mode 100644
index e0b0134..0000000
--- a/core/res/res/drawable-mdpi/ic_lockscreen_chevron_up.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_down.png b/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_down.png
deleted file mode 100644
index b8e5733..0000000
--- a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_down.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_left.png b/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_left.png
deleted file mode 100644
index ce5da43..0000000
--- a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_left.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_right.png b/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_right.png
deleted file mode 100644
index c16f143..0000000
--- a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_right.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_up.png b/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_up.png
deleted file mode 100644
index 9bed39a..0000000
--- a/core/res/res/drawable-xhdpi/ic_lockscreen_chevron_up.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 8ba9573..31bda10 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -324,7 +324,7 @@
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"menggunakan media pengawasandi apa pun untuk pemutaran"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Mengizinkan apl menggunakan pengawasandi media apa pun yang terpasang guna mengawasandikan media untuk diputar."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"baca/tulis ke sumber daya yang dimiliki oleh diag"</string>
-    <string name="permdesc_diagnostic" msgid="6608295692002452283">"Mengizinkan apl membaca dan menulis ke sumber daya apa pun yang dimiliki oleh grup diag; misalnya, file dalam /dev. Izin ini berpotensi memengaruhi kestabilan dan keamanan sistem. Sebaiknya ini HANYA digunakan untuk diagnostik khusus perangkat keras oleh pabrikan atau operator."</string>
+    <string name="permdesc_diagnostic" msgid="6608295692002452283">"Mengizinkan apl membaca dan menulis ke sumber daya apa pun yang dimiliki oleh grup diag; misalnya, file dalam /dev. Izin ini berpotensi memengaruhi kestabilan dan keamanan sistem. Sebaiknya ini HANYA digunakan untuk diagnosis khusus perangkat keras oleh pabrikan atau operator."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"mengaktifkan atau menonaktifkan komponen apl"</string>
     <string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"Mengizinkan apl mengubah apakah komponen apl lain diaktifkan atau tidak. Apl berbahaya dapat menggunakan ini untuk menonaktifkan kemampuan tablet yang penting. Izin ini harus digunakan dengan hati-hati karena dapat menjadikan komponen apl tidak dapat digunakan, tidak konsisten, atau tidak stabil."</string>
     <string name="permdesc_changeComponentState" product="default" msgid="1827232484416505615">"Mengizinkan apl mengubah apakah komponen apl lain diaktifkan atau tidak. Apl berbahaya dapat menggunakan izin ini untuk menonaktifkan kemampuan ponsel yang penting. Izin ini harus digunakan dengan hati-hati, karena mungkin saja menjadikan komponen apl tidak dapat digunakan, tidak konsisten, atau tidak stabil."</string>
diff --git a/core/res/res/values-land/arrays.xml b/core/res/res/values-land/arrays.xml
index 6db3a508..1cd9e74 100644
--- a/core/res/res/values-land/arrays.xml
+++ b/core/res/res/values-land/arrays.xml
@@ -69,11 +69,4 @@
         <item>@string/description_target_camera</item>
     </array>
 
-    <array name="lockscreen_chevron_drawables">
-        <item>@null</item>
-        <item>@drawable/ic_lockscreen_chevron_up</item>
-        <item>@null</item>
-        <item>@null</item>
-    </array>
-
 </resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index bbb0681..7b1ee78 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -187,7 +187,7 @@
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Hifadhi"</string>
     <string name="permgroupdesc_storage" product="nosdcard" msgid="7442318502446874999">"Fikia hifadhi ya USB."</string>
     <string name="permgroupdesc_storage" product="default" msgid="9203302214915355774">"Fikia kadi ya SD."</string>
-    <string name="permlab_statusBar" msgid="7417192629601890791">"lemaza au rekebisha mwambaa hali"</string>
+    <string name="permlab_statusBar" msgid="7417192629601890791">"zima au rekebisha mwambaa hali"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Inaruhusu programu kulemaza upau wa hali au kuongeza na kutoa ikoni za mfumo."</string>
     <string name="permlab_statusBarService" msgid="7247281911387931485">"mwamba hali"</string>
     <string name="permdesc_statusBarService" msgid="716113660795976060">"Inaruhusu programu kuwa upau wa hali."</string>
@@ -391,7 +391,7 @@
     <string name="permdesc_recordAudio" msgid="4906839301087980680">"Inaruhusu programu kurekodi sauti kwa kinasa sauti. Idhini hii inaruhusu programu kurekodi sauti wakati wowote bila ya uthibitisho wako."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"chukua picha na video"</string>
     <string name="permdesc_camera" msgid="8497216524735535009">"Inaruhusu programu kupiga picha na video kwa kamera. Kibali hiki kinaruhusu programu kutumia kamera kwa wakati wowote bila uthibitisho wako."</string>
-    <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"lemaza kompyuta ndogo kabisa"</string>
+    <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"zima kompyuta ndogo kabisa"</string>
     <string name="permlab_brick" product="default" msgid="8337817093326370537">"simu iliyolemazwa kabisa"</string>
     <string name="permdesc_brick" product="tablet" msgid="4334818808001699530">"Inaruhusu programu kulemaza kompyuta yote kibao kabisa. Hii ni hatari sana."</string>
     <string name="permdesc_brick" product="default" msgid="5788903297627283099">"Inaruhusu programu kulemaza simu yote kabisa. Hii ni hatari sana."</string>
@@ -508,7 +508,7 @@
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Inaruhusu programu kuona usanidi wa Bluetooth kwenye simu, na kuunda na kukubali miunganisho kwa vifaa vilivyooanishwa."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"dhibiti Mawasiliano Karibu na Uga"</string>
     <string name="permdesc_nfc" msgid="7120611819401789907">"Inaruhusu programu kuwasiliana na lebo, kadi na wasomaji wa Near Field Communication (NFC)."</string>
-    <string name="permlab_disableKeyguard" msgid="3598496301486439258">"lemaza kufuli la skrini yako"</string>
+    <string name="permlab_disableKeyguard" msgid="3598496301486439258">"zima kufuli la skrini yako"</string>
     <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Inaruhusu programu kulemaza ufunguo wa vitufe na usalama mwingine ambata wa nenosiri. Kwa mfano, simu inalemaza ufunguo wa viitufe inapopokea simu inayoingia, kisha inawezesha upya ufunguo wa vitufe wakati simu inapokamilika."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"soma mipangilio ya usawazishaji"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Inaruhusu programu kusoma mipangilio ya upatanishi wa akaunti. Kwa mfano, huku kunaweza kuamua kama programu ya Watu imepatanishwa na akaunti."</string>
diff --git a/core/res/res/values-sw720dp-land/arrays.xml b/core/res/res/values-sw720dp-land/arrays.xml
deleted file mode 100644
index d845875..0000000
--- a/core/res/res/values-sw720dp-land/arrays.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* //device/apps/common/assets/res/any/colors.xml
-**
-** Copyright 2012, 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.
-*/
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <array name="lockscreen_chevron_drawables">
-        <item>@drawable/ic_lockscreen_chevron_right</item>
-        <item>@null</item>
-        <item>@null</item>
-        <item>@null</item>
-    </array>
-
-</resources>
diff --git a/core/res/res/values-sw720dp-port/arrays.xml b/core/res/res/values-sw720dp-port/arrays.xml
deleted file mode 100644
index d845875..0000000
--- a/core/res/res/values-sw720dp-port/arrays.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* //device/apps/common/assets/res/any/colors.xml
-**
-** Copyright 2012, 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.
-*/
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <array name="lockscreen_chevron_drawables">
-        <item>@drawable/ic_lockscreen_chevron_right</item>
-        <item>@null</item>
-        <item>@null</item>
-        <item>@null</item>
-    </array>
-
-</resources>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index b425ad7..8615476 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -242,8 +242,6 @@
        <item>@drawable/list_divider_holo_dark</item>
        <item>@drawable/list_divider_holo_light</item>
        <item>@drawable/list_divider_holo_light</item>
-       <item>@drawable/ic_lockscreen_chevron_left</item>
-       <item>@drawable/ic_lockscreen_chevron_right</item>
        <item>@drawable/ab_transparent_dark_holo</item>
        <item>@drawable/ab_stacked_transparent_dark_holo</item>
        <item>@drawable/ab_bottom_transparent_dark_holo</item>
@@ -400,11 +398,4 @@
         <item>@null</item>
     </array>
 
-    <array name="lockscreen_chevron_drawables">
-        <item>@drawable/ic_lockscreen_chevron_right</item>
-        <item>@null</item>
-        <item>@null</item>
-        <item>@null</item>
-    </array>
-
 </resources>
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 2e153dd..6f85bf8 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -143,11 +143,12 @@
     private static final int MSG_REEVALUATE_REMOTE = 17;
     private static final int MSG_RCC_NEW_PLAYBACK_INFO = 18;
     private static final int MSG_RCC_NEW_VOLUME_OBS = 19;
+    private static final int MSG_SET_FORCE_BT_A2DP_USE = 20;
     // start of messages handled under wakelock
     //   these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
     //   and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
-    private static final int MSG_SET_WIRED_DEVICE_CONNECTION_STATE = 20;
-    private static final int MSG_SET_A2DP_CONNECTION_STATE = 21;
+    private static final int MSG_SET_WIRED_DEVICE_CONNECTION_STATE = 21;
+    private static final int MSG_SET_A2DP_CONNECTION_STATE = 22;
     // end of messages handled under wakelock
 
     // flags for MSG_PERSIST_VOLUME indicating if current and/or last audible volume should be
@@ -1701,7 +1702,13 @@
 
     /** @see AudioManager#setBluetoothA2dpOn() */
     public void setBluetoothA2dpOn(boolean on) {
-        setBluetoothA2dpOnInt(on);
+        synchronized (mBluetoothA2dpEnabledLock) {
+            mBluetoothA2dpEnabled = on;
+            sendMsg(mAudioHandler, MSG_SET_FORCE_BT_A2DP_USE, SENDMSG_QUEUE,
+                    AudioSystem.FOR_MEDIA,
+                    mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP,
+                    null, 0);
+        }
     }
 
     /** @see AudioManager#isBluetoothA2dpOn() */
@@ -3049,6 +3056,7 @@
                     break;
 
                 case MSG_SET_FORCE_USE:
+                case MSG_SET_FORCE_BT_A2DP_USE:
                     setForceUse(msg.arg1, msg.arg2);
                     break;
 
@@ -5290,10 +5298,9 @@
     public void setBluetoothA2dpOnInt(boolean on) {
         synchronized (mBluetoothA2dpEnabledLock) {
             mBluetoothA2dpEnabled = on;
-            sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE,
-                    AudioSystem.FOR_MEDIA,
-                    mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP,
-                    null, 0);
+            mAudioHandler.removeMessages(MSG_SET_FORCE_BT_A2DP_USE);
+            AudioSystem.setForceUse(AudioSystem.FOR_MEDIA,
+                    mBluetoothA2dpEnabled ? AudioSystem.FORCE_NONE : AudioSystem.FORCE_NO_BT_A2DP);
         }
     }
 
diff --git a/packages/SystemUI/res/drawable/navbar_search_handle.xml b/packages/SystemUI/res/drawable/navbar_search_handle.xml
deleted file mode 100644
index e40fa2c..0000000
--- a/packages/SystemUI/res/drawable/navbar_search_handle.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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.
--->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <item
-        android:state_enabled="true"
-        android:state_active="false"
-        android:state_focused="false"
-        android:drawable="@*android:drawable/ic_lockscreen_handle_pressed" />
-
-    <item
-        android:state_enabled="true"
-        android:state_active="true"
-        android:state_focused="false"
-        android:drawable="@*android:drawable/ic_lockscreen_handle_pressed" />
-
-</selector>
diff --git a/packages/SystemUI/res/layout-land/status_bar_search_panel.xml b/packages/SystemUI/res/layout-land/status_bar_search_panel.xml
index c8a120d4..f56b03b 100644
--- a/packages/SystemUI/res/layout-land/status_bar_search_panel.xml
+++ b/packages/SystemUI/res/layout-land/status_bar_search_panel.xml
@@ -49,7 +49,6 @@
                 prvandroid:targetDrawables="@array/navbar_search_targets"
                 prvandroid:targetDescriptions="@array/navbar_search_target_descriptions"
                 prvandroid:directionDescriptions="@array/navbar_search_direction_descriptions"
-                prvandroid:handleDrawable="@drawable/navbar_search_handle"
                 prvandroid:outerRingDrawable="@drawable/navbar_search_outerring"
                 prvandroid:outerRadius="@dimen/navbar_search_outerring_radius"
                 prvandroid:innerRadius="@*android:dimen/glowpadview_inner_radius"
diff --git a/packages/SystemUI/res/layout-port/status_bar_search_panel.xml b/packages/SystemUI/res/layout-port/status_bar_search_panel.xml
index 1e4bb57..b871bef 100644
--- a/packages/SystemUI/res/layout-port/status_bar_search_panel.xml
+++ b/packages/SystemUI/res/layout-port/status_bar_search_panel.xml
@@ -49,7 +49,6 @@
                 prvandroid:targetDrawables="@array/navbar_search_targets"
                 prvandroid:targetDescriptions="@array/navbar_search_target_descriptions"
                 prvandroid:directionDescriptions="@array/navbar_search_direction_descriptions"
-                prvandroid:handleDrawable="@drawable/navbar_search_handle"
                 prvandroid:outerRingDrawable="@drawable/navbar_search_outerring"
                 prvandroid:outerRadius="@dimen/navbar_search_outerring_radius"
                 prvandroid:innerRadius="@*android:dimen/glowpadview_inner_radius"
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_search_panel.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_search_panel.xml
index 3b6c52e..1fa67bd 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar_search_panel.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_search_panel.xml
@@ -35,7 +35,6 @@
         prvandroid:targetDrawables="@array/navbar_search_targets"
         prvandroid:targetDescriptions="@array/navbar_search_target_descriptions"
         prvandroid:directionDescriptions="@array/navbar_search_direction_descriptions"
-        prvandroid:handleDrawable="@drawable/navbar_search_handle"
         prvandroid:outerRingDrawable="@drawable/navbar_search_outerring"
         prvandroid:outerRadius="@dimen/navbar_search_outerring_radius"
         prvandroid:innerRadius="@*android:dimen/glowpadview_inner_radius"
diff --git a/packages/SystemUI/res/layout-sw720dp/status_bar_search_panel.xml b/packages/SystemUI/res/layout-sw720dp/status_bar_search_panel.xml
index 8c2360e..b5f1f90 100644
--- a/packages/SystemUI/res/layout-sw720dp/status_bar_search_panel.xml
+++ b/packages/SystemUI/res/layout-sw720dp/status_bar_search_panel.xml
@@ -36,7 +36,6 @@
         prvandroid:targetDrawables="@array/navbar_search_targets"
         prvandroid:targetDescriptions="@array/navbar_search_target_descriptions"
         prvandroid:directionDescriptions="@array/navbar_search_direction_descriptions"
-        prvandroid:handleDrawable="@drawable/navbar_search_handle"
         prvandroid:outerRingDrawable="@drawable/navbar_search_outerring"
         prvandroid:outerRadius="@dimen/navbar_search_outerring_radius"
         prvandroid:innerRadius="@*android:dimen/glowpadview_inner_radius"
diff --git a/packages/VpnDialogs/res/values-in/strings.xml b/packages/VpnDialogs/res/values-in/strings.xml
index c9710e5..2848f83 100644
--- a/packages/VpnDialogs/res/values-in/strings.xml
+++ b/packages/VpnDialogs/res/values-in/strings.xml
@@ -17,7 +17,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="prompt" msgid="8359175999006833462">"<xliff:g id="APP">%s</xliff:g> mencoba membuat sambungan VPN."</string>
-    <string name="warning" msgid="5470743576660160079">"Dengan melanjutkan, Anda memberikan izin kepada aplikasi untuk mencegat semua lalu lintas jaringan. "<b>"JANGAN memberi izin kecuali Anda mempercayai aplikasi ini."</b>" Jika tidak, data Anda berisiko disusupi oleh perangkat lunak jahat."</string>
+    <string name="warning" msgid="5470743576660160079">"Dengan melanjutkan, Anda memberikan izin kepada aplikasi untuk mencegat semua lalu lintas jaringan. "<b>"JANGAN memberi izin kecuali Anda mempercayai aplikasi ini."</b>" Jika tidak, data Anda berisiko disusupi oleh perangkat lunak perusak."</string>
     <string name="accept" msgid="2889226408765810173">"Saya mempercayai aplikasi ini."</string>
     <string name="legacy_title" msgid="192936250066580964">"VPN tersambung"</string>
     <string name="configure" msgid="4905518375574791375">"Konfigurasikan"</string>
diff --git a/services/java/com/android/server/AppWidgetServiceImpl.java b/services/java/com/android/server/AppWidgetServiceImpl.java
index 4d6c058..7725f35 100644
--- a/services/java/com/android/server/AppWidgetServiceImpl.java
+++ b/services/java/com/android/server/AppWidgetServiceImpl.java
@@ -210,11 +210,19 @@
 
             synchronized (mAppWidgetIds) {
                 ensureStateLoadedLocked();
-                int N = mInstalledProviders.size();
+                // Note: updateProvidersForPackageLocked() may remove providers, so we must copy the
+                // list of installed providers and skip providers that we don't need to update.
+                // Also note that remove the provider does not clear the Provider component data.
+                ArrayList<Provider> installedProviders =
+                        new ArrayList<Provider>(mInstalledProviders);
+                HashSet<ComponentName> removedProviders = new HashSet<ComponentName>();
+                int N = installedProviders.size();
                 for (int i = N - 1; i >= 0; i--) {
-                    Provider p = mInstalledProviders.get(i);
-                    String pkgName = p.info.provider.getPackageName();
-                    updateProvidersForPackageLocked(pkgName);
+                    Provider p = installedProviders.get(i);
+                    ComponentName cn = p.info.provider;
+                    if (!removedProviders.contains(cn)) {
+                        updateProvidersForPackageLocked(cn.getPackageName(), removedProviders);
+                    }
                 }
                 saveStateLocked();
             }
@@ -257,7 +265,7 @@
                         || (extras != null && extras.getBoolean(Intent.EXTRA_REPLACING, false))) {
                     for (String pkgName : pkgList) {
                         // The package was just upgraded
-                        providersModified |= updateProvidersForPackageLocked(pkgName);
+                        providersModified |= updateProvidersForPackageLocked(pkgName, null);
                     }
                 } else {
                     // The package was just added
@@ -1677,7 +1685,13 @@
         return providersAdded;
     }
 
-    boolean updateProvidersForPackageLocked(String pkgName) {
+    /**
+     * Updates all providers with the specified package names, and records any providers that were
+     * pruned.
+     *
+     * @return whether any providers were updated
+     */
+    boolean updateProvidersForPackageLocked(String pkgName, Set<ComponentName> removedProviders) {
         boolean providersUpdated = false;
         HashSet<String> keep = new HashSet<String>();
         Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
@@ -1754,6 +1768,9 @@
             Provider p = mInstalledProviders.get(i);
             if (pkgName.equals(p.info.provider.getPackageName())
                     && !keep.contains(p.info.provider.getClassName())) {
+                if (removedProviders != null) {
+                    removedProviders.add(p.info.provider);
+                }
                 removeProviderLocked(i, p);
                 providersUpdated = true;
             }