Merge "The wave view attributes should not be public."
diff --git a/api/current.txt b/api/current.txt
index 6284724..47648a7 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -434,7 +434,7 @@
     field public static final int fadeEnabled = 16843390; // 0x101027e
     field public static final int fadeOffset = 16843383; // 0x1010277
     field public static final int fadeScrollbars = 16843434; // 0x10102aa
-    field public static final int fadingEdge = 16842975; // 0x10100df
+    field public static final deprecated int fadingEdge = 16842975; // 0x10100df
     field public static final int fadingEdgeLength = 16842976; // 0x10100e0
     field public static final int fastScrollAlwaysVisible = 16843573; // 0x1010335
     field public static final int fastScrollEnabled = 16843302; // 0x1010226
@@ -783,6 +783,7 @@
     field public static final int reqNavigation = 16843306; // 0x101022a
     field public static final int reqTouchScreen = 16843303; // 0x1010227
     field public static final int required = 16843406; // 0x101028e
+    field public static final int requiresFadingEdge = 16843699; // 0x10103b3
     field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
     field public static final int resizeMode = 16843619; // 0x1010363
     field public static final int resizeable = 16843405; // 0x101028d
diff --git a/core/java/android/app/ProgressDialog.java b/core/java/android/app/ProgressDialog.java
index f1a04f8..7f1f385 100644
--- a/core/java/android/app/ProgressDialog.java
+++ b/core/java/android/app/ProgressDialog.java
@@ -16,7 +16,10 @@
 
 package android.app;
 
+import com.android.internal.R;
+
 import android.content.Context;
+import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.Handler;
@@ -29,8 +32,6 @@
 import android.widget.ProgressBar;
 import android.widget.TextView;
 
-import com.android.internal.R;
-
 import java.text.NumberFormat;
 
 /**
@@ -119,6 +120,9 @@
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         LayoutInflater inflater = LayoutInflater.from(mContext);
+        TypedArray a = mContext.obtainStyledAttributes(null,
+                com.android.internal.R.styleable.AlertDialog,
+                com.android.internal.R.attr.alertDialogStyle, 0);
         if (mProgressStyle == STYLE_HORIZONTAL) {
             
             /* Use a separate handler to update the text views as they
@@ -149,17 +153,22 @@
                     }
                 }
             };
-            View view = inflater.inflate(R.layout.alert_dialog_progress, null);
+            View view = inflater.inflate(a.getResourceId(
+                    com.android.internal.R.styleable.AlertDialog_horizontalProgressLayout,
+                    R.layout.alert_dialog_progress), null);
             mProgress = (ProgressBar) view.findViewById(R.id.progress);
             mProgressNumber = (TextView) view.findViewById(R.id.progress_number);
             mProgressPercent = (TextView) view.findViewById(R.id.progress_percent);
             setView(view);
         } else {
-            View view = inflater.inflate(R.layout.progress_dialog, null);
+            View view = inflater.inflate(a.getResourceId(
+                    com.android.internal.R.styleable.AlertDialog_progressLayout,
+                    R.layout.progress_dialog), null);
             mProgress = (ProgressBar) view.findViewById(R.id.progress);
             mMessageView = (TextView) view.findViewById(R.id.message);
             setView(view);
         }
+        a.recycle();
         if (mMax > 0) {
             setMax(mMax);
         }
diff --git a/core/java/android/text/style/SuggestionRangeSpan.java b/core/java/android/text/style/SuggestionRangeSpan.java
index a637b1c..2dbfc72 100644
--- a/core/java/android/text/style/SuggestionRangeSpan.java
+++ b/core/java/android/text/style/SuggestionRangeSpan.java
@@ -28,15 +28,11 @@
  * @hide
  */
 public class SuggestionRangeSpan extends CharacterStyle implements ParcelableSpan {
-    private final int mBackgroundColor;
+    private int mBackgroundColor;
 
-    @Override
-    public void updateDrawState(TextPaint tp) {
-        tp.bgColor = mBackgroundColor;
-    }
-
-    public SuggestionRangeSpan(int color) {
-        mBackgroundColor = color;
+    public SuggestionRangeSpan() {
+        // 0 is a fully transparent black. Has to be set using #setBackgroundColor
+        mBackgroundColor = 0;
     }
 
     public SuggestionRangeSpan(Parcel src) {
@@ -57,4 +53,13 @@
     public int getSpanTypeId() {
         return TextUtils.SUGGESTION_RANGE_SPAN;
     }
+
+    public void setBackgroundColor(int backgroundColor) {
+        mBackgroundColor = backgroundColor;
+    }
+
+    @Override
+    public void updateDrawState(TextPaint tp) {
+        tp.bgColor = mBackgroundColor;
+    }
 }
diff --git a/core/java/android/text/style/SuggestionSpan.java b/core/java/android/text/style/SuggestionSpan.java
index 693a7a9..51e9d7d 100644
--- a/core/java/android/text/style/SuggestionSpan.java
+++ b/core/java/android/text/style/SuggestionSpan.java
@@ -264,4 +264,16 @@
             tp.setUnderlineText(mEasyCorrectUnderlineColor, mEasyCorrectUnderlineThickness);
         }
     }
