Merge "audio framework: manage stream volume per device"
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 8a9be85..700d3df 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -61,6 +61,7 @@
     private final float[] mLine = new float[4];
     
     private final Rect mClipBounds = new Rect();
+    private final RectF mPathBounds = new RectF();
 
     private DrawFilter mFilter;
 
@@ -406,12 +407,18 @@
 
     @Override
     public boolean clipPath(Path path) {
-        throw new UnsupportedOperationException();
+        // TODO: Implement
+        path.computeBounds(mPathBounds, true);
+        return nClipRect(mRenderer, mPathBounds.left, mPathBounds.top,
+                mPathBounds.right, mPathBounds.bottom, Region.Op.INTERSECT.nativeInt);
     }
 
     @Override
     public boolean clipPath(Path path, Region.Op op) {
-        throw new UnsupportedOperationException();
+        // TODO: Implement
+        path.computeBounds(mPathBounds, true);
+        return nClipRect(mRenderer, mPathBounds.left, mPathBounds.top,
+                mPathBounds.right, mPathBounds.bottom, op.nativeInt);
     }
 
     @Override
@@ -459,12 +466,18 @@
 
     @Override
     public boolean clipRegion(Region region) {
-        throw new UnsupportedOperationException();
+        // TODO: Implement
+        region.getBounds(mClipBounds);
+        return nClipRect(mRenderer, mClipBounds.left, mClipBounds.top,
+                mClipBounds.right, mClipBounds.bottom, Region.Op.INTERSECT.nativeInt);
     }
 
     @Override
     public boolean clipRegion(Region region, Region.Op op) {
-        throw new UnsupportedOperationException();
+        // TODO: Implement
+        region.getBounds(mClipBounds);
+        return nClipRect(mRenderer, mClipBounds.left, mClipBounds.top,
+                mClipBounds.right, mClipBounds.bottom, op.nativeInt);
     }
 
     @Override
@@ -484,12 +497,14 @@
 
     @Override
     public boolean quickReject(Path path, EdgeType type) {
-        throw new UnsupportedOperationException();
+        path.computeBounds(mPathBounds, true);
+        return nQuickReject(mRenderer, mPathBounds.left, mPathBounds.top,
+                mPathBounds.right, mPathBounds.bottom, type.nativeInt);
     }
 
     @Override
     public boolean quickReject(RectF rect, EdgeType type) {
-        return quickReject(rect.left, rect.top, rect.right, rect.bottom, type);
+        return nQuickReject(mRenderer, rect.left, rect.top, rect.right, rect.bottom, type.nativeInt);
     }
 
     ///////////////////////////////////////////////////////////////////////////
