Merge "Update TextureView.lockCanvas() test."
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 42eda02..8e2d360 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -168,6 +168,7 @@
         SearchBar searchBar = (SearchBar) findViewById(com.android.internal.R.id.search_bar);
         searchBar.setSearchDialog(this);
         mSearchView = (SearchView) findViewById(com.android.internal.R.id.search_view);
+        mSearchView.setIconified(false);
         mSearchView.setOnCloseListener(mOnCloseListener);
         mSearchView.setOnQueryTextListener(mOnQueryChangeListener);
         mSearchView.setOnSuggestionListener(mOnSuggestionSelectionListener);
@@ -633,31 +634,6 @@
         }
 
         /**
-         * Overrides the handling of the back key to move back to the previous
-         * sources or dismiss the search dialog, instead of dismissing the input
-         * method.
-         */
-        @Override
-        public boolean dispatchKeyEventPreIme(KeyEvent event) {
-            if (DBG)
-                Log.d(LOG_TAG, "onKeyPreIme(" + event + ")");
-            if (mSearchDialog != null && event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
-                KeyEvent.DispatcherState state = getKeyDispatcherState();
-                if (state != null) {
-                    if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
-                        state.startTracking(event, this);
-                        return true;
-                    } else if (event.getAction() == KeyEvent.ACTION_UP && !event.isCanceled()
-                            && state.isTracking(event)) {
-                        mSearchDialog.onBackPressed();
-                        return true;
-                    }
-                }
-            }
-            return super.dispatchKeyEventPreIme(event);
-        }
-
-        /**
          * Don't allow action modes in a SearchBar, it looks silly.
          */
         @Override
