Merge "Remove hardcoded typeface pointers"
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 3e0942c..3b26af7 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -98,6 +98,7 @@
     private static final int MSG_WALLPAPER_OFFSETS = 10020;
     private static final int MSG_WALLPAPER_COMMAND = 10025;
     private static final int MSG_WINDOW_RESIZED = 10030;
+    private static final int MSG_WINDOW_MOVED = 10035;
     private static final int MSG_TOUCH_EVENT = 10040;
     
     private Looper mCallbackLooper;
@@ -259,7 +260,13 @@
                         reportDraw ? 1 : 0);
                 mCaller.sendMessage(msg);
             }
-            
+
+            @Override
+            public void moved(int newX, int newY) {
+                Message msg = mCaller.obtainMessageII(MSG_WINDOW_MOVED, newX, newY);
+                mCaller.sendMessage(msg);
+            }
+
             @Override
             public void dispatchAppVisibility(boolean visible) {
                 // We don't do this in preview mode; we'll let the preview
@@ -290,7 +297,8 @@
                     }
                 }
             }
-            
+
+            @Override
             public void dispatchWallpaperCommand(String action, int x, int y,
                     int z, Bundle extras, boolean sync) {
                 synchronized (mLock) {
@@ -1044,6 +1052,9 @@
                     mEngine.updateSurface(true, false, reportDraw);
                     mEngine.doOffsetsChanged(true);
                 } break;
+                case MSG_WINDOW_MOVED: {
+                    // Do nothing. What does it mean for a Wallpaper to move?
+                } break;
                 case MSG_TOUCH_EVENT: {
                     boolean skip = false;
                     MotionEvent ev = (MotionEvent)message.obj;
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index b4caad3..9f22870 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -47,6 +47,7 @@
 
     void resized(int w, int h, in Rect contentInsets,
             in Rect visibleInsets, boolean reportDraw, in Configuration newConfig);
+    void moved(int newX, int newY);
     void dispatchAppVisibility(boolean visible);
     void dispatchGetNewSurface();
     void dispatchScreenState(boolean on);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ecccbd1..149470a 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4766,9 +4766,9 @@
      * @hide
      */
     public int getActualAndReportedWindowLeftDelta() {
-        if (mAttachInfo != null) {
-            return mAttachInfo.mActualWindowLeft - mAttachInfo.mWindowLeft; 
-        }
+//        if (mAttachInfo != null) {
+//            return mAttachInfo.mActualWindowLeft - mAttachInfo.mWindowLeft; 
+//        }
         return 0;
     }
 
@@ -4778,9 +4778,9 @@
      * @hide
      */
     public int getActualAndReportedWindowTopDelta() {
-        if (mAttachInfo != null) {
-            return mAttachInfo.mActualWindowTop - mAttachInfo.mWindowTop;
-        }
+//        if (mAttachInfo != null) {
+//            return mAttachInfo.mActualWindowTop - mAttachInfo.mWindowTop;
+//        }
         return 0;
     }
 
@@ -5568,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();
         }
@@ -11096,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;
@@ -11269,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:
@@ -14129,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/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 9798877..85b6d3d 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2717,6 +2717,7 @@
     private final static int MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST = 22;
     private final static int MSG_DISPATCH_DONE_ANIMATING = 23;
     private final static int MSG_INVALIDATE_WORLD = 24;
+    private final static int MSG_WINDOW_MOVED = 25;
 
     final class ViewRootHandler extends Handler {
         @Override
@@ -2768,6 +2769,8 @@
                     return "MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST";
                 case MSG_DISPATCH_DONE_ANIMATING:
                     return "MSG_DISPATCH_DONE_ANIMATING";
+                case MSG_WINDOW_MOVED:
+                    return "MSG_WINDOW_MOVED";
             }
             return super.getMessageName(message);
         }
@@ -2812,6 +2815,7 @@
                     if (config != null) {
                         updateConfiguration(config, false);
                     }
+                    // TODO: Should left/top stay unchanged and only change the right/bottom?
                     mWinFrame.left = 0;
                     mWinFrame.right = msg.arg1;
                     mWinFrame.top = 0;
@@ -2828,6 +2832,23 @@
                     requestLayout();
                 }
                 break;