diff --git a/core/java/android/view/VelocityTracker.java b/core/java/android/view/VelocityTracker.java
index dfb2c32..1c35e31 100644
--- a/core/java/android/view/VelocityTracker.java
+++ b/core/java/android/view/VelocityTracker.java
@@ -29,7 +29,7 @@
  * to begin tracking.  Put the motion events you receive into it with
  * {@link #addMovement(MotionEvent)}.  When you want to determine the velocity call
  * {@link #computeCurrentVelocity(int)} and then call {@link #getXVelocity(int)}
- * and {@link #getXVelocity(int)} to retrieve the velocity for each pointer id.
+ * and {@link #getYVelocity(int)} to retrieve the velocity for each pointer id.
  */
 public final class VelocityTracker implements Poolable<VelocityTracker> {
     private static final Pool<VelocityTracker> sPool = Pools.synchronizedPool(
@@ -39,6 +39,7 @@
                 }
 
                 public void onAcquired(VelocityTracker element) {
+                    // Intentionally empty
                 }
 
                 public void onReleased(VelocityTracker element) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index e280286..a9d6cdf 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4107,7 +4107,7 @@
      */
     void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
         event.setSource(this);
-        event.setClassName(getClass().getName());
+        event.setClassName(View.class.getName());
         event.setPackageName(getContext().getPackageName());
         event.setEnabled(isEnabled());
         event.setContentDescription(mContentDescription);
@@ -4212,7 +4212,7 @@
         }
 
         info.setPackageName(mContext.getPackageName());
-        info.setClassName(getClass().getName());
+        info.setClassName(View.class.getName());
         info.setContentDescription(getContentDescription());
 
         info.setEnabled(isEnabled());
@@ -7597,15 +7597,17 @@
      */
     public void setAlpha(float alpha) {
         ensureTransformationInfo();
-        mTransformationInfo.mAlpha = alpha;
-        invalidateParentCaches();
-        if (onSetAlpha((int) (alpha * 255))) {
-            mPrivateFlags |= ALPHA_SET;
-            // subclass is handling alpha - don't optimize rendering cache invalidation
-            invalidate(true);
-        } else {
-            mPrivateFlags &= ~ALPHA_SET;
-            invalidate(false);
+        if (mTransformationInfo.mAlpha != alpha) {
+            mTransformationInfo.mAlpha = alpha;
+            invalidateParentCaches();
+            if (onSetAlpha((int) (alpha * 255))) {
+                mPrivateFlags |= ALPHA_SET;
+                // subclass is handling alpha - don't optimize rendering cache invalidation
+                invalidate(true);
+            } else {
+                mPrivateFlags &= ~ALPHA_SET;
+                invalidate(false);
+            }
         }
     }
 
@@ -7616,18 +7618,22 @@
      * alpha (the return value for onSetAlpha()).
      *
      * @param alpha The new value for the alpha property
-     * @return true if the View subclass handles alpha (the return value for onSetAlpha())
+     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
+     *         the new value for the alpha property is different from the old value
      */
     boolean setAlphaNoInvalidation(float alpha) {
         ensureTransformationInfo();
-        mTransformationInfo.mAlpha = alpha;
-        boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
-        if (subclassHandlesAlpha) {
-            mPrivateFlags |= ALPHA_SET;
-        } else {
-            mPrivateFlags &= ~ALPHA_SET;
+        if (mTransformationInfo.mAlpha != alpha) {
+            mTransformationInfo.mAlpha = alpha;
+            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
+            if (subclassHandlesAlpha) {
+                mPrivateFlags |= ALPHA_SET;
+                return true;
+            } else {
+                mPrivateFlags &= ~ALPHA_SET;
+            }
         }
-        return subclassHandlesAlpha;
+        return false;
     }
 
     /**
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 09901ff..5c63366 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -2229,6 +2229,7 @@
     @Override
     void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfoInternal(info);
+        info.setClassName(ViewGroup.class.getName());
         for (int i = 0, count = mChildrenCount; i < count; i++) {
             View child = mChildren[i];
             if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
@@ -2238,6 +2239,12 @@
         }
     }
 
+    @Override
+    void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEventInternal(event);
+        event.setClassName(ViewGroup.class.getName());
+    }
+
     /**
      * {@inheritDoc}
      */
diff --git a/core/java/android/webkit/HTML5VideoViewProxy.java b/core/java/android/webkit/HTML5VideoViewProxy.java
index 7c2dc38..1c09bb9 100644
--- a/core/java/android/webkit/HTML5VideoViewProxy.java
+++ b/core/java/android/webkit/HTML5VideoViewProxy.java
@@ -162,6 +162,16 @@
                 mHTML5VideoView.enterFullScreenVideoState(layerId, proxy, webView);
         }
 
+        public static void exitFullScreenVideo(HTML5VideoViewProxy proxy,
+                WebView webView) {
+            if (!mHTML5VideoView.fullScreenExited() && mHTML5VideoView.isFullScreenMode()) {
+                WebChromeClient client = webView.getWebChromeClient();
+                if (client != null) {
+                    client.onHideCustomView();
+                }
+            }
+        }
+
         // This is on the UI thread.
         // When native tell Java to play, we need to check whether or not it is
         // still the same video by using videoLayerId and treat it differently.
@@ -682,6 +692,10 @@
         VideoPlayer.enterFullScreenVideo(layerId, url, this, mWebView);
     }
 
+    public void exitFullScreenVideo() {
+        VideoPlayer.exitFullScreenVideo(this, mWebView);
+    }
+
     /**
      * The factory for HTML5VideoViewProxy instances.
      * @param webViewCore is the WebViewCore that is requesting the proxy.
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index ab4665a..c3b6416 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -327,6 +327,15 @@
  * property to {@code device-dpi}. This stops Android from performing scaling in your web page and
  * allows you to make the necessary adjustments for each density via CSS and JavaScript.</p>
  *
+ * <h3>HTML5 Video support</h3>
+ *
+ * <p>In order to support inline HTML5 video in your application, you need to have hardware
+ * acceleration turned on, and set a {@link android.webkit.WebChromeClient}. For full screen support,
+ * implementations of {@link WebChromeClient#onShowCustomView(View, WebChromeClient.CustomViewCallback)}
+ * and {@link WebChromeClient#onHideCustomView()} are required,
+ * {@link WebChromeClient#getVideoLoadingProgressView()} is optional.
+ * </p>
+ *
  *
  */
 @Widget
@@ -611,6 +620,7 @@
     private boolean mIsPaused;
 
     private HitTestResult mInitialHitTestResult;
+    private WebKitHitTest mFocusedNode;
 
     /**
      * Customizable constant
@@ -787,6 +797,7 @@
     static final int ENTER_FULLSCREEN_VIDEO             = 137;
     static final int UPDATE_SELECTION                   = 138;
     static final int UPDATE_ZOOM_DENSITY                = 139;
+    static final int EXIT_FULLSCREEN_VIDEO              = 140;
 
     private static final int FIRST_PACKAGE_MSG_ID = SCROLL_TO_MSG_ID;
     private static final int LAST_PACKAGE_MSG_ID = HIT_TEST_RESULT;
@@ -1073,6 +1084,15 @@
     }
 
     /**
+     * Refer to {@link WebView#requestFocusNodeHref(Message)} for more information
+     */
+    static class FocusNodeHref {
+        static final String TITLE = "title";
+        static final String URL = "url";
+        static final String SRC = "src";
+    }
+
+    /**
      * Construct a new WebView with a Context object.
      * @param context A Context object used to access application assets.
      */
@@ -2704,6 +2724,14 @@
         }
         int contentX = viewToContentX(mLastTouchX + mScrollX);
         int contentY = viewToContentY(mLastTouchY + mScrollY);
+        if (mFocusedNode != null && mFocusedNode.mHitTestX == contentX
+                && mFocusedNode.mHitTestY == contentY) {
+            hrefMsg.getData().putString(FocusNodeHref.URL, mFocusedNode.mLinkUrl);
+            hrefMsg.getData().putString(FocusNodeHref.TITLE, mFocusedNode.mAnchorText);
+            hrefMsg.getData().putString(FocusNodeHref.SRC, mFocusedNode.mImageUrl);
+            hrefMsg.sendToTarget();
+            return;
+        }
         if (nativeHasCursorNode()) {
             Rect cursorBounds = nativeGetCursorRingBounds();
             if (!cursorBounds.contains(contentX, contentY)) {
@@ -8745,6 +8773,12 @@
                     }
                     break;
 
+                case EXIT_FULLSCREEN_VIDEO:
+                    if (mHTML5VideoViewProxy != null) {
+                        mHTML5VideoViewProxy.exitFullScreenVideo();
+                    }
+                    break;
+
                 case SHOW_FULLSCREEN: {
                     View view = (View) msg.obj;
                     int orientation = msg.arg1;
@@ -8839,13 +8873,25 @@
 
                 case HIT_TEST_RESULT:
                     WebKitHitTest hit = (WebKitHitTest) msg.obj;
+                    mFocusedNode = hit;
                     setTouchHighlightRects(hit != null ? hit.mTouchRects : null);
                     if (hit == null) {
                         mInitialHitTestResult = null;
                     } else {
                         mInitialHitTestResult = new HitTestResult();
-                        mInitialHitTestResult.mType = hit.mType;
-                        mInitialHitTestResult.mExtra = hit.mExtra;
+                        if (hit.mLinkUrl != null) {
+                            mInitialHitTestResult.mType = HitTestResult.SRC_ANCHOR_TYPE;
+                            mInitialHitTestResult.mExtra = hit.mLinkUrl;
+                            if (hit.mImageUrl != null) {
+                                mInitialHitTestResult.mType = HitTestResult.SRC_IMAGE_ANCHOR_TYPE;
+                                mInitialHitTestResult.mExtra = hit.mImageUrl;
+                            }
+                        } else if (hit.mImageUrl != null) {
+                            mInitialHitTestResult.mType = HitTestResult.IMAGE_TYPE;
+                            mInitialHitTestResult.mExtra = hit.mImageUrl;
+                        } else if (hit.mEditable) {
+                            mInitialHitTestResult.mType = HitTestResult.EDIT_TEXT_TYPE;
+                        }
                     }
                     break;
 
@@ -8884,8 +8930,10 @@
     }
 
     private void setTouchHighlightRects(Rect[] rects) {
-        invalidate(mTouchHighlightRegion.getBounds());
-        mTouchHighlightRegion.setEmpty();
+        if (!mTouchHighlightRegion.isEmpty()) {
+            invalidate(mTouchHighlightRegion.getBounds());
+            mTouchHighlightRegion.setEmpty();
+        }
         if (rects != null) {
             for (Rect rect : rects) {
                 Rect viewRect = contentToViewRect(rect);
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 962a8f1..bfca07c 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -26,6 +26,7 @@
 import android.media.MediaFile;
 import android.net.ProxyProperties;
 import android.net.Uri;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -37,6 +38,7 @@
 import android.view.MotionEvent;
 import android.view.SurfaceView;
 import android.view.View;
+import android.webkit.WebView.FocusNodeHref;
 
 import junit.framework.Assert;
 
@@ -502,6 +504,17 @@
     }
 
     /**
+     * Notify the webview that we want to exit the video fullscreen.
+     * This is called through JNI by webcore.
+     */
+    protected void exitFullscreenVideo() {
+        if (mWebView == null) return;
+        Message message = Message.obtain(mWebView.mPrivateHandler,
+                       WebView.EXIT_FULLSCREEN_VIDEO);
+        message.sendToTarget();
+    }
+
+    /**
      * Clear the picture set. To be called only on the WebCore thread.
      */
     /* package */ void clearContent() {
@@ -861,9 +874,19 @@
     }
 
     static class WebKitHitTest {
-        int mType;
-        String mExtra;
+        String mLinkUrl;
+        String mAnchorText;
+        String mImageUrl;
+        String mAltDisplayString;
+        String mTitle;
         Rect[] mTouchRects;
+        boolean mEditable;
+
+        // These are the input values that produced this hit test
+        int mHitTestX;
+        int mHitTestY;
+        int mHitTestSlop;
+        boolean mHitTestMovedMouse;
     }
 
     static class AutoFillData {
@@ -1514,13 +1537,12 @@
                             break;
 
                         case REQUEST_CURSOR_HREF: {
+                            WebKitHitTest hit = performHitTest(msg.arg1, msg.arg2, 1, false);
                             Message hrefMsg = (Message) msg.obj;
-                            hrefMsg.getData().putString("url",
-                                    nativeRetrieveHref(mNativeClass, msg.arg1, msg.arg2));
-                            hrefMsg.getData().putString("title",
-                                    nativeRetrieveAnchorText(mNativeClass, msg.arg1, msg.arg2));
-                            hrefMsg.getData().putString("src",
-                                    nativeRetrieveImageSource(mNativeClass, msg.arg1, msg.arg2));
+                            Bundle data = hrefMsg.getData();
+                            data.putString(FocusNodeHref.URL,hit.mLinkUrl);
+                            data.putString(FocusNodeHref.TITLE, hit.mAnchorText);
+                            data.putString(FocusNodeHref.SRC, hit.mImageUrl);
                             hrefMsg.sendToTarget();
                             break;
                         }
@@ -1685,8 +1707,7 @@
                                 nativeScrollLayer(mNativeClass,
                                         d.mNativeLayer, d.mNativeLayerRect);
                             }
-                            WebKitHitTest hit = nativeHitTest(mNativeClass,
-                                    d.mX, d.mY, d.mSlop);
+                            WebKitHitTest hit = performHitTest(d.mX, d.mY, d.mSlop, true);
                             mWebView.mPrivateHandler.obtainMessage(
                                     WebView.HIT_TEST_RESULT, hit)
                                     .sendToTarget();
@@ -1890,6 +1911,15 @@
     // WebViewCore private methods
     //-------------------------------------------------------------------------
 
+    private WebKitHitTest performHitTest(int x, int y, int slop, boolean moveMouse) {
+        WebKitHitTest hit = nativeHitTest(mNativeClass, x, y, slop, moveMouse);
+        hit.mHitTestX = x;
+        hit.mHitTestY = y;
+        hit.mHitTestSlop = slop;
+        hit.mHitTestMovedMouse = moveMouse;
+        return hit;
+    }
+
     private void clearCache(boolean includeDiskFiles) {
         mBrowserFrame.clearCache();
         if (includeDiskFiles) {
@@ -2940,7 +2970,8 @@
     private native boolean nativeValidNodeAndBounds(int nativeClass, int frame,
             int node, Rect bounds);
 
-    private native WebKitHitTest nativeHitTest(int nativeClass, int x, int y, int slop);
+    private native WebKitHitTest nativeHitTest(int nativeClass, int x, int y,
+            int slop, boolean moveMouse);
 
     private native void nativeAutoFillForm(int nativeClass, int queryId);
     private native void nativeScrollLayer(int nativeClass, int layer, Rect rect);
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 38bb2e1..e94b1cb 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -20,7 +20,6 @@
 
 import android.content.Context;
 import android.content.Intent;
-import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Rect;
@@ -1297,6 +1296,18 @@
         super.sendAccessibilityEvent(eventType);
     }
 
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(AbsListView.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(AbsListView.class.getName());
+    }
+
     /**
      * Indicates whether the children's drawing cache is used during a scroll.
      * By default, the drawing cache is enabled but this will consume more memory.
@@ -5572,6 +5583,16 @@
     }
 
     /**
+     * Hints the RemoteViewsAdapter, if it exists, about which views are currently
+     * being displayed by the AbsListView.
+     */
+    void setVisibleRangeHint(int start, int end) {
+        if (mRemoteAdapter != null) {
+            mRemoteAdapter.setVisibleRangeHint(start, end);
+        }
+    }
+
+    /**
      * Sets the recycler listener to be notified whenever a View is set aside in
      * the recycler for later reuse. This listener can be used to free resources
      * associated to the View.
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index bdaf89e..e36afa3 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -25,6 +25,8 @@
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.ViewConfiguration;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 public abstract class AbsSeekBar extends ProgressBar {
     private Drawable mThumb;
@@ -464,4 +466,15 @@
         return super.onKeyDown(keyCode, event);
     }
 
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(AbsSeekBar.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(AbsSeekBar.class.getName());
+    }
 }
diff --git a/core/java/android/widget/AbsSpinner.java b/core/java/android/widget/AbsSpinner.java
index 3d79205..efdfae3 100644
--- a/core/java/android/widget/AbsSpinner.java
+++ b/core/java/android/widget/AbsSpinner.java
@@ -28,6 +28,8 @@
 import android.util.SparseArray;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 /**
  * An abstract base class for spinner widgets. SDK users will probably not
@@ -40,7 +42,6 @@
 
     int mHeightMeasureSpec;
     int mWidthMeasureSpec;
-    boolean mBlockLayoutRequests;
 
     int mSelectionLeftPadding = 0;
     int mSelectionTopPadding = 0;
@@ -463,4 +464,16 @@
             scrapHeap.clear();
         }
     }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(AbsSpinner.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(AbsSpinner.class.getName());
+    }
 }
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index 40df168..97a864c 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -913,6 +913,7 @@
     @Override
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(AdapterView.class.getName());
         info.setScrollable(isScrollableForAccessibility());
         View selectedView = getSelectedView();
         if (selectedView != null) {
@@ -923,6 +924,7 @@
     @Override
     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
         super.onInitializeAccessibilityEvent(event);
+        event.setClassName(AdapterView.class.getName());
         event.setScrollable(isScrollableForAccessibility());
         View selectedView = getSelectedView();
         if (selectedView != null) {
diff --git a/core/java/android/widget/AdapterViewAnimator.java b/core/java/android/widget/AdapterViewAnimator.java
index c83c780..e226d37 100644
--- a/core/java/android/widget/AdapterViewAnimator.java
+++ b/core/java/android/widget/AdapterViewAnimator.java
@@ -29,6 +29,8 @@
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -555,6 +557,9 @@
             mCurrentWindowStart = newWindowStart;
             mCurrentWindowEnd = newWindowEnd;
             mCurrentWindowStartUnbounded = newWindowStartUnbounded;
+            if (mRemoteViewsAdapter != null) {
+                mRemoteViewsAdapter.setVisibleRangeHint(mCurrentWindowStart, mCurrentWindowEnd);
+            }
         }
         requestLayout();
         invalidate();
@@ -1045,4 +1050,16 @@
      */
     public void fyiWillBeAdvancedByHostKThx() {
     }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(AdapterViewAnimator.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(AdapterViewAnimator.class.getName());
+    }
 }
diff --git a/core/java/android/widget/AdapterViewFlipper.java b/core/java/android/widget/AdapterViewFlipper.java
index 4419886..5096227 100644
--- a/core/java/android/widget/AdapterViewFlipper.java
+++ b/core/java/android/widget/AdapterViewFlipper.java
@@ -16,7 +16,6 @@
 
 package android.widget;
 
-import android.animation.ObjectAnimator;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -27,7 +26,8 @@
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.RemotableViewMethod;
-import android.view.animation.AlphaAnimation;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.RemoteViews.RemoteView;
 
 /**
@@ -268,4 +268,16 @@
         mAdvancedByHost = true;
         updateRunning(false);
     }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(AdapterViewFlipper.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(AdapterViewFlipper.class.getName());
+    }
 }
diff --git a/core/java/android/widget/Button.java b/core/java/android/widget/Button.java
index 8d58a6d..99f4cae 100644
--- a/core/java/android/widget/Button.java
+++ b/core/java/android/widget/Button.java
@@ -18,9 +18,8 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.KeyEvent;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.RemoteViews.RemoteView;
 
 
@@ -107,4 +106,16 @@
     public Button(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
     }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(Button.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(Button.class.getName());
+    }
 }
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index e0403ff..85252af 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -39,6 +39,8 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.AbsListView.OnScrollListener;
 
 import com.android.internal.R;
@@ -431,6 +433,18 @@
         setCurrentLocale(newConfig.locale);
     }
 
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(CalendarView.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(CalendarView.class.getName());
+    }
+
     /**
      * Gets the minimal date supported by this {@link CalendarView} in milliseconds
      * since January 1, 1970 00:00:00 in {@link TimeZone#getDefault()} time
diff --git a/core/java/android/widget/CheckBox.java b/core/java/android/widget/CheckBox.java
index 2788846..0685eea 100644
--- a/core/java/android/widget/CheckBox.java
+++ b/core/java/android/widget/CheckBox.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.util.AttributeSet;
 import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 import com.android.internal.R;
 
@@ -78,4 +79,16 @@
             event.getText().add(mContext.getString(R.string.checkbox_not_checked));
         }
     }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(CheckBox.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(CheckBox.class.getName());
+    }
 }
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index 0a54743..5c7e5a3 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -220,6 +220,7 @@
     @Override
     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
         super.onInitializeAccessibilityEvent(event);
+        event.setClassName(CheckedTextView.class.getName());
         event.setChecked(mChecked);
     }
 
@@ -236,6 +237,7 @@
     @Override
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(CheckedTextView.class.getName());
         info.setChecked(mChecked);
     }
 }
diff --git a/core/java/android/widget/Chronometer.java b/core/java/android/widget/Chronometer.java
index 7e66722..0370049 100644
--- a/core/java/android/widget/Chronometer.java
+++ b/core/java/android/widget/Chronometer.java
@@ -25,6 +25,8 @@
 import android.text.format.DateUtils;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.RemoteViews.RemoteView;
 
 import java.util.Formatter;
@@ -276,4 +278,16 @@
             mOnChronometerTickListener.onChronometerTick(this);
         }
     }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(Chronometer.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(Chronometer.class.getName());
+    }
 }
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index d3cdad8..02c4c4f 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -211,12 +211,14 @@
     @Override
     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
         super.onInitializeAccessibilityEvent(event);
+        event.setClassName(CompoundButton.class.getName());
         event.setChecked(mChecked);
     }
 
     @Override
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(CompoundButton.class.getName());
         info.setCheckable(true);
         info.setChecked(mChecked);
     }
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 0f462ff..110c8f3 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -31,6 +31,7 @@
 import android.view.LayoutInflater;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.NumberPicker.OnValueChangeListener;
@@ -391,6 +392,18 @@
     }
 
     @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(DatePicker.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(DatePicker.class.getName());
+    }
+
+    @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
         setCurrentLocale(newConfig.locale);
diff --git a/core/java/android/widget/DigitalClock.java b/core/java/android/widget/DigitalClock.java
index 379883a..add9d9b 100644
--- a/core/java/android/widget/DigitalClock.java
+++ b/core/java/android/widget/DigitalClock.java
@@ -24,6 +24,8 @@
 import android.provider.Settings;
 import android.text.format.DateFormat;
 import android.util.AttributeSet;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 import java.util.Calendar;
 
@@ -126,4 +128,16 @@
             setFormat();
         }
     }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(DigitalClock.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(DigitalClock.class.getName());
+    }
 }
diff --git a/core/java/android/widget/EditText.java b/core/java/android/widget/EditText.java
index 0da68a4..2fd8768 100644
--- a/core/java/android/widget/EditText.java
+++ b/core/java/android/widget/EditText.java
@@ -24,6 +24,8 @@
 import android.text.method.ArrowKeyMovementMethod;
 import android.text.method.MovementMethod;
 import android.util.AttributeSet;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 
 /*
@@ -114,4 +116,16 @@
         }
         super.setEllipsize(ellipsis);
     }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(EditText.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(EditText.class.getName());
+    }
 }
diff --git a/core/java/android/widget/ExpandableListView.java b/core/java/android/widget/ExpandableListView.java
index ead9b4f..badfaa7 100644
--- a/core/java/android/widget/ExpandableListView.java
+++ b/core/java/android/widget/ExpandableListView.java
@@ -30,6 +30,8 @@
 import android.view.SoundEffectConstants;
 import android.view.View;
 import android.view.ContextMenu.ContextMenuInfo;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.ExpandableListConnector.PositionMetadata;
 
 import java.util.ArrayList;
@@ -1167,4 +1169,15 @@
         }
     }
 
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(ExpandableListView.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(ExpandableListView.class.getName());
+    }
 }
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index 74a57b00..da98884 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -29,6 +29,8 @@
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.RemoteViews.RemoteView;
 
 
@@ -555,6 +557,19 @@
         return new LayoutParams(p);
     }
 
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(FrameLayout.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(FrameLayout.class.getName());
+    }
+
     /**
      * Per-child layout information for layouts that support margins.
      * See {@link android.R.styleable#FrameLayout_Layout FrameLayout Layout Attributes}
diff --git a/core/java/android/widget/Gallery.java b/core/java/android/widget/Gallery.java
index 5e37fa8..03fdc39 100644
--- a/core/java/android/widget/Gallery.java
+++ b/core/java/android/widget/Gallery.java
@@ -32,6 +32,8 @@
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.Transformation;
 
 import com.android.internal.R;
@@ -1355,6 +1357,18 @@
 
     }
 
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(Gallery.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(Gallery.class.getName());
+    }
+
     /**
      * Responsible for fling behavior. Use {@link #startUsingVelocity(int)} to
      * initiate a fling. Each frame of the fling is handled in {@link #run()}.
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index 7cf5168..7d58011 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -27,6 +27,9 @@
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+
 import com.android.internal.R;
 
 import java.lang.reflect.Array;
@@ -1041,6 +1044,18 @@
         }
     }
 
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(GridLayout.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(GridLayout.class.getName());
+    }
+
     // Inner classes
 
     /*
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index 5d406de..be2df8e 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -27,6 +27,8 @@
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.GridLayoutAnimationController;
 import android.widget.RemoteViews.RemoteView;
 
@@ -290,6 +292,7 @@
             pos += mNumColumns;
         }
 
+        setVisibleRangeHint(mFirstPosition, mFirstPosition + getChildCount() - 1);
         return selectedView;
     }
 
@@ -382,6 +385,7 @@
             mFirstPosition = Math.max(0, pos + 1);
         }
 
+        setVisibleRangeHint(mFirstPosition, mFirstPosition + getChildCount() - 1);
         return selectedView;
     }
 
@@ -2116,5 +2120,16 @@
         }
         return result;
     }
-}
 
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(GridView.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(GridView.class.getName());
+    }
+}
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index 1683d20..0b4ebf4 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -721,12 +721,14 @@
     @Override
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(HorizontalScrollView.class.getName());
         info.setScrollable(getScrollRange() > 0);
     }
 
     @Override
     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
         super.onInitializeAccessibilityEvent(event);
+        event.setClassName(HorizontalScrollView.class.getName());
         event.setScrollable(getScrollRange() > 0);
         event.setScrollX(mScrollX);
         event.setScrollY(mScrollY);
diff --git a/core/java/android/widget/ImageButton.java b/core/java/android/widget/ImageButton.java
index d680fad..59a8f28 100644
--- a/core/java/android/widget/ImageButton.java
+++ b/core/java/android/widget/ImageButton.java
@@ -21,6 +21,8 @@
 import android.os.Message;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.RemoteViews.RemoteView;
 
 import java.util.Map;
@@ -90,4 +92,16 @@
     protected boolean onSetAlpha(int alpha) {
         return false;
     }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(ImageButton.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(ImageButton.class.getName());
+    }
 }
diff --git a/core/java/android/widget/ImageSwitcher.java b/core/java/android/widget/ImageSwitcher.java
index bcb750a..c048970 100644
--- a/core/java/android/widget/ImageSwitcher.java
+++ b/core/java/android/widget/ImageSwitcher.java
@@ -16,12 +16,12 @@
 
 package android.widget;
 
-import java.util.Map;
-
 import android.content.Context;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.util.AttributeSet;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 
 public class ImageSwitcher extends ViewSwitcher
@@ -55,5 +55,16 @@
         image.setImageDrawable(drawable);
         showNext();
     }
-}
 
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(ImageSwitcher.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(ImageSwitcher.class.getName());
+    }
+}
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 73e1273..07ae93b 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -37,6 +37,7 @@
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.RemoteViews.RemoteView;
 
 /**
@@ -1060,4 +1061,16 @@
             mDrawable.setVisible(false, false);
         }
     }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(ImageView.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(ImageView.class.getName());
+    }
 }
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index 427fd3e..b5deec7 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -27,6 +27,8 @@
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.RemoteViews.RemoteView;
 
 
@@ -1729,7 +1731,19 @@
     protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
         return p instanceof LinearLayout.LayoutParams;
     }
-    
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(LinearLayout.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(LinearLayout.class.getName());
+    }
+
     /**
      * Per-child layout information associated with ViewLinearLayout.
      * 
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 7f7a3a7..e20d12a 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -32,13 +32,13 @@
 import android.util.SparseBooleanArray;
 import android.view.FocusFinder;
 import android.view.KeyEvent;
-import android.view.MotionEvent;
 import android.view.SoundEffectConstants;
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
 import android.view.ViewParent;
 import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.RemoteViews.RemoteView;
 
 import java.util.ArrayList;
@@ -678,6 +678,7 @@
             pos++;
         }
 
+        setVisibleRangeHint(mFirstPosition, mFirstPosition + getChildCount() - 1);
         return selectedView;
     }
 
@@ -711,7 +712,7 @@
         }
 
         mFirstPosition = pos + 1;
-
+        setVisibleRangeHint(mFirstPosition, mFirstPosition + getChildCount() - 1);
         return selectedView;
     }
 
@@ -3609,4 +3610,16 @@
         }
         return new long[0];
     }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(ListView.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(ListView.class.getName());
+    }
 }
diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java
index f2ea3fc..fc35f05 100644
--- a/core/java/android/widget/MediaController.java
+++ b/core/java/android/widget/MediaController.java
@@ -31,6 +31,8 @@
 import android.view.ViewGroup;
 import android.view.Window;
 import android.view.WindowManager;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.SeekBar.OnSeekBarChangeListener;
 
 import com.android.internal.policy.PolicyManager;
@@ -592,6 +594,18 @@
         super.setEnabled(enabled);
     }
 
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(MediaController.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(MediaController.class.getName());
+    }
+
     private View.OnClickListener mRewListener = new View.OnClickListener() {
         public void onClick(View v) {
             int pos = mPlayer.getCurrentPosition();
diff --git a/core/java/android/widget/MultiAutoCompleteTextView.java b/core/java/android/widget/MultiAutoCompleteTextView.java
index 134e4c4..0b30c84 100644
--- a/core/java/android/widget/MultiAutoCompleteTextView.java
+++ b/core/java/android/widget/MultiAutoCompleteTextView.java
@@ -23,7 +23,8 @@
 import android.text.TextUtils;
 import android.text.method.QwertyKeyListener;
 import android.util.AttributeSet;
-import android.widget.MultiAutoCompleteTextView.Tokenizer;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 /**
  * An editable text view, extending {@link AutoCompleteTextView}, that
@@ -196,6 +197,18 @@
         editable.replace(start, end, mTokenizer.terminateToken(text));
     }
 
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(MultiAutoCompleteTextView.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(MultiAutoCompleteTextView.class.getName());
+    }
+
     public static interface Tokenizer {
         /**
          * Returns the start of the token that ends at offset
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 7d0f98e..a210f0b 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -47,6 +47,7 @@
 import android.view.ViewConfiguration;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.DecelerateInterpolator;
 import android.view.inputmethod.InputMethodManager;
 
@@ -1382,6 +1383,18 @@
         // perceive this widget as several controls rather as a whole.
     }
 
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(NumberPicker.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(NumberPicker.class.getName());
+    }
+
     /**
      * Makes a measure spec that tries greedily to use the max value.
      *
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index df88fec..ace3f60 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -45,6 +45,7 @@
 import android.view.ViewDebug;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.AlphaAnimation;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
@@ -1124,10 +1125,17 @@
     @Override
     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
         super.onInitializeAccessibilityEvent(event);
+        event.setClassName(ProgressBar.class.getName());
         event.setItemCount(mMax);
         event.setCurrentItemIndex(mProgress);
     }
 
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(ProgressBar.class.getName());
+    }
+
     /**
      * Schedule a command for sending an accessibility event.
      * </br>
diff --git a/core/java/android/widget/QuickContactBadge.java b/core/java/android/widget/QuickContactBadge.java
index adc0fb0..786afe2 100644
--- a/core/java/android/widget/QuickContactBadge.java
+++ b/core/java/android/widget/QuickContactBadge.java
@@ -36,6 +36,8 @@
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.View.OnClickListener;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 /**
  * Widget used to show an image with the standard QuickContact badge
@@ -228,6 +230,18 @@
         }
     }
 
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(QuickContactBadge.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(QuickContactBadge.class.getName());
+    }
+
     /**
      * Set a list of specific MIME-types to exclude and not display. For
      * example, this can be used to hide the {@link Contacts#CONTENT_ITEM_TYPE}
diff --git a/core/java/android/widget/RadioButton.java b/core/java/android/widget/RadioButton.java
index 9fa649f..b6dac3e 100644
--- a/core/java/android/widget/RadioButton.java
+++ b/core/java/android/widget/RadioButton.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.util.AttributeSet;
 import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 import com.android.internal.R;
 
@@ -85,4 +86,16 @@
             event.getText().add(mContext.getString(R.string.radiobutton_not_selected));
         }
     }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(RadioButton.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(RadioButton.class.getName());
+    }
 }
diff --git a/core/java/android/widget/RadioGroup.java b/core/java/android/widget/RadioGroup.java
index 393346a..7f53ffd 100644
--- a/core/java/android/widget/RadioGroup.java
+++ b/core/java/android/widget/RadioGroup.java
@@ -23,6 +23,8 @@
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 
 /**
@@ -236,6 +238,18 @@
         return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
     }
 
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(RadioGroup.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(RadioGroup.class.getName());
+    }
+
     /**
      * <p>This set of layout parameters defaults the width and the height of
      * the children to {@link #WRAP_CONTENT} when they are not specified in the
diff --git a/core/java/android/widget/RatingBar.java b/core/java/android/widget/RatingBar.java
index 9e6ff4b..e69577b 100644
--- a/core/java/android/widget/RatingBar.java
+++ b/core/java/android/widget/RatingBar.java
@@ -21,6 +21,8 @@
 import android.graphics.drawable.shapes.RectShape;
 import android.graphics.drawable.shapes.Shape;
 import android.util.AttributeSet;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 import com.android.internal.R;
 
@@ -324,4 +326,15 @@
         super.setMax(max);
     }
     
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(RatingBar.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(RatingBar.class.getName());
+    }
 }
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index a452fec..e4b8f34 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -40,6 +40,7 @@
 import android.view.ViewDebug;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.RemoteViews.RemoteView;
 
 import static android.util.Log.d;
@@ -985,6 +986,18 @@
         return false;
     }
 
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(RelativeLayout.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(RelativeLayout.class.getName());
+    }
+
     /**
      * Compares two views in left-to-right and top-to-bottom fashion.
      */
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index 7b43032..586fdf4 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -68,6 +68,8 @@
     private RemoteViewsAdapterServiceConnection mServiceConnection;
     private WeakReference<RemoteAdapterConnectionCallback> mCallback;
     private FixedSizeRemoteViewsCache mCache;
+    private int mVisibleWindowLowerBound;
+    private int mVisibleWindowUpperBound;
 
     // A flag to determine whether we should notify data set changed after we connect
     private boolean mNotifyDataSetChangedAfterOnServiceConnected = false;
@@ -765,7 +767,7 @@
                     }
                     if (position > -1) {
                         // Load the item, and notify any existing RemoteViewsFrameLayouts
-                        updateRemoteViews(position, isRequested);
+                        updateRemoteViews(position, isRequested, true);
 
                         // Queue up for the next one to load
                         loadNextIndexInBackground();
@@ -827,8 +829,8 @@
         }
     }
 
-    private void updateRemoteViews(final int position, boolean isRequested) {
-        if (!mServiceConnection.isConnected()) return;
+    private void updateRemoteViews(final int position, boolean isRequested, boolean
+            notifyWhenLoaded) {
         IRemoteViewsFactory factory = mServiceConnection.getRemoteViewsFactory();
 
         // Load the item information from the remote service
@@ -864,12 +866,14 @@
             // there is new data for it.
             final RemoteViews rv = remoteViews;
             final int typeId = mCache.getMetaDataAt(position).typeId;
-            mMainQueue.post(new Runnable() {
-                @Override
-                public void run() {
-                    mRequestedViews.notifyOnRemoteViewsLoaded(position, rv, typeId);
-                }
-            });
+            if (notifyWhenLoaded) {
+                mMainQueue.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        mRequestedViews.notifyOnRemoteViewsLoaded(position, rv, typeId);
+                    }
+                });
+            }
         }
     }
 
@@ -929,6 +933,16 @@
         return typeId;
     }
 