+
+    /**
+     * @return The color of the underline for that span, or 0 if there is no underline
+     *
+     * @hide
+     */
+    public int getUnderlineColor() {
+        // The order here should match what is used in updateDrawState
+        if ((mFlags & FLAG_MISSPELLED) != 0) return mMisspelledUnderlineColor;
+        if ((mFlags & FLAG_EASY_CORRECT) != 0) return mEasyCorrectUnderlineColor;
+        return 0;
+    }
 }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 7a35015..637f6466 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -69,6 +69,8 @@
 import android.view.inputmethod.InputMethodManager;
 import android.widget.ScrollBarDrawable;
 
+import static android.os.Build.VERSION_CODES.*;
+
 import com.android.internal.R;
 import com.android.internal.util.Predicate;
 import com.android.internal.view.menu.MenuBuilder;
@@ -585,7 +587,7 @@
  * @attr ref android.R.styleable#View_drawingCacheQuality
  * @attr ref android.R.styleable#View_duplicateParentState
  * @attr ref android.R.styleable#View_id
- * @attr ref android.R.styleable#View_fadingEdge
+ * @attr ref android.R.styleable#View_requiresFadingEdge
  * @attr ref android.R.styleable#View_fadingEdgeLength
  * @attr ref android.R.styleable#View_filterTouchesWhenObscured
  * @attr ref android.R.styleable#View_fitsSystemWindows
@@ -2895,6 +2897,12 @@
                     }
                     break;
                 case R.styleable.View_fadingEdge:
+                    if (context.getApplicationInfo().targetSdkVersion >= ICE_CREAM_SANDWICH) {
+                        // Ignore the attribute starting with ICS
+                        break;
+                    }
+                    // With builds < ICS, fall through and apply fading edges
+                case R.styleable.View_requiresFadingEdge:
                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
                     if (fadingEdge != FADING_EDGE_NONE) {
                         viewFlagValues |= fadingEdge;
@@ -8642,7 +8650,7 @@
      *         otherwise
      *
      * @see #setHorizontalFadingEdgeEnabled(boolean)
-     * @attr ref android.R.styleable#View_fadingEdge
+     * @attr ref android.R.styleable#View_requiresFadingEdge
      */
     public boolean isHorizontalFadingEdgeEnabled() {
         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
@@ -8657,7 +8665,7 @@
      *                                    horizontally
      *
      * @see #isHorizontalFadingEdgeEnabled()
-     * @attr ref android.R.styleable#View_fadingEdge
+     * @attr ref android.R.styleable#View_requiresFadingEdge
      */
     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
@@ -8677,7 +8685,7 @@
      *         otherwise
      *
      * @see #setVerticalFadingEdgeEnabled(boolean)
-     * @attr ref android.R.styleable#View_fadingEdge
+     * @attr ref android.R.styleable#View_requiresFadingEdge
      */
     public boolean isVerticalFadingEdgeEnabled() {
         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
@@ -8692,7 +8700,7 @@
      *                                  vertically
      *
      * @see #isVerticalFadingEdgeEnabled()
-     * @attr ref android.R.styleable#View_fadingEdge
+     * @attr ref android.R.styleable#View_requiresFadingEdge
      */
     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index 071701e..25b980b 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -104,6 +104,7 @@
     public void setSameThreadMessage(Message message) {
         synchronized (mInstanceLock) {
             mSameThreadMessage = message;
+            mInstanceLock.notifyAll();
         }
     }
 
@@ -125,7 +126,6 @@
                     Thread.currentThread().getId());
             // If the scale is zero the call has failed.
             if (windowScale > 0) {
-                handleSameThreadMessageIfNeeded();
                 AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
                         interactionId);
                 finalizeAccessibilityNodeInfo(info, connection, windowScale);
@@ -142,7 +142,7 @@
      * in the currently active window and starts from the root View in the window.
      *
      * @param connection A connection for interacting with the system.
-     * @param id The id of the node.
+     * @param viewId The id of the view.
      * @return An {@link AccessibilityNodeInfo} if found, null otherwise.
      */
     public AccessibilityNodeInfo findAccessibilityNodeInfoByViewIdInActiveWindow(
@@ -153,7 +153,6 @@
                     viewId, interactionId, this, Thread.currentThread().getId());
             // If the scale is zero the call has failed.
             if (windowScale > 0) {
-                handleSameThreadMessageIfNeeded();
                 AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear(
                         interactionId);
                 finalizeAccessibilityNodeInfo(info, connection, windowScale);
@@ -182,7 +181,6 @@
                     text, interactionId, this, Thread.currentThread().getId());
             // If the scale is zero the call has failed.
             if (windowScale > 0) {
-                handleSameThreadMessageIfNeeded();
                 List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
                         interactionId);
                 finalizeAccessibilityNodeInfos(infos, connection, windowScale);
@@ -217,7 +215,6 @@
                     Thread.currentThread().getId());
             // If the scale is zero the call has failed.
             if (windowScale > 0) {
-                handleSameThreadMessageIfNeeded();
                 List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
                         interactionId);
                 finalizeAccessibilityNodeInfos(infos, connection, windowScale);
@@ -246,7 +243,6 @@
                     accessibilityWindowId, accessibilityViewId, action, interactionId, this,
                     Thread.currentThread().getId());
             if (success) {
-                handleSameThreadMessageIfNeeded();
                 return getPerformAccessibilityActionResult(interactionId);
             }
         } catch (RemoteException re) {
@@ -363,6 +359,11 @@
         final long startTimeMillis = SystemClock.uptimeMillis();
         while (true) {
             try {
+                Message sameProcessMessage = getSameProcessMessageAndClear();
+                if (sameProcessMessage != null) {
+                    sameProcessMessage.getTarget().handleMessage(sameProcessMessage);
+                }
+
                 if (mInteractionId == interactionId) {
                     return true;
                 }
@@ -402,17 +403,6 @@
     }
 
     /**
-     * Handles the message stored if the interacted and interacting
-     * threads are the same otherwise this is a NOP.
-     */
-    private void handleSameThreadMessageIfNeeded() {
-        Message sameProcessMessage = getSameProcessMessageAndClear();
-        if (sameProcessMessage != null) {
-            sameProcessMessage.getTarget().handleMessage(sameProcessMessage);
-        }
-    }
-
-    /**
      * Finalize an {@link AccessibilityNodeInfo} before passing it to the client.
      *
      * @param info The info.
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 49b4f66..309857d 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -422,9 +422,9 @@
             final WebHistoryItem h = mCallbackProxy.getBackForwardList()
                     .getCurrentItem();
             if (h != null) {
-                String currentUrl = h.getUrl();
-                if (currentUrl != null) {
-                    mDatabase.setFormData(currentUrl, data);
+                String url = WebTextView.urlForAutoCompleteData(h.getUrl());
+                if (url != null) {
+                    mDatabase.setFormData(url, data);
                 }
             }
         }
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index 2a79caa..217ad7c 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -60,6 +60,8 @@
 import android.widget.AutoCompleteTextView;
 import android.widget.TextView;
 
+import java.net.MalformedURLException;
+import java.net.URL;
 import java.util.ArrayList;
 
 import junit.framework.Assert;
@@ -1044,6 +1046,7 @@
                 break;
         }
         setHint(null);
+        setThreshold(1);
         if (single) {
             mWebView.requestLabel(mWebView.nativeFocusCandidateFramePointer(),
                     mNodePointer);
@@ -1077,4 +1080,16 @@
     /* package */ void setAutoFillProfileIsSet(boolean autoFillProfileIsSet) {
         mAutoFillProfileIsSet = autoFillProfileIsSet;
     }
+
+    static String urlForAutoCompleteData(String urlString) {
+        // Remove any fragment or query string.
+        URL url = null;
+        try {
+            url = new URL(urlString);
+        } catch (MalformedURLException e) {
+            Log.e(LOGTAG, "Unable to parse URL "+url);
+        }
+
+        return url != null ? url.getProtocol() + "://" + url.getHost() + url.getPath() : null;
+    }
 }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 7ba93da0..47abbc2 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -4826,7 +4826,7 @@
         public RequestFormData(String name, String url, Message msg,
                 boolean autoFillable, boolean autoComplete) {
             mName = name;
-            mUrl = url;
+            mUrl = WebTextView.urlForAutoCompleteData(url);
             mUpdateMessage = msg;
             mAutoFillable = autoFillable;
             mAutoComplete = autoComplete;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index cf0971f..b948114 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -9559,8 +9559,8 @@
 
                 TextView.this.getPositionListener().removeSubscriber(SuggestionsPopupWindow.this);
 
-                if ((mText instanceof Editable) && mSuggestionRangeSpan != null) {
-                    ((Editable) mText).removeSpan(mSuggestionRangeSpan);
+                if ((mText instanceof Spannable)) {
+                    ((Spannable) mText).removeSpan(mSuggestionRangeSpan);
                 }
 
                 setCursorVisible(mCursorWasVisibleBeforeSuggestions);
@@ -9744,7 +9744,7 @@
         }
 
         private boolean updateSuggestions() {
-            Spannable spannable = (Spannable)TextView.this.mText;
+            Spannable spannable = (Spannable) TextView.this.mText;
             SuggestionSpan[] suggestionSpans = getSuggestionSpans();
 
             final int nbSpans = suggestionSpans.length;
@@ -9754,6 +9754,7 @@
             int spanUnionEnd = 0;
 
             SuggestionSpan misspelledSpan = null;
+            int underlineColor = 0;
 
             for (int spanIndex = 0; spanIndex < nbSpans; spanIndex++) {
                 SuggestionSpan suggestionSpan = suggestionSpans[spanIndex];
@@ -9766,6 +9767,9 @@
                     misspelledSpan = suggestionSpan;
                 }
 
+                // The first span dictates the background color of the highlighted text
+                if (spanIndex == 0) underlineColor = suggestionSpan.getUnderlineColor();
+
                 String[] suggestions = suggestionSpan.getSuggestions();
                 int nbSuggestions = suggestions.length;
                 for (int suggestionIndex = 0; suggestionIndex < nbSuggestions; suggestionIndex++) {
@@ -9808,9 +9812,17 @@
 
             if (mNumberOfSuggestions == 0) return false;
 
-            if (mSuggestionRangeSpan == null) mSuggestionRangeSpan =
-                    new SuggestionRangeSpan(mHighlightColor);
-            ((Editable) mText).setSpan(mSuggestionRangeSpan, spanUnionStart, spanUnionEnd,
+            if (mSuggestionRangeSpan == null) mSuggestionRangeSpan = new SuggestionRangeSpan();
+            if (underlineColor == 0) {
+                // Fallback on the default highlight color when the first span does not provide one
+                mSuggestionRangeSpan.setBackgroundColor(mHighlightColor);
+            } else {
+                final float BACKGROUND_TRANSPARENCY = 0.3f;
+                final int newAlpha = (int) (Color.alpha(underlineColor) * BACKGROUND_TRANSPARENCY);
+                mSuggestionRangeSpan.setBackgroundColor(
+                        (underlineColor & 0x00FFFFFF) + (newAlpha << 24));
+            }
+            spannable.setSpan(mSuggestionRangeSpan, spanUnionStart, spanUnionEnd,
                     Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
 
             mSuggestionsAdapter.notifyDataSetChanged();
@@ -9902,6 +9914,9 @@
                                     suggestionSpansFlags[i]);
                         }
                     }
+                    
+                    // Move cursor at the end of the replacement word
+                    Selection.setSelection(editable, spanEnd + lengthDifference);
                 }
             }
             hide();
diff --git a/core/res/res/layout/alert_dialog_progress_holo.xml b/core/res/res/layout/alert_dialog_progress_holo.xml
new file mode 100644
index 0000000..94dbb2b
--- /dev/null
+++ b/core/res/res/layout/alert_dialog_progress_holo.xml
@@ -0,0 +1,48 @@
+<?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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content" android:layout_height="match_parent">
+        <ProgressBar android:id="@+id/progress"
+            style="?android:attr/progressBarStyleHorizontal"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="16dip"
+            android:layout_marginBottom="1dip"
+            android:layout_marginLeft="16dip"
+            android:layout_marginRight="16dip"
+            android:layout_centerHorizontal="true" />
+        <TextView
+            android:id="@+id/progress_percent"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:paddingBottom="16dip"
+            android:layout_marginLeft="16dip"
+            android:layout_marginRight="16dip"
+            android:layout_alignParentLeft="true"
+            android:layout_below="@id/progress"
+        />
+        <TextView
+            android:id="@+id/progress_number"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:paddingBottom="16dip"
+            android:layout_marginLeft="16dip"
+            android:layout_marginRight="16dip"
+            android:layout_alignParentRight="true"
+            android:layout_below="@id/progress"
+        />
+</RelativeLayout>
diff --git a/core/res/res/layout/progress_dialog_holo.xml b/core/res/res/layout/progress_dialog_holo.xml
new file mode 100644
index 0000000..9631efd
--- /dev/null
+++ b/core/res/res/layout/progress_dialog_holo.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** 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.
+*/
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+
+    <LinearLayout android:id="@+id/body"
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:baselineAligned="false"
+        android:padding="16dip">
+
+        <ProgressBar android:id="@android:id/progress"
+            style="?android:attr/progressBarStyle"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:max="10000"
+            android:layout_marginRight="16dip" />
+
+        <TextView android:id="@+id/message"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical" />
+    </LinearLayout>
+</FrameLayout>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 525b03a..f90d67b 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1551,6 +1551,8 @@
         <attr name="multiChoiceItemLayout" format="reference" />
         <attr name="singleChoiceItemLayout" format="reference" />
         <attr name="listItemLayout" format="reference" />
+        <attr name="progressLayout" format="reference" />
+        <attr name="horizontalProgressLayout" format="reference" />
     </declare-styleable>
 
     <!-- Fragment animation class attributes. -->
@@ -1804,7 +1806,13 @@
         <!-- Defines whether the vertical scrollbar track should always be drawn. -->
         <attr name="scrollbarAlwaysDrawVerticalTrack" format="boolean" />
 
-        <!-- Defines which edges should be fadeded on scrolling. -->
+        <!-- {@deprecated This attribute is deprecated and will be ignored as of
+             API level {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH}.
+             Using fading edges may introduce noticeable performance
+             degradations and should be used only when required by the application's
+             visual design. To request fading edges with API level
+             {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH} and above,
+             use the <code>requiresFadingEdge</code> attribute instead.} -->
         <attr name="fadingEdge">
             <!-- No edge is faded. -->
             <flag name="none" value="0x00000000" />
@@ -1813,6 +1821,15 @@
             <!-- Fades vertical edges only. -->
             <flag name="vertical" value="0x00002000" />
         </attr>
+        <!-- Defines which edges should be faded on scrolling. -->
+        <attr name="requiresFadingEdge">
+            <!-- No edge is faded. -->
+            <flag name="none" value="0x00000000" />
+            <!-- Fades horizontal edges only. -->
+            <flag name="horizontal" value="0x00001000" />
+            <!-- Fades vertical edges only. -->
+            <flag name="vertical" value="0x00002000" />
+        </attr>
         <!-- Defines the length of the fading edges. -->
         <attr name="fadingEdgeLength" format="dimension" />
 
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 6b75979..ba8be2e 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1792,6 +1792,8 @@
   <public type="attr" name="listPreferredItemPaddingLeft" />
   <public type="attr" name="listPreferredItemPaddingRight" />
 
+  <public type="attr" name="requiresFadingEdge" />
+
   <public type="style" name="TextAppearance.SuggestionHighlight" />
 
   <public type="style" name="Theme.Holo.Light.DarkActionBar" />
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 5033611..356a2ad 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -61,6 +61,8 @@
         <item name="bottomBright">@android:drawable/popup_bottom_bright</item>
         <item name="bottomMedium">@android:drawable/popup_bottom_medium</item>
         <item name="centerMedium">@android:drawable/popup_center_medium</item>
+        <item name="progressLayout">@android:layout/progress_dialog</item>
+        <item name="horizontalProgressLayout">@android:layout/alert_dialog_progress</item>
     </style>
 
     <style name="Widget.PreferenceFrameLayout">
@@ -2350,6 +2352,8 @@
         <item name="centerMedium">@android:drawable/dialog_middle_holo_dark</item>
         <item name="layout">@android:layout/alert_dialog_holo</item>
         <item name="listLayout">@android:layout/select_dialog_holo</item>
+        <item name="progressLayout">@android:layout/progress_dialog_holo</item>
+        <item name="horizontalProgressLayout">@android:layout/alert_dialog_progress_holo</item>
         <item name="listItemLayout">@android:layout/select_dialog_item_holo</item>
         <item name="multiChoiceItemLayout">@android:layout/select_dialog_multichoice_holo</item>
         <item name="singleChoiceItemLayout">@android:layout/select_dialog_singlechoice_holo</item>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index dae808a..d19c97f 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -1540,6 +1540,9 @@
         
         <item name="textAppearance">@android:style/TextAppearance.Holo</item>
         <item name="textAppearanceInverse">@android:style/TextAppearance.Holo.Inverse</item>
+
+        <item name="listPreferredItemPaddingLeft">16dip</item>
+        <item name="listPreferredItemPaddingRight">16dip</item>
     </style>
 
     <!-- Variation of Theme.Holo.Dialog that has a nice minumum width for
@@ -1629,6 +1632,9 @@
 
         <item name="textAppearance">@android:style/TextAppearance.Holo.Light</item>
         <item name="textAppearanceInverse">@android:style/TextAppearance.Holo.Light.Inverse</item>
+
+        <item name="listPreferredItemPaddingLeft">16dip</item>
+        <item name="listPreferredItemPaddingRight">16dip</item>
     </style>
 
     <!-- Variation of Theme.Holo.Light.Dialog that has a nice minumum width for
diff --git a/include/media/mediascanner.h b/include/media/mediascanner.h
index 803bffb..a73403b 100644
--- a/include/media/mediascanner.h
+++ b/include/media/mediascanner.h
@@ -62,12 +62,17 @@
 private:
     // current locale (like "ja_JP"), created/destroyed with strdup()/free()
     char *mLocale;
+    char *mSkipList;
+    int *mSkipIndex;
 
     MediaScanResult doProcessDirectory(
             char *path, int pathRemaining, MediaScannerClient &client, bool noMedia);
     MediaScanResult doProcessDirectoryEntry(
             char *path, int pathRemaining, MediaScannerClient &client, bool noMedia,
             struct dirent* entry, char* fileSpot);
+    void loadSkipList();
+    bool shouldSkipDirectory(char *path);
+
 
     MediaScanner(const MediaScanner &);
     MediaScanner &operator=(const MediaScanner &);
@@ -103,4 +108,3 @@
 }; // namespace android
 
 #endif // MEDIASCANNER_H