+            case MSG_WINDOW_MOVED:
+                if (mAdded) {
+                    final int w = mWinFrame.width();
+                    final int h = mWinFrame.height();
+                    final int l = msg.arg1;
+                    final int t = msg.arg2;
+                    mWinFrame.left = l;
+                    mWinFrame.right = l + w;
+                    mWinFrame.top = t;
+                    mWinFrame.bottom = t + h;
+
+                    if (mView != null) {
+                        forceLayout(mView);
+                    }
+                    requestLayout();
+                }
+                break;
             case MSG_WINDOW_FOCUS_CHANGED: {
                 if (mAdded) {
                     boolean hasWindowFocus = msg.arg1 != 0;
@@ -4047,6 +4068,18 @@
         mHandler.sendMessage(msg);
     }
 
+    public void dispatchMoved(int newX, int newY) {
+        if (DEBUG_LAYOUT) Log.v(TAG, "Window moved " + this + ": newX=" + newX + " newY=" + newY);
+        if (mTranslator != null) {
+            PointF point = new PointF(newX, newY);
+            mTranslator.translatePointInScreenToAppWindow(point);
+            newX = (int) (point.x + 0.5);
+            newY = (int) (point.y + 0.5);
+        }
+        Message msg = mHandler.obtainMessage(MSG_WINDOW_MOVED, newX, newY);
+        mHandler.sendMessage(msg);
+    }
+
     /**
      * Represents a pending input event that is waiting in a queue.
      *
@@ -4686,6 +4719,14 @@
             }
         }
 
+        @Override
+        public void moved(int newX, int newY) {
+            final ViewRootImpl viewAncestor = mViewAncestor.get();
+            if (viewAncestor != null) {
+                viewAncestor.dispatchMoved(newX, newY);
+            }
+        }
+
         public void dispatchAppVisibility(boolean visible) {
             final ViewRootImpl viewAncestor = mViewAncestor.get();
             if (viewAncestor != null) {
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/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index 4c34d73..ac1d594 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -28,11 +28,12 @@
 public class BaseIWindow extends IWindow.Stub {
     private IWindowSession mSession;
     public int mSeq;
-    
+
     public void setSession(IWindowSession session) {
         mSession = session;
     }
-    
+
+    @Override
     public void resized(int w, int h, Rect contentInsets,
             Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
         if (reportDraw) {
@@ -43,24 +44,35 @@
         }
     }
 
+    @Override
+    public void moved(int newX, int newY) {
+    }
+
+    @Override
     public void dispatchAppVisibility(boolean visible) {
     }
 
+    @Override
     public void dispatchGetNewSurface() {
     }
 
+    @Override
     public void dispatchScreenState(boolean on) {
     }
 
+    @Override
     public void windowFocusChanged(boolean hasFocus, boolean touchEnabled) {
     }
 
+    @Override
     public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {
     }
-    
+
+    @Override
     public void closeSystemDialogs(String reason) {
     }
-    
+
+    @Override
     public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep, boolean sync) {
         if (sync) {
             try {
@@ -70,14 +82,17 @@
         }
     }
 
+    @Override
     public void dispatchDragEvent(DragEvent event) {
     }
 
+    @Override
     public void dispatchSystemUiVisibilityChanged(int seq, int globalUi,
             int localValue, int localChanges) {
         mSeq = seq;
     }
 
+    @Override
     public void dispatchWallpaperCommand(String action, int x, int y,
             int z, Bundle extras, boolean sync) {
         if (sync) {
@@ -88,6 +103,7 @@
         }
     }
 
+    @Override
     public void doneAnimating() {
     }
 }
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/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-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/docs/html/guide/google/gcm/c2dm.jd b/docs/html/guide/google/gcm/c2dm.jd
index 91c6ac5..ecc08c1 100644
--- a/docs/html/guide/google/gcm/c2dm.jd
+++ b/docs/html/guide/google/gcm/c2dm.jd
@@ -17,7 +17,11 @@
 
 <ol>
 <li><a href="#history">Historical Overview</a></li>
-<li><a href="#diffs">How is GCM Different from C2DM?</a></li>
+<li><a href="#diffs">How is GCM Different from C2DM?</a>
+  <ol>
+    <li><a href="#interop">Relationship between C2DM and GCM</a></li>
+  </ol>
+</li>
 <li><a href="#migrating">Migrating Your Apps</a>
   <ol>
     <li><a href="#client">Client changes</a></li>
@@ -72,6 +76,14 @@
 <dd>There may be situations where the server ends up with 2 registration IDs for the same device. If the GCM response contains a registration ID, simply replace the registration ID you have with the one provided. With this feature your application doesn't need to send the device ID to your server anymore. For more information, see <a href="adv.html#canonical">Advanced Topics</a>.</dd>
 </dl>
 <p>GCM also provides helper libraries (<a href="{@docRoot}guide/google/gcm/client-javadoc/index.html">client</a> and <a href="{@docRoot}guide/google/gcm/server-javadoc/index.html">server</a>) to make writing your code easier.</p>
+
+<h3 id="interop">Relationship between C2DM and GCM</h3>
+
+<p>C2DM and GCM are not interoperable. For example, you cannot post notifications from GCM to C2DM registration IDs, nor can you use C2DM registration IDs as GCM registration IDs. From your server-side application, you must keep keep track of whether a registration ID is from C2DM or GCM and use the proper endpoint. </p>
+
+<p>As you transition from C2DM to GCM, your server needs to be aware of whether a given registration ID
+contains an old C2DM sender or a new GCM project ID. This is the approach we recommend: have the new app version (the one that uses GCM) send a bit along with the registration ID. This bit tells your server that this registration ID is for GCM. If you don't get the extra bit, you mark the registration ID as C2DM. Once no more valid registration IDs are marked as C2DM, you can complete the migration.</p>
+
 <h2 id="migrating">Migrating Your Apps</h2>
 <p>This section describes how to move existing C2DM apps to GCM.</p>
 <h3 id="client">Client changes</h3>
diff --git a/docs/html/guide/google/gcm/demo.jd b/docs/html/guide/google/gcm/demo.jd
index 2e1e975..4c56373 100644
--- a/docs/html/guide/google/gcm/demo.jd
+++ b/docs/html/guide/google/gcm/demo.jd
@@ -74,11 +74,11 @@
   <li> From the SDK Manager, install <strong>Extras &gt; Google Cloud Messaging for Android Library</strong>.
     
     
-    <p>This creates a <code>gcm</code> directory under <code><em>YOUR_SDK_ROOT</em>/extras/google/</code> containing these subdirectories: <code>gcm-client</code>, <code>gcm-demo-appengine</code>, <code>gcm-demo-client</code>, <code>gcm-demo-server</code>, and <code>gcm-server</code>.</p>
+    <p>This creates a <code>gcm</code> directory under <code><em>YOUR_SDK_ROOT</em>/extras/google/</code> containing these subdirectories: <code>gcm-client</code>, <code>gcm-server</code>, <code>samples/gcm-demo-client</code>, <code>samples/gcm-demo-server</code>, and <code>samples/gcm-demo-appengine</code>.</p>
   </li>
 
-  <li>In a text editor, edit the <code>gcm-demo-server/WebContent/WEB-INF/classes/api.key</code> and replace the existing text with the API key obtained above.</li>
-  <li>In a shell window, go to the <code>gcm-demo-server</code> directory.</li>
+  <li>In a text editor, edit the <code>samples/gcm-demo-server/WebContent/WEB-INF/classes/api.key</code> and replace the existing text with the API key obtained above.</li>
+  <li>In a shell window, go to the <code>samples/gcm-demo-server</code> directory.</li>
   <li>Generate the server's WAR file by running <code>ant war</code>:</li>
   
   <pre class="prettyprint">$ ant war
@@ -112,13 +112,13 @@
 <p>To set up the server using a standard App Engine for Java:</p>
 <ol>
   <li> From the SDK Manager, install <strong>Extras &gt; Google Cloud Messaging for Android Library</strong>.
-    <p>This creates a <code>gcm</code> directory under <code><em>YOUR_SDK_ROOT</em>/extras/google/</code> containing these subdirectories: <code>gcm-client</code>, <code>gcm-demo-appengine</code>, <code>gcm-demo-client</code>, <code>gcm-demo-server</code>, and <code>gcm-server</code>.</p>
+    <p>This creates a <code>gcm</code> directory under <code><em>YOUR_SDK_ROOT</em>/extras/google/</code> containing these subdirectories: <code>gcm-client</code>, <code>gcm-server</code>, <code>samples/gcm-demo-client</code>, <code>samples/gcm-demo-server</code>, and <code>samples/gcm-demo-appengine</code>.</p>
   </li>
-  <li>In a text editor, edit the <code>gcm-demo-appengine/src/com/google/android/gcm/demo/server/ApiKeyInitializer.java</code> and replace the existing text with the API key obtained above.
+  <li>In a text editor, edit <code>samples/gcm-demo-appengine/src/com/google/android/gcm/demo/server/ApiKeyInitializer.java</code> and replace the existing text with the API key obtained above.
   <p class="note"><strong>Note:</strong> The API key value set in that class will be used just once to create a persistent entity on App Engine. If you deploy the application, you can use App Engine's <code>Datastore Viewer</code> to change it later.</p>
   
   </li>
-  <li>In a shell window, go to the <code>gcm-api-server</code> directory.</li>
+  <li>In a shell window, go to the <code>samples/gcm-demo-appengine</code> directory.</li>
   <li>Start the development App Engine server by <code>ant runserver</code>, using the <code>-Dsdk.dir</code> to indicate the location of the App Engine SDK and <code>-Dserver.host</code> to set your server's hostname or IP address:</li>
 
 <pre class="prettyprint">
@@ -163,9 +163,9 @@
 <p>To set up the device:</p>
 <ol>
   <li> From the SDK Manager, install <strong>Extras &gt; Google Cloud Messaging for Android Library</strong>.
-    <p>This creates a <code>gcm</code> directory under <code><em>YOUR_SDK_ROOT</em>/extras/google</code> containing these subdirectories: <code>gcm-client</code>, <code>gcm-demo-appengine</code>, <code>gcm-demo-client</code>, <code>gcm-demo-server</code>, <code>gcm-server</code>, and <code>source.properties</code>.</p>
+    <p>This creates a <code>gcm</code> directory under <code><em>YOUR_SDK_ROOT</em>/extras/google</code> containing these subdirectories: <code>gcm-client</code>, <code>gcm-server</code>, <code>samples/gcm-demo-client</code>, <code>samples/gcm-demo-server</code>, and <code>samples/gcm-demo-appengine</code>.</p>
   </li>
-  <li>Using a text editor, open  <code>gcm-demo-client/src/com/google/android/gcm/demo/app/CommonUtilities.java</code> and set the proper values for the <code>SENDER_ID</code> and <code>SERVER_URL</code> constants. For example:</li>
+  <li>Using a text editor, open  <code>samples/gcm-demo-client/src/com/google/android/gcm/demo/app/CommonUtilities.java</code> and set the proper values for the <code>SENDER_ID</code> and <code>SERVER_URL</code> constants. For example:</li>
 
 <pre class="prettyprint pretty-java">
 static final String SERVER_URL = &quot;http://192.168.1.10:8080/gcm-demo&quot;;
diff --git a/docs/html/guide/google/gcm/gs.jd b/docs/html/guide/google/gcm/gs.jd
index 5e426c2..8f05d30 100644
--- a/docs/html/guide/google/gcm/gs.jd
+++ b/docs/html/guide/google/gcm/gs.jd
@@ -85,7 +85,7 @@
 <p class="note"><strong>Note:</strong> If you need to rotate the key, click  <strong>Generate new key</strong>. A new key  will be created while the old one will still be active for up to 24 hours. If you want to get rid of the old key immediately (for example, if you feel it was compromised), click <strong>Delete key</strong>.</p>
 
 <h2 id="libs">Install the Helper Libraries</h2>
-<p>To perform the steps described in the following sections, you must first install the helper libraries (reference: <a href="{@docRoot}guide/google/gcm/client-javadoc/index.html">client</a> and <a href="{@docRoot}guide/google/gcm/server-javadoc/index.html">server</a>). From the SDK Manager, install <strong>Extras &gt; Google Cloud Messaging for Android Library</strong>. This creates a <code>gcm</code> directory under <code><em>YOUR_SDK_ROOT</em>/extras/google/</code> containing these subdirectories: <code>gcm-client</code>, <code>gcm-demo-appengine</code>, <code>gcm-demo-client</code>, <code>gcm-demo-server</code>, and <code>gcm-server</code>.</p>
+<p>To perform the steps described in the following sections, you must first install the helper libraries (reference: <a href="{@docRoot}guide/google/gcm/client-javadoc/index.html">client</a> and <a href="{@docRoot}guide/google/gcm/server-javadoc/index.html">server</a>). From the SDK Manager, install <strong>Extras &gt; Google Cloud Messaging for Android Library</strong>. This creates a <code>gcm</code> directory under <code><em>YOUR_SDK_ROOT</em>/extras/google/</code> containing these subdirectories: <code>gcm-client</code>, <code>gcm-server</code>, <code>samples/gcm-demo-client</code>, <code>samples/gcm-demo-server</code>, and <code>samples/gcm-demo-appengine</code>.</p>
 <h2 id="android-app">Writing the Android Application</h2>
 <p>This section describes the steps involved in writing an Android application that uses GCM.</p>
 <h4>Step 1: Copy the gcm.jar file into your application classpath</h4>
@@ -104,9 +104,16 @@
 <p> This permission must be called <code>my_app_package.permission.C2D_MESSAGE</code> (where <code>my_app_package</code> is the package name of your app as defined by the manifest tag), otherwise it will not  work.</p>
 <p class="note"><strong>Note:</strong> This permission is not required if you are targeting your application to 4.1 or above (i.e., minSdkVersion 16)</p>
 
-  <li>Add the permission to receive GCM messages:</li>
+  <li>Add the following permissions:</li>
 
-<pre class="prettyprint pretty-xml">&lt;uses-permission android:name=&quot;com.google.android.c2dm.permission.RECEIVE&quot; /&gt;</pre>
+<pre class="prettyprint pretty-xml">&lt;!-- App receives GCM messages. --&gt;
+&lt;uses-permission android:name=&quot;com.google.android.c2dm.permission.RECEIVE&quot; /&gt;
+&lt;!-- GCM connects to Google Services. --&gt;
+&lt;uses-permission android:name=&quot;android.permission.INTERNET&quot; /&gt; 
+&lt;!-- GCM requires a Google account. --&gt;
+&lt;uses-permission android:name=&quot;android.permission.GET_ACCOUNTS&quot; /&gt;
+&lt;!-- Keeps the processor from sleeping when a message is received. --&gt;
+&lt;uses-permission android:name=&quot;android.permission.WAKE_LOCK&quot; /&gt;</pre>
 
   <li>Add the following broadcast receiver:</li>
 
@@ -127,7 +134,7 @@
  <pre class="prettyprint pretty-xml">&lt;service android:name=&quot;.GCMIntentService&quot; /&gt;</pre>
 
 </ol>
-<p> This intent service will be called by the <code>GCMBroadcastReceiver</code> (which is is provided by GCM library), as shown in the next step. It must be named <code>my_app_package.GCMIntentService</code>, unless you use a subclass of <code>GCMBroadcastReceiver</code> that overrides the method used to name the service.</p>
+<p>This intent service will be called by the <code>GCMBroadcastReceiver</code> (which is is provided by GCM library), as shown in the next step. It must be a subclass of <code>com.google.android.gcm.GCMBaseIntentService</code>, must contain a public constructor, and should be named <code>my_app_package.GCMIntentService</code> (unless you use a subclass of <code>GCMBroadcastReceiver</code> that overrides the method used to name the service).</p>
 <h4><br>
   Step 3: Write the my_app_package.GCMIntentService class</h4>
 <p>Next write the <code>my_app_package.GCMIntentService</code> class, overriding the following callback methods (which are called by <code>GCMBroadcastReceiver</code>):<br>
diff --git a/docs/html/guide/google/gcm/index.jd b/docs/html/guide/google/gcm/index.jd
index cba8d0b..140b076 100644
--- a/docs/html/guide/google/gcm/index.jd
+++ b/docs/html/guide/google/gcm/index.jd
@@ -5,7 +5,7 @@
 <p><img src="{@docRoot}images/gcm/gcm-logo.png" /></p>
 <p>Google Cloud Messaging for Android (GCM) is a service that helps developers send data from servers to their Android applications on Android devices. This could be a lightweight message telling the Android application that there is new data to be fetched from the server (for instance, a movie uploaded by a friend), or it could be a message containing up to 4kb of payload data (so apps like instant messaging can consume the message directly). The GCM service handles all aspects of queueing of messages and delivery to the target Android application running on the target device.</p>
 
-<p>To learn more about GCM, read the following documents:</p>
+<p>To learn more about GCM, you can join the <a href="https://groups.google.com/forum/?fromgroups#!forum/android-gcm">android-gcm group</a> and read the following documents:</p>
 
 <dl>
   <dt><strong><a href="{@docRoot}guide/google/gcm/gs.html">Getting Started</a></strong></dt>
@@ -23,3 +23,4 @@
 <p>GCM also provides helper libraries for <a href="{@docRoot}guide/google/gcm/client-javadoc/index.html"><strong>client</strong></a> and <a href="{@docRoot}guide/google/gcm/server-javadoc/index.html"><strong>server</strong></a> development.</p>
 
 
+
diff --git a/graphics/java/android/renderscript/Matrix2f.java b/graphics/java/android/renderscript/Matrix2f.java
index acc5bd8..39abd4f 100644
--- a/graphics/java/android/renderscript/Matrix2f.java
+++ b/graphics/java/android/renderscript/Matrix2f.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2009-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.
@@ -59,23 +59,23 @@
     /**
     * Returns the value for a given row and column
     *
-    * @param i row of the value to return
-    * @param j column of the value to return
+    * @param x column of the value to return
+    * @param y row of the value to return
     *
-    * @return value in the ith row and jth column
+    * @return value in the yth row and xth column
     */
-    public float get(int i, int j) {
-        return mMat[i*2 + j];
+    public float get(int x, int y) {
+        return mMat[x*2 + y];
     }
 
     /**
     * Sets the value for a given row and column
     *
-    * @param i row of the value to set
-    * @param j column of the value to set
+    * @param x column of the value to set
+    * @param y row of the value to set
     */
-    public void set(int i, int j, float v) {
-        mMat[i*2 + j] = v;
+    public void set(int x, int y, float v) {
+        mMat[x*2 + y] = v;
     }
 
     /**
diff --git a/graphics/java/android/renderscript/Matrix3f.java b/graphics/java/android/renderscript/Matrix3f.java
index 253506d..66f2c81 100644
--- a/graphics/java/android/renderscript/Matrix3f.java
+++ b/graphics/java/android/renderscript/Matrix3f.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2009-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.
@@ -59,23 +59,23 @@
     /**
     * Returns the value for a given row and column
     *
-    * @param i row of the value to return
-    * @param j column of the value to return
+    * @param x column of the value to return
+    * @param y row of the value to return
     *
-    * @return value in the ith row and jth column
+    * @return value in the yth row and xth column
     */
-    public float get(int i, int j) {
-        return mMat[i*3 + j];
+    public float get(int x, int y) {
+        return mMat[x*3 + y];
     }
 
     /**
     * Sets the value for a given row and column
     *
-    * @param i row of the value to set
-    * @param j column of the value to set
+    * @param x column of the value to set
+    * @param y row of the value to set
     */
-    public void set(int i, int j, float v) {
-        mMat[i*3 + j] = v;
+    public void set(int x, int y, float v) {
+        mMat[x*3 + y] = v;
     }
 
     /**
diff --git a/graphics/java/android/renderscript/Matrix4f.java b/graphics/java/android/renderscript/Matrix4f.java
index adc1806..a85d464 100644
--- a/graphics/java/android/renderscript/Matrix4f.java
+++ b/graphics/java/android/renderscript/Matrix4f.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2009-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.
@@ -59,23 +59,23 @@
     /**
     * Returns the value for a given row and column
     *
-    * @param i row of the value to return
-    * @param j column of the value to return
+    * @param x column of the value to return
+    * @param y row of the value to return
     *
-    * @return value in the ith row and jth column
+    * @return value in the yth row and xth column
     */
-    public float get(int i, int j) {
-        return mMat[i*4 + j];
+    public float get(int x, int y) {
+        return mMat[x*4 + y];
     }
 
     /**
     * Sets the value for a given row and column
     *
-    * @param i row of the value to set
-    * @param j column of the value to set
+    * @param x column of the value to set
+    * @param y row of the value to set
     */
-    public void set(int i, int j, float v) {
-        mMat[i*4 + j] = v;
+    public void set(int x, int y, float v) {
+        mMat[x*4 + y] = v;
     }
 
     /**
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 2e153dd..d2a8298 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
@@ -381,7 +382,7 @@
     // message looper for SoundPool listener
     private Looper mSoundPoolLooper = null;
     // volume applied to sound played with playSoundEffect()
-    private static int SOUND_EFFECT_VOLUME_DB;
+    private static int sSoundEffectVolumeDb;
     // getActiveStreamType() will return STREAM_NOTIFICATION during this period after a notification
     // stopped
     private static final int NOTIFICATION_VOLUME_DELAY_MS = 5000;
@@ -438,7 +439,7 @@
             "ro.config.vc_call_vol_steps",
            MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]);
 
-        SOUND_EFFECT_VOLUME_DB = context.getResources().getInteger(
+        sSoundEffectVolumeDb = context.getResources().getInteger(
                 com.android.internal.R.integer.config_soundEffectVolumeDb);
 
         mVolumePanel = new VolumePanel(context, this);
@@ -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() */
@@ -2875,7 +2882,7 @@
                 float volFloat;
                 // use default if volume is not specified by caller
                 if (volume < 0) {
-                    volFloat = (float)Math.pow(10, SOUND_EFFECT_VOLUME_DB/20);
+                    volFloat = (float)Math.pow(10, (float)sSoundEffectVolumeDb/20);
                 } else {
                     volFloat = (float) volume / 1000.0f;
                 }
@@ -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/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStressTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStressTest.java
index 25b6e7f..67da6ac 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStressTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaPlayerStressTest.java
@@ -24,6 +24,7 @@
 import android.hardware.Camera;
 import android.media.MediaPlayer;
 import android.media.MediaRecorder;
+import android.os.Environment;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.util.Log;
@@ -66,6 +67,9 @@
     private int mTotalNotSeekable = 0;
     private int mTotalMetaDataUpdate = 0;
 
+    //Test result output file
+    private static final String PLAYBACK_RESULT = "PlaybackTestResult.txt";
+
     private void writeTestOutput(String filename, Writer output) throws Exception{
         output.write("File Name: " + filename);
         output.write(" Complete: " + CodecTest.onCompleteSuccess);
@@ -109,27 +113,19 @@
     @LargeTest
     public void testVideoPlayback() throws Exception {
         String fileWithError = "Filename:\n";
-        File playbackOutput = new File("/sdcard/PlaybackTestResult.txt");
+        File playbackOutput = new File(Environment.getExternalStorageDirectory(), PLAYBACK_RESULT);
         Writer output = new BufferedWriter(new FileWriter(playbackOutput, true));
 
         boolean testResult = true;
         // load directory files
         boolean onCompleteSuccess = false;
         File dir = new File(MediaNames.MEDIA_SAMPLE_POOL);
-
-        Instrumentation inst = getInstrumentation();
-        Intent intent = new Intent();
-
-        intent.setClass(getInstrumentation().getTargetContext(), MediaFrameworkTest.class);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
         String[] children = dir.list();
         if (children == null) {
             Log.v("MediaPlayerApiTest:testMediaSamples", "dir is empty");
             return;
         } else {
             for (int i = 0; i < children.length; i++) {
-                Activity act = inst.startActivitySync(intent);
                 //Get filename of directory
                 String filename = children[i];
                 onCompleteSuccess =
@@ -141,8 +137,6 @@
                     testResult = false;
                 }
                 Thread.sleep(3000);
-                //Call onCreat to recreate the surface
-                act.finish();
                 //Write test result to an output file
                 writeTestOutput(filename,output);
                 //Get the summary
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png
index f949e59..8ddb375 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight_land.png
index bbda474..57a3b99 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight_land.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_highlight_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight.png
index b97c664..71e1303 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight_land.png
index 222a826..1de0a3a 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight_land.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_highlight_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_highlight.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_highlight.png
index c9d96ec..202c8bc 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_highlight.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_highlight.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_highlight_land.png b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_highlight_land.png
index 4c64b28..31bc09c 100644
--- a/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_highlight_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_highlight_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_highlight.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_highlight.png
index 5f18ae3..bef6de3 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_highlight.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_highlight.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_highlight_land.png b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_highlight_land.png
index d9df25c..406eeab 100644
--- a/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_highlight_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_highlight_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_highlight.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_highlight.png
index 2412a4e..75b5fbb 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_highlight.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_highlight.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_highlight_land.png b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_highlight_land.png
index 114c778..a7a4ce3 100644
--- a/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_highlight_land.png
+++ b/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_highlight_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight.png
index bf2553e..c44aafc 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight_land.png
index 8df299e..05da6da 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_highlight_land.png
Binary files differ
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/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
index e84e912..4b2066f 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
@@ -335,7 +335,7 @@
         }
         int lockSoundDefaultAttenuation = context.getResources().getInteger(
                 com.android.internal.R.integer.config_lockSoundVolumeDb);
-        mLockSoundVolume = (float)Math.pow(10, lockSoundDefaultAttenuation/20);
+        mLockSoundVolume = (float)Math.pow(10, (float)lockSoundDefaultAttenuation/20);
         IntentFilter userFilter = new IntentFilter();
         userFilter.addAction(Intent.ACTION_USER_SWITCHED);
         userFilter.addAction(Intent.ACTION_USER_REMOVED);
diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java
index dda6b10..eb98e7d 100644
--- a/services/java/com/android/server/wm/WindowAnimator.java
+++ b/services/java/com/android/server/wm/WindowAnimator.java
@@ -254,7 +254,13 @@
         ArrayList<WindowStateAnimator> unForceHiding = null;
         boolean wallpaperInUnForceHiding = false;
 
-        boolean forceHiding = false;
+        // forceHiding states.
+        final int KEYGUARD_NOT_SHOWN     = 0;
+        final int KEYGUARD_ANIMATING_IN  = 1;
+        final int KEYGUARD_SHOWN         = 2;
+        final int KEYGUARD_ANIMATING_OUT = 3;
+        int forceHiding = KEYGUARD_NOT_SHOWN;
+
         for (int i = mWinAnimators.size() - 1; i >= 0; i--) {
             WindowStateAnimator winAnimator = mWinAnimators.get(i);
             WindowState win = winAnimator.mWin;
@@ -291,8 +297,16 @@
                         }
                         mService.mFocusMayChange = true;
                     }
-                    if (win.isReadyForDisplay() && winAnimator.mAnimationIsEntrance) {
-                        forceHiding = true;
+                    if (win.isReadyForDisplay()) {
+                        if (nowAnimating) {
+                            if (winAnimator.mAnimationIsEntrance) {
+                                forceHiding = KEYGUARD_ANIMATING_IN;
+                            } else {
+                                forceHiding = KEYGUARD_ANIMATING_OUT;
+                            }
+                        } else {
+                            forceHiding = KEYGUARD_SHOWN;
+                        }
                     }
                     if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
                             "Force hide " + forceHiding
@@ -304,9 +318,12 @@
                             + " hidden=" + win.mRootToken.hidden
                             + " anim=" + win.mWinAnimator.mAnimation);
                 } else if (mPolicy.canBeForceHidden(win, win.mAttrs)) {
+                    final boolean hideWhenLocked =
+                            (winAnimator.mAttrFlags & FLAG_SHOW_WHEN_LOCKED) == 0;
                     final boolean changed;
-                    if (forceHiding && (!winAnimator.isAnimating()
-                            || (winAnimator.mAttrFlags & FLAG_SHOW_WHEN_LOCKED) == 0)) {
+                    if (((forceHiding == KEYGUARD_ANIMATING_IN)
+                                && (!winAnimator.isAnimating() || hideWhenLocked))
+                            || ((forceHiding == KEYGUARD_SHOWN) && hideWhenLocked)) {
                         changed = win.hideLw(false, false);
                         if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
                                 "Now policy hidden: " + win);
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index d29a8c2..4cffb32 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -8684,6 +8684,10 @@
                     winAnimator.setAnimation(a);
                     winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left;
                     winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top;
+                    try {
+                        w.mClient.moved(w.mFrame.left, w.mFrame.top);
+                    } catch (RemoteException e) {
+                    }
                 }
 
                 //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
diff --git a/telephony/java/com/android/internal/telephony/ApnContext.java b/telephony/java/com/android/internal/telephony/ApnContext.java
index 3a3044e..9746398 100644
--- a/telephony/java/com/android/internal/telephony/ApnContext.java
+++ b/telephony/java/com/android/internal/telephony/ApnContext.java
@@ -50,6 +50,8 @@
 
     String mReason;
 
+    int mRetryCount;
+
     /**
      * user/app requested connection on this APN
      */
@@ -64,6 +66,7 @@
         mApnType = apnType;
         mState = DataConnectionTracker.State.IDLE;
         setReason(Phone.REASON_DATA_ENABLED);
+        setRetryCount(0);
         mDataEnabled = new AtomicBoolean(false);
         mDependencyMet = new AtomicBoolean(true);
         mWaitingApnsPermanentFailureCountDown = new AtomicInteger(0);
@@ -182,6 +185,21 @@
         return mReason;
     }
 
+    public synchronized void setRetryCount(int retryCount) {
+        if (DBG) {
+            log("setRetryCount: " + retryCount);
+        }
+        mRetryCount = retryCount;
+        DataConnection dc = mDataConnection;
+        if (dc != null) {
+            dc.setRetryCount(retryCount);
+        }
+    }
+
+    public synchronized int getRetryCount() {
+        return mRetryCount;
+    }
+
     public boolean isReady() {
         return mDataEnabled.get() && mDependencyMet.get();
     }
@@ -214,8 +232,8 @@
         return "{mApnType=" + mApnType + " mState=" + getState() + " mWaitingApns=" + mWaitingApns +
                 " mWaitingApnsPermanentFailureCountDown=" + mWaitingApnsPermanentFailureCountDown +
                 " mApnSetting=" + mApnSetting + " mDataConnectionAc=" + mDataConnectionAc +
-                " mReason=" + mReason + " mDataEnabled=" + mDataEnabled +
-                " mDependencyMet=" + mDependencyMet + "}";
+                " mReason=" + mReason + " mRetryCount=" + mRetryCount +
+                " mDataEnabled=" + mDataEnabled + " mDependencyMet=" + mDependencyMet + "}";
     }
 
     protected void log(String s) {
diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java
index a6bd85e..d8aba92 100644
--- a/telephony/java/com/android/internal/telephony/DataConnection.java
+++ b/telephony/java/com/android/internal/telephony/DataConnection.java
@@ -445,6 +445,14 @@
     }
 
     /**
+     * set retry manager retryCount
+     */
+    public void setRetryCount(int retryCount) {
+        if (DBG) log("setRetryCount: " + retryCount);
+        mRetryMgr.setRetryCount(retryCount);
+    }
+
+    /**
      * @return retry manager retryTimer
      */
     public int getRetryTimer() {
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 588515b..0dee7a1 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -303,7 +303,8 @@
                                     new HashMap<String, Integer>();
 
     /** Phone.APN_TYPE_* ===> ApnContext */
-    protected ConcurrentHashMap<String, ApnContext> mApnContexts;
+    protected ConcurrentHashMap<String, ApnContext> mApnContexts =
+                                    new ConcurrentHashMap<String, ApnContext>();
 
     /* Currently active APN */
     protected ApnSetting mActiveApn;
@@ -1203,6 +1204,9 @@
     }
 
     protected void resetAllRetryCounts() {
+        for (ApnContext ac : mApnContexts.values()) {
+            ac.setRetryCount(0);
+        }
         for (DataConnection dc : mDataConnections.values()) {
             dc.resetRetryCount();
         }
diff --git a/telephony/java/com/android/internal/telephony/RetryManager.java b/telephony/java/com/android/internal/telephony/RetryManager.java
index ae451b9..250d99e 100644
--- a/telephony/java/com/android/internal/telephony/RetryManager.java
+++ b/telephony/java/com/android/internal/telephony/RetryManager.java
@@ -73,7 +73,7 @@
  * {@hide}
  */
 public class RetryManager {
-    static public final String LOG_TAG = "RetryManager";
+    static public final String LOG_TAG = "GSM";
     static public final boolean DBG = true;
     static public final boolean VDBG = false;
 
@@ -304,7 +304,6 @@
 
     /**
      * Set retry count to the specified value
-     * and turns off retrying forever.
      */
     public void setRetryCount(int count) {
         mRetryCount = count;
@@ -316,11 +315,18 @@
             mRetryCount = 0;
         }
 
-        mRetryForever = false;
         if (DBG) log("setRetryCount: " + mRetryCount);
     }
 
     /**
+     * Set retry forever to the specified value
+     */
+    public void setRetryForever(boolean retryForever) {
+        mRetryForever = retryForever;
+        if (DBG) log("setRetryForever: " + mRetryForever);
+    }
+
+    /**
      * Clear the data-retry counter
      */
     public void resetRetryCount() {
@@ -399,6 +405,6 @@
     }
 
     private void log(String s) {
-        Log.d(LOG_TAG, s);
+        Log.d(LOG_TAG, "[RM] " + s);
     }
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 83fc9c1..6b863a7 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -134,6 +134,8 @@
     private static final String INTENT_RECONNECT_ALARM =
         "com.android.internal.telephony.gprs-reconnect";
     private static final String INTENT_RECONNECT_ALARM_EXTRA_TYPE = "reconnect_alarm_extra_type";
+    private static final String INTENT_RECONNECT_ALARM_EXTRA_RETRY_COUNT =
+        "reconnect_alaram_extra_retry_count";
 
     private static final String INTENT_DATA_STALL_ALARM =
         "com.android.internal.telephony.gprs-data-stall";
@@ -148,16 +150,23 @@
 
     @Override
     protected void onActionIntentReconnectAlarm(Intent intent) {
-        if (DBG) log("GPRS reconnect alarm. Previous state was " + mState);
-
         String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON);
         int connectionId = intent.getIntExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE, -1);
+        int retryCount = intent.getIntExtra(INTENT_RECONNECT_ALARM_EXTRA_RETRY_COUNT, 0);
 
         DataConnectionAc dcac= mDataConnectionAsyncChannels.get(connectionId);
 
+        if (DBG) {
+            log("onActionIntentReconnectAlarm: mState=" + mState + " reason=" + reason +
+                    " connectionId=" + connectionId + " retryCount=" + retryCount);
+        }
+
         if (dcac != null) {
             for (ApnContext apnContext : dcac.getApnListSync()) {
+                apnContext.setDataConnectionAc(null);
+                apnContext.setDataConnection(null);
                 apnContext.setReason(reason);
+                apnContext.setRetryCount(retryCount);
                 if (apnContext.getState() == State.FAILED) {
                     apnContext.setState(State.IDLE);
                 }
@@ -205,7 +214,6 @@
         p.getContext().getContentResolver().registerContentObserver(
                 Telephony.Carriers.CONTENT_URI, true, mApnObserver);
 
-        mApnContexts = new ConcurrentHashMap<String, ApnContext>();
         initApnContextsAndDataConnection();
         broadcastMessenger();
     }
@@ -672,10 +680,15 @@
                         break;
                     }
                 }
-                configureRetry(dcac.dataConnection, hasDefault);
+                configureRetry(dcac.dataConnection, hasDefault, 0);
             }
         }
 
+        // Be sure retry counts for Apncontexts and DC's are sync'd.
+        // When DCT/ApnContexts are refactored and we cleanup retrying
+        // this won't be needed.
+        resetAllRetryCounts();
+
         // Only check for default APN state
         for (ApnContext apnContext : mApnContexts.values()) {
             if (apnContext.getState() == State.FAILED) {
@@ -1076,7 +1089,8 @@
 
         // configure retry count if no other Apn is using the same connection.
         if (refCount == 0) {
-            configureRetry(dc, apn.canHandleType(Phone.APN_TYPE_DEFAULT));
+            configureRetry(dc, apn.canHandleType(Phone.APN_TYPE_DEFAULT),
+                    apnContext.getRetryCount());
         }
         apnContext.setDataConnectionAc(dcac);
         apnContext.setDataConnection(dc);
@@ -1328,7 +1342,7 @@
         startNetStatPoll();
         startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
         // reset reconnect timer
-        apnContext.getDataConnection().resetRetryCount();
+        apnContext.setRetryCount(0);
     }
 
     // TODO: For multiple Active APNs not exactly sure how to do this.
@@ -1599,6 +1613,10 @@
             loge("reconnectAfterFail: apnContext == null, impossible");
             return;
         }
+        if (DBG) {
+            log("reconnectAfterFail: lastFailCause=" + lastFailCauseCode +
+                    " retryOverride=" + retryOverride + " apnContext=" + apnContext);
+        }
         if ((apnContext.getState() == State.FAILED) &&
             (apnContext.getDataConnection() != null)) {
             if (!apnContext.getDataConnection().isRetryNeeded()) {
@@ -1614,7 +1632,7 @@
                     if (DBG) log("reconnectAfterFail: activate failed, Reregistering to network");
                     mReregisterOnReconnectFailure = true;
                     mPhone.getServiceStateTracker().reRegisterNetwork(null);
-                    apnContext.getDataConnection().resetRetryCount();
+                    apnContext.setRetryCount(0);
                     return;
                 }
             }
@@ -1625,6 +1643,11 @@
             if (nextReconnectDelay < 0) {
                 nextReconnectDelay = apnContext.getDataConnection().getRetryTimer();
                 apnContext.getDataConnection().increaseRetryCount();
+                if (DBG) {
+                    log("reconnectAfterFail: increaseRetryCount=" +
+                            apnContext.getDataConnection().getRetryCount() +
+                            " nextReconnectDelay=" + nextReconnectDelay);
+                }
             }
             startAlarmForReconnect(nextReconnectDelay, apnContext);
 
@@ -1641,16 +1664,11 @@
 
     private void startAlarmForReconnect(int delay, ApnContext apnContext) {
 
-        if (DBG) {
-            log("Schedule alarm for reconnect: activate failed. Scheduling next attempt for "
-                + (delay / 1000) + "s");
-        }
-
         DataConnectionAc dcac = apnContext.getDataConnectionAc();
 
         if ((dcac == null) || (dcac.dataConnection == null)) {
             // should not happen, but just in case.
-            loge("null dcac or dc.");
+            loge("startAlarmForReconnect: null dcac or dc.");
             return;
         }
 
@@ -1659,12 +1677,29 @@
 
         Intent intent = new Intent(INTENT_RECONNECT_ALARM + '.' +
                                    dcac.dataConnection.getDataConnectionId());
-        intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, apnContext.getReason());
-        intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE,
-                        dcac.dataConnection.getDataConnectionId());
+        String reason = apnContext.getReason();
+        intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, reason);
+        int connectionId = dcac.dataConnection.getDataConnectionId();
+        intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE, connectionId);
+
+        // TODO: Until a real fix is created, which probably entails pushing
+        // retires into the DC itself, this fix gets the retry count and
+        // puts it in the reconnect alarm. When the reconnect alarm fires
+        // onActionIntentReconnectAlarm is called which will use the value saved
+        // here and save it in the ApnContext and send the EVENT_CONNECT message
+        // which invokes setupData. Then setupData will use the value in the ApnContext
+        // and to tell the DC to set the retry count in the retry manager.
+        int retryCount = dcac.dataConnection.getRetryCount();
+        intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_RETRY_COUNT, retryCount);
+
+        if (DBG) {
+            log("startAlarmForReconnect: next attempt in " + (delay / 1000) + "s" +
+                    " reason='" + reason + "' connectionId=" + connectionId +
+                    " retryCount=" + retryCount);
+        }
 
         PendingIntent alarmIntent = PendingIntent.getBroadcast (mPhone.getContext(), 0,
-                                                                intent, 0);
+                                        intent, PendingIntent.FLAG_UPDATE_CURRENT);
         dcac.setReconnectIntentSync(alarmIntent);
         am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                 SystemClock.elapsedRealtime() + delay, alarmIntent);