+    /**
+     * This method allows an AdapterView using this Adapter to provide information about which
+     * views are currently being displayed. This allows for certain optimizations and preloading
+     * which  wouldn't otherwise be possible.
+     */
+    public void setVisibleRangeHint(int lowerBound, int upperBound) {
+        mVisibleWindowLowerBound = lowerBound;
+        mVisibleWindowUpperBound = upperBound;
+    }
+
     public View getView(int position, View convertView, ViewGroup parent) {
         // "Request" an index so that we can queue it for loading, initiate subsequent
         // preloading, etc.
@@ -1059,6 +1073,13 @@
         // Re-request the new metadata (only after the notification to the factory)
         updateTemporaryMetaData();
 
+        // Pre-load (our best guess of) the views which are currently visible in the AdapterView.
+        // This mitigates flashing and flickering of loading views when a widget notifies that
+        // its data has changed.
+        for (int i = mVisibleWindowLowerBound; i <= mVisibleWindowUpperBound; i++) {
+            updateRemoteViews(i, false, false);
+        }
+
         // Propagate the notification back to the base adapter
         mMainQueue.post(new Runnable() {
             @Override
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 767eaee..3ffc0fe 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -721,12 +721,14 @@
     @Override
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(ScrollView.class.getName());
         info.setScrollable(getScrollRange() > 0);
     }
 
     @Override
     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
         super.onInitializeAccessibilityEvent(event);
+        event.setClassName(ScrollView.class.getName());
         final boolean scrollable = getScrollRange() > 0;
         event.setScrollable(scrollable);
         event.setScrollX(mScrollX);
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 9d2ff2e..99cd0b8 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -35,7 +35,6 @@
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
-import android.os.Handler;
 import android.speech.RecognizerIntent;
 import android.text.Editable;
 import android.text.InputType;
@@ -51,6 +50,8 @@
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.AdapterView.OnItemClickListener;
@@ -1206,6 +1207,18 @@
         setIconified(false);
     }
 
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(SearchView.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(SearchView.class.getName());
+    }
+
     private void adjustDropDownSizeAndPosition() {
         if (mDropDownAnchor.getWidth() > 1) {
             Resources res = getContext().getResources();
diff --git a/core/java/android/widget/SeekBar.java b/core/java/android/widget/SeekBar.java
index c76728f..2737f94 100644
--- a/core/java/android/widget/SeekBar.java
+++ b/core/java/android/widget/SeekBar.java
@@ -18,6 +18,8 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 
 
@@ -117,5 +119,16 @@
             mOnSeekBarChangeListener.onStopTrackingTouch(this);
         }
     }
-    
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(SeekBar.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(SeekBar.class.getName());
+    }
 }