diff --git a/core/java/android/content/SearchRecentSuggestionsProvider.java b/core/java/android/content/SearchRecentSuggestionsProvider.java
index 3d89e92..e1a8d21 100644
--- a/core/java/android/content/SearchRecentSuggestionsProvider.java
+++ b/core/java/android/content/SearchRecentSuggestionsProvider.java
@@ -186,6 +186,9 @@
 
             mSuggestionProjection = new String [] {
                     "0 AS " + SearchManager.SUGGEST_COLUMN_FORMAT,
+                    "'android.resource://system/"
+                            + com.android.internal.R.drawable.ic_menu_recent_history + "' AS "
+                            + SearchManager.SUGGEST_COLUMN_ICON_1,
                     "display1 AS " + SearchManager.SUGGEST_COLUMN_TEXT_1,
                     "display2 AS " + SearchManager.SUGGEST_COLUMN_TEXT_2,
                     "query AS " + SearchManager.SUGGEST_COLUMN_QUERY,
@@ -196,6 +199,9 @@
 
             mSuggestionProjection = new String [] {
                     "0 AS " + SearchManager.SUGGEST_COLUMN_FORMAT,
+                    "'android.resource://system/"
+                            + com.android.internal.R.drawable.ic_menu_recent_history + "' AS "
+                            + SearchManager.SUGGEST_COLUMN_ICON_1,
                     "display1 AS " + SearchManager.SUGGEST_COLUMN_TEXT_1,
                     "query AS " + SearchManager.SUGGEST_COLUMN_QUERY,
                     "_id"
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index f3bda43..b2d1a1e 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -18,8 +18,6 @@
 
 import static android.widget.SuggestionsAdapter.getColumnString;
 
-import com.android.internal.R;
-
 import android.app.PendingIntent;
 import android.app.SearchManager;
 import android.app.SearchableInfo;
@@ -39,10 +37,14 @@
 import android.os.Bundle;
 import android.speech.RecognizerIntent;
 import android.text.Editable;
+import android.text.Spannable;
+import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
 import android.text.TextWatcher;
+import android.text.style.ImageSpan;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.TypedValue;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -51,6 +53,8 @@
 import android.widget.AdapterView.OnItemSelectedListener;
 import android.widget.TextView.OnEditorActionListener;
 
+import com.android.internal.R;
+
 import java.util.WeakHashMap;
 
 /**
@@ -87,6 +91,8 @@
     private View mSearchEditFrame;
     private View mVoiceButton;
     private SearchAutoComplete mQueryTextView;
+    private View mDropDownAnchor;
+    private ImageView mSearchHintIcon;
     private boolean mSubmitButtonEnabled;
     private CharSequence mQueryHint;
     private boolean mQueryRefinement;
@@ -195,6 +201,7 @@
         mSubmitButton = findViewById(R.id.search_go_btn);
         mCloseButton = (ImageView) findViewById(R.id.search_close_btn);
         mVoiceButton = findViewById(R.id.search_voice_btn);
+        mSearchHintIcon = (ImageView) findViewById(R.id.search_mag_icon);
 
         mSearchButton.setOnClickListener(mOnClickListener);
         mCloseButton.setOnClickListener(mOnClickListener);
@@ -244,7 +251,20 @@
         mVoiceAppSearchIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
         mVoiceAppSearchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 
+        mDropDownAnchor = findViewById(mQueryTextView.getDropDownAnchor());
+        if (mDropDownAnchor != null) {
+            mDropDownAnchor.addOnLayoutChangeListener(new OnLayoutChangeListener() {
+                @Override
+                public void onLayoutChange(View v, int left, int top, int right, int bottom,
+                        int oldLeft, int oldTop, int oldRight, int oldBottom) {
+                    adjustDropDownSizeAndPosition();
+                }
+
+            });
+        }
+
         updateViewsVisibility(mIconifiedByDefault);
+        updateQueryHint();
     }
 
     /**
@@ -263,7 +283,7 @@
         }
         // Cache the voice search capability
         mVoiceButtonEnabled = hasVoiceSearch();
-        updateViewsVisibility(mIconifiedByDefault);
+        updateViewsVisibility(isIconified());
     }
 
     /**
@@ -300,7 +320,6 @@
         mQueryTextView.clearFocus();
         setImeVisibility(false);
         mClearingFocus = false;
-        updateViewsVisibility(mIconifiedByDefault);
     }
 
     /**
@@ -555,6 +574,7 @@
         mSearchButton.setVisibility(visCollapsed);
         updateSubmitButton(hasText);
         mSearchEditFrame.setVisibility(collapsed ? GONE : VISIBLE);
+        mSearchHintIcon.setVisibility(mIconifiedByDefault ? GONE : VISIBLE);
         updateCloseButton();
         updateVoiceButton(!hasText);
         updateSubmitArea();
@@ -822,9 +842,29 @@
         return result;
     }
 
+    private int getSearchIconId() {
+        TypedValue outValue = new TypedValue();
+        getContext().getTheme().resolveAttribute(com.android.internal.R.attr.searchViewSearchIcon,
+                outValue, true);
+        return outValue.resourceId;
+    }
+
+    private CharSequence getDecoratedHint(CharSequence hintText) {
+        // If the field is always expanded, then don't add the search icon to the hint
+        if (!mIconifiedByDefault) return hintText;
+
+        SpannableStringBuilder ssb = new SpannableStringBuilder("   "); // for the icon
+        ssb.append(hintText);
+        Drawable searchIcon = getContext().getResources().getDrawable(getSearchIconId());
+        int textSize = (int) (mQueryTextView.getTextSize() * 1.25);
+        searchIcon.setBounds(0, 0, textSize, textSize);
+        ssb.setSpan(new ImageSpan(searchIcon), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+        return ssb;
+    }
+
     private void updateQueryHint() {
         if (mQueryHint != null) {
-            mQueryTextView.setHint(mQueryHint);
+            mQueryTextView.setHint(getDecoratedHint(mQueryHint));
         } else if (mSearchable != null) {
             CharSequence hint = null;
             int hintId = mSearchable.getHintId();
@@ -832,8 +872,10 @@
                 hint = getContext().getString(hintId);
             }
             if (hint != null) {
-                mQueryTextView.setHint(hint);
+                mQueryTextView.setHint(getDecoratedHint(hint));
             }
+        } else {
+            mQueryTextView.setHint(getDecoratedHint(""));
         }
     }
 
@@ -922,9 +964,13 @@
         CharSequence text = mQueryTextView.getText();
         if (TextUtils.isEmpty(text)) {
             if (mIconifiedByDefault) {
-                // query field already empty, hide the keyboard and remove focus
-                clearFocus();
-                setImeVisibility(false);
+                // If the app doesn't override the close behavior
+                if (mOnCloseListener == null || !mOnCloseListener.onClose()) {
+                    // hide the keyboard and remove focus
+                    clearFocus();
+                    // collapse the search field
+                    updateViewsVisibility(true);
+                }
             }
         } else {
             mQueryTextView.setText("");
@@ -932,10 +978,6 @@
             setImeVisibility(true);
         }
 
-        if (mIconifiedByDefault && (mOnCloseListener == null || !mOnCloseListener.onClose())) {
-            updateViewsVisibility(mIconifiedByDefault);
-            setImeVisibility(false);
-        }
     }
 
     private void onSearchClicked() {
@@ -975,6 +1017,28 @@
         updateFocusedState(mQueryTextView.hasFocus());
     }
 
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+    }
+
+    private void adjustDropDownSizeAndPosition() {
+        if (mDropDownAnchor.getWidth() > 1) {
+            Resources res = getContext().getResources();
+            int anchorPadding = mSearchPlate.getPaddingLeft();
+            Rect dropDownPadding = new Rect();
+            int iconOffset = mIconifiedByDefault
+                    ? res.getDimensionPixelSize(R.dimen.dropdownitem_icon_width)
+                    + res.getDimensionPixelSize(R.dimen.dropdownitem_text_padding_left)
+                    : 0;
+            mQueryTextView.getDropDownBackground().getPadding(dropDownPadding);
+            mQueryTextView.setDropDownHorizontalOffset(-(dropDownPadding.left + iconOffset)
+                    + anchorPadding);
+            mQueryTextView.setDropDownWidth(mDropDownAnchor.getWidth() + dropDownPadding.left
+                    + dropDownPadding.right + iconOffset - (anchorPadding));
+        }
+    }
+
     private boolean onItemClicked(int position, int actionKey, String actionMsg) {
         if (mOnSuggestionListener == null
                 || !mOnSuggestionListener.onSuggestionClick(position)) {
@@ -1393,5 +1457,32 @@
         public boolean enoughToFilter() {
             return mThreshold <= 0 || super.enoughToFilter();
         }
+
+        @Override
+        public boolean onKeyPreIme(int keyCode, KeyEvent event) {
+            if (keyCode == KeyEvent.KEYCODE_BACK) {
+                // special case for the back key, we do not even try to send it
+                // to the drop down list but instead, consume it immediately
+                if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
+                    KeyEvent.DispatcherState state = getKeyDispatcherState();
+                    if (state != null) {
+                        state.startTracking(event, this);
+                    }
+                    return true;
+                } else if (event.getAction() == KeyEvent.ACTION_UP) {
+                    KeyEvent.DispatcherState state = getKeyDispatcherState();
+                    if (state != null) {
+                        state.handleUpEvent(event);
+                    }
+                    if (event.isTracking() && !event.isCanceled()) {
+                        mSearchView.clearFocus();
+                        mSearchView.setImeVisibility(false);
+                        return true;
+                    }
+                }
+            }
+            return super.onKeyPreIme(keyCode, event);
+        }
+
     }
 }
diff --git a/core/java/android/widget/SuggestionsAdapter.java b/core/java/android/widget/SuggestionsAdapter.java
index 2cfc016..9e32c9a 100644
--- a/core/java/android/widget/SuggestionsAdapter.java
+++ b/core/java/android/widget/SuggestionsAdapter.java
@@ -16,8 +16,6 @@
 
 package android.widget;
 
-import com.android.internal.R;
-
 import android.app.SearchDialog;
 import android.app.SearchManager;
 import android.app.SearchableInfo;
@@ -47,6 +45,8 @@
 import android.view.ViewGroup;
 import android.view.View.OnClickListener;
 
+import com.android.internal.R;
+
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
@@ -88,8 +88,8 @@
     private int mIconName2Col = INVALID_INDEX;
     private int mFlagsCol = INVALID_INDEX;
 
-    private final Runnable mStartSpinnerRunnable;
-    private final Runnable mStopSpinnerRunnable;
+    // private final Runnable mStartSpinnerRunnable;
+    // private final Runnable mStopSpinnerRunnable;
 
     /**
      * The amount of time we delay in the filter when the user presses the delete key.
@@ -113,17 +113,18 @@
 
         mOutsideDrawablesCache = outsideDrawablesCache;
         
-        mStartSpinnerRunnable = new Runnable() {
-                public void run() {
-                // mSearchView.setWorking(true); // TODO:
-                }
-            };
 
-        mStopSpinnerRunnable = new Runnable() {
-            public void run() {
-                // mSearchView.setWorking(false); // TODO:
-            }
-        };
+        // mStartSpinnerRunnable = new Runnable() {
+        // public void run() {
+        // // mSearchView.setWorking(true); // TODO:
+        // }
+        // };
+        //
+        // mStopSpinnerRunnable = new Runnable() {
+        // public void run() {
+        // // mSearchView.setWorking(false); // TODO:
+        // }
+        // };
 
         // delay 500ms when deleting
         getFilter().setDelayer(new Filter.Delayer() {
@@ -341,10 +342,10 @@
         }
 
         if (views.mIcon1 != null) {
-            setViewDrawable(views.mIcon1, getIcon1(cursor));
+            setViewDrawable(views.mIcon1, getIcon1(cursor), View.INVISIBLE);
         }
         if (views.mIcon2 != null) {
-            setViewDrawable(views.mIcon2, getIcon2(cursor));
+            setViewDrawable(views.mIcon2, getIcon2(cursor), View.GONE);
         }
         if (mQueryRefinement == REFINE_ALL
                 || (mQueryRefinement == REFINE_BY_ENTRY
@@ -414,13 +415,13 @@
      * Sets the drawable in an image view, makes sure the view is only visible if there
      * is a drawable.
      */
-    private void setViewDrawable(ImageView v, Drawable drawable) {
+    private void setViewDrawable(ImageView v, Drawable drawable, int nullVisibility) {
         // Set the icon even if the drawable is null, since we need to clear any
         // previous icon.
         v.setImageDrawable(drawable);
 
         if (drawable == null) {
-            v.setVisibility(View.GONE);
+            v.setVisibility(nullVisibility);
         } else {
             v.setVisibility(View.VISIBLE);
 
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 06dc083..514e59d 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -139,6 +139,7 @@
 	android_bluetooth_common.cpp \
 	android_bluetooth_BluetoothAudioGateway.cpp \
 	android_bluetooth_BluetoothSocket.cpp \
+	android_bluetooth_c.c \
 	android_server_BluetoothService.cpp \
 	android_server_BluetoothEventLoop.cpp \
 	android_server_BluetoothA2dpService.cpp \
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index 6a13876..30fe298 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -323,9 +323,7 @@
 
 void TextLayoutCacheValue::setupShaperItem(HB_ShaperItem* shaperItem, HB_FontRec* font,
         FontData* fontData, SkPaint* paint, const UChar* chars, size_t start, size_t count,
-        size_t contextCount, int dirFlags) {
-    bool isRTL = dirFlags & 0x1;
-
+        size_t contextCount, bool isRTL) {
     font->klass = &harfbuzzSkiaClass;
     font->userData = 0;
     // The values which harfbuzzSkiaClass returns are already scaled to
@@ -374,10 +372,10 @@
 
 void TextLayoutCacheValue::shapeWithHarfbuzz(HB_ShaperItem* shaperItem, HB_FontRec* font,
         FontData* fontData, SkPaint* paint, const UChar* chars, size_t start, size_t count,
-        size_t contextCount, int dirFlags) {
+        size_t contextCount, bool isRTL) {
     // Setup Harfbuzz Shaper
     setupShaperItem(shaperItem, font, fontData, paint, chars, start, count,
-            contextCount, dirFlags);
+            contextCount, isRTL);
 
     // Shape
     resetGlyphArrays(shaperItem);
@@ -430,7 +428,7 @@
                     LOGD("computeValuesWithHarfbuzz -- forcing run with LTR=%d RTL=%d",
                             forceLTR, forceRTL);
 #endif
-            computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, dirFlags,
+            computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, forceRTL,
                     outAdvances, outTotalAdvance, outGlyphs, outGlyphsCount);
 
             if (forceRTL && *outGlyphsCount > 1) {
@@ -451,10 +449,15 @@
                     LOGD("computeValuesWithHarfbuzz -- dirFlags=%d run-count=%d paraDir=%d", dirFlags, rc, paraDir);
 #endif
                     if (rc == 1 || !U_SUCCESS(status)) {
+                        bool isRTL = (paraDir == 1);
+#if DEBUG_GLYPHS
+                        LOGD("computeValuesWithHarfbuzz -- processing SINGLE run "
+                                "-- run-start=%d run-len=%d isRTL=%d", start, count, isRTL);
+#endif
                         computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount,
-                                dirFlags, outAdvances, outTotalAdvance, outGlyphs, outGlyphsCount);
+                                isRTL, outAdvances, outTotalAdvance, outGlyphs, outGlyphsCount);
 
-                        if (dirFlags == 1 && *outGlyphsCount > 1) {
+                        if (isRTL && *outGlyphsCount > 1) {
                             reverseGlyphArray(*outGlyphs, *outGlyphsCount);
                         }
                     } else {
@@ -485,14 +488,14 @@
 
                             lengthRun = endRun - startRun;
 
-                            int newFlags = (runDir == UBIDI_RTL) ? kDirection_RTL : kDirection_LTR;
+                            bool isRTL = (runDir == UBIDI_RTL);
                             jfloat runTotalAdvance = 0;
 #if DEBUG_GLYPHS
-                            LOGD("computeValuesWithHarfbuzz -- run-start=%d run-len=%d newFlags=%d",
-                                    startRun, lengthRun, newFlags);
+                            LOGD("computeValuesWithHarfbuzz -- run-start=%d run-len=%d isRTL=%d",
+                                    startRun, lengthRun, isRTL);
 #endif
                             computeRunValuesWithHarfbuzz(paint, chars, startRun,
-                                    lengthRun, contextCount, newFlags,
+                                    lengthRun, contextCount, isRTL,
                                     outAdvances, &runTotalAdvance,
                                     &runGlyphs, &runGlyphsCount);
 
@@ -506,7 +509,7 @@
                                 LOGD("                          -- glyphs[%d]=%d", j, runGlyphs[j]);
                             }
 #endif
-                            glyphRuns.push(GlyphRun(runGlyphs, runGlyphsCount, newFlags));
+                            glyphRuns.push(GlyphRun(runGlyphs, runGlyphsCount, isRTL));
                         }
                         *outGlyphs = new jchar[*outGlyphsCount];
 
@@ -528,13 +531,15 @@
                 ubidi_close(bidi);
             } else {
                 // Cannot run BiDi, just consider one Run
+                bool isRTL = (bidiReq = 1) || (bidiReq = UBIDI_DEFAULT_RTL);
 #if DEBUG_GLYPHS
-                LOGD("computeValuesWithHarfbuzz -- cannot run BiDi, considering only one Run");
+                LOGD("computeValuesWithHarfbuzz -- cannot run BiDi, considering a SINGLE Run "
+                        "-- run-start=%d run-len=%d isRTL=%d", start, count, isRTL);
 #endif
-                computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, dirFlags,
+                computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, isRTL,
                         outAdvances, outTotalAdvance, outGlyphs, outGlyphsCount);
 
-                if (dirFlags == 1 && *outGlyphsCount > 1) {
+                if (isRTL && *outGlyphsCount > 1) {
                     reverseGlyphArray(*outGlyphs, *outGlyphsCount);
                 }
             }
@@ -545,17 +550,15 @@
 }
 
 void TextLayoutCacheValue::computeRunValuesWithHarfbuzz(SkPaint* paint, const UChar* chars,
-        size_t start, size_t count, size_t contextCount, int dirFlags,
+        size_t start, size_t count, size_t contextCount, bool isRTL,
         jfloat* outAdvances, jfloat* outTotalAdvance,
         jchar** outGlyphs, size_t* outGlyphsCount) {
 
-    bool isRTL = dirFlags & 0x1;
-
     HB_ShaperItem shaperItem;
     HB_FontRec font;
     FontData fontData;
     shapeWithHarfbuzz(&shaperItem, &font, &fontData, paint, chars, start, count,
-            contextCount, dirFlags);
+            contextCount, isRTL);
 
 #if DEBUG_GLYPHS
     LOGD("HARFBUZZ -- num_glypth=%d - kerning_applied=%d", shaperItem.num_glyphs,
diff --git a/core/jni/android/graphics/TextLayoutCache.h b/core/jni/android/graphics/TextLayoutCache.h
index 690caac..10dee87 100644
--- a/core/jni/android/graphics/TextLayoutCache.h
+++ b/core/jni/android/graphics/TextLayoutCache.h
@@ -128,11 +128,11 @@
 
     static void setupShaperItem(HB_ShaperItem* shaperItem, HB_FontRec* font, FontData* fontData,
             SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount,
-            int dirFlags);
+            bool isRTL);
 
     static void shapeWithHarfbuzz(HB_ShaperItem* shaperItem, HB_FontRec* font, FontData* fontData,
             SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount,
-            int dirFlags);
+            bool isRTL);
 
     static void computeValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, size_t start,
             size_t count, size_t contextCount, int dirFlags,
@@ -179,7 +179,7 @@
     static void resetGlyphArrays(HB_ShaperItem* shaperItem);
 
     static void computeRunValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, size_t start,
-            size_t count, size_t contextCount, int dirFlags,
+            size_t count, size_t contextCount, bool isRTL,
             jfloat* outAdvances, jfloat* outTotalAdvance,
             jchar** outGlyphs, size_t* outGlyphsCount);
 }; // TextLayoutCacheValue