@@ -1940,9 +1975,7 @@
         // Make sure our reconnect delay starts at the initial value
         // next time the radio comes on
 
-        for (DataConnection dc : mDataConnections.values()) {
-            dc.resetRetryCount();
-        }
+        resetAllRetryCounts();
         mReregisterOnReconnectFailure = false;
 
         if (mPhone.getSimulatedRadioControl() != null) {
@@ -2285,7 +2318,11 @@
         return conn;
     }
 
-    private void configureRetry(DataConnection dc, boolean forDefault) {
+    private void configureRetry(DataConnection dc, boolean forDefault, int retryCount) {
+        if (DBG) {
+            log("configureRetry: forDefault=" + forDefault + " retryCount=" + retryCount +
+                    " dc=" + dc);
+        }
         if (dc == null) return;
 
         if (!dc.configureRetry(getReryConfig(forDefault))) {
@@ -2305,6 +2342,7 @@
                 }
             }
         }
+        dc.setRetryCount(retryCount);
     }
 
     private void destroyDataConnections() {
diff --git a/tests/RenderScriptTests/LivePreview/Android.mk b/tests/RenderScriptTests/LivePreview/Android.mk
index be7ab6e..1b45573 100644
--- a/tests/RenderScriptTests/LivePreview/Android.mk
+++ b/tests/RenderScriptTests/LivePreview/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
 
diff --git a/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/CameraPreviewActivity.java b/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/CameraPreviewActivity.java
index bba3b5b..f21331f 100644
--- a/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/CameraPreviewActivity.java
+++ b/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/CameraPreviewActivity.java
@@ -299,6 +299,38 @@
     }
 
 