diff --git a/core/java/android/widget/SlidingDrawer.java b/core/java/android/widget/SlidingDrawer.java
index bdeb5c2..14edd10 100644
--- a/core/java/android/widget/SlidingDrawer.java
+++ b/core/java/android/widget/SlidingDrawer.java
@@ -32,6 +32,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 /**
  * SlidingDrawer hides content out of the screen and allows the user to drag a handle
@@ -810,6 +811,18 @@
         }
     }
 
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(SlidingDrawer.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(SlidingDrawer.class.getName());
+    }
+
     private void closeDrawer() {
         moveHandle(COLLAPSED_FULL_CLOSED);
         mContent.setVisibility(View.GONE);
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index ec3790e..ecf19b3 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -29,6 +29,8 @@
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 
 /**
@@ -456,12 +458,24 @@
 
         return handled;
     }
-    
+
     public void onClick(DialogInterface dialog, int which) {
         setSelection(which);
         dialog.dismiss();
     }
 
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(Spinner.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(Spinner.class.getName());
+    }
+
     /**
      * Sets the prompt to display when the dialog is shown.
      * @param prompt the prompt to set
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index 03e6e99..22df3bc 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -40,6 +40,8 @@
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.LinearInterpolator;
 import android.widget.RemoteViews.RemoteView;
 
@@ -1216,6 +1218,18 @@
         measureChildren();
     }
 
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(StackView.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(StackView.class.getName());
+    }
+
     class LayoutParams extends ViewGroup.LayoutParams {
         int horizontalOffset;
         int verticalOffset;
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 02c9d03..334b9c4 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -35,6 +35,7 @@
 import android.view.VelocityTracker;
 import android.view.ViewConfiguration;
 import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 import com.android.internal.R;
 
@@ -651,4 +652,16 @@
         mThumbDrawable.jumpToCurrentState();
         mTrackDrawable.jumpToCurrentState();
     }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(Switch.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(Switch.class.getName());
+    }
 }
diff --git a/core/java/android/widget/TabHost.java b/core/java/android/widget/TabHost.java
index 88d7230..9b292be 100644
--- a/core/java/android/widget/TabHost.java
+++ b/core/java/android/widget/TabHost.java
@@ -33,6 +33,8 @@
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 import android.view.Window;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -321,6 +323,18 @@
         }
     }
 
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(TabHost.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(TabHost.class.getName());
+    }
+
     public void setCurrentTab(int index) {
         if (index < 0 || index >= mTabSpecs.size()) {
             return;
diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java
index 80bfe99..8901037 100644
--- a/core/java/android/widget/TabWidget.java
+++ b/core/java/android/widget/TabWidget.java
@@ -29,6 +29,7 @@
 import android.view.View.OnFocusChangeListener;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 /**
  *
@@ -416,10 +417,28 @@
     @Override
     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
         super.onInitializeAccessibilityEvent(event);
+        event.setClassName(TabWidget.class.getName());
         event.setItemCount(getTabCount());
         event.setCurrentItemIndex(mSelectedTab);
     }
 
+
+    @Override
+    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
+        // this class fires events only when tabs are focused or selected
+        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED && isFocused()) {
+            event.recycle();
+            return;
+        }
+        super.sendAccessibilityEventUnchecked(event);
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(TabWidget.class.getName());
+    }
+
     /**
      * Sets the current tab and focuses the UI on it.
      * This method makes sure that the focused tab matches the selected
@@ -485,16 +504,6 @@
         mSelectedTab = -1;
     }
 
-    @Override
-    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
-        // this class fires events only when tabs are focused or selected
-        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED && isFocused()) {
-            event.recycle();
-            return;
-        }
-        super.sendAccessibilityEventUnchecked(event);
-    }
-
     /**
      * Provides a way for {@link TabHost} to be notified that the user clicked on a tab indicator.
      */
diff --git a/core/java/android/widget/TableLayout.java b/core/java/android/widget/TableLayout.java
index 842b087..f5d3746 100644
--- a/core/java/android/widget/TableLayout.java
+++ b/core/java/android/widget/TableLayout.java
@@ -24,6 +24,8 @@
 import android.util.SparseBooleanArray;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 import java.util.regex.Pattern;
 