-
diff --git a/include/ui/Input.h b/include/ui/Input.h
index f1385a0..af899ef 100644
--- a/include/ui/Input.h
+++ b/include/ui/Input.h
@@ -660,15 +660,19 @@
     static const uint32_t HISTORY_SIZE = 10;
 
     // Oldest sample to consider when calculating the velocity.
-    static const nsecs_t MAX_AGE = 200 * 1000000; // 200 ms
+    static const nsecs_t MAX_AGE = 100 * 1000000; // 100 ms
 
     // The minimum duration between samples when estimating velocity.
-    static const nsecs_t MIN_DURATION = 10 * 1000000; // 10 ms
+    static const nsecs_t MIN_DURATION = 5 * 1000000; // 5 ms
 
     struct Movement {
         nsecs_t eventTime;
         BitSet32 idBits;
         Position positions[MAX_POINTERS];
+
+        inline const Position& getPosition(uint32_t id) const {
+            return positions[idBits.getIndexOfBit(id)];
+        }
     };
 
     uint32_t mIndex;
diff --git a/libs/ui/Input.cpp b/libs/ui/Input.cpp
index 688b998..0d25823 100644
--- a/libs/ui/Input.cpp
+++ b/libs/ui/Input.cpp
@@ -752,6 +752,7 @@
 
     switch (actionMasked) {
     case AMOTION_EVENT_ACTION_DOWN:
+    case AMOTION_EVENT_ACTION_HOVER_ENTER:
         // Clear all pointers on down before adding the new movement.
         clear();
         break;
@@ -764,12 +765,11 @@
         clearPointers(downIdBits);
         break;
     }