+    private class ProcessPreviewDataTask extends AsyncTask<byte[], Void, Boolean> {
+        protected Boolean doInBackground(byte[]... datas) {
+            byte[] data = datas[0];
+
+            long t1 = java.lang.System.currentTimeMillis();
+
+            mFilterYuv.execute(data);
+            mFilterYuv.copyOut(mCallbackBitmap);
+
+            long t2 = java.lang.System.currentTimeMillis();
+            mTiming[mTimingSlot++] = t2 - t1;
+            if (mTimingSlot >= mTiming.length) {
+                float total = 0;
+                for (int i=0; i<mTiming.length; i++) {
+                    total += (float)mTiming[i];
+                }
+                total /= mTiming.length;
+                Log.e(TAG, "time + " + total);
+                mTimingSlot = 0;
+            }
+
+            mCamera.addCallbackBuffer(data);
+            mProcessInProgress = false;
+            return true;
+        }
+
+        protected void onPostExecute(Boolean result) {
+            mFormatView.invalidate();
+        }
+
+    }
+
     private long mTiming[] = new long[50];
     private int mTimingSlot = 0;
 
@@ -307,6 +339,9 @@
             mCamera.addCallbackBuffer(data);
             return;
         }
+        if (data == null) {
+            return;
+        }
 
         int expectedBytes = mPreviewSize.width * mPreviewSize.height *
                 ImageFormat.getBitsPerPixel(ImageFormat.NV21) / 8;