@@ -658,6 +660,18 @@
         return new LayoutParams(p);
     }
 
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(TableLayout.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(TableLayout.class.getName());
+    }
+
     /**
      * <p>This set of layout parameters enforces the width of each child to be
      * {@link #MATCH_PARENT} and the height of each child to be
diff --git a/core/java/android/widget/TableRow.java b/core/java/android/widget/TableRow.java
index 3fd4631..01c4c2c 100644
--- a/core/java/android/widget/TableRow.java
+++ b/core/java/android/widget/TableRow.java
@@ -24,6 +24,8 @@
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 
 /**
@@ -377,6 +379,18 @@
         return new LayoutParams(p);
     }
 
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(TableRow.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(TableRow.class.getName());
+    }
+
     /**
      * <p>Set of layout parameters used in table rows.</p>
      *
diff --git a/core/java/android/widget/TextSwitcher.java b/core/java/android/widget/TextSwitcher.java
index a8794a3..1aefd2b 100644
--- a/core/java/android/widget/TextSwitcher.java
+++ b/core/java/android/widget/TextSwitcher.java
@@ -21,6 +21,8 @@
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 /**
  * Specialized {@link android.widget.ViewSwitcher} that contains
@@ -88,4 +90,16 @@
     public void setCurrentText(CharSequence text) {
         ((TextView)getCurrentView()).setText(text);
     }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(TextSwitcher.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(TextSwitcher.class.getName());
+    }
 }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index acea1a1..02144a8 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -9029,6 +9029,7 @@
     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
         super.onInitializeAccessibilityEvent(event);
 
+        event.setClassName(TextView.class.getName());
         final boolean isPassword = hasPasswordTransformationMethod();
         event.setPassword(isPassword);
 
@@ -9043,11 +9044,13 @@
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
 
+        info.setClassName(TextView.class.getName());
         final boolean isPassword = hasPasswordTransformationMethod();
+        info.setPassword(isPassword);
+
         if (!isPassword) {
             info.setText(getTextForAccessibility());
         }
-        info.setPassword(isPassword);
     }
 
     @Override
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index afca2db..8f10fff 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -27,6 +27,7 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.NumberPicker.OnValueChangeListener;
@@ -476,6 +477,18 @@
         event.getText().add(selectedDateUtterance);
     }
 
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(TimePicker.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(TimePicker.class.getName());
+    }
+
     private void updateHourControl() {
         if (is24HourView()) {
             mHourSpinner.setMinValue(0);
diff --git a/core/java/android/widget/ToggleButton.java b/core/java/android/widget/ToggleButton.java
index a754268..a0edafe 100644
--- a/core/java/android/widget/ToggleButton.java
+++ b/core/java/android/widget/ToggleButton.java
@@ -23,6 +23,7 @@
 import android.graphics.drawable.LayerDrawable;
 import android.util.AttributeSet;
 import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 import com.android.internal.R;
 
@@ -161,4 +162,16 @@
             event.getText().add(mContext.getString(R.string.togglebutton_not_pressed));
         }
     }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(ToggleButton.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(ToggleButton.class.getName());
+    }
 }
diff --git a/core/java/android/widget/TwoLineListItem.java b/core/java/android/widget/TwoLineListItem.java
index eab6f2d..e707ea3 100644
--- a/core/java/android/widget/TwoLineListItem.java
+++ b/core/java/android/widget/TwoLineListItem.java
@@ -16,14 +16,12 @@
 
 package android.widget;
 
-import com.android.internal.R;
-
-
 import android.annotation.Widget;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
-import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.RelativeLayout;
 
 /**
@@ -86,4 +84,16 @@
     public TextView getText2() {
         return mText2;
     }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(TwoLineListItem.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(TwoLineListItem.class.getName());
+    }
 }
diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java
index 64fdf34..0fba498 100644
--- a/core/java/android/widget/VideoView.java
+++ b/core/java/android/widget/VideoView.java
@@ -34,6 +34,8 @@
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
 import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.MediaController.MediaPlayerControl;
 
 import java.io.IOException;
@@ -124,6 +126,18 @@
         setMeasuredDimension(width, height);
     }
 
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(VideoView.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(VideoView.class.getName());
+    }
+
     public int resolveAdjustedSize(int desiredSize, int measureSpec) {
         int result = desiredSize;
         int specMode = MeasureSpec.getMode(measureSpec);
diff --git a/core/java/android/widget/ViewAnimator.java b/core/java/android/widget/ViewAnimator.java
index 71ff66b..6a68240 100644
--- a/core/java/android/widget/ViewAnimator.java
+++ b/core/java/android/widget/ViewAnimator.java
@@ -22,6 +22,8 @@
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 
@@ -341,4 +343,16 @@
     public int getBaseline() {
         return (getCurrentView() != null) ? getCurrentView().getBaseline() : super.getBaseline();
     }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(ViewAnimator.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(ViewAnimator.class.getName());
+    }
 }
diff --git a/core/java/android/widget/ViewFlipper.java b/core/java/android/widget/ViewFlipper.java
index c6f6e81..061bb00 100644
--- a/core/java/android/widget/ViewFlipper.java
+++ b/core/java/android/widget/ViewFlipper.java
@@ -25,6 +25,8 @@
 import android.os.Message;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.RemoteViews.RemoteView;
 
 /**
@@ -139,6 +141,18 @@
         updateRunning();
     }
 
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(ViewFlipper.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(ViewFlipper.class.getName());
+    }
+
     /**
      * Internal method to start or stop dispatching flip {@link Message} based
      * on {@link #mRunning} and {@link #mVisible} state.
diff --git a/core/java/android/widget/ViewSwitcher.java b/core/java/android/widget/ViewSwitcher.java
index 71ae624..0376918 100644
--- a/core/java/android/widget/ViewSwitcher.java
+++ b/core/java/android/widget/ViewSwitcher.java
@@ -20,6 +20,8 @@
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 /**
  * {@link ViewAnimator} that switches between two views, and has a factory
@@ -66,6 +68,18 @@
         super.addView(child, index, params);
     }
 
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(ViewSwitcher.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(ViewSwitcher.class.getName());
+    }
+
     /**
      * Returns the next view to be displayed.
      *
diff --git a/core/java/android/widget/ZoomButton.java b/core/java/android/widget/ZoomButton.java
index eb372ca..af17c94 100644
--- a/core/java/android/widget/ZoomButton.java
+++ b/core/java/android/widget/ZoomButton.java
@@ -23,6 +23,8 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.View.OnLongClickListener;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 public class ZoomButton extends ImageButton implements OnLongClickListener {
 
@@ -96,4 +98,16 @@
         clearFocus();
         return super.dispatchUnhandledMove(focused, direction);
     }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(ZoomButton.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(ZoomButton.class.getName());
+    }
 }
diff --git a/core/java/android/widget/ZoomControls.java b/core/java/android/widget/ZoomControls.java
index a12aee5..8897875 100644
--- a/core/java/android/widget/ZoomControls.java
+++ b/core/java/android/widget/ZoomControls.java
@@ -22,6 +22,8 @@
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.AlphaAnimation;
 
 import com.android.internal.R;
@@ -106,4 +108,16 @@
     public boolean hasFocus() {
         return mZoomIn.hasFocus() || mZoomOut.hasFocus();
     }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(ZoomControls.class.getName());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(ZoomControls.class.getName());
+    }
 }
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 4aa13f9..3e9ab86 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -820,7 +820,12 @@
             posPtr[indx].fX = SkFloatToScalar(posArray[indx << 1]);
             posPtr[indx].fY = SkFloatToScalar(posArray[(indx << 1) + 1]);
         }
+        
+        SkPaint::TextEncoding encoding = paint->getTextEncoding();
+        paint->setTextEncoding(SkPaint::kUTF16_TextEncoding);
         canvas->drawPosText(textArray + index, count << 1, posPtr, *paint);
+        paint->setTextEncoding(encoding);
+        
         if (text) {
             env->ReleaseCharArrayElements(text, textArray, 0);
         }
@@ -844,7 +849,12 @@
             posPtr[indx].fX = SkFloatToScalar(posArray[indx << 1]);
             posPtr[indx].fY = SkFloatToScalar(posArray[(indx << 1) + 1]);
         }
+
+        SkPaint::TextEncoding encoding = paint->getTextEncoding();
+        paint->setTextEncoding(SkPaint::kUTF16_TextEncoding);
         canvas->drawPosText(text_, byteLength << 1, posPtr, *paint);
+        paint->setTextEncoding(encoding);
+
         if (text) {
             env->ReleaseStringChars(text, (const jchar*) text_);
         }
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index 1b7623d..d26f563 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -659,6 +659,13 @@
             continue;
         }
 
+#if DEBUG_GLYPHS
+        ALOGD("Returned logclusters");
+        for (size_t i = 0; i < mShaperItem.num_glyphs; i++) {
+            ALOGD("         -- lc[%d] = %d, hb-adv[%d] = %0.2f", i, mShaperItem.log_clusters[i],
+                    i, HBFixedToFloat(mShaperItem.advances[i]));
+        }
+#endif
         // Get Advances and their total
         jfloat currentAdvance = HBFixedToFloat(mShaperItem.advances[mShaperItem.log_clusters[0]]);
         jfloat totalFontRunAdvance = currentAdvance;
@@ -670,11 +677,14 @@
                 outAdvances->add(0);
             } else {
                 currentAdvance = HBFixedToFloat(mShaperItem.advances[mShaperItem.log_clusters[i]]);
-                totalFontRunAdvance += currentAdvance;
                 outAdvances->add(currentAdvance);
             }
         }
-
+        // TODO: can be removed and go back in the previous loop when Harfbuzz log clusters are fixed
+        for (size_t i = 1; i < mShaperItem.num_glyphs; i++) {
+            currentAdvance = HBFixedToFloat(mShaperItem.advances[i]);
+            totalFontRunAdvance += currentAdvance;
+        }
         totalAdvance += totalFontRunAdvance;
 
 #if DEBUG_ADVANCES
@@ -684,7 +694,6 @@
                     (*outAdvances)[i], mShaperItem.log_clusters[i], totalFontRunAdvance);
         }
 #endif
-
         // Get Glyphs and reverse them in place if RTL
         if (outGlyphs) {
             size_t countGlyphs = mShaperItem.num_glyphs;
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 41756a1..8341e4c 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -152,7 +152,7 @@
 static int
 android_media_AudioSystem_setPhoneState(JNIEnv *env, jobject thiz, jint state)
 {
-    return check_AudioSystem_Command(AudioSystem::setPhoneState(state));
+    return check_AudioSystem_Command(AudioSystem::setPhoneState((audio_mode_t) state));
 }
 
 static int
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 23ad154..c8251bf 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -44,6 +44,7 @@
 #include <SkiaColorFilter.h>
 #include <Rect.h>
 
+#include <TextLayout.h>
 #include <TextLayoutCache.h>
 
 namespace android {
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml b/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml
index 568933c..43d0a2c 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_password_landscape.xml
@@ -97,8 +97,7 @@
                     android:textAppearance="?android:attr/textAppearanceMedium"
                     android:background="@null"
                     android:textColor="#ffffffff"
-                    android:imeOptions="flagNoFullscreen|actionDone"
-                    android:privateImeOptions="com.google.android.inputmethod.latin.forceAscii"
+                    android:imeOptions="flagForceAscii|flagNoFullscreen|actionDone"
                     />
 
                 <!-- This delete button is only visible for numeric PIN entry -->
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml b/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
index 335a641..8c02888 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
@@ -98,7 +98,7 @@
                     android:textAppearance="?android:attr/textAppearanceMedium"
                     android:background="@null"
                     android:textColor="#ffffffff"
-                    android:privateImeOptions="com.google.android.inputmethod.latin.forceAscii"
+                    android:imeOptions="flagForceAscii"
                 />
 
                 <!-- This delete button is only visible for numeric PIN entry -->
diff --git a/core/res/res/layout/keyguard_screen_password_landscape.xml b/core/res/res/layout/keyguard_screen_password_landscape.xml
index e95553f..66d7fd7 100644
--- a/core/res/res/layout/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_password_landscape.xml
@@ -153,8 +153,7 @@
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:background="@null"
             android:textColor="?android:attr/textColorPrimary"
-            android:imeOptions="flagNoFullscreen|actionDone"
-            android:privateImeOptions="com.google.android.inputmethod.latin.forceAscii"
+            android:imeOptions="flagForceAscii|flagNoFullscreen|actionDone"
             />
 
         <!-- This delete button is only visible for numeric PIN entry -->
diff --git a/core/res/res/layout/keyguard_screen_password_portrait.xml b/core/res/res/layout/keyguard_screen_password_portrait.xml
index cfcc794..426b2f7 100644
--- a/core/res/res/layout/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_password_portrait.xml
@@ -119,8 +119,7 @@
             android:background="@null"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textColor="#ffffffff"
-            android:imeOptions="actionDone"
-            android:privateImeOptions="com.google.android.inputmethod.latin.forceAscii"
+            android:imeOptions="flagForceAscii|actionDone"
             />
 
         <!-- This delete button is only visible for numeric PIN entry -->
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index e1c73fd..5cac42a 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -1516,6 +1516,9 @@
     /**
      * Draw the text in the array, with each character's origin specified by
      * the pos array.
+     * 
+     * This method does not support glyph composition and decomposition and
+     * should therefore not be used to render complex scripts.
      *
      * @param text     The text to be drawn
      * @param index    The index of the first character to draw
@@ -1536,6 +1539,9 @@
     /**
      * Draw the text in the array, with each character's origin specified by
      * the pos array.
+     * 
+     * This method does not support glyph composition and decomposition and
+     * should therefore not be used to render complex scripts.
      *
      * @param text  The text to be drawn
      * @param pos   Array of [x,y] positions, used to position each character
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 13beaa5..b56701b 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -62,8 +62,8 @@
     static status_t setStreamMute(audio_stream_type_t stream, bool mute);
     static status_t getStreamMute(audio_stream_type_t stream, bool* mute);
 
-    // set audio mode in audio hardware (see audio_mode_t)
-    static status_t setMode(int mode);
+    // set audio mode in audio hardware
+    static status_t setMode(audio_mode_t mode);
 
     // returns true in *state if tracks are active on the specified stream or has been active
     // in the past inPastMs milliseconds
@@ -142,7 +142,7 @@
     //
     static status_t setDeviceConnectionState(audio_devices_t device, audio_policy_dev_state_t state, const char *device_address);
     static audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device, const char *device_address);
-    static status_t setPhoneState(int state);
+    static status_t setPhoneState(audio_mode_t state);
     static status_t setRingerMode(uint32_t mode, uint32_t mask);
     static status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config);
     static audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage);
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index 15d3ca9..3999479 100644
--- a/include/media/IAudioFlinger.h
+++ b/include/media/IAudioFlinger.h
@@ -96,7 +96,7 @@
     virtual     bool        streamMute(audio_stream_type_t stream) const = 0;
 
     // set audio mode
-    virtual     status_t    setMode(int mode) = 0;
+    virtual     status_t    setMode(audio_mode_t mode) = 0;
 
     // mic mute/state
     virtual     status_t    setMicMute(bool state) = 0;
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
index 5a4d59b..a83d806 100644
--- a/include/media/IAudioPolicyService.h
+++ b/include/media/IAudioPolicyService.h
@@ -45,7 +45,7 @@
                                               const char *device_address) = 0;
     virtual audio_policy_dev_state_t getDeviceConnectionState(audio_devices_t device,
                                                                           const char *device_address) = 0;
-    virtual status_t setPhoneState(int state) = 0;
+    virtual status_t setPhoneState(audio_mode_t state) = 0;
     virtual status_t setRingerMode(uint32_t mode, uint32_t mask) = 0;
     virtual status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config) = 0;
     virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) = 0;
diff --git a/include/media/Visualizer.h b/include/media/Visualizer.h
index 5d2c874..1a4cbca 100644
--- a/include/media/Visualizer.h
+++ b/include/media/Visualizer.h
@@ -143,7 +143,7 @@
     void periodicCapture();
     uint32_t initCaptureSize();
 
-    Mutex mLock;
+    Mutex mCaptureLock;
     uint32_t mCaptureRate;
     uint32_t mCaptureSize;
     uint32_t mSampleRate;
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 7af4a87..23670df 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -43,13 +43,12 @@
     IEffectClient.cpp \
     AudioEffect.cpp \
     Visualizer.cpp \
-    MemoryLeakTrackUtil.cpp \
-    fixedfft.cpp.arm
+    MemoryLeakTrackUtil.cpp
 
 LOCAL_SHARED_LIBRARIES := \
 	libui libcutils libutils libbinder libsonivox libicuuc libexpat \
         libcamera_client libstagefright_foundation \
-        libgui libdl
+        libgui libdl libaudioutils
 
 LOCAL_WHOLE_STATIC_LIBRARY := libmedia_helper
 
@@ -61,6 +60,7 @@
     $(TOP)/frameworks/base/include/media/stagefright/openmax \
     external/icu4c/common \
     external/expat/lib \
-    system/media/audio_effects/include
+    system/media/audio_effects/include \
+    system/media/audio_utils/include
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index d52f8f8..28892df 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -156,7 +156,7 @@
     return NO_ERROR;
 }
 
-status_t AudioSystem::setMode(int mode)
+status_t AudioSystem::setMode(audio_mode_t mode)
 {
     if (uint32_t(mode) >= AUDIO_MODE_CNT) return BAD_VALUE;
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
@@ -536,7 +536,7 @@
     return aps->getDeviceConnectionState(device, device_address);
 }
 
-status_t AudioSystem::setPhoneState(int state)
+status_t AudioSystem::setPhoneState(audio_mode_t state)
 {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 9ed1a2a..eef551c 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -289,7 +289,7 @@
         return reply.readInt32();
     }
 
-    virtual status_t setMode(int mode)
+    virtual status_t setMode(audio_mode_t mode)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
@@ -786,7 +786,7 @@
         } break;
         case SET_MODE: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            int mode = data.readInt32();
+            audio_mode_t mode = (audio_mode_t) data.readInt32();
             reply->writeInt32( setMode(mode) );
             return NO_ERROR;
         } break;
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index 952d7b2..6205ebd 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -91,7 +91,7 @@
         return static_cast <audio_policy_dev_state_t>(reply.readInt32());
     }
 
-    virtual status_t setPhoneState(int state)
+    virtual status_t setPhoneState(audio_mode_t state)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
@@ -401,7 +401,7 @@
 
         case SET_PHONE_STATE: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
-            reply->writeInt32(static_cast <uint32_t>(setPhoneState(data.readInt32())));
+            reply->writeInt32(static_cast <uint32_t>(setPhoneState((audio_mode_t) data.readInt32())));
             return NO_ERROR;
         } break;
 
diff --git a/media/libmedia/Visualizer.cpp b/media/libmedia/Visualizer.cpp
index 66758d2..478654a 100644
--- a/media/libmedia/Visualizer.cpp
+++ b/media/libmedia/Visualizer.cpp
@@ -27,8 +27,7 @@
 #include <cutils/bitops.h>
 
 #include <media/Visualizer.h>
-
-extern void fixed_fft_real(int n, int32_t *v);
+#include <audio_utils/fixedfft.h>
 
 namespace android {
 
@@ -54,7 +53,7 @@
 
 status_t Visualizer::setEnabled(bool enabled)
 {
-    Mutex::Autolock _l(mLock);
+    Mutex::Autolock _l(mCaptureLock);
 
     sp<CaptureThread> t = mCaptureThread;
     if (t != 0) {
@@ -93,7 +92,7 @@
     if (rate > CAPTURE_RATE_MAX) {
         return BAD_VALUE;
     }
-    Mutex::Autolock _l(mLock);
+    Mutex::Autolock _l(mCaptureLock);
 
     if (mEnabled) {
         return INVALID_OPERATION;
@@ -129,7 +128,7 @@
         return BAD_VALUE;
     }
 
-    Mutex::Autolock _l(mLock);
+    Mutex::Autolock _l(mCaptureLock);
     if (mEnabled) {
         return INVALID_OPERATION;
     }
@@ -231,7 +230,7 @@
 
 void Visualizer::periodicCapture()
 {
-    Mutex::Autolock _l(mLock);
+    Mutex::Autolock _l(mCaptureLock);
     ALOGV("periodicCapture() %p mCaptureCallBack %p mCaptureFlags 0x%08x",
             this, mCaptureCallBack, mCaptureFlags);
     if (mCaptureCallBack != NULL &&
diff --git a/media/libmedia/fixedfft.cpp b/media/libmedia/fixedfft.cpp
deleted file mode 100644
index 2b495e6..0000000
--- a/media/libmedia/fixedfft.cpp
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* A Fixed point implementation of Fast Fourier Transform (FFT). Complex numbers
- * are represented by 32-bit integers, where higher 16 bits are real part and
- * lower ones are imaginary part. Few compromises are made between efficiency,
- * accuracy, and maintainability. To make it fast, arithmetic shifts are used
- * instead of divisions, and bitwise inverses are used instead of negates. To
- * keep it small, only radix-2 Cooley-Tukey algorithm is implemented, and only
- * half of the twiddle factors are stored. Although there are still ways to make
- * it even faster or smaller, it costs too much on one of the aspects.
- */
-
-#include <stdio.h>
-#include <stdint.h>
-#ifdef __arm__
-#include <machine/cpu-features.h>
-#endif
-
-#define LOG_FFT_SIZE 10
-#define MAX_FFT_SIZE (1 << LOG_FFT_SIZE)
-
-static const int32_t twiddle[MAX_FFT_SIZE / 4] = {
-    0x00008000, 0xff378001, 0xfe6e8002, 0xfda58006, 0xfcdc800a, 0xfc13800f,
-    0xfb4a8016, 0xfa81801e, 0xf9b88027, 0xf8ef8032, 0xf827803e, 0xf75e804b,
-    0xf6958059, 0xf5cd8068, 0xf5058079, 0xf43c808b, 0xf374809e, 0xf2ac80b2,
-    0xf1e480c8, 0xf11c80de, 0xf05580f6, 0xef8d8110, 0xeec6812a, 0xedff8146,
-    0xed388163, 0xec718181, 0xebab81a0, 0xeae481c1, 0xea1e81e2, 0xe9588205,
-    0xe892822a, 0xe7cd824f, 0xe7078276, 0xe642829d, 0xe57d82c6, 0xe4b982f1,
-    0xe3f4831c, 0xe3308349, 0xe26d8377, 0xe1a983a6, 0xe0e683d6, 0xe0238407,
-    0xdf61843a, 0xde9e846e, 0xdddc84a3, 0xdd1b84d9, 0xdc598511, 0xdb998549,
-    0xdad88583, 0xda1885be, 0xd95885fa, 0xd8988637, 0xd7d98676, 0xd71b86b6,
-    0xd65c86f6, 0xd59e8738, 0xd4e1877b, 0xd42487c0, 0xd3678805, 0xd2ab884c,
-    0xd1ef8894, 0xd13488dd, 0xd0798927, 0xcfbe8972, 0xcf0489be, 0xce4b8a0c,
-    0xcd928a5a, 0xccd98aaa, 0xcc218afb, 0xcb698b4d, 0xcab28ba0, 0xc9fc8bf5,
-    0xc9468c4a, 0xc8908ca1, 0xc7db8cf8, 0xc7278d51, 0xc6738dab, 0xc5c08e06,
-    0xc50d8e62, 0xc45b8ebf, 0xc3a98f1d, 0xc2f88f7d, 0xc2488fdd, 0xc198903e,
-    0xc0e990a1, 0xc03a9105, 0xbf8c9169, 0xbedf91cf, 0xbe329236, 0xbd86929e,
-    0xbcda9307, 0xbc2f9371, 0xbb8593dc, 0xbadc9448, 0xba3394b5, 0xb98b9523,
-    0xb8e39592, 0xb83c9603, 0xb7969674, 0xb6f196e6, 0xb64c9759, 0xb5a897ce,
-    0xb5059843, 0xb46298b9, 0xb3c09930, 0xb31f99a9, 0xb27f9a22, 0xb1df9a9c,
-    0xb1409b17, 0xb0a29b94, 0xb0059c11, 0xaf689c8f, 0xaecc9d0e, 0xae319d8e,
-    0xad979e0f, 0xacfd9e91, 0xac659f14, 0xabcd9f98, 0xab36a01c, 0xaaa0a0a2,
-    0xaa0aa129, 0xa976a1b0, 0xa8e2a238, 0xa84fa2c2, 0xa7bda34c, 0xa72ca3d7,
-    0xa69ca463, 0xa60ca4f0, 0xa57ea57e, 0xa4f0a60c, 0xa463a69c, 0xa3d7a72c,
-    0xa34ca7bd, 0xa2c2a84f, 0xa238a8e2, 0xa1b0a976, 0xa129aa0a, 0xa0a2aaa0,
-    0xa01cab36, 0x9f98abcd, 0x9f14ac65, 0x9e91acfd, 0x9e0fad97, 0x9d8eae31,
-    0x9d0eaecc, 0x9c8faf68, 0x9c11b005, 0x9b94b0a2, 0x9b17b140, 0x9a9cb1df,
-    0x9a22b27f, 0x99a9b31f, 0x9930b3c0, 0x98b9b462, 0x9843b505, 0x97ceb5a8,
-    0x9759b64c, 0x96e6b6f1, 0x9674b796, 0x9603b83c, 0x9592b8e3, 0x9523b98b,
-    0x94b5ba33, 0x9448badc, 0x93dcbb85, 0x9371bc2f, 0x9307bcda, 0x929ebd86,
-    0x9236be32, 0x91cfbedf, 0x9169bf8c, 0x9105c03a, 0x90a1c0e9, 0x903ec198,
-    0x8fddc248, 0x8f7dc2f8, 0x8f1dc3a9, 0x8ebfc45b, 0x8e62c50d, 0x8e06c5c0,
-    0x8dabc673, 0x8d51c727, 0x8cf8c7db, 0x8ca1c890, 0x8c4ac946, 0x8bf5c9fc,
-    0x8ba0cab2, 0x8b4dcb69, 0x8afbcc21, 0x8aaaccd9, 0x8a5acd92, 0x8a0cce4b,
-    0x89becf04, 0x8972cfbe, 0x8927d079, 0x88ddd134, 0x8894d1ef, 0x884cd2ab,
-    0x8805d367, 0x87c0d424, 0x877bd4e1, 0x8738d59e, 0x86f6d65c, 0x86b6d71b,
-    0x8676d7d9, 0x8637d898, 0x85fad958, 0x85beda18, 0x8583dad8, 0x8549db99,
-    0x8511dc59, 0x84d9dd1b, 0x84a3dddc, 0x846ede9e, 0x843adf61, 0x8407e023,
-    0x83d6e0e6, 0x83a6e1a9, 0x8377e26d, 0x8349e330, 0x831ce3f4, 0x82f1e4b9,
-    0x82c6e57d, 0x829de642, 0x8276e707, 0x824fe7cd, 0x822ae892, 0x8205e958,
-    0x81e2ea1e, 0x81c1eae4, 0x81a0ebab, 0x8181ec71, 0x8163ed38, 0x8146edff,
-    0x812aeec6, 0x8110ef8d, 0x80f6f055, 0x80def11c, 0x80c8f1e4, 0x80b2f2ac,
-    0x809ef374, 0x808bf43c, 0x8079f505, 0x8068f5cd, 0x8059f695, 0x804bf75e,
-    0x803ef827, 0x8032f8ef, 0x8027f9b8, 0x801efa81, 0x8016fb4a, 0x800ffc13,
-    0x800afcdc, 0x8006fda5, 0x8002fe6e, 0x8001ff37,
-};
-
-/* Returns the multiplication of \conj{a} and {b}. */
-static inline int32_t mult(int32_t a, int32_t b)
-{
-#if __ARM_ARCH__ >= 6
-    int32_t t = b;
-    __asm__("smuad  %0, %0, %1"          : "+r" (t) : "r" (a));
-    __asm__("smusdx %0, %0, %1"          : "+r" (b) : "r" (a));
-    __asm__("pkhtb  %0, %0, %1, ASR #16" : "+r" (t) : "r" (b));
-    return t;
-#else
-    return (((a >> 16) * (b >> 16) + (int16_t)a * (int16_t)b) & ~0xFFFF) |
-        ((((a >> 16) * (int16_t)b - (int16_t)a * (b >> 16)) >> 16) & 0xFFFF);
-#endif
-}
-
-static inline int32_t half(int32_t a)
-{
-#if __ARM_ARCH__ >= 6
-    __asm__("shadd16 %0, %0, %1" : "+r" (a) : "r" (0));
-    return a;
-#else
-    return ((a >> 1) & ~0x8000) | (a & 0x8000);
-#endif
-}
-
-void fixed_fft(int n, int32_t *v)
-{
-    int scale = LOG_FFT_SIZE, i, p, r;
-
-    for (r = 0, i = 1; i < n; ++i) {
-        for (p = n; !(p & r); p >>= 1, r ^= p);
-        if (i < r) {
-            int32_t t = v[i];
-            v[i] = v[r];
-            v[r] = t;
-        }
-    }
-
-    for (p = 1; p < n; p <<= 1) {
-        --scale;
-
-        for (i = 0; i < n; i += p << 1) {
-            int32_t x = half(v[i]);
-            int32_t y = half(v[i + p]);
-            v[i] = x + y;
-            v[i + p] = x - y;
-        }
-
-        for (r = 1; r < p; ++r) {
-            int32_t w = MAX_FFT_SIZE / 4 - (r << scale);
-            i = w >> 31;
-            w = twiddle[(w ^ i) - i] ^ (i << 16);
-            for (i = r; i < n; i += p << 1) {
-                int32_t x = half(v[i]);
-                int32_t y = mult(w, v[i + p]);
-                v[i] = x - y;
-                v[i + p] = x + y;
-            }
-        }
-    }
-}
-
-void fixed_fft_real(int n, int32_t *v)
-{
-    int scale = LOG_FFT_SIZE, m = n >> 1, i;
-
-    fixed_fft(n, v);
-    for (i = 1; i <= n; i <<= 1, --scale);
-    v[0] = mult(~v[0], 0x80008000);
-    v[m] = half(v[m]);
-
-    for (i = 1; i < n >> 1; ++i) {
-        int32_t x = half(v[i]);
-        int32_t z = half(v[n - i]);
-        int32_t y = z - (x ^ 0xFFFF);
-        x = half(x + (z ^ 0xFFFF));
-        y = mult(y, twiddle[i << scale]);
-        v[i] = x - y;
-        v[n - i] = (x + y) ^ 0xFFFF;
-    }
-}
diff --git a/opengl/libs/GLES_trace/src/gltrace_fixup.cpp b/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
index 5220aa4..daba3ff 100644
--- a/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
+++ b/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
@@ -107,19 +107,11 @@
     fb->add_contents(fbcontents, fbsize);
 }
 