diff --git a/core/jni/android_bluetooth_BluetoothAudioGateway.cpp b/core/jni/android_bluetooth_BluetoothAudioGateway.cpp
index cb742a3..29c9c2d 100755
--- a/core/jni/android_bluetooth_BluetoothAudioGateway.cpp
+++ b/core/jni/android_bluetooth_BluetoothAudioGateway.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "BluetoothAudioGateway.cpp"
 
 #include "android_bluetooth_common.h"
+#include "android_bluetooth_c.h"
 #include "android_runtime/AndroidRuntime.h"
 #include "JNIHelp.h"
 #include "jni.h"
@@ -491,7 +492,8 @@
     }
 
     laddr.rc_family = AF_BLUETOOTH;
-    memcpy(&laddr.rc_bdaddr, BDADDR_ANY, sizeof(bdaddr_t));
+    bdaddr_t any = android_bluetooth_bdaddr_any();
+    memcpy(&laddr.rc_bdaddr, &any, sizeof(bdaddr_t));
     laddr.rc_channel = channel;
 
     if (bind(sk, (struct sockaddr *)&laddr, sizeof(laddr)) < 0) {
diff --git a/core/jni/android_bluetooth_BluetoothSocket.cpp b/core/jni/android_bluetooth_BluetoothSocket.cpp
index d09c4e9..4c84324 100644
--- a/core/jni/android_bluetooth_BluetoothSocket.cpp
+++ b/core/jni/android_bluetooth_BluetoothSocket.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "BluetoothSocket.cpp"
 
 #include "android_bluetooth_common.h"
+#include "android_bluetooth_c.h"
 #include "android_runtime/AndroidRuntime.h"
 #include "JNIHelp.h"
 #include "utils/Log.h"
@@ -245,7 +246,7 @@
     jint type;
     socklen_t addr_sz;
     struct sockaddr *addr;
-    bdaddr_t bdaddr = *BDADDR_ANY;
+    bdaddr_t bdaddr = android_bluetooth_bdaddr_any();
     struct asocket *s = get_socketData(env, obj);
 
     if (!s)
diff --git a/core/jni/android_bluetooth_c.c b/core/jni/android_bluetooth_c.c
new file mode 100755
index 0000000..b4c6727
--- /dev/null
+++ b/core/jni/android_bluetooth_c.c
@@ -0,0 +1,31 @@
+/*
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifdef HAVE_BLUETOOTH
+
+#include "android_bluetooth_c.h"
+
+/*
+ * A C helper for creating a bdaddr_t object with the value BDADDR_ANY.
+ * We have to do this in C because the macro BDADDR_ANY in bluetooth.h
+ * is not valid C++ code.
+ */
+bdaddr_t android_bluetooth_bdaddr_any(void)
+{
+  bdaddr_t any = *BDADDR_ANY;
+  return any;
+}
+#endif
diff --git a/core/jni/android_bluetooth_c.h b/core/jni/android_bluetooth_c.h
new file mode 100644
index 0000000..e890244
--- /dev/null
+++ b/core/jni/android_bluetooth_c.h
@@ -0,0 +1,39 @@
+/*
+** Copyright 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.
+*/
+
+#ifndef ANDROID_BLUETOOTH_C_H
+#define ANDROID_BLUETOOTH_C_H
+#ifdef HAVE_BLUETOOTH
+
+#include <bluetooth/bluetooth.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * A C helper for creating a bdaddr_t object with the value BDADDR_ANY.
+ * We have to do this in C because the macro BDADDR_ANY in bluetooth.h
+ * is not valid C++ code.
+ */
+bdaddr_t android_bluetooth_bdaddr_any(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*HAVE_BLUETOOTH*/
+#endif /*ANDROID_BLUETOOTH_C_H*/
diff --git a/core/res/res/layout/search_bar.xml b/core/res/res/layout/search_bar.xml
index 790ac6b..f6b5b53 100644
--- a/core/res/res/layout/search_bar.xml
+++ b/core/res/res/layout/search_bar.xml
@@ -66,7 +66,6 @@
             android:layout_height="wrap_content"
             android:layout_weight="1"
             android:maxWidth="600dip"
-            android:iconifiedByDefault="false"
             android:layout_gravity="center_vertical"
             />
 
diff --git a/core/res/res/layout/search_dropdown_item_icons_2line.xml b/core/res/res/layout/search_dropdown_item_icons_2line.xml
index 53906f9..acef2cc 100644
--- a/core/res/res/layout/search_dropdown_item_icons_2line.xml
+++ b/core/res/res/layout/search_dropdown_item_icons_2line.xml
@@ -19,21 +19,21 @@
 -->
 
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:paddingLeft="4dip"
-    android:paddingRight="2dip"
+    android:paddingLeft="@dimen/dropdownitem_text_padding_left"
+    android:paddingRight="4dip"
     android:layout_width="match_parent"
     android:layout_height="?android:attr/searchResultListItemHeight" >
 
     <!-- Icons come first in the layout, since their placement doesn't depend on
          the placement of the text views. -->
     <ImageView android:id="@android:id/icon1"
-        android:layout_width="48dip"
+        android:layout_width="@dimen/dropdownitem_icon_width"
         android:layout_height="48dip"
         android:scaleType="centerInside"
         android:layout_alignParentLeft="true"
         android:layout_alignParentTop="true"
         android:layout_alignParentBottom="true"
-        android:visibility="gone" />
+        android:visibility="invisible" />
 
     <ImageView android:id="@+id/edit_query"
         android:layout_width="48dip"
diff --git a/core/res/res/layout/search_view.xml b/core/res/res/layout/search_view.xml
index fee27eb..6b70d8d 100644
--- a/core/res/res/layout/search_view.xml
+++ b/core/res/res/layout/search_view.xml
@@ -22,6 +22,8 @@
     android:id="@+id/search_bar"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
+    android:paddingLeft="8dip"
+    android:paddingRight="8dip"
     android:orientation="horizontal"
     >
 
@@ -30,7 +32,7 @@
         android:id="@+id/search_badge"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
-        android:layout_gravity="center_vertical"
+        android:gravity="center_vertical"
         android:layout_marginBottom="2dip"
         android:drawablePadding="0dip"
         android:textAppearance="?android:attr/textAppearanceMedium"
@@ -54,12 +56,21 @@
         android:layout_height="wrap_content"
         android:layout_weight="1"
         android:layout_gravity="center_vertical"
-        android:layout_marginLeft="8dip"
-        android:layout_marginRight="8dip"
         android:layout_marginTop="4dip"
         android:layout_marginBottom="4dip"
         android:orientation="horizontal">
 
+        <ImageView
+            android:id="@+id/search_mag_icon"
+            android:layout_width="@dimen/dropdownitem_icon_width"
+            android:layout_height="wrap_content"
+            android:scaleType="centerInside"
+            android:layout_marginLeft="@dimen/dropdownitem_text_padding_left"
+            android:layout_gravity="center_vertical"
+            android:src="?android:attr/searchViewSearchIcon"
+            android:visibility="gone"
+        />
+
         <!-- Inner layout contains the app icon, button(s) and EditText -->
         <LinearLayout
             android:id="@+id/search_plate"
@@ -70,14 +81,6 @@
             android:orientation="horizontal"
             android:background="?android:attr/searchViewTextField">
 
-            <ImageView
-                android:id="@+id/search_app_icon"
-                android:layout_width="wrap_content"
-                android:layout_height="match_parent"
-                android:layout_gravity="center_vertical"
-                android:src="?android:attr/searchViewSearchIcon"
-            />
-
             <view class="android.widget.SearchView$SearchAutoComplete"
                 android:id="@+id/search_src_text"
                 android:layout_height="36dip"
@@ -85,8 +88,8 @@
                 android:layout_weight="1"
                 android:minWidth="@dimen/search_view_text_min_width"
                 android:layout_gravity="bottom"
-                android:paddingLeft="8dip"
-                android:paddingRight="6dip"
+                android:paddingLeft="@dimen/dropdownitem_text_padding_left"
+                android:paddingRight="@dimen/dropdownitem_text_padding_right"
                 android:singleLine="true"
                 android:ellipsize="end"
                 android:background="@null"
@@ -100,7 +103,7 @@
 
             <ImageView
                 android:id="@+id/search_close_btn"
-                android:layout_width="wrap_content"
+                android:layout_width="@dimen/dropdownitem_icon_width"
                 android:layout_height="match_parent"
                 android:paddingLeft="8dip"
                 android:paddingRight="8dip"
@@ -131,7 +134,7 @@
                 android:visibility="gone"
                 android:focusable="true"
             />
-    
+
             <ImageView
                 android:id="@+id/search_voice_btn"
                 android:layout_width="wrap_content"
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 73f636f..2ba4e66 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -141,4 +141,13 @@
     <!-- The default gap between components in a layout. -->
     <dimen name="default_gap">16dip</dimen>
 
+    <!-- Text padding for dropdown items -->
+    <dimen name="dropdownitem_text_padding_left">6dip</dimen>
+
+    <!-- Text padding for dropdown items -->
+    <dimen name="dropdownitem_text_padding_right">6dip</dimen>
+
+    <!-- Width of the icon in a dropdown list -->
+    <dimen name="dropdownitem_icon_width">48dip</dimen>
+
 </resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 5b5e7c3..d647467 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -563,8 +563,8 @@
 
     <style name="Widget.DropDownItem">
         <item name="android:textAppearance">@style/TextAppearance.Widget.DropDownItem</item>
-        <item name="android:paddingLeft">6dip</item>
-        <item name="android:paddingRight">6dip</item>
+        <item name="android:paddingLeft">@dimen/dropdownitem_text_padding_left</item>
+        <item name="android:paddingRight">@dimen/dropdownitem_text_padding_right</item>
         <item name="android:gravity">center_vertical</item>
     </style>
     
diff --git a/media/libstagefright/codecs/aacenc/src/bit_cnt.c b/media/libstagefright/codecs/aacenc/src/bit_cnt.c
index dd0b9b4..8853efc 100644
--- a/media/libstagefright/codecs/aacenc/src/bit_cnt.c
+++ b/media/libstagefright/codecs/aacenc/src/bit_cnt.c
@@ -496,7 +496,7 @@
 {
 
   Word32 i, t0, t1, t2, t3, t00, t01;
-  Word16 codeWord, codeLength;
+  UWord16 codeWord, codeLength;
   Word16 sign, signLength;
 
    
diff --git a/tests/BiDiTests/res/layout/canvas2.xml b/tests/BiDiTests/res/layout/canvas2.xml
new file mode 100644
index 0000000..b3e038f
--- /dev/null
+++ b/tests/BiDiTests/res/layout/canvas2.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/canvas2"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent">
+
+    <LinearLayout
+        xmlns:local="http://schemas.android.com/apk/res/com.android.bidi"
+        android:orientation="vertical"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent">
+
+        <TextView
+            android:text="@string/ltr"
+            android:textSize="40dip"
+            android:gravity="center"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content" />
+
+        <com.android.bidi.BiDiTestViewDrawText
+            local:text="@string/ltr"
+            android:layout_width="fill_parent"
+            android:layout_height="64dp" />
+
+        <TextView
+            android:text="@string/rtl"
+            android:textSize="40dip"
+            android:gravity="center"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"/>
+
+        <com.android.bidi.BiDiTestViewDrawText
+            local:text="@string/rtl"
+            android:layout_width="fill_parent"
+            android:layout_height="64dp" />
+
+        <TextView
+            android:text="@string/composing"
+            android:textSize="40dip"
+            android:gravity="center"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"/>
+
+        <com.android.bidi.BiDiTestViewDrawText
+            local:text="@string/composing"
+            android:layout_width="fill_parent"
+            android:layout_height="64dp" />
+
+    </LinearLayout>
+
+</FrameLayout>
\ No newline at end of file
diff --git a/tests/BiDiTests/res/values/attrs.xml b/tests/BiDiTests/res/values/attrs.xml
new file mode 100644
index 0000000..7f8a1d8
--- /dev/null
+++ b/tests/BiDiTests/res/values/attrs.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <declare-styleable name="DrawTextTestView">
+        <attr name="size" format="dimension" />
+        <attr name="color" format="color" />
+        <attr name="text" format="string" />
+    </declare-styleable>
+</resources>
\ No newline at end of file
diff --git a/tests/BiDiTests/res/values/strings.xml b/tests/BiDiTests/res/values/strings.xml
index bc99e79..1f6be7f 100644
--- a/tests/BiDiTests/res/values/strings.xml
+++ b/tests/BiDiTests/res/values/strings.xml
@@ -42,5 +42,8 @@
     <string name="textview_hebrew_text">&#x05DD;&#x05DE;ab?!</string>
     <string name="textview_latin_text">ab&#x05DD;&#x05DE;?!</string>
     <string name="textview_multiline_text">&#x05DD;&#x05DE;?!\nab?!\n?!</string>
+    <string name="ltr">Left to right text"</string>
+    <string name="rtl">"والحق أن تترك ونص"</string>
+    <string name="composing">"\u0644\u0627"</string>
 </resources>
 
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
index 7002c41..6b38cc1 100644
--- a/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
@@ -102,6 +102,7 @@
         addItem(result, "Basic", BiDiTestBasic.class, R.id.basic);
 
         addItem(result, "Canvas", BiDiTestCanvas.class, R.id.canvas);
+        addItem(result, "Canvas2", BiDiTestCanvas2.class, R.id.canvas2);
 
         addItem(result, "Linear LTR", BiDiTestLinearLayoutLtr.class, R.id.linear_layout_ltr);
         addItem(result, "Linear RTL", BiDiTestLinearLayoutRtl.class, R.id.linear_layout_rtl);
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestCanvas2.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestCanvas2.java
new file mode 100644
index 0000000..b801f0e
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestCanvas2.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bidi;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.SeekBar;
+
+import static com.android.bidi.BiDiTestConstants.FONT_MAX_SIZE;
+import static com.android.bidi.BiDiTestConstants.FONT_MIN_SIZE;
+
+public class BiDiTestCanvas2 extends Fragment {
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        return inflater.inflate(R.layout.canvas2, container, false);
+    }
+}
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestView.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestView.java
index 27e1887..0126dea 100644
--- a/tests/BiDiTests/src/com/android/bidi/BiDiTestView.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestView.java
@@ -21,7 +21,7 @@
 import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.Rect;
-import android.graphics.Typeface;
+import android.text.TextPaint;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.View;
@@ -37,7 +37,6 @@
 
     private static final float DEFAULT_ITALIC_SKEW_X = -0.25f;
 
-    private Paint paint = new Paint();
     private Rect rect = new Rect();
 
     private String NORMAL_TEXT;
@@ -51,8 +50,7 @@
     private String CHINESE_TEXT;
     private String MIXED_TEXT_1;
     private String HEBREW_TEXT;
-
-    private Typeface typeface;
+    private String RTL_TEXT;
 
     private int currentTextSize;
 
@@ -83,9 +81,7 @@
         CHINESE_TEXT = context.getString(R.string.chinese_text);
         MIXED_TEXT_1 = context.getString(R.string.mixed_text_1);
         HEBREW_TEXT = context.getString(R.string.hebrew_text);
-
-        typeface = paint.getTypeface();
-        paint.setAntiAlias(true);
+        RTL_TEXT = context.getString(R.string.rtl);
     }
 
     public void setCurrentTextSize(int size) {
@@ -95,54 +91,56 @@
 
     @Override
     public void onDraw(Canvas canvas) {
-        drawInsideRect(canvas, Color.BLACK);
+        drawInsideRect(canvas, new Paint(), Color.BLACK);
 
         int deltaX = 0;
 
         deltaX  = testString(canvas, NORMAL_TEXT, ORIGIN, ORIGIN,
-                paint, typeface, false, false,  Paint.DIRECTION_LTR, currentTextSize);
+                false, false,  Paint.DIRECTION_LTR, currentTextSize);
 
         deltaX += testString(canvas, ITALIC_TEXT, ORIGIN + deltaX, ORIGIN,
-                paint, typeface, true, false,  Paint.DIRECTION_LTR, currentTextSize);
+                true, false,  Paint.DIRECTION_LTR, currentTextSize);
 
         deltaX += testString(canvas, BOLD_TEXT, ORIGIN + deltaX, ORIGIN,
-                paint, typeface, false, true,  Paint.DIRECTION_LTR, currentTextSize);
+                false, true,  Paint.DIRECTION_LTR, currentTextSize);
 
         deltaX += testString(canvas, BOLD_ITALIC_TEXT, ORIGIN + deltaX, ORIGIN,
-                paint, typeface, true, true,  Paint.DIRECTION_LTR, currentTextSize);
+                true, true,  Paint.DIRECTION_LTR, currentTextSize);
 
         // Test with a long string
         deltaX = testString(canvas, NORMAL_LONG_TEXT, ORIGIN, ORIGIN + 2 * currentTextSize,
-                paint, typeface, false, false,  Paint.DIRECTION_LTR, currentTextSize);
+                false, false,  Paint.DIRECTION_LTR, currentTextSize);
 
         // Test with a long string
         deltaX = testString(canvas, NORMAL_LONG_TEXT_2, ORIGIN, ORIGIN + 4 * currentTextSize,
-                paint, typeface, false, false,  Paint.DIRECTION_LTR, currentTextSize);
+                false, false,  Paint.DIRECTION_LTR, currentTextSize);
 
         // Test with a long string
         deltaX = testString(canvas, NORMAL_LONG_TEXT_3, ORIGIN, ORIGIN + 6 * currentTextSize,
-                paint, typeface, false, false,  Paint.DIRECTION_LTR, currentTextSize);
+                false, false,  Paint.DIRECTION_LTR, currentTextSize);
 
         // Test Arabic ligature
         deltaX = testString(canvas, ARABIC_TEXT, ORIGIN, ORIGIN + 8 * currentTextSize,
-                paint, typeface, false, false,  Paint.DIRECTION_RTL, currentTextSize);
+                false, false,  Paint.DIRECTION_RTL, currentTextSize);
 
         // Test Chinese
         deltaX = testString(canvas, CHINESE_TEXT, ORIGIN, ORIGIN + 10 * currentTextSize,
-                paint, typeface, false, false,  Paint.DIRECTION_LTR, currentTextSize);
+                false, false,  Paint.DIRECTION_LTR, currentTextSize);
 
         // Test Mixed (English and Arabic)
         deltaX = testString(canvas, MIXED_TEXT_1, ORIGIN, ORIGIN + 12 * currentTextSize,
-                paint, typeface, false, false,  Paint.DIRECTION_LTR, currentTextSize);
+                false, false,  Paint.DIRECTION_LTR, currentTextSize);
 
         // Test Hebrew