@@ -328,33 +363,16 @@
                     Bitmap.createBitmap(
                         mPreviewSize.width, mPreviewSize.height,
                         Bitmap.Config.ARGB_8888);
-            mFormatView.setImageBitmap(mCallbackBitmap);
             mFilterYuv = new RsYuv(mRS, getResources(), mPreviewSize.width, mPreviewSize.height);
             mFormatView.setImageBitmap(mCallbackBitmap);
         }
 
-        long t1 = java.lang.System.currentTimeMillis();
-
-        mFilterYuv.execute(data);
-        mFilterYuv.copyOut(mCallbackBitmap);
-
-        long t2 = java.lang.System.currentTimeMillis();
-        mTiming[mTimingSlot++] = t2 - t1;
-        if (mTimingSlot >= mTiming.length) {
-            float total = 0;
-            for (int i=0; i<mTiming.length; i++) {
-                total += (float)mTiming[i];
-            }
-            total /= mTiming.length;
-            Log.e(TAG, "time + " + total);
-            mTimingSlot = 0;
-        }
-
 
         mFormatView.invalidate();
 
         mCamera.addCallbackBuffer(data);
-        mProcessInProgress = false;
+        mProcessInProgress = true;
+        new ProcessPreviewDataTask().execute(data);
     }
 
 