-void fixup_glTexImage2D(GLMessage *glmsg) {
-    /* void glTexImage2D(GLenum target,
-                        GLint level,
-                        GLint internalformat,
-                        GLsizei width,
-                        GLsizei height,
-                        GLint border,
-                        GLenum format,
-                        GLenum type,
-                        const GLvoid *data); 
-     */
-    GLMessage_DataType arg_width  = glmsg->args(3);
-    GLMessage_DataType arg_height = glmsg->args(4);
+/** Common fixup routing for glTexImage2D & glTexSubImage2D. */
+void fixup_glTexImage(int widthIndex, int heightIndex, GLMessage *glmsg) {
+    GLMessage_DataType arg_width  = glmsg->args(widthIndex);
+    GLMessage_DataType arg_height = glmsg->args(heightIndex);
+
     GLMessage_DataType arg_format = glmsg->args(6);
     GLMessage_DataType arg_type   = glmsg->args(7);
     GLMessage_DataType *arg_data  = glmsg->mutable_args(8);
@@ -133,21 +125,51 @@
     int bytesPerTexel = getBytesPerTexel(format, type);
 
     arg_data->set_type(GLMessage::DataType::BYTE);
-    arg_data->set_isarray(true);
     arg_data->clear_rawbytes();
 
     if (data != NULL) {
+        arg_data->set_isarray(true);
         arg_data->add_rawbytes(data, bytesPerTexel * width * height);
     } else {
-        ALOGE("fixup_glTexImage2D: image data is NULL.\n");
+        arg_data->set_isarray(false);
         arg_data->set_type(GLMessage::DataType::VOID);
-        // FIXME:
-        // This will create the texture, but it will be uninitialized. 
-        // It can later be initialized with glTexSubImage2D or by
-        // attaching an FBO to it and rendering into the FBO.
     }
 }
 
+
+void fixup_glTexImage2D(GLMessage *glmsg) {
+    /* void glTexImage2D(GLenum target,
+                        GLint level,
+                        GLint internalformat,
+                        GLsizei width,
+                        GLsizei height,
+                        GLint border,
+                        GLenum format,
+                        GLenum type,
+                        const GLvoid *data); 
+    */
+    int widthIndex = 3;
+    int heightIndex = 4;
+    fixup_glTexImage(widthIndex, heightIndex, glmsg);
+}
+
+void fixup_glTexSubImage2D(GLMessage *glmsg) {
+    /*
+    void glTexSubImage2D(GLenum target,
+                        GLint level,
+                        GLint xoffset,
+                        GLint yoffset,
+                        GLsizei width,
+                        GLsizei height,
+                        GLenum format,
+                        GLenum type,
+                        const GLvoid * data);
+    */
+    int widthIndex = 4;
+    int heightIndex = 5;
+    fixup_glTexImage(widthIndex, heightIndex, glmsg);
+}
+
 void fixup_glShaderSource(GLMessage *glmsg) {
     /* void glShaderSource(GLuint shader, GLsizei count, const GLchar** string, 
                                     const GLint* length) */
@@ -218,6 +240,14 @@
     fixup_GenericIntArray(1, n, glmsg);
 }
 
+void fixup_glDeleteGeneric(GLMessage *glmsg) {
+    /* void glDelete*(GLsizei n, GLuint *buffers); */
+    GLMessage_DataType arg_n  = glmsg->args(0);
+    GLsizei n = arg_n.intvalue(0);
+
+    fixup_GenericIntArray(1, n, glmsg);
+}
+
 void fixup_glGetBooleanv(GLMessage *glmsg) {
     /* void glGetBooleanv(GLenum pname, GLboolean *params); */
     GLMessage_DataType *arg_params = glmsg->mutable_args(1);
@@ -250,10 +280,16 @@
 
     // do any custom message dependent processing
     switch (glmsg->function()) {
-    case GLMessage::glGenBuffers:        /* void glGenBuffers(GLsizei n, GLuint * buffers); */
-    case GLMessage::glGenFramebuffers:   /* void glGenFramebuffers(GLsizei n, GLuint * buffers); */
-    case GLMessage::glGenRenderbuffers:  /* void glGenFramebuffers(GLsizei n, GLuint * buffers); */
-    case GLMessage::glGenTextures:       /* void glGenTextures(GLsizei n, GLuint * buffers); */
+    case GLMessage::glDeleteBuffers:      /* glDeleteBuffers(GLsizei n, GLuint *buffers); */
+    case GLMessage::glDeleteFramebuffers: /* glDeleteFramebuffers(GLsizei n, GLuint *buffers); */
+    case GLMessage::glDeleteRenderbuffers:/* glDeleteRenderbuffers(GLsizei n, GLuint *buffers); */
+    case GLMessage::glDeleteTextures:     /* glDeleteTextures(GLsizei n, GLuint *textures); */
+        fixup_glDeleteGeneric(glmsg);
+        break;
+    case GLMessage::glGenBuffers:        /* void glGenBuffers(GLsizei n, GLuint *buffers); */
+    case GLMessage::glGenFramebuffers:   /* void glGenFramebuffers(GLsizei n, GLuint *buffers); */
+    case GLMessage::glGenRenderbuffers:  /* void glGenFramebuffers(GLsizei n, GLuint *buffers); */
+    case GLMessage::glGenTextures:       /* void glGenTextures(GLsizei n, GLuint *textures); */
         fixup_glGenGeneric(glmsg);
         break;
     case GLMessage::glGetAttribLocation:  
@@ -287,6 +323,11 @@
             fixup_glTexImage2D(glmsg);
         }
         break;
+    case GLMessage::glTexSubImage2D:
+        if (context->getGlobalTraceState()->shouldCollectTextureDataOnGlTexImage()) {
+            fixup_glTexSubImage2D(glmsg);
+        }
+        break;
     case GLMessage::glShaderSource:
         fixup_glShaderSource(glmsg);
         break;
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index 24744b5..a10e363 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -397,8 +397,10 @@
 
         mPreloadTasksRunnable = new Runnable() {
             public void run() {
-                setVisibility(INVISIBLE);
-                refreshRecentTasksList();
+                if (!mShowing) {
+                    setVisibility(INVISIBLE);
+                    refreshRecentTasksList();
+                }
             }
         };
     }
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index cf925b0..593f558 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -565,7 +565,7 @@
     return NO_ERROR;
 }
 