-        deltaX = testString(canvas, HEBREW_TEXT, ORIGIN, ORIGIN + 14 * currentTextSize,
-                paint, typeface, false, false,  Paint.DIRECTION_RTL, currentTextSize);
+        deltaX = testString(canvas, RTL_TEXT, ORIGIN, ORIGIN + 14 * currentTextSize,
+                false, false,  Paint.DIRECTION_RTL, currentTextSize);
     }
 
-    private int testString(Canvas canvas, String text, int x, int y, Paint paint, Typeface typeface,
+    private int testString(Canvas canvas, String text, int x, int y,
             boolean isItalic, boolean isBold, int dir, int textSize) {
-        paint.setTypeface(typeface);
+
+        TextPaint paint = new TextPaint();
+        paint.setAntiAlias(true);
 
         // Set paint properties
         boolean oldFakeBold = paint.isFakeBoldText();
@@ -153,9 +151,9 @@
             paint.setTextSkewX(DEFAULT_ITALIC_SKEW_X);
         }
 
-        Log.v(TAG, "START -- drawTextWithCanvasDrawText");
-        drawTextWithCanvasDrawText(text, canvas, x, y, textSize, Color.WHITE, dir);
-        Log.v(TAG, "END   -- drawTextWithCanvasDrawText");
+        paint.setTextSize(textSize);
+        paint.setColor(Color.WHITE);
+        canvas.drawText(text, x, y, paint);
 
         int length = text.length();
         float[] advances = new float[length];
@@ -167,13 +165,6 @@
         logAdvances(text, textWidthHB, textWidthICU, advances);
         drawMetricsAroundText(canvas, x, y, textWidthHB, textWidthICU, textSize, Color.RED, Color.GREEN);
 
-        paint.setColor(Color.WHITE);
-
-        Log.v(TAG, "START -- drawText");
-        setPaintDir(paint, dir);
-        canvas.drawText(text, x, y + currentTextSize, this.paint);
-        Log.v(TAG, "END   -- drawText");
-
         // Restore old paint properties
         paint.setFakeBoldText(oldFakeBold);
         paint.setTextSkewX(oldTextSkewX);
@@ -186,7 +177,7 @@
         paint.setBidiFlags(dir);
     }
 