diff --git a/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/yuv.rs b/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/yuv.rs
index b81cf93..6057eff 100644
--- a/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/yuv.rs
+++ b/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/yuv.rs
@@ -65,47 +65,31 @@
     return new_color;
 }
 
-//float vignetteCenter = (img_width/2.0, img_height/2.0)
-
 
 static float vignette_dist_mod;
+int2 vignette_half_dims;
 static uchar4 vignette(uchar4 color, uint32_t x, uint32_t y) {
-    x -= gWidth >> 1;
-    y -= gHeight >> 1;
+    int2 xy = {x, y};
+    xy -= vignette_half_dims;
+    xy *= xy;
 
-    uint32_t dist = (x * x + y * y);
-    //float d = sqrt((float)dist) * vignette_dist_mod;
-    float d = vignette_dist_mod * dist;
-
-    //RS_DEBUG(d);
-
+    float d = vignette_dist_mod * (xy.x + xy.y);
     ushort4 c = convert_ushort4(color);
     c *= vignette_table[(int)d];
     c >>= (ushort4)8;
     return convert_uchar4(c);
 }
 
-
-
 void root(uchar4 *out, uint32_t x, uint32_t y) {
     uchar Y = gYuvIn[(y * gWidth) + x];
     uchar *uv = &gYuvIn[gWidth * gHeight];
     uv += (((x>>1)<<1) + (y>>1) * gWidth);
 
-#if 0
-    float4 p = toRGB_F(Y, uv[1], uv[0]);
-    p = crossProcess(p);
-    p = colortemp(p);
-    out->rgba = rsPackColorTo8888(p);
-
-#else
     uchar4 p = rsYuvToRGBA_uchar4(Y, uv[1], uv[0]);
     p = crossProcess_i(p);
     p = vignette(p, x, y);
 
     out->rgba = p;
-#endif
-
     out->a = 0xff;
 }
 
@@ -131,7 +115,6 @@
         lumen = clamp(lumen, 0.f, 1.f);
 
         vignette_table[i] = (uchar)(lumen * 255.f + 0.5f);
-        RS_DEBUG(lumen);
     }
 }
 