-status_t AudioFlinger::setMode(int mode)
+status_t AudioFlinger::setMode(audio_mode_t mode)
 {
     status_t ret = initCheck();
     if (ret != NO_ERROR) {
@@ -3385,8 +3385,6 @@
         if (mName < 0) {
             ALOGE("no more track names available");
         }
-        mVolume[0] = 1.0f;
-        mVolume[1] = 1.0f;
         mStreamType = streamType;
         // NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
         // 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
@@ -3648,12 +3646,6 @@
     mMute = muted;
 }
 
-void AudioFlinger::PlaybackThread::Track::setVolume(float left, float right)
-{
-    mVolume[0] = left;
-    mVolume[1] = right;
-}
-
 status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId)
 {
     status_t status = DEAD_OBJECT;
@@ -4103,10 +4095,6 @@
     mTrack->pause();
 }
 
-void AudioFlinger::TrackHandle::setVolume(float left, float right) {
-    mTrack->setVolume(left, right);
-}
-
 sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
     return mTrack->getCblk();
 }
@@ -5900,7 +5888,7 @@
     return chain;
 }
 
-void AudioFlinger::ThreadBase::setMode(uint32_t mode)
+void AudioFlinger::ThreadBase::setMode(audio_mode_t mode)
 {
     Mutex::Autolock _l(mLock);
     size_t size = mEffectChains.size();
@@ -6698,7 +6686,7 @@
     return status;
 }
 
-status_t AudioFlinger::EffectModule::setMode(uint32_t mode)
+status_t AudioFlinger::EffectModule::setMode(audio_mode_t mode)
 {
     Mutex::Autolock _l(mLock);
     status_t status = NO_ERROR;
@@ -6707,7 +6695,7 @@
         uint32_t size = sizeof(status_t);
         status = (*mEffectInterface)->command(mEffectInterface,
                                               EFFECT_CMD_SET_AUDIO_MODE,
-                                              sizeof(int),
+                                              sizeof(audio_mode_t),
                                               &mode,
                                               &size,
                                               &cmdStatus);
@@ -7357,7 +7345,7 @@
 }
 
 // setMode_l() must be called with PlaybackThread::mLock held
-void AudioFlinger::EffectChain::setMode_l(uint32_t mode)
+void AudioFlinger::EffectChain::setMode_l(audio_mode_t mode)
 {
     size_t size = mEffects.size();
     for (size_t i = 0; i < size; i++) {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 9d1d862..275f40e 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -99,7 +99,7 @@
     virtual     float       streamVolume(audio_stream_type_t stream, int output) const;
     virtual     bool        streamMute(audio_stream_type_t stream) const;
 
-    virtual     status_t    setMode(int mode);
+    virtual     status_t    setMode(audio_mode_t mode);
 
     virtual     status_t    setMicMute(bool state);
     virtual     bool        getMicMute() const;
@@ -202,7 +202,7 @@
                                 Parcel* reply,
                                 uint32_t flags);
 
-                uint32_t    getMode() { return mMode; }
+               audio_mode_t getMode() const { return mMode; }
 
                 bool        btNrecIsOff() { return mBtNrecIsOff; }
 
@@ -461,7 +461,7 @@
                     // unlock effect chains after process
                     void unlockEffectChains(Vector<sp <EffectChain> >& effectChains);
                     // set audio mode to all effect chains
-                    void setMode(uint32_t mode);
+                    void setMode(audio_mode_t mode);
                     // get effect module with corresponding ID on specified audio session
                     sp<AudioFlinger::EffectModule> getEffect_l(int sessionId, int effectId);
                     // add and effect module. Also creates the effect chain is none exists for
@@ -590,7 +590,6 @@
                     void        flush();
                     void        destroy();
                     void        mute(bool);
-                    void        setVolume(float left, float right);
                     int name() const {
                         return mName;
                     }
@@ -633,7 +632,6 @@
             }
 
             // we don't really need a lock for these
-            float               mVolume[2];
             volatile bool       mMute;
             // FILLED state is used for suppressing volume ramp at begin of playing
             enum {FS_FILLING, FS_FILLED, FS_ACTIVE};
@@ -908,7 +906,6 @@
         virtual void        flush();
         virtual void        mute(bool);
         virtual void        pause();
-        virtual void        setVolume(float left, float right);
         virtual sp<IMemory> getCblk() const;
         virtual status_t    attachAuxEffect(int effectId);
         virtual status_t onTransact(
@@ -1113,7 +1110,7 @@
 
         status_t         setDevice(uint32_t device);
         status_t         setVolume(uint32_t *left, uint32_t *right, bool controller);
-        status_t         setMode(uint32_t mode);
+        status_t         setMode(audio_mode_t mode);
         status_t         start();
         status_t         stop();
         void             setSuspended(bool suspended);
@@ -1266,7 +1263,7 @@
         sp<EffectModule> getEffectFromType_l(const effect_uuid_t *type);
         bool setVolume_l(uint32_t *left, uint32_t *right);
         void setDevice_l(uint32_t device);
-        void setMode_l(uint32_t mode);
+        void setMode_l(audio_mode_t mode);
 
         void setInBuffer(int16_t *buffer, bool ownsBuffer = false) {
             mInBuffer = buffer;
@@ -1399,7 +1396,7 @@
 
                 DefaultKeyedVector< pid_t, sp<NotificationClient> >    mNotificationClients;
                 volatile int32_t                    mNextUniqueId;
-                uint32_t                            mMode;
+                audio_mode_t                        mMode;
                 bool                                mBtNrecIsOff;
 
                 Vector<AudioSessionRef*> mAudioSessionRefs;
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index 586406b..fcf014f 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -185,7 +185,7 @@
                                                       device_address);
 }
 
-status_t AudioPolicyService::setPhoneState(int state)
+status_t AudioPolicyService::setPhoneState(audio_mode_t state)
 {
     if (mpAudioPolicy == NULL) {
         return NO_INIT;
diff --git a/services/audioflinger/AudioPolicyService.h b/services/audioflinger/AudioPolicyService.h
index 333bc02..0715790 100644
--- a/services/audioflinger/AudioPolicyService.h
+++ b/services/audioflinger/AudioPolicyService.h
@@ -58,7 +58,7 @@
     virtual audio_policy_dev_state_t getDeviceConnectionState(
                                                                 audio_devices_t device,
                                                                 const char *device_address);
-    virtual status_t setPhoneState(int state);
+    virtual status_t setPhoneState(audio_mode_t state);
     virtual status_t setRingerMode(uint32_t mode, uint32_t mask);
     virtual status_t setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config);
     virtual audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage);
diff --git a/tests/BiDiTests/res/values/strings.xml b/tests/BiDiTests/res/values/strings.xml
index b1f5e50e..1d4fc84 100644
--- a/tests/BiDiTests/res/values/strings.xml
+++ b/tests/BiDiTests/res/values/strings.xml
@@ -50,5 +50,6 @@
     <string name="rtl">"والحق أن تترك ونص"</string>
     <string name="composing">"\u0644\u0627"</string>
     <string name="url">www.amazon.co.uk/gp/aw/h.html/275-8912818-8203452</string>
+    <string name="pointer_location" msgid="6084434787496938001">"ตำแหน่งของตัวชี้"</string>
 </resources>
 
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestView.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestView.java
index 0126dea..0b1974a 100644
--- a/tests/BiDiTests/src/com/android/bidi/BiDiTestView.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestView.java
@@ -51,6 +51,7 @@
     private String MIXED_TEXT_1;
     private String HEBREW_TEXT;
     private String RTL_TEXT;
+    private String THAI_TEXT;
 
     private int currentTextSize;
 
@@ -82,6 +83,7 @@
         MIXED_TEXT_1 = context.getString(R.string.mixed_text_1);
         HEBREW_TEXT = context.getString(R.string.hebrew_text);
         RTL_TEXT = context.getString(R.string.rtl);
+        THAI_TEXT = context.getString(R.string.pointer_location);
     }
 
     public void setCurrentTextSize(int size) {
@@ -134,6 +136,10 @@
         // Test Hebrew
         deltaX = testString(canvas, RTL_TEXT, ORIGIN, ORIGIN + 14 * currentTextSize,
                 false, false,  Paint.DIRECTION_RTL, currentTextSize);
+
+        // Test Thai
+        deltaX = testString(canvas, THAI_TEXT, ORIGIN, ORIGIN + 16 * currentTextSize,
+                false, false,  Paint.DIRECTION_LTR, currentTextSize);
     }
 
     private int testString(Canvas canvas, String text, int x, int y,
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 929b103..6f97ff0 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -466,6 +466,16 @@
         </activity>
 
         <activity
+                android:name="PosTextActivity"
+                android:label="_PosText"
+                android:theme="@android:style/Theme.NoTitleBar">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <activity
                 android:name="ListActivity"
                 android:label="__List">
             <intent-filter>
diff --git a/tests/HwAccelerationTest/res/values/strings.xml b/tests/HwAccelerationTest/res/values/strings.xml
new file mode 100644
index 0000000..69e58aa
--- /dev/null
+++ b/tests/HwAccelerationTest/res/values/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <string name="complex_string">"ตำแหน่งของตัวชี้"</string>
+</resources>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PosTextActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/PosTextActivity.java
new file mode 100644
index 0000000..f0ff737
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/PosTextActivity.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.os.Bundle;
+import android.view.View;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class PosTextActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(new CustomTextView(this));
+    }
+
+    static class CustomTextView extends View {
+        private final Paint mLargePaint;
+        private final String mText;
+        private final float[] mPos;
+
+        CustomTextView(Context c) {
+            super(c);
+
+            mText = c.getResources().getString(R.string.complex_string);
+            mPos = new float[mText.length() * 2];
+            for (int i = 0; i < mPos.length; i += 2) {
+                mPos[i] = i * 30.0f;
+                mPos[i + 1] = i * 10.0f;
+            }
+
+            mLargePaint = new Paint();
+            mLargePaint.setAntiAlias(true);
+            mLargePaint.setTextSize(36.0f);
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            super.onDraw(canvas);
+            canvas.drawRGB(255, 255, 255);
+            
+            canvas.save();
+            canvas.translate(100.0f, 100.0f);
+            canvas.drawPosText(mText, mPos, mLargePaint);
+            canvas.restore();
+        }
+    }
+}
diff --git a/voip/jni/rtp/AudioGroup.cpp b/voip/jni/rtp/AudioGroup.cpp
index 4db5738..1139577 100644
--- a/voip/jni/rtp/AudioGroup.cpp
+++ b/voip/jni/rtp/AudioGroup.cpp
@@ -1008,7 +1008,7 @@
     delete stream;
     delete codec;
     close(socket);
-    env->SetIntField(thiz, gNative, NULL);
+    env->SetIntField(thiz, gNative, 0);
 }
 
 void remove(JNIEnv *env, jobject thiz, jint socket)
@@ -1017,7 +1017,7 @@
     if (group) {
         if (socket == -1 || !group->remove(socket)) {
             delete group;
-            env->SetIntField(thiz, gNative, NULL);
+            env->SetIntField(thiz, gNative, 0);
         }
     }
 }