-    private void drawInsideRect(Canvas canvas, int color) {
+    private void drawInsideRect(Canvas canvas, Paint paint, int color) {
         paint.setColor(color);
         int width = getWidth();
         int height = getHeight();
@@ -194,16 +185,9 @@
         canvas.drawRect(rect, paint);
     }
 
-    private void drawTextWithCanvasDrawText(String text, Canvas canvas,
-            float x, float y, float textSize, int color, int dir) {
-        setPaintDir(paint, dir);
-        paint.setColor(color);
-        paint.setTextSize(textSize);
-        canvas.drawText(text, x, y, paint);
-    }
-
     private void drawMetricsAroundText(Canvas canvas, int x, int y, float textWidthHB,
             float textWidthICU, int textSize, int color, int colorICU) {
+        Paint paint = new Paint();
         paint.setColor(color);
         canvas.drawLine(x, y - textSize, x, y + 8, paint);
         canvas.drawLine(x, y + 8, x + textWidthHB, y + 8, paint);
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestViewDrawText.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestViewDrawText.java
new file mode 100644
index 0000000..dfdb807
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestViewDrawText.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.bidi;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint.Align;
+import android.text.TextPaint;
+import android.util.AttributeSet;
+import android.view.View;
+
+public class BiDiTestViewDrawText extends View {
+    private float mSize;
+    private int mColor;
+    private String mText;
+
+    public BiDiTestViewDrawText(Context context) {
+        this(context, null);
+    }
+
+    public BiDiTestViewDrawText(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public BiDiTestViewDrawText(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+
+        final TypedArray a = context.obtainStyledAttributes(attrs,
+                R.styleable.DrawTextTestView, defStyle, 0);
+        mSize = a.getDimension(R.styleable.DrawTextTestView_size, 40.0f);
+        mColor = a.getColor(R.styleable.DrawTextTestView_color, Color.YELLOW);
+        final CharSequence text = a.getText(R.styleable.DrawTextTestView_text);
+        mText = (text != null) ? text.toString() : "(empty)";
+        a.recycle();
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+        final int width = getWidth();
+        final int height = getHeight();
+
+        final TextPaint paint = new TextPaint();
+        paint.setTextSize(mSize);
+        paint.setColor(mColor);
+        paint.setTextAlign(Align.CENTER);
+
+        canvas.drawText(mText, width / 2, height * 2 / 3, paint);
+    }
+}
\ No newline at end of file