@@ -142,7 +125,7 @@
 void setSize(int w, int h) {
     gWidth = w;
     gHeight = h;
-
+    vignette_half_dims = (int2){w / 2, h / 2};
     vignette_dist_mod = 512.f;
     vignette_dist_mod /= (float)(w*w + h*h) / 4.f;
 
diff --git a/tools/layoutlib/bridge/src/android/util/LruCache.java b/tools/layoutlib/bridge/src/android/util/LruCache.java
new file mode 100644
index 0000000..5208606
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/util/LruCache.java
@@ -0,0 +1,391 @@
+/*
+ * 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.
+ */
+
+package android.util;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * BEGIN LAYOUTLIB CHANGE
+ * This is a custom version that doesn't use the non standard LinkedHashMap#eldest.
+ * END LAYOUTLIB CHANGE
+ *
+ * A cache that holds strong references to a limited number of values. Each time
+ * a value is accessed, it is moved to the head of a queue. When a value is
+ * added to a full cache, the value at the end of that queue is evicted and may
+ * become eligible for garbage collection.
+ *
+ * <p>If your cached values hold resources that need to be explicitly released,
+ * override {@link #entryRemoved}.
+ *
+ * <p>If a cache miss should be computed on demand for the corresponding keys,
+ * override {@link #create}. This simplifies the calling code, allowing it to
+ * assume a value will always be returned, even when there's a cache miss.
+ *
+ * <p>By default, the cache size is measured in the number of entries. Override
+ * {@link #sizeOf} to size the cache in different units. For example, this cache
+ * is limited to 4MiB of bitmaps:
+ * <pre>   {@code
+ *   int cacheSize = 4 * 1024 * 1024; // 4MiB
+ *   LruCache<String, Bitmap> bitmapCache = new LruCache<String, Bitmap>(cacheSize) {
+ *       protected int sizeOf(String key, Bitmap value) {
+ *           return value.getByteCount();
+ *       }
+ *   }}</pre>
+ *
+ * <p>This class is thread-safe. Perform multiple cache operations atomically by
+ * synchronizing on the cache: <pre>   {@code
+ *   synchronized (cache) {
+ *     if (cache.get(key) == null) {
+ *         cache.put(key, value);
+ *     }
+ *   }}</pre>
+ *
+ * <p>This class does not allow null to be used as a key or value. A return
+ * value of null from {@link #get}, {@link #put} or {@link #remove} is
+ * unambiguous: the key was not in the cache.
+ *
+ * <p>This class appeared in Android 3.1 (Honeycomb MR1); it's available as part
+ * of <a href="http://developer.android.com/sdk/compatibility-library.html">Android's
+ * Support Package</a> for earlier releases.
+ */
+public class LruCache<K, V> {
+    private final LinkedHashMap<K, V> map;
+
+    /** Size of this cache in units. Not necessarily the number of elements. */
+    private int size;
+    private int maxSize;
+
+    private int putCount;
+    private int createCount;
+    private int evictionCount;
+    private int hitCount;
+    private int missCount;
+
+    /**
+     * @param maxSize for caches that do not override {@link #sizeOf}, this is
+     *     the maximum number of entries in the cache. For all other caches,
+     *     this is the maximum sum of the sizes of the entries in this cache.
+     */
+    public LruCache(int maxSize) {
+        if (maxSize <= 0) {
+            throw new IllegalArgumentException("maxSize <= 0");
+        }
+        this.maxSize = maxSize;
+        this.map = new LinkedHashMap<K, V>(0, 0.75f, true);
+    }
+
+    /**
+     * Sets the size of the cache.
+     * @param maxSize The new maximum size.
+     *
+     * @hide
+     */
+    public void resize(int maxSize) {
+        if (maxSize <= 0) {
+            throw new IllegalArgumentException("maxSize <= 0");
+        }
+
+        synchronized (this) {
+            this.maxSize = maxSize;
+        }
+        trimToSize(maxSize);
+    }
+
+    /**
+     * Returns the value for {@code key} if it exists in the cache or can be
+     * created by {@code #create}. If a value was returned, it is moved to the
+     * head of the queue. This returns null if a value is not cached and cannot
+     * be created.
+     */
+    public final V get(K key) {
+        if (key == null) {
+            throw new NullPointerException("key == null");
+        }
+
+        V mapValue;
+        synchronized (this) {
+            mapValue = map.get(key);
+            if (mapValue != null) {
+                hitCount++;
+                return mapValue;
+            }
+            missCount++;
+        }
+
+        /*
+         * Attempt to create a value. This may take a long time, and the map
+         * may be different when create() returns. If a conflicting value was
+         * added to the map while create() was working, we leave that value in
+         * the map and release the created value.
+         */
+
+        V createdValue = create(key);
+        if (createdValue == null) {
+            return null;
+        }
+
+        synchronized (this) {
+            createCount++;
+            mapValue = map.put(key, createdValue);
+
+            if (mapValue != null) {
+                // There was a conflict so undo that last put
+                map.put(key, mapValue);
+            } else {
+                size += safeSizeOf(key, createdValue);
+            }
+        }
+
+        if (mapValue != null) {
+            entryRemoved(false, key, createdValue, mapValue);
+            return mapValue;
+        } else {
+            trimToSize(maxSize);
+            return createdValue;
+        }
+    }
+
+    /**
+     * Caches {@code value} for {@code key}. The value is moved to the head of
+     * the queue.
+     *
+     * @return the previous value mapped by {@code key}.
+     */
+    public final V put(K key, V value) {
+        if (key == null || value == null) {
+            throw new NullPointerException("key == null || value == null");
+        }
+
+        V previous;
+        synchronized (this) {
+            putCount++;
+            size += safeSizeOf(key, value);
+            previous = map.put(key, value);
+            if (previous != null) {
+                size -= safeSizeOf(key, previous);
+            }
+        }
+
+        if (previous != null) {
+            entryRemoved(false, key, previous, value);
+        }
+
+        trimToSize(maxSize);
+        return previous;
+    }
+
+    /**
+     * @param maxSize the maximum size of the cache before returning. May be -1
+     *     to evict even 0-sized elements.
+     */
+    private void trimToSize(int maxSize) {
+        while (true) {
+            K key;
+            V value;
+            synchronized (this) {
+                if (size < 0 || (map.isEmpty() && size != 0)) {
+                    throw new IllegalStateException(getClass().getName()
+                            + ".sizeOf() is reporting inconsistent results!");
+                }
+
+                if (size <= maxSize) {
+                    break;
+                }
+
+                // BEGIN LAYOUTLIB CHANGE
+                // get the last item in the linked list.
+                // This is not efficient, the goal here is to minimize the changes
+                // compared to the platform version.
+                Map.Entry<K, V> toEvict = null;
+                for (Map.Entry<K, V> entry : map.entrySet()) {
+                    toEvict = entry;
+                }
+                // END LAYOUTLIB CHANGE
+
+                if (toEvict == null) {
+                    break;
+                }
+
+                key = toEvict.getKey();
+                value = toEvict.getValue();
+                map.remove(key);
+                size -= safeSizeOf(key, value);
+                evictionCount++;
+            }
+
+            entryRemoved(true, key, value, null);
+        }
+    }
+
+    /**
+     * Removes the entry for {@code key} if it exists.
+     *
+     * @return the previous value mapped by {@code key}.
+     */
+    public final V remove(K key) {
+        if (key == null) {
+            throw new NullPointerException("key == null");
+        }
+
+        V previous;
+        synchronized (this) {
+            previous = map.remove(key);
+            if (previous != null) {
+                size -= safeSizeOf(key, previous);
+            }
+        }
+
+        if (previous != null) {
+            entryRemoved(false, key, previous, null);
+        }
+
+        return previous;
+    }
+
+    /**
+     * Called for entries that have been evicted or removed. This method is
+     * invoked when a value is evicted to make space, removed by a call to
+     * {@link #remove}, or replaced by a call to {@link #put}. The default
+     * implementation does nothing.
+     *
+     * <p>The method is called without synchronization: other threads may
+     * access the cache while this method is executing.
+     *
+     * @param evicted true if the entry is being removed to make space, false
+     *     if the removal was caused by a {@link #put} or {@link #remove}.
+     * @param newValue the new value for {@code key}, if it exists. If non-null,
+     *     this removal was caused by a {@link #put}. Otherwise it was caused by
+     *     an eviction or a {@link #remove}.
+     */
+    protected void entryRemoved(boolean evicted, K key, V oldValue, V newValue) {}
+
+    /**
+     * Called after a cache miss to compute a value for the corresponding key.
+     * Returns the computed value or null if no value can be computed. The
+     * default implementation returns null.
+     *
+     * <p>The method is called without synchronization: other threads may
+     * access the cache while this method is executing.
+     *
+     * <p>If a value for {@code key} exists in the cache when this method
+     * returns, the created value will be released with {@link #entryRemoved}
+     * and discarded. This can occur when multiple threads request the same key
+     * at the same time (causing multiple values to be created), or when one
+     * thread calls {@link #put} while another is creating a value for the same
+     * key.
+     */
+    protected V create(K key) {
+        return null;
+    }
+
+    private int safeSizeOf(K key, V value) {
+        int result = sizeOf(key, value);
+        if (result < 0) {
+            throw new IllegalStateException("Negative size: " + key + "=" + value);
+        }
+        return result;
+    }
+
+    /**
+     * Returns the size of the entry for {@code key} and {@code value} in
+     * user-defined units.  The default implementation returns 1 so that size
+     * is the number of entries and max size is the maximum number of entries.
+     *
+     * <p>An entry's size must not change while it is in the cache.
+     */
+    protected int sizeOf(K key, V value) {
+        return 1;
+    }
+
+    /**
+     * Clear the cache, calling {@link #entryRemoved} on each removed entry.
+     */
+    public final void evictAll() {
+        trimToSize(-1); // -1 will evict 0-sized elements
+    }
+
+    /**
+     * For caches that do not override {@link #sizeOf}, this returns the number
+     * of entries in the cache. For all other caches, this returns the sum of
+     * the sizes of the entries in this cache.
+     */
+    public synchronized final int size() {
+        return size;
+    }
+
+    /**
+     * For caches that do not override {@link #sizeOf}, this returns the maximum
+     * number of entries in the cache. For all other caches, this returns the
+     * maximum sum of the sizes of the entries in this cache.
+     */
+    public synchronized final int maxSize() {
+        return maxSize;
+    }
+
+    /**
+     * Returns the number of times {@link #get} returned a value that was
+     * already present in the cache.
+     */
+    public synchronized final int hitCount() {
+        return hitCount;
+    }
+
+    /**
+     * Returns the number of times {@link #get} returned null or required a new
+     * value to be created.
+     */
+    public synchronized final int missCount() {
+        return missCount;
+    }
+
+    /**
+     * Returns the number of times {@link #create(Object)} returned a value.
+     */
+    public synchronized final int createCount() {
+        return createCount;
+    }
+
+    /**
+     * Returns the number of times {@link #put} was called.
+     */
+    public synchronized final int putCount() {
+        return putCount;
+    }
+
+    /**
+     * Returns the number of values that have been evicted.
+     */
+    public synchronized final int evictionCount() {
+        return evictionCount;
+    }
+
+    /**
+     * Returns a copy of the current contents of the cache, ordered from least
+     * recently accessed to most recently accessed.
+     */
+    public synchronized final Map<K, V> snapshot() {
+        return new LinkedHashMap<K, V>(map);
+    }
+
+    @Override public synchronized final String toString() {
+        int accesses = hitCount + missCount;
+        int hitPercent = accesses != 0 ? (100 * hitCount / accesses) : 0;
+        return String.format("LruCache[maxSize=%d,hits=%d,misses=%d,hitRate=%d%%]",
+                maxSize, hitCount, missCount, hitPercent);
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index f9e48e2..3ae660d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -732,14 +732,16 @@
         for (int i = 0 ; i < attrs.length ; i++) {
             Pair<String, Boolean> attribute = attributes.get(i);
 
-            // look for the value in the given style
-            ResourceValue resValue = mRenderResources.findItemInStyle(style, attribute.getFirst(),
-                    attribute.getSecond());
+            if (attribute != null) {
+                // look for the value in the given style
+                ResourceValue resValue = mRenderResources.findItemInStyle(style,
+                        attribute.getFirst(), attribute.getSecond());
 
-            if (resValue != null) {
-                // resolve it to make sure there are no references left.
-                ta.bridgeSetValue(i, attribute.getFirst(), attribute.getSecond(),
-                        mRenderResources.resolveResValue(resValue));
+                if (resValue != null) {
+                    // resolve it to make sure there are no references left.
+                    ta.bridgeSetValue(i, attribute.getFirst(), attribute.getSecond(),
+                            mRenderResources.resolveResValue(resValue));
+                }
             }
         }
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
index 379fb81..e28375d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
@@ -53,6 +53,11 @@
     }
 
     @Override
+    public void moved(int arg0, int arg1) throws RemoteException {
+        // pass for now.
+    }
+
+    @Override
     public void dispatchScreenState(boolean on) throws RemoteException {
         // pass for now.
     }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
index 1817ab5..62c886b 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
@@ -233,7 +233,7 @@
         BridgeContext bridgeContext = (BridgeContext) mContext;
         RenderResources res = bridgeContext.getRenderResources();
 
-        ResourceValue value = res.findItemInTheme(themeEntryName);
+        ResourceValue value = res.findItemInTheme(themeEntryName, true /*isFrameworkAttr*/);
         value = res.resolveResValue(value);
 
         if (value instanceof StyleResourceValue == false) {
@@ -243,24 +243,27 @@
         StyleResourceValue style = (StyleResourceValue) value;
 
         // get the background
-        ResourceValue backgroundValue = res.findItemInStyle(style, "background");
+        ResourceValue backgroundValue = res.findItemInStyle(style, "background",
+                true /*isFrameworkAttr*/);
         backgroundValue = res.resolveResValue(backgroundValue);
         if (backgroundValue != null) {
             Drawable d = ResourceHelper.getDrawable(backgroundValue, bridgeContext);
             if (d != null) {
-                setBackgroundDrawable(d);
+                setBackground(d);
             }
         }
 
         TextView textView = getStyleableTextView();
         if (textView != null) {
             // get the text style
-            ResourceValue textStyleValue = res.findItemInStyle(style, "titleTextStyle");
+            ResourceValue textStyleValue = res.findItemInStyle(style, "titleTextStyle",
+                    true /*isFrameworkAttr*/);
             textStyleValue = res.resolveResValue(textStyleValue);
             if (textStyleValue instanceof StyleResourceValue) {
                 StyleResourceValue textStyle = (StyleResourceValue) textStyleValue;
 
-                ResourceValue textSize = res.findItemInStyle(textStyle, "textSize");
+                ResourceValue textSize = res.findItemInStyle(textStyle, "textSize",
+                        true /*isFrameworkAttr*/);
                 textSize = res.resolveResValue(textSize);
 
                 if (textSize != null) {
@@ -273,7 +276,8 @@
                 }
 
 
-                ResourceValue textColor = res.findItemInStyle(textStyle, "textColor");
+                ResourceValue textColor = res.findItemInStyle(textStyle, "textColor",
+                        true /*isFrameworkAttr*/);
                 textColor = res.resolveResValue(textColor);
                 if (textColor != null) {
                     ColorStateList stateList = ResourceHelper.getColorStateList(
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 6840f46..e93b41d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -952,7 +952,8 @@
 
     private void findBackground(RenderResources resources) {
         if (getParams().isBgColorOverridden() == false) {
-            mWindowBackground = resources.findItemInTheme("windowBackground");
+            mWindowBackground = resources.findItemInTheme("windowBackground",
+                    true /*isFrameworkAttr*/);
             if (mWindowBackground != null) {
                 mWindowBackground = resources.resolveResValue(mWindowBackground);
             }
@@ -1003,7 +1004,8 @@
             mActionBarSize = DEFAULT_TITLE_BAR_HEIGHT;
 
             // get value from the theme.
-            ResourceValue value = resources.findItemInTheme("actionBarSize");
+            ResourceValue value = resources.findItemInTheme("actionBarSize",
+                    true /*isFrameworkAttr*/);
 
             // resolve it
             value = resources.resolveResValue(value);
@@ -1028,7 +1030,8 @@
                 mTitleBarSize = DEFAULT_TITLE_BAR_HEIGHT;
 
                 // get value from the theme.
-                ResourceValue value = resources.findItemInTheme("windowTitleSize");
+                ResourceValue value = resources.findItemInTheme("windowTitleSize",
+                        true /*isFrameworkAttr*/);
 
                 // resolve it
                 value = resources.resolveResValue(value);
@@ -1068,11 +1071,20 @@
         }
     }
 
+    /**
+     * Looks for a attribute in the current theme. The attribute is in the android
+     * namespace.
+     *
+     * @param resources the render resources
+     * @param name the name of the attribute
+     * @param defaultValue the default value.
+     * @return the value of the attribute or the default one if not found.
+     */
     private boolean getBooleanThemeValue(RenderResources resources,
             String name, boolean defaultValue) {
 
         // get the title bar flag from the current theme.
-        ResourceValue value = resources.findItemInTheme(name);
+        ResourceValue value = resources.findItemInTheme(name, true /*isFrameworkAttr*/);
 
         // because it may reference something else, we resolve it.
         value = resources.resolveResValue(value);
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 79e02c8..5109810 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -116,7 +116,6 @@
         "android.view.View#isInEditMode",
         "android.view.ViewRootImpl#isInTouchMode",
         "android.view.inputmethod.InputMethodManager#getInstance",
-        "android.util.Log#println_native",
         "com.android.internal.util.XmlUtils#convertValueToInt",
         "com.android.internal.textservice.ITextServicesManager$Stub#asInterface",
     };
@@ -185,6 +184,7 @@
     private final static String[] RENAMED_CLASSES =
         new String[] {
             "android.os.ServiceManager",                       "android.os._Original_ServiceManager",
+            "android.util.LruCache",                           "android.util._Original_LruCache",
             "android.view.SurfaceView",                        "android.view._Original_SurfaceView",
             "android.view.accessibility.AccessibilityManager", "android.view.accessibility._Original_AccessibilityManager",
             "android.webkit.WebView",                          "android.webkit._Original_WebView",