-    case AMOTION_EVENT_ACTION_OUTSIDE:
-    case AMOTION_EVENT_ACTION_CANCEL:
-    case AMOTION_EVENT_ACTION_SCROLL:
-    case AMOTION_EVENT_ACTION_UP:
-    case AMOTION_EVENT_ACTION_POINTER_UP:
-        // Ignore these actions because they do not convey any new information about
+    case AMOTION_EVENT_ACTION_MOVE:
+    case AMOTION_EVENT_ACTION_HOVER_MOVE:
+        break;
+    default:
+        // Ignore all other actions because they do not convey any new information about
         // pointer movement.  We also want to preserve the last known velocity of the pointers.
         // Note that ACTION_UP and ACTION_POINTER_UP always report the last known position
         // of the pointers that went up.  ACTION_POINTER_UP does include the new position of
@@ -814,68 +814,36 @@
 bool VelocityTracker::getVelocity(uint32_t id, float* outVx, float* outVy) const {
     const Movement& newestMovement = mMovements[mIndex];
     if (newestMovement.idBits.hasBit(id)) {
-        // Find the oldest sample that contains the pointer and that is not older than MAX_AGE.
-        nsecs_t minTime = newestMovement.eventTime - MAX_AGE;
-        uint32_t oldestIndex = mIndex;
-        uint32_t numTouches = 1;
-        do {
-            uint32_t nextOldestIndex = (oldestIndex == 0 ? HISTORY_SIZE : oldestIndex) - 1;
-            const Movement& nextOldestMovement = mMovements[nextOldestIndex];
-            if (!nextOldestMovement.idBits.hasBit(id)
-                    || nextOldestMovement.eventTime < minTime) {
-                break;
-            }
-            oldestIndex = nextOldestIndex;
-        } while (++numTouches < HISTORY_SIZE);
-
-        // Calculate an exponentially weighted moving average of the velocity estimate
-        // at different points in time measured relative to the oldest sample.
-        // This is essentially an IIR filter.  Newer samples are weighted more heavily
-        // than older samples.  Samples at equal time points are weighted more or less
-        // equally.
-        //
-        // One tricky problem is that the sample data may be poorly conditioned.
-        // Sometimes samples arrive very close together in time which can cause us to
-        // overestimate the velocity at that time point.  Most samples might be measured
-        // 16ms apart but some consecutive samples could be only 0.5sm apart because
-        // the hardware or driver reports them irregularly or in bursts.
+        const Position& newestPosition = newestMovement.getPosition(id);
         float accumVx = 0;
         float accumVy = 0;
-        uint32_t index = oldestIndex;
-        uint32_t samplesUsed = 0;
-        const Movement& oldestMovement = mMovements[oldestIndex];
-        const Position& oldestPosition =
-                oldestMovement.positions[oldestMovement.idBits.getIndexOfBit(id)];
-        nsecs_t lastDuration = 0;
+        float duration = 0;
 
-        while (numTouches-- > 1) {
-            if (++index == HISTORY_SIZE) {
-                index = 0;
-            }
+        // Iterate over movement samples in reverse time order and accumulate velocity.
+        uint32_t index = mIndex;
+        do {
+            index = (index == 0 ? HISTORY_SIZE : index) - 1;
             const Movement& movement = mMovements[index];
-            nsecs_t duration = movement.eventTime - oldestMovement.eventTime;
-
-            // If the duration between samples is small, we may significantly overestimate
-            // the velocity.  Consequently, we impose a minimum duration constraint on the
-            // samples that we include in the calculation.
-            if (duration >= MIN_DURATION) {
-                const Position& position = movement.positions[movement.idBits.getIndexOfBit(id)];
-                float scale = 1000000000.0f / duration; // one over time delta in seconds
-                float vx = (position.x - oldestPosition.x) * scale;
-                float vy = (position.y - oldestPosition.y) * scale;
-
-                accumVx = (accumVx * lastDuration + vx * duration) / (duration + lastDuration);
-                accumVy = (accumVy * lastDuration + vy * duration) / (duration + lastDuration);
-
-                lastDuration = duration;
-                samplesUsed += 1;
+            if (!movement.idBits.hasBit(id)) {
+                break;
             }
-        }
+
+            nsecs_t age = newestMovement.eventTime - movement.eventTime;
+            if (age > MAX_AGE) {
+                break;
+            }
+
+            const Position& position = movement.getPosition(id);
+            accumVx += newestPosition.x - position.x;
+            accumVy += newestPosition.y - position.y;
+            duration += age;
+        } while (index != mIndex);
 
         // Make sure we used at least one sample.
-        if (samplesUsed != 0) {
-            *outVx = accumVx;
-            *outVy = accumVy;
+        if (duration >= MIN_DURATION) {
+            float scale = 1000000000.0f / duration; // one over time delta in seconds
+            *outVx = accumVx * scale;
+            *outVy = accumVy * scale;
             return true;
         }
     }
diff --git a/media/libmedia/MediaScanner.cpp b/media/libmedia/MediaScanner.cpp
index 41f8593..19dedfc 100644
--- a/media/libmedia/MediaScanner.cpp
+++ b/media/libmedia/MediaScanner.cpp
@@ -16,6 +16,7 @@
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "MediaScanner"
+#include <cutils/properties.h>
 #include <utils/Log.h>
 
 #include <media/mediascanner.h>
@@ -26,11 +27,14 @@
 namespace android {
 
 MediaScanner::MediaScanner()
-    : mLocale(NULL) {
+    : mLocale(NULL), mSkipList(NULL), mSkipIndex(NULL) {
+    loadSkipList();
 }
 
 MediaScanner::~MediaScanner() {
     setLocale(NULL);
+    free(mSkipList);
+    free(mSkipIndex);
 }
 
 void MediaScanner::setLocale(const char *locale) {
@@ -47,6 +51,33 @@
     return mLocale;
 }
 
+void MediaScanner::loadSkipList() {
+    mSkipList = (char *)malloc(PROPERTY_VALUE_MAX * sizeof(char));
+    if (mSkipList) {
+      property_get("testing.mediascanner.skiplist", mSkipList, "");
+    }
+    if (!mSkipList || (strlen(mSkipList) == 0)) {
+        free(mSkipList);
+        mSkipList = NULL;
+        return;
+    }
+    mSkipIndex = (int *)malloc(PROPERTY_VALUE_MAX * sizeof(int));
+    if (mSkipIndex) {
+        // dup it because strtok will modify the string
+        char *skipList = strdup(mSkipList);
+        if (skipList) {
+            char * path = strtok(skipList, ",");
+            int i = 0;
+            while (path) {
+                mSkipIndex[i++] = strlen(path);
+                path = strtok(NULL, ",");
+            }
+            mSkipIndex[i] = -1;
+            free(skipList);
+        }
+    }
+}
+
 MediaScanResult MediaScanner::processDirectory(
         const char *path, MediaScannerClient &client) {
     int pathLength = strlen(path);
@@ -75,12 +106,39 @@
     return result;
 }
 
+bool MediaScanner::shouldSkipDirectory(char *path) {
+    if (path && mSkipList && mSkipIndex) {
+        int len = strlen(path);
+        int idx = 0;
+        // track the start position of next path in the comma
+        // separated list obtained from getprop
+        int startPos = 0;
+        while (mSkipIndex[idx] != -1) {
+            // no point to match path name if strlen mismatch
+            if ((len == mSkipIndex[idx])
+                // pick out the path segment from comma separated list
+                // to compare against current path parameter
+                && (strncmp(path, &mSkipList[startPos], len) == 0)) {
+                return true;
+            }
+            startPos += mSkipIndex[idx] + 1; // extra char for the delimiter
+            idx++;
+        }
+    }
+    return false;
+}
+
 MediaScanResult MediaScanner::doProcessDirectory(
         char *path, int pathRemaining, MediaScannerClient &client, bool noMedia) {
     // place to copy file or directory name
     char* fileSpot = path + strlen(path);
     struct dirent* entry;
 
+    if (shouldSkipDirectory(path)) {
+      LOGD("Skipping: %s", path);
+      return MEDIA_SCAN_RESULT_OK;
+    }
+
     // Treat all files as non-media in directories that contain a  ".nomedia" file
     if (pathRemaining >= 8 /* strlen(".nomedia") */ ) {
         strcpy(fileSpot, ".nomedia");
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaProfileReader.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaProfileReader.java
index b1ad315..b1d049e 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaProfileReader.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaProfileReader.java
@@ -95,6 +95,25 @@
         return audioEncoderMap.get(audioEncoder);
     }
 
+    public static int getMinFrameRateForCodec(int codec) {
+        return getMinOrMaxFrameRateForCodec(codec, false);
+    }
+
+    public static int getMaxFrameRateForCodec(int codec) {
+        return getMinOrMaxFrameRateForCodec(codec, true);
+    }
+
+    private static int getMinOrMaxFrameRateForCodec(int codec, boolean max) {
+        for (VideoEncoderCap cap: videoEncoders) {
+            if (cap.mCodec == codec) {
+                if (max) return cap.mMaxFrameRate;
+                else return cap.mMinFrameRate;
+            }
+        }
+        // Should never reach here
+        throw new IllegalArgumentException("Unsupported video codec " + codec);
+    }
+
     private MediaProfileReader() {} // Don't call me
 
     private static void initVideoEncoderMap() {
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
index 82df6690..796b52c 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java
@@ -247,7 +247,9 @@
             mCamera.unlock();
             mRecorder.setCamera(mCamera);
             Thread.sleep(1000);
-            recordVideo(15, 352, 288, MediaRecorder.VideoEncoder.H263,
+            int codec = MediaRecorder.VideoEncoder.H263;
+            int frameRate = MediaProfileReader.getMaxFrameRateForCodec(codec);
+            recordVideo(frameRate, 352, 288, codec,
                     MediaRecorder.OutputFormat.THREE_GPP, 
                     MediaNames.RECORDED_PORTRAIT_H263, true);
             mCamera.lock();
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
index 0f79515..0b887b9 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
@@ -365,16 +365,6 @@
         assertTrue("H264 playback memory test", memoryResult);
     }
 
-    private int getMaxFrameRateForVideoEncoder(int codec) {
-        int frameRate = -1;
-        for (VideoEncoderCap cap: videoEncoders) {
-            if (cap.mCodec == MediaRecorder.VideoEncoder.H263) {
-                frameRate = cap.mMaxFrameRate;
-            }
-        }
-        return frameRate;
-    }
-
     // Test case 4: Capture the memory usage after every 20 video only recorded
     @LargeTest
     public void testH263RecordVideoOnlyMemoryUsage() throws Exception {
@@ -384,7 +374,7 @@
         File videoH263RecordOnlyMemoryOut = new File(MEDIA_MEMORY_OUTPUT);
         Writer output = new BufferedWriter(new FileWriter(videoH263RecordOnlyMemoryOut, true));
         output.write("H263 video record only\n");
-        int frameRate = getMaxFrameRateForVideoEncoder(MediaRecorder.VideoEncoder.H263);
+        int frameRate = MediaProfileReader.getMaxFrameRateForCodec(MediaRecorder.VideoEncoder.H263);
         assertTrue("H263 video recording frame rate", frameRate != -1);
         for (int i = 0; i < NUM_STRESS_LOOP; i++) {
             assertTrue(stressVideoRecord(frameRate, 352, 288, MediaRecorder.VideoEncoder.H263,
@@ -406,7 +396,7 @@
         File videoMp4RecordOnlyMemoryOut = new File(MEDIA_MEMORY_OUTPUT);
         Writer output = new BufferedWriter(new FileWriter(videoMp4RecordOnlyMemoryOut, true));
         output.write("MPEG4 video record only\n");
-        int frameRate = getMaxFrameRateForVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
+        int frameRate = MediaProfileReader.getMaxFrameRateForCodec(MediaRecorder.VideoEncoder.MPEG_4_SP);
         assertTrue("MPEG4 video recording frame rate", frameRate != -1);
         for (int i = 0; i < NUM_STRESS_LOOP; i++) {
             assertTrue(stressVideoRecord(frameRate, 352, 288, MediaRecorder.VideoEncoder.MPEG_4_SP,
@@ -428,7 +418,7 @@
 
         File videoRecordAudioMemoryOut = new File(MEDIA_MEMORY_OUTPUT);
         Writer output = new BufferedWriter(new FileWriter(videoRecordAudioMemoryOut, true));
-        int frameRate = getMaxFrameRateForVideoEncoder(MediaRecorder.VideoEncoder.H263);
+        int frameRate = MediaProfileReader.getMaxFrameRateForCodec(MediaRecorder.VideoEncoder.H263);
         assertTrue("H263 video recording frame rate", frameRate != -1);
         output.write("Audio and h263 video record\n");
         for (int i = 0; i < NUM_STRESS_LOOP; i++) {
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java
index ae0589c..e6177ba 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java
@@ -205,7 +205,7 @@
                 mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
                 mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
                 mRecorder.setOutputFile(filename);
-                mRecorder.setVideoFrameRate(20);
+                mRecorder.setVideoFrameRate(MediaRecorderStressTestRunner.mFrameRate);
                 mRecorder.setVideoSize(176,144);
                 Log.v(TAG, "setEncoder");
                 mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263);
@@ -269,7 +269,7 @@
                 mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
                 mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
                 mRecorder.setOutputFile(filename);
-                mRecorder.setVideoFrameRate(20);
+                mRecorder.setVideoFrameRate(MediaRecorderStressTestRunner.mFrameRate);
                 mRecorder.setVideoSize(176,144);
                 Log.v(TAG, "Media recorder setEncoder");
                 mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263);