Merge "Support for setting the NfcA transceive timeout (API)."
diff --git a/api/current.txt b/api/current.txt
index f06df4b..89654b8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11180,6 +11180,8 @@
     method public static org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache);
     method public static javax.net.ssl.SSLSocketFactory getInsecure(int, android.net.SSLSessionCache);
     method public java.lang.String[] getSupportedCipherSuites();
+    method public void setKeyManagers(javax.net.ssl.KeyManager[]);
+    method public void setTrustManagers(javax.net.ssl.TrustManager[]);
   }
 
   public final class SSLSessionCache {
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 906a564..9bd45d3 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -277,24 +277,24 @@
     public int compatSmallestScreenWidthDp;
 
     /**
-     * @hide
+     * @hide Do not use. Implementation not finished.
      */
-    public static final int LAYOUT_DIRECTION_UNDEFINED = -1;
+    public static final int TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE = -1;
 
     /**
-     * @hide
+     * @hide Do not use. Implementation not finished.
      */
-    public static final int LAYOUT_DIRECTION_LTR = 0;
+    public static final int TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE = 0;
 
     /**
-     * @hide
+     * @hide Do not use. Implementation not finished.
      */
-    public static final int LAYOUT_DIRECTION_RTL = 1;
+    public static final int TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE = 1;
 
     /**
-     * @hide The layout direction associated to the current Locale
+     * @hide The text layout direction associated to the current Locale
      */
-    public int layoutDirection;
+    public int textLayoutDirection;
 
     /**
      * @hide Internal book-keeping.
@@ -322,7 +322,7 @@
         mnc = o.mnc;
         if (o.locale != null) {
             locale = (Locale) o.locale.clone();
-            layoutDirection = o.layoutDirection;
+            textLayoutDirection = o.textLayoutDirection;
         }
         userSetLocale = o.userSetLocale;
         touchscreen = o.touchscreen;
@@ -358,6 +358,11 @@
         } else {
             sb.append(" (no locale)");
         }
+        switch (textLayoutDirection) {
+            case TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE: sb.append(" ?layoutdir"); break;
+            case TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE: sb.append(" rtl"); break;
+            default: sb.append(" layoutdir="); sb.append(textLayoutDirection); break;
+        }
         if (smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
             sb.append(" sw"); sb.append(smallestScreenWidthDp); sb.append("dp");
         } else {
@@ -450,11 +455,6 @@
             case NAVIGATIONHIDDEN_YES: sb.append("/h"); break;
             default: sb.append("/"); sb.append(navigationHidden); break;
         }
-        switch (layoutDirection) {
-            case LAYOUT_DIRECTION_UNDEFINED: sb.append(" ?layoutdir"); break;
-            case LAYOUT_DIRECTION_LTR: sb.append(" ltr"); break;
-            case LAYOUT_DIRECTION_RTL: sb.append(" rtl"); break;
-        }
         if (seq != 0) {
             sb.append(" s.");
             sb.append(seq);
@@ -483,8 +483,8 @@
         screenWidthDp = compatScreenWidthDp = SCREEN_WIDTH_DP_UNDEFINED;
         screenHeightDp = compatScreenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED;
         smallestScreenWidthDp = compatSmallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
+        textLayoutDirection = TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE;
         seq = 0;
-        layoutDirection = LAYOUT_DIRECTION_LTR;
     }
 
     /** {@hide} */
@@ -519,7 +519,7 @@
             changed |= ActivityInfo.CONFIG_LOCALE;
             locale = delta.locale != null
                     ? (Locale) delta.locale.clone() : null;
-            layoutDirection = getLayoutDirectionFromLocale(locale);
+            textLayoutDirection = getLayoutDirectionFromLocale(locale);
         }
         if (delta.userSetLocale && (!userSetLocale || ((changed & ActivityInfo.CONFIG_LOCALE) != 0)))
         {
@@ -611,23 +611,25 @@
     /**
      * Return the layout direction for a given Locale
      * @param locale the Locale for which we want the layout direction. Can be null.
-     * @return the layout direction. This may be one of {@link #LAYOUT_DIRECTION_UNDEFINED},
-     * {@link #LAYOUT_DIRECTION_LTR} or {@link #LAYOUT_DIRECTION_RTL}.
+     * @return the layout direction. This may be one of:
+     * {@link #TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE} or
+     * {@link #TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE} or
+     * {@link #TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE}.
      *
      * @hide
      */
     public static int getLayoutDirectionFromLocale(Locale locale) {
-        if (locale == null || locale.equals(Locale.ROOT)) return LAYOUT_DIRECTION_UNDEFINED;
+        if (locale == null || locale.equals(Locale.ROOT)) return TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE;
         // Be careful: this code will need to be changed when vertical scripts will be supported
         // OR if ICU4C is updated to have the "likelySubtags" file
         switch(Character.getDirectionality(locale.getDisplayName(locale).charAt(0))) {
             case Character.DIRECTIONALITY_LEFT_TO_RIGHT:
-                return LAYOUT_DIRECTION_LTR;
+                return TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE;
             case Character.DIRECTIONALITY_RIGHT_TO_LEFT:
             case Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC:
-                return LAYOUT_DIRECTION_RTL;
+                return TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE;
             default:
-                return LAYOUT_DIRECTION_UNDEFINED;
+                return TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE;
         }
     }
 
@@ -810,7 +812,7 @@
         dest.writeInt(compatScreenWidthDp);
         dest.writeInt(compatScreenHeightDp);
         dest.writeInt(compatSmallestScreenWidthDp);
-        dest.writeInt(layoutDirection);
+        dest.writeInt(textLayoutDirection);
         dest.writeInt(seq);
     }
 
@@ -838,7 +840,7 @@
         compatScreenWidthDp = source.readInt();
         compatScreenHeightDp = source.readInt();
         compatSmallestScreenWidthDp = source.readInt();
-        layoutDirection = source.readInt();
+        textLayoutDirection = source.readInt();
         seq = source.readInt();
     }
     
diff --git a/core/java/android/net/SSLCertificateSocketFactory.java b/core/java/android/net/SSLCertificateSocketFactory.java
index 8e50cd5..5c4b258 100644
--- a/core/java/android/net/SSLCertificateSocketFactory.java
+++ b/core/java/android/net/SSLCertificateSocketFactory.java
@@ -240,7 +240,6 @@
 
     /**
      * Sets the {@link TrustManager}s to be used for connections made by this factory.
-     * @hide
      */
     public void setTrustManagers(TrustManager[] trustManager) {
         mTrustManagers = trustManager;
@@ -253,7 +252,6 @@
 
     /**
      * Sets the {@link KeyManager}s to be used for connections made by this factory.
-     * @hide
      */
     public void setKeyManagers(KeyManager[] keyManagers) {
         mKeyManagers = keyManagers;
diff --git a/core/java/android/webkit/HTML5VideoFullScreen.java b/core/java/android/webkit/HTML5VideoFullScreen.java
index 44229a4..4cae9d8 100644
--- a/core/java/android/webkit/HTML5VideoFullScreen.java
+++ b/core/java/android/webkit/HTML5VideoFullScreen.java
@@ -253,18 +253,19 @@
         mLayout.setVisibility(View.VISIBLE);
 
         WebChromeClient client = webView.getWebChromeClient();
-        client.onShowCustomView(mLayout, mCallback);
-        // Plugins like Flash will draw over the video so hide
-        // them while we're playing.
-        if (webView.getViewManager() != null)
-            webView.getViewManager().hideAll();
+        if (client != null) {
+            client.onShowCustomView(mLayout, mCallback);
+            // Plugins like Flash will draw over the video so hide
+            // them while we're playing.
+            if (webView.getViewManager() != null)
+                webView.getViewManager().hideAll();
 
-        mProgressView = client.getVideoLoadingProgressView();
-        if (mProgressView != null) {
-            mLayout.addView(mProgressView, layoutParams);
-            mProgressView.setVisibility(View.VISIBLE);
+            mProgressView = client.getVideoLoadingProgressView();
+            if (mProgressView != null) {
+                mLayout.addView(mProgressView, layoutParams);
+                mProgressView.setVisibility(View.VISIBLE);
+            }
         }
-
     }
 
     /**
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 95e4880..10c7390 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -5605,8 +5605,8 @@
      * Adjustable parameters. Angle is the radians on a unit circle, limited
      * to quadrant 1. Values range from 0f (horizontal) to PI/2 (vertical)
      */
-    private static final float HSLOPE_TO_START_SNAP = .1f;
-    private static final float HSLOPE_TO_BREAK_SNAP = .2f;
+    private static final float HSLOPE_TO_START_SNAP = .25f;
+    private static final float HSLOPE_TO_BREAK_SNAP = .4f;
     private static final float VSLOPE_TO_START_SNAP = 1.25f;
     private static final float VSLOPE_TO_BREAK_SNAP = .95f;
     /*
@@ -5617,6 +5617,11 @@
      */
     private static final float ANGLE_VERT = 2f;
     private static final float ANGLE_HORIZ = 0f;
+    /*
+     *  The modified moving average weight.
+     *  Formula: MAV[t]=MAV[t-1] + (P[t]-MAV[t-1])/n
+     */
+    private static final float MMA_WEIGHT_N = 5;
 
     private boolean hitFocusedPlugin(int contentX, int contentY) {
         if (DebugFlags.WEB_VIEW) {
@@ -6003,8 +6008,9 @@
                 if (deltaX == 0 && deltaY == 0) {
                     keepScrollBarsVisible = done = true;
                 } else {
-                    mAverageAngle = (mAverageAngle +
-                            calculateDragAngle(deltaX, deltaY)) / 2;
+                    mAverageAngle +=
+                        (calculateDragAngle(deltaX, deltaY) - mAverageAngle)
+                        / MMA_WEIGHT_N;
                     if (mSnapScrollMode != SNAP_NONE) {
                         if (mSnapScrollMode == SNAP_Y) {
                             // radical change means getting out of snap mode
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index bda82a3..092c2f7 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -494,6 +494,14 @@
         requestLayout();
     }
 
+    private static int max2(int[] a, int valueIfEmpty) {
+        int result = valueIfEmpty;
+        for (int i = 0, N = a.length; i < N; i++) {
+            result = Math.max(result, a[i]);
+        }
+        return result;
+    }
+
     private static int sum(float[] a) {
         int result = 0;
         for (int i = 0, length = a.length; i < length; i++) {
@@ -1409,7 +1417,7 @@
         // External entry points
 
         private int size(int[] locations) {
-            return locations[locations.length - 1] - locations[0];
+            return max2(locations, 0) - locations[0];
         }
 
         private int getMin() {
@@ -1878,21 +1886,13 @@
             return result;
         }
 
-        private static int max(int[] a, int valueIfEmpty) {
-            int result = valueIfEmpty;
-            for (int i = 0, length = a.length; i < length; i++) {
-                result = Math.max(result, a[i]);
-            }
-            return result;
-        }
-
         /*
         Create a compact array of keys or values using the supplied index.
          */
         private static <K> K[] compact(K[] a, int[] index) {
             int size = a.length;
             Class<?> componentType = a.getClass().getComponentType();
-            K[] result = (K[]) Array.newInstance(componentType, max(index, -1) + 1);
+            K[] result = (K[]) Array.newInstance(componentType, max2(index, -1) + 1);
 
             // this overwrite duplicates, retaining the last equivalent entry
             for (int i = 0; i < size; i++) {
diff --git a/core/tests/coretests/src/android/content/res/ConfigurationTest.java b/core/tests/coretests/src/android/content/res/ConfigurationTest.java
index f1f745e..54a5e4e 100644
--- a/core/tests/coretests/src/android/content/res/ConfigurationTest.java
+++ b/core/tests/coretests/src/android/content/res/ConfigurationTest.java
@@ -30,169 +30,169 @@
         args = {Locale.class}
     )
     public void testGetLayoutDirectionFromLocale() {
-        assertEquals(Configuration.LAYOUT_DIRECTION_UNDEFINED,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(null));
 
-        assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(Locale.ENGLISH));
-        assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(Locale.CANADA));
-        assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(Locale.CANADA_FRENCH));
-        assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(Locale.FRANCE));
-        assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(Locale.FRENCH));
-        assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(Locale.GERMAN));
-        assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(Locale.GERMANY));
-        assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(Locale.ITALIAN));
-        assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(Locale.ITALY));
-        assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(Locale.UK));
-        assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(Locale.US));
 
-        assertEquals(Configuration.LAYOUT_DIRECTION_UNDEFINED,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_UNDEFINED_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(Locale.ROOT));
 
-        assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(Locale.CHINA));
-        assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(Locale.CHINESE));
-        assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(Locale.JAPAN));
-        assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(Locale.JAPANESE));
-        assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(Locale.KOREA));
-        assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(Locale.KOREAN));
-        assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(Locale.PRC));
-        assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(Locale.SIMPLIFIED_CHINESE));
-        assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(Locale.TAIWAN));
-        assertEquals(Configuration.LAYOUT_DIRECTION_LTR,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_LTR_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(Locale.TRADITIONAL_CHINESE));
 
         Locale locale = new Locale("ar");
-        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(locale));
         locale = new Locale("ar", "AE");
-        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(locale));
         locale = new Locale("ar", "BH");
-        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(locale));
         locale = new Locale("ar", "DZ");
-        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(locale));
         locale = new Locale("ar", "EG");
-        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(locale));
         locale = new Locale("ar", "IQ");
-        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(locale));
         locale = new Locale("ar", "JO");
-        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(locale));
         locale = new Locale("ar", "KW");
-        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(locale));
         locale = new Locale("ar", "LB");
-        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(locale));
         locale = new Locale("ar", "LY");
-        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(locale));
         locale = new Locale("ar", "MA");
-        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(locale));
         locale = new Locale("ar", "OM");
-        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(locale));
         locale = new Locale("ar", "QA");
-        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(locale));
         locale = new Locale("ar", "SA");
-        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(locale));
         locale = new Locale("ar", "SD");
-        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(locale));
         locale = new Locale("ar", "SY");
-        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(locale));
         locale = new Locale("ar", "TN");
-        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(locale));
         locale = new Locale("ar", "YE");
-        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(locale));
 
         locale = new Locale("fa");
-        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(locale));
         locale = new Locale("fa", "AF");
-        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(locale));
         locale = new Locale("fa", "IR");
-        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(locale));
 
         locale = new Locale("iw");
-        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(locale));
         locale = new Locale("iw", "IL");
-        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(locale));
         locale = new Locale("he");
-        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(locale));
         locale = new Locale("he", "IL");
-        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(locale));
 
         // The following test will not pass until we are able to take care about the scrip subtag
         // thru having the "likelySubTags" file into ICU4C
 //        locale = new Locale("pa_Arab");
-//        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+//        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
 //            Configuration.getLayoutDirectionFromLocale(locale));
 //        locale = new Locale("pa_Arab", "PK");
-//        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+//        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
 //            Configuration.getLayoutDirectionFromLocale(locale));
 
         locale = new Locale("ps");
-        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(locale));
         locale = new Locale("ps", "AF");
-        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
             Configuration.getLayoutDirectionFromLocale(locale));
 
         // The following test will not work as the localized display name would be "Urdu" with ICU 4.4
         // We will need ICU 4.6 to get the correct localized display name
 //        locale = new Locale("ur");
-//        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+//        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
 //            Configuration.getLayoutDirectionFromLocale(locale));
 //        locale = new Locale("ur", "IN");
-//        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+//        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
 //            Configuration.getLayoutDirectionFromLocale(locale));
 //        locale = new Locale("ur", "PK");
-//        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+//        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
 //            Configuration.getLayoutDirectionFromLocale(locale));
 
         // The following test will not pass until we are able to take care about the scrip subtag
         // thru having the "likelySubTags" file into ICU4C
 //        locale = new Locale("uz_Arab");
-//        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+//        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
 //            Configuration.getLayoutDirectionFromLocale(locale));
 //        locale = new Locale("uz_Arab", "AF");
-//        assertEquals(Configuration.LAYOUT_DIRECTION_RTL,
+//        assertEquals(Configuration.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE,
 //            Configuration.getLayoutDirectionFromLocale(locale));
     }
 }
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index 2b31462..9294df6 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -188,6 +188,11 @@
 
     status_t setBufferCountServerLocked(int bufferCount);
 
+    // computeCurrentTransformMatrix computes the transform matrix for the
+    // current texture.  It uses mCurrentTransform and the current GraphicBuffer
+    // to compute this matrix and stores it in mCurrentTransformMatrix.
+    void computeCurrentTransformMatrix();
+
     enum { INVALID_BUFFER_SLOT = -1 };
 
     struct BufferSlot {
@@ -288,9 +293,9 @@
     // by calling setBufferCount or setBufferCountServer
     int mBufferCount;
 
-    // mRequestedBufferCount is the number of buffer slots requested by the
-    // client. The default is zero, which means the client doesn't care how
-    // many buffers there is.
+    // mClientBufferCount is the number of buffer slots requested by the client.
+    // The default is zero, which means the client doesn't care how many buffers
+    // there is.
     int mClientBufferCount;
 
     // mServerBufferCount buffer count requested by the server-side
@@ -322,6 +327,11 @@
     // gets set to mLastQueuedTransform each time updateTexImage is called.
     uint32_t mCurrentTransform;
 
+    // mCurrentTransformMatrix is the transform matrix for the current texture.
+    // It gets computed by computeTransformMatrix each time updateTexImage is
+    // called.
+    float mCurrentTransformMatrix[16];
+
     // mCurrentTimestamp is the timestamp for the current texture. It
     // gets set to mLastQueuedTimestamp each time updateTexImage is called.
     int64_t mCurrentTimestamp;
@@ -362,6 +372,7 @@
     // variables of SurfaceTexture objects. It must be locked whenever the
     // member variables are accessed.
     mutable Mutex mMutex;
+
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/utils/threads.h b/include/utils/threads.h
index 41e5766..0bd69cf 100644
--- a/include/utils/threads.h
+++ b/include/utils/threads.h
@@ -526,6 +526,7 @@
     Thread& operator=(const Thread&);
     static  int             _threadLoop(void* user);
     const   bool            mCanCallJava;
+    // always hold mLock when reading or writing
             thread_id_t     mThread;
     mutable Mutex           mLock;
             Condition       mThreadExitedCondition;
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index ee97dcf..2cda4c8 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -96,6 +96,7 @@
     sp<ISurfaceComposer> composer(ComposerService::getComposerService());
     mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
     mNextCrop.makeInvalid();
+    memcpy(mCurrentTransformMatrix, mtxIdentity, sizeof(mCurrentTransformMatrix));
 }
 
 SurfaceTexture::~SurfaceTexture() {
@@ -547,6 +548,7 @@
         mCurrentCrop = mSlots[buf].mCrop;
         mCurrentTransform = mSlots[buf].mTransform;
         mCurrentTimestamp = mSlots[buf].mTimestamp;
+        computeCurrentTransformMatrix();
         mDequeueCondition.signal();
     } else {
         // We always bind the texture even if we don't update its contents.
@@ -596,8 +598,12 @@
 }
 
 void SurfaceTexture::getTransformMatrix(float mtx[16]) {
-    LOGV("SurfaceTexture::getTransformMatrix");
     Mutex::Autolock lock(mMutex);
+    memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
+}
+
+void SurfaceTexture::computeCurrentTransformMatrix() {
+    LOGV("SurfaceTexture::computeCurrentTransformMatrix");
 
     float xform[16];
     for (int i = 0; i < 16; i++) {
@@ -684,7 +690,7 @@
     // coordinate of 0, so SurfaceTexture must behave the same way.  We don't
     // want to expose this to applications, however, so we must add an
     // additional vertical flip to the transform after all the other transforms.
-    mtxMul(mtx, mtxFlipV, mtxBeforeFlipV);
+    mtxMul(mCurrentTransformMatrix, mtxFlipV, mtxBeforeFlipV);
 }
 
 nsecs_t SurfaceTexture::getTimestamp() {
diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp
index 2f704c8..da04b4a 100644
--- a/libs/gui/tests/SurfaceTextureClient_test.cpp
+++ b/libs/gui/tests/SurfaceTextureClient_test.cpp
@@ -514,4 +514,112 @@
     thread->requestExitAndWait();
 }
 
+TEST_F(SurfaceTextureClientTest, GetTransformMatrixReturnsVerticalFlip) {
+    sp<ANativeWindow> anw(mSTC);
+    sp<SurfaceTexture> st(mST);
+    android_native_buffer_t* buf[3];
+    float mtx[16] = {};
+    ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 4));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+    ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0]));
+    ASSERT_EQ(OK, st->updateTexImage());
+    st->getTransformMatrix(mtx);
+
+    EXPECT_EQ(1.f, mtx[0]);
+    EXPECT_EQ(0.f, mtx[1]);
+    EXPECT_EQ(0.f, mtx[2]);
+    EXPECT_EQ(0.f, mtx[3]);
+
+    EXPECT_EQ(0.f, mtx[4]);
+    EXPECT_EQ(-1.f, mtx[5]);
+    EXPECT_EQ(0.f, mtx[6]);
+    EXPECT_EQ(0.f, mtx[7]);
+
+    EXPECT_EQ(0.f, mtx[8]);
+    EXPECT_EQ(0.f, mtx[9]);
+    EXPECT_EQ(1.f, mtx[10]);
+    EXPECT_EQ(0.f, mtx[11]);
+
+    EXPECT_EQ(0.f, mtx[12]);
+    EXPECT_EQ(1.f, mtx[13]);
+    EXPECT_EQ(0.f, mtx[14]);
+    EXPECT_EQ(1.f, mtx[15]);
 }
+
+TEST_F(SurfaceTextureClientTest, GetTransformMatrixSucceedsAfterFreeingBuffers) {
+    sp<ANativeWindow> anw(mSTC);
+    sp<SurfaceTexture> st(mST);
+    android_native_buffer_t* buf[3];
+    float mtx[16] = {};
+    ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 4));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+    ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0]));
+    ASSERT_EQ(OK, st->updateTexImage());
+    ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 6)); // frees buffers
+    st->getTransformMatrix(mtx);
+
+    EXPECT_EQ(1.f, mtx[0]);
+    EXPECT_EQ(0.f, mtx[1]);
+    EXPECT_EQ(0.f, mtx[2]);
+    EXPECT_EQ(0.f, mtx[3]);
+
+    EXPECT_EQ(0.f, mtx[4]);
+    EXPECT_EQ(-1.f, mtx[5]);
+    EXPECT_EQ(0.f, mtx[6]);
+    EXPECT_EQ(0.f, mtx[7]);
+
+    EXPECT_EQ(0.f, mtx[8]);
+    EXPECT_EQ(0.f, mtx[9]);
+    EXPECT_EQ(1.f, mtx[10]);
+    EXPECT_EQ(0.f, mtx[11]);
+
+    EXPECT_EQ(0.f, mtx[12]);
+    EXPECT_EQ(1.f, mtx[13]);
+    EXPECT_EQ(0.f, mtx[14]);
+    EXPECT_EQ(1.f, mtx[15]);
+}
+
+TEST_F(SurfaceTextureClientTest, GetTransformMatrixSucceedsAfterFreeingBuffersWithCrop) {
+    sp<ANativeWindow> anw(mSTC);
+    sp<SurfaceTexture> st(mST);
+    android_native_buffer_t* buf[3];
+    float mtx[16] = {};
+    android_native_rect_t crop;
+    crop.left = 0;
+    crop.top = 0;
+    crop.right = 5;
+    crop.bottom = 5;
+
+    ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 4));
+    ASSERT_EQ(OK, native_window_set_buffers_geometry(anw.get(), 8, 8, 0));
+    ASSERT_EQ(OK, anw->dequeueBuffer(anw.get(), &buf[0]));
+    ASSERT_EQ(OK, native_window_set_crop(anw.get(), &crop));
+    ASSERT_EQ(OK, anw->queueBuffer(anw.get(), buf[0]));
+    ASSERT_EQ(OK, st->updateTexImage());
+    ASSERT_EQ(OK, native_window_set_buffer_count(anw.get(), 6)); // frees buffers
+    st->getTransformMatrix(mtx);
+
+    // This accounts for the 1 texel shrink for each edge that's included in the
+    // transform matrix to avoid texturing outside the crop region.
+    EXPECT_EQ(.5f, mtx[0]);
+    EXPECT_EQ(0.f, mtx[1]);
+    EXPECT_EQ(0.f, mtx[2]);
+    EXPECT_EQ(0.f, mtx[3]);
+
+    EXPECT_EQ(0.f, mtx[4]);
+    EXPECT_EQ(-.5f, mtx[5]);
+    EXPECT_EQ(0.f, mtx[6]);
+    EXPECT_EQ(0.f, mtx[7]);
+
+    EXPECT_EQ(0.f, mtx[8]);
+    EXPECT_EQ(0.f, mtx[9]);
+    EXPECT_EQ(1.f, mtx[10]);
+    EXPECT_EQ(0.f, mtx[11]);
+
+    EXPECT_EQ(0.f, mtx[12]);
+    EXPECT_EQ(.5f, mtx[13]);
+    EXPECT_EQ(0.f, mtx[14]);
+    EXPECT_EQ(1.f, mtx[15]);
+}
+
+} // namespace android
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index 8747ba5..16280d2 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -14,11 +14,14 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+
 #include <gtest/gtest.h>
 #include <gui/SurfaceTexture.h>
 #include <gui/SurfaceTextureClient.h>
 #include <ui/GraphicBuffer.h>
 #include <utils/String8.h>
+#include <utils/threads.h>
 
 #include <surfaceflinger/ISurfaceComposer.h>
 #include <surfaceflinger/Surface.h>
@@ -618,4 +621,269 @@
     }
 }
 
+/*
+ * This test is for testing GL -> GL texture streaming via SurfaceTexture.  It
+ * contains functionality to create a producer thread that will perform GL
+ * rendering to an ANativeWindow that feeds frames to a SurfaceTexture.
+ * Additionally it supports interlocking the producer and consumer threads so
+ * that a specific sequence of calls can be deterministically created by the
+ * test.
+ *
+ * The intended usage is as follows:
+ *
+ * TEST_F(...) {
+ *     class PT : public ProducerThread {
+ *         virtual void render() {
+ *             ...
+ *             swapBuffers();
+ *         }
+ *     };
+ *
+ *     runProducerThread(new PT());
+ *
+ *     // The order of these calls will vary from test to test and may include
+ *     // multiple frames and additional operations (e.g. GL rendering from the
+ *     // texture).
+ *     fc->waitForFrame();
+ *     mST->updateTexImage();
+ *     fc->finishFrame();
+ * }
+ *
+ */
+class SurfaceTextureGLToGLTest : public SurfaceTextureGLTest {
+protected:
+
+    // ProducerThread is an abstract base class to simplify the creation of
+    // OpenGL ES frame producer threads.
+    class ProducerThread : public Thread {
+    public:
+        virtual ~ProducerThread() {
+        }
+
+        void setEglObjects(EGLDisplay producerEglDisplay,
+                EGLSurface producerEglSurface,
+                EGLContext producerEglContext) {
+            mProducerEglDisplay = producerEglDisplay;
+            mProducerEglSurface = producerEglSurface;
+            mProducerEglContext = producerEglContext;
+        }
+
+        virtual bool threadLoop() {
+            eglMakeCurrent(mProducerEglDisplay, mProducerEglSurface,
+                    mProducerEglSurface, mProducerEglContext);
+            render();
+            eglMakeCurrent(mProducerEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
+                    EGL_NO_CONTEXT);
+            return false;
+        }
+
+    protected:
+        virtual void render() = 0;
+
+        void swapBuffers() {
+            eglSwapBuffers(mProducerEglDisplay, mProducerEglSurface);
+        }
+
+        EGLDisplay mProducerEglDisplay;
+        EGLSurface mProducerEglSurface;
+        EGLContext mProducerEglContext;
+    };
+
+    // FrameCondition is a utility class for interlocking between the producer
+    // and consumer threads.  The FrameCondition object should be created and
+    // destroyed in the consumer thread only.  The consumer thread should set
+    // the FrameCondition as the FrameAvailableListener of the SurfaceTexture,
+    // and should call both waitForFrame and finishFrame once for each expected
+    // frame.
+    //
+    // This interlocking relies on the fact that onFrameAvailable gets called
+    // synchronously from SurfaceTexture::queueBuffer.
+    class FrameCondition : public SurfaceTexture::FrameAvailableListener {
+    public:
+        // waitForFrame waits for the next frame to arrive.  This should be
+        // called from the consumer thread once for every frame expected by the
+        // test.
+        void waitForFrame() {
+            LOGV("+waitForFrame");
+            Mutex::Autolock lock(mMutex);
+            status_t result = mFrameAvailableCondition.wait(mMutex);
+            LOGV("-waitForFrame");
+        }
+
+        // Allow the producer to return from its swapBuffers call and continue
+        // on to produce the next frame.  This should be called by the consumer
+        // thread once for every frame expected by the test.
+        void finishFrame() {
+            LOGV("+finishFrame");
+            Mutex::Autolock lock(mMutex);
+            mFrameFinishCondition.signal();
+            LOGV("-finishFrame");
+        }
+
+        // This should be called by SurfaceTexture on the producer thread.
+        virtual void onFrameAvailable() {
+            LOGV("+onFrameAvailable");
+            Mutex::Autolock lock(mMutex);
+            mFrameAvailableCondition.signal();
+            mFrameFinishCondition.wait(mMutex);
+            LOGV("-onFrameAvailable");
+        }
+
+    protected:
+        Mutex mMutex;
+        Condition mFrameAvailableCondition;
+        Condition mFrameFinishCondition;
+    };
+
+    SurfaceTextureGLToGLTest():
+            mProducerEglSurface(EGL_NO_SURFACE),
+            mProducerEglContext(EGL_NO_CONTEXT) {
+    }
+
+    virtual void SetUp() {
+        SurfaceTextureGLTest::SetUp();
+
+        EGLConfig myConfig = {0};
+        EGLint numConfigs = 0;
+        EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), &myConfig,
+                1, &numConfigs));
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+        mProducerEglSurface = eglCreateWindowSurface(mEglDisplay, myConfig,
+                mANW.get(), NULL);
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+        ASSERT_NE(EGL_NO_SURFACE, mProducerEglSurface);
+
+        mProducerEglContext = eglCreateContext(mEglDisplay, myConfig,
+                EGL_NO_CONTEXT, getContextAttribs());
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+        ASSERT_NE(EGL_NO_CONTEXT, mProducerEglContext);
+
+        mFC = new FrameCondition();
+        mST->setFrameAvailableListener(mFC);
+    }
+
+    virtual void TearDown() {
+        if (mProducerThread != NULL) {
+            mProducerThread->requestExitAndWait();
+        }
+        if (mProducerEglContext != EGL_NO_CONTEXT) {
+            eglDestroyContext(mEglDisplay, mProducerEglContext);
+        }
+        if (mProducerEglSurface != EGL_NO_SURFACE) {
+            eglDestroySurface(mEglDisplay, mProducerEglSurface);
+        }
+        mProducerThread.clear();
+        mFC.clear();
+    }
+
+    void runProducerThread(const sp<ProducerThread> producerThread) {
+        ASSERT_TRUE(mProducerThread == NULL);
+        mProducerThread = producerThread;
+        producerThread->setEglObjects(mEglDisplay, mProducerEglSurface,
+                mProducerEglContext);
+        producerThread->run();
+    }
+
+    EGLSurface mProducerEglSurface;
+    EGLContext mProducerEglContext;
+    sp<ProducerThread> mProducerThread;
+    sp<FrameCondition> mFC;
+};
+
+// XXX: This test is disabled because it causes hangs on some devices.
+TEST_F(SurfaceTextureGLToGLTest, DISABLED_UpdateTexImageBeforeFrameFinishedWorks) {
+    class PT : public ProducerThread {
+        virtual void render() {
+            glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+            glClear(GL_COLOR_BUFFER_BIT);
+            swapBuffers();
+        }
+    };
+
+    runProducerThread(new PT());
+
+    mFC->waitForFrame();
+    mST->updateTexImage();
+    mFC->finishFrame();
+
+    // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
 }
+
+TEST_F(SurfaceTextureGLToGLTest, UpdateTexImageAfterFrameFinishedWorks) {
+    class PT : public ProducerThread {
+        virtual void render() {
+            glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+            glClear(GL_COLOR_BUFFER_BIT);
+            swapBuffers();
+        }
+    };
+
+    runProducerThread(new PT());
+
+    mFC->waitForFrame();
+    mFC->finishFrame();
+    mST->updateTexImage();
+
+    // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
+}
+
+// XXX: This test is disabled because it causes hangs on some devices.
+TEST_F(SurfaceTextureGLToGLTest, DISABLED_RepeatedUpdateTexImageBeforeFrameFinishedWorks) {
+    enum { NUM_ITERATIONS = 1024 };
+
+    class PT : public ProducerThread {
+        virtual void render() {
+            for (int i = 0; i < NUM_ITERATIONS; i++) {
+                glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+                glClear(GL_COLOR_BUFFER_BIT);
+                LOGV("+swapBuffers");
+                swapBuffers();
+                LOGV("-swapBuffers");
+            }
+        }
+    };
+
+    runProducerThread(new PT());
+
+    for (int i = 0; i < NUM_ITERATIONS; i++) {
+        mFC->waitForFrame();
+        LOGV("+updateTexImage");
+        mST->updateTexImage();
+        LOGV("-updateTexImage");
+        mFC->finishFrame();
+
+        // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
+    }
+}
+
+// XXX: This test is disabled because it causes hangs on some devices.
+TEST_F(SurfaceTextureGLToGLTest, DISABLED_RepeatedUpdateTexImageAfterFrameFinishedWorks) {
+    enum { NUM_ITERATIONS = 1024 };
+
+    class PT : public ProducerThread {
+        virtual void render() {
+            for (int i = 0; i < NUM_ITERATIONS; i++) {
+                glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+                glClear(GL_COLOR_BUFFER_BIT);
+                LOGV("+swapBuffers");
+                swapBuffers();
+                LOGV("-swapBuffers");
+            }
+        }
+    };
+
+    runProducerThread(new PT());
+
+    for (int i = 0; i < NUM_ITERATIONS; i++) {
+        mFC->waitForFrame();
+        mFC->finishFrame();
+        LOGV("+updateTexImage");
+        mST->updateTexImage();
+        LOGV("-updateTexImage");
+
+        // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported!
+    }
+}
+
+} // namespace android
diff --git a/libs/utils/Threads.cpp b/libs/utils/Threads.cpp
index 8b5da0e..c748228 100644
--- a/libs/utils/Threads.cpp
+++ b/libs/utils/Threads.cpp
@@ -168,6 +168,9 @@
         return 0;
     }
 
+    // Note that *threadID is directly available to the parent only, as it is
+    // assigned after the child starts.  Use memory barrier / lock if the child
+    // or other threads also need access.
     if (threadId != NULL) {
         *threadId = (android_thread_id_t)thread; // XXX: this is not portable
     }
@@ -718,7 +721,6 @@
         res = androidCreateRawThreadEtc(_threadLoop,
                 this, name, priority, stack, &mThread);
     }
-    // The new thread wakes up at _threadLoop, but immediately blocks on mLock
     
     if (res == false) {
         mStatus = UNKNOWN_ERROR;   // something happened!
@@ -742,11 +744,6 @@
 {
     Thread* const self = static_cast<Thread*>(user);
 
-    // force a memory barrier before reading any fields, in particular mHoldSelf
-    {
-    Mutex::Autolock _l(self->mLock);
-    }
-
     sp<Thread> strong(self->mHoldSelf);
     wp<Thread> weak(strong);
     self->mHoldSelf.clear();
@@ -816,6 +813,7 @@
 
 status_t Thread::requestExitAndWait()
 {
+    Mutex::Autolock _l(mLock);
     if (mThread == getThreadId()) {
         LOGW(
         "Thread (this=%p): don't call waitForExit() from this "
@@ -825,9 +823,8 @@
         return WOULD_BLOCK;
     }
     
-    requestExit();
+    mExitPending = true;
 
-    Mutex::Autolock _l(mLock);
     while (mRunning == true) {
         mThreadExitedCondition.wait(mLock);
     }
diff --git a/tests/GridLayoutTest/res/layout/grid3.xml b/tests/GridLayoutTest/res/layout/grid3.xml
index 31dc75a..5cdacf7 100644
--- a/tests/GridLayoutTest/res/layout/grid3.xml
+++ b/tests/GridLayoutTest/res/layout/grid3.xml
@@ -19,14 +19,17 @@
 
         android:layout_width="match_parent"
         android:layout_height="match_parent"
+
         android:useDefaultMargins="true"
         android:marginsIncludedInAlignment="false"
+
         android:columnCount="4"
         >
 
     <TextView
             android:text="Email account"
             android:textSize="48dip"
+
             android:layout_columnSpan="4"
             android:layout_gravity="center_horizontal"
             />
@@ -34,12 +37,14 @@
     <TextView
             android:text="You can configure email in just a few steps:"
             android:textSize="20dip"
+
             android:layout_columnSpan="4"
             android:layout_gravity="left"
             />
 
     <TextView
             android:text="Email address:"
+
             android:layout_gravity="right"
             />
 
@@ -49,6 +54,7 @@
 
     <TextView
             android:text="Password:"
+
             android:layout_column="0"
             android:layout_gravity="right"
             />
@@ -58,14 +64,15 @@
             />
 
     <Space
-            android:layout_rowWeight="1"
-            android:layout_columnWeight="1"
             android:layout_row="4"
             android:layout_column="2"
+            android:layout_rowWeight="1"
+            android:layout_columnWeight="1"
             />
 
     <Button
             android:text="Manual setup"
+
             android:layout_row="5"
             android:layout_column="3"
             android:layout_gravity="fill_horizontal"
@@ -73,6 +80,7 @@
 
     <Button
             android:text="Next"
+
             android:layout_column="3"
             android:layout_gravity="fill_horizontal"
             />
diff --git a/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java b/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java
index 5e29cf1..32365d7 100644
--- a/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java
+++ b/tests/GridLayoutTest/src/com/android/test/layout/Activity2.java
@@ -20,11 +20,15 @@
 import android.content.Context;
 import android.os.Bundle;
 import android.view.View;
-
-import android.widget.*;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.GridLayout;
+import android.widget.Space;
+import android.widget.TextView;
 
 import static android.text.InputType.TYPE_CLASS_TEXT;
-import static android.view.inputmethod.EditorInfo.*;
+import static android.view.inputmethod.EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;
+import static android.view.inputmethod.EditorInfo.TYPE_TEXT_VARIATION_PASSWORD;
 import static android.widget.GridLayout.*;
 
 public class Activity2 extends Activity {
@@ -42,12 +46,12 @@
         Group row6 = new Group(6, CENTER);
         Group row7 = new Group(7, CENTER);
 
-        Group col1a = new Group(1, 5, CENTER);
-        Group col1b = new Group(1, 5, LEFT);
+        Group col1a = new Group(1, 4, CENTER);
+        Group col1b = new Group(1, 4, LEFT);
         Group col1c = new Group(1, RIGHT);
-        Group col2 =  new Group(2, LEFT);
-        Group col3 =  new Group(3, FILL);
-        Group col4 =  new Group(4, FILL);
+        Group col2 = new Group(2, LEFT);
+        Group col3 = new Group(3, FILL);
+        Group col4 = new Group(4, FILL);
 
         {
             TextView v = new TextView(context);
@@ -55,20 +59,17 @@
             v.setText("Email setup");
             vg.addView(v, new LayoutParams(row1, col1a));
         }
-
         {
             TextView v = new TextView(context);
             v.setTextSize(20);
             v.setText("You can configure email in just a few steps:");
             vg.addView(v, new LayoutParams(row2, col1b));
         }
-
         {
             TextView v = new TextView(context);
             v.setText("Email address:");
             vg.addView(v, new LayoutParams(row3, col1c));
         }
-
         {
             EditText v = new EditText(context);
             v.setInputType(TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
@@ -78,13 +79,11 @@
                 vg.addView(v, lp);
             }
         }
-
         {
             TextView v = new TextView(context);
             v.setText("Password:");
             vg.addView(v, new LayoutParams(row4, col1c));
         }
-
         {
             TextView v = new EditText(context);
             v.setInputType(TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_PASSWORD);
@@ -94,7 +93,6 @@
                 vg.addView(v, lp);
             }
         }
-
         {
             Space v = new Space(context);
             {
@@ -104,13 +102,11 @@
                 vg.addView(v, lp);
             }
         }
-
         {
             Button v = new Button(context);
             v.setText("Manual setup");
             vg.addView(v, new LayoutParams(row6, col4));
         }
-
         {
             Button v = new Button(context);
             v.setText("Next");
diff --git a/wifi/java/android/net/wifi/SupplicantState.java b/wifi/java/android/net/wifi/SupplicantState.java
index 91e685f..509b02c 100644
--- a/wifi/java/android/net/wifi/SupplicantState.java
+++ b/wifi/java/android/net/wifi/SupplicantState.java
@@ -216,6 +216,28 @@
         }
     }
 
+    static boolean isDriverActive(SupplicantState state) {
+        switch(state) {
+            case DISCONNECTED:
+            case DORMANT:
+            case INACTIVE:
+            case AUTHENTICATING:
+            case ASSOCIATING:
+            case ASSOCIATED:
+            case SCANNING:
+            case FOUR_WAY_HANDSHAKE:
+            case GROUP_HANDSHAKE:
+            case COMPLETED:
+                return true;
+            case INTERFACE_DISABLED:
+            case UNINITIALIZED:
+            case INVALID:
+                return false;
+            default:
+                throw new IllegalArgumentException("Unknown supplicant state");
+        }
+    }
+
     /** Implement the Parcelable interface {@hide} */
     public int describeContents() {
         return 0;
diff --git a/wifi/java/android/net/wifi/WifiMonitor.java b/wifi/java/android/net/wifi/WifiMonitor.java
index 4a45825..4ec4cfc 100644
--- a/wifi/java/android/net/wifi/WifiMonitor.java
+++ b/wifi/java/android/net/wifi/WifiMonitor.java
@@ -107,7 +107,7 @@
      * <pre>
      * CTRL-EVENT-DRIVER-STATE state
      * </pre>
-     * <code>state</code> is either STARTED or STOPPED
+     * <code>state</code> can be HANGED
      */
     private static final String driverStateEvent = "DRIVER-STATE";
     /**
@@ -304,11 +304,7 @@
             if (state == null) {
                 return;
             }
-            if (state.equals("STOPPED")) {
-                mWifiStateMachine.notifyDriverStopped();
-            } else if (state.equals("STARTED")) {
-                mWifiStateMachine.notifyDriverStarted();
-            } else if (state.equals("HANGED")) {
+            if (state.equals("HANGED")) {
                 mWifiStateMachine.notifyDriverHung();
             }
         }
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 6df37bb..3df3736 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -212,22 +212,18 @@
     static final int SUP_CONNECTION_EVENT                 = BASE + 31;
     /* Connection to supplicant lost */
     static final int SUP_DISCONNECTION_EVENT              = BASE + 32;
-    /* Driver start completed */
-    static final int DRIVER_START_EVENT                   = BASE + 33;
-    /* Driver stop completed */
-    static final int DRIVER_STOP_EVENT                    = BASE + 34;
-    /* Network connection completed */
-    static final int NETWORK_CONNECTION_EVENT             = BASE + 36;
+   /* Network connection completed */
+    static final int NETWORK_CONNECTION_EVENT             = BASE + 33;
     /* Network disconnection completed */
-    static final int NETWORK_DISCONNECTION_EVENT          = BASE + 37;
+    static final int NETWORK_DISCONNECTION_EVENT          = BASE + 34;
     /* Scan results are available */
-    static final int SCAN_RESULTS_EVENT                   = BASE + 38;
+    static final int SCAN_RESULTS_EVENT                   = BASE + 35;
     /* Supplicate state changed */
-    static final int SUPPLICANT_STATE_CHANGE_EVENT        = BASE + 39;
+    static final int SUPPLICANT_STATE_CHANGE_EVENT        = BASE + 36;
     /* Password failure and EAP authentication failure */
-    static final int AUTHENTICATION_FAILURE_EVENT         = BASE + 40;
+    static final int AUTHENTICATION_FAILURE_EVENT         = BASE + 37;
     /* WPS overlap detected */
-    static final int WPS_OVERLAP_EVENT                    = BASE + 41;
+    static final int WPS_OVERLAP_EVENT                    = BASE + 38;
 
 
     /* Supplicant commands */
@@ -1421,6 +1417,35 @@
         return mNetworkInfo.getDetailedState();
     }
 
+
+    private SupplicantState handleSupplicantStateChange(Message message) {
+        StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
+        SupplicantState state = stateChangeResult.state;
+        // Supplicant state change
+        // [31-13] Reserved for future use
+        // [8 - 0] Supplicant state (as defined in SupplicantState.java)
+        // 50023 supplicant_state_changed (custom|1|5)
+        EventLog.writeEvent(EVENTLOG_SUPPLICANT_STATE_CHANGED, state.ordinal());
+        mWifiInfo.setSupplicantState(state);
+        // Network id is only valid when we start connecting
+        if (SupplicantState.isConnecting(state)) {
+            mWifiInfo.setNetworkId(stateChangeResult.networkId);
+        } else {
+            mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID);
+        }
+
+        if (state == SupplicantState.ASSOCIATING) {
+            /* BSSID is valid only in ASSOCIATING state */
+            mWifiInfo.setBSSID(stateChangeResult.BSSID);
+        }
+        setNetworkDetailedState(WifiInfo.getDetailedStateOf(state));
+
+        mSupplicantStateTracker.sendMessage(Message.obtain(message));
+        mWpsStateMachine.sendMessage(Message.obtain(message));
+
+        return state;
+    }
+
     /**
      * Resets the Wi-Fi Connections by clearing any state, resetting any sockets
      * using the interface, stopping DHCP & disabling interface
@@ -1674,14 +1699,6 @@
         sendMessage(SCAN_RESULTS_EVENT);
     }
 
-    void notifyDriverStarted() {
-        sendMessage(DRIVER_START_EVENT);
-    }
-
-    void notifyDriverStopped() {
-        sendMessage(DRIVER_STOP_EVENT);
-    }
-
     void notifyDriverHung() {
         setWifiEnabled(false);
         setWifiEnabled(true);
@@ -1737,8 +1754,6 @@
                 case CMD_REASSOCIATE:
                 case SUP_CONNECTION_EVENT:
                 case SUP_DISCONNECTION_EVENT:
-                case DRIVER_START_EVENT:
-                case DRIVER_STOP_EVENT:
                 case NETWORK_CONNECTION_EVENT:
                 case NETWORK_DISCONNECTION_EVENT:
                 case SCAN_RESULTS_EVENT:
@@ -2284,13 +2299,19 @@
         public boolean processMessage(Message message) {
             if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
             switch(message.what) {
-                case DRIVER_START_EVENT:
-                    transitionTo(mDriverStartedState);
+               case SUPPLICANT_STATE_CHANGE_EVENT:
+                    SupplicantState state = handleSupplicantStateChange(message);
+                    /* If suplicant is exiting out of INTERFACE_DISABLED state into
+                     * a state that indicates driver has started, it is ready to
+                     * receive driver commands
+                     */
+                    if (SupplicantState.isDriverActive(state)) {
+                        transitionTo(mDriverStartedState);
+                    }
                     break;
                     /* Queue driver commands & connection events */
                 case CMD_START_DRIVER:
                 case CMD_STOP_DRIVER:
-                case SUPPLICANT_STATE_CHANGE_EVENT:
                 case NETWORK_CONNECTION_EVENT:
                 case NETWORK_DISCONNECTION_EVENT:
                 case AUTHENTICATION_FAILURE_EVENT:
@@ -2429,8 +2450,11 @@
         public boolean processMessage(Message message) {
             if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
             switch(message.what) {
-                case DRIVER_STOP_EVENT:
-                    transitionTo(mDriverStoppedState);
+                case SUPPLICANT_STATE_CHANGE_EVENT:
+                    SupplicantState state = handleSupplicantStateChange(message);
+                    if (state == SupplicantState.INTERFACE_DISABLED) {
+                        transitionTo(mDriverStoppedState);
+                    }
                     break;
                     /* Queue driver commands */
                 case CMD_START_DRIVER:
@@ -2465,11 +2489,23 @@
         public boolean processMessage(Message message) {
             if (DBG) Log.d(TAG, getName() + message.toString() + "\n");
             switch (message.what) {
-                case CMD_START_DRIVER:
-                    mWakeLock.acquire();
-                    WifiNative.startDriverCommand();
-                    transitionTo(mDriverStartingState);
-                    mWakeLock.release();
+               case CMD_START_DRIVER:
+                   mWakeLock.acquire();
+                   WifiNative.startDriverCommand();
+                   mWakeLock.release();
+                   break;
+                case SUPPLICANT_STATE_CHANGE_EVENT:
+                    SupplicantState state = handleSupplicantStateChange(message);
+                    /* A driver start causes supplicant to first report an INTERFACE_DISABLED
+                     * state before transitioning out of it for connection. Stay in
+                     * DriverStoppedState until we get an INTERFACE_DISABLED state and transition
+                     * to DriverStarting upon getting that
+                     * TODO: Fix this when the supplicant can be made to just transition out of
+                     * INTERFACE_DISABLED state when driver gets started
+                     */
+                    if (state == SupplicantState.INTERFACE_DISABLED) {
+                        transitionTo(mDriverStartingState);
+                    }
                     break;
                 default:
                     return NOT_HANDLED;
@@ -2535,29 +2571,8 @@
                     sendErrorBroadcast(WifiManager.WPS_OVERLAP_ERROR);
                     break;
                 case SUPPLICANT_STATE_CHANGE_EVENT:
-                    stateChangeResult = (StateChangeResult) message.obj;
-                    SupplicantState state = stateChangeResult.state;
-                    // Supplicant state change
-                    // [31-13] Reserved for future use
-                    // [8 - 0] Supplicant state (as defined in SupplicantState.java)
-                    // 50023 supplicant_state_changed (custom|1|5)
-                    EventLog.writeEvent(EVENTLOG_SUPPLICANT_STATE_CHANGED, state.ordinal());
-                    mWifiInfo.setSupplicantState(state);
-                    // Network id is only valid when we start connecting
-                    if (SupplicantState.isConnecting(state)) {
-                        mWifiInfo.setNetworkId(stateChangeResult.networkId);
-                    } else {
-                        mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID);
-                    }
-
-                    if (state == SupplicantState.ASSOCIATING) {
-                        /* BSSID is valid only in ASSOCIATING state */
-                        mWifiInfo.setBSSID(stateChangeResult.BSSID);
-                    }
-
-                    mSupplicantStateTracker.sendMessage(Message.obtain(message));
-                    mWpsStateMachine.sendMessage(Message.obtain(message));
-                    break;
+                    handleSupplicantStateChange(message);
+                   break;
                     /* Do a redundant disconnect without transition */
                 case CMD_DISCONNECT:
                     WifiNative.disconnectCommand();
@@ -2964,12 +2979,7 @@
                     /* Ignore network disconnect */
                 case NETWORK_DISCONNECTION_EVENT:
                     break;
-                case SUPPLICANT_STATE_CHANGE_EVENT:
-                    StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
-                    setNetworkDetailedState(WifiInfo.getDetailedStateOf(stateChangeResult.state));
-                    /* DriverStartedState does the rest of the handling */
-                    return NOT_HANDLED;
-                case CMD_START_SCAN:
+               case CMD_START_SCAN:
                     /* Disable background scan temporarily during a regular scan */
                     if (mEnableBackgroundScan) {
                         WifiNative.enableBackgroundScanCommand(false);