Merge "Revert "Dedupe resource config pointers""
diff --git a/api/current.xml b/api/current.xml
index ed3f696..8d15665 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -179390,6 +179390,17 @@
  visibility="public"
 >
 </method>
+<method name="getScaledPagingTouchSlop"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getScaledScrollBarSize"
  return="int"
  abstract="false"
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 3e426f5..bf9b021 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -668,7 +668,10 @@
                 // The user changed the query, remember it.
                 mUserQuery = s == null ? "" : s.toString();
             }
-            updateVoiceButton(mSearchAutoComplete.isEmpty());
+            // Always want to show the microphone if the context is voice.
+            updateVoiceButton(mSearchAutoComplete.isEmpty()
+                    || (mAppSearchData != null && mAppSearchData.getBoolean(
+                    SearchManager.CONTEXT_IS_VOICE)));
         }
 
         public void afterTextChanged(Editable s) {
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 0ed572a..625b120 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -1544,6 +1544,15 @@
     public final static String INTENT_ACTION_NONE = "android.search.action.ZILCH";
 
     /**
+     * This means that context is voice, and therefore the SearchDialog should
+     * continue showing the microphone until the user indicates that he/she does
+     * not want to re-speak (e.g. by typing).
+     *
+     * @hide
+     */
+    public final static String CONTEXT_IS_VOICE = "android.search.CONTEXT_IS_VOICE";
+
+    /**
      * Reference to the shared system search service.
      */
     private static ISearchManager mService;
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 8773f59..423f4bc 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -237,7 +237,7 @@
      *
      * {@hide}
      */
-    public static final int FLAG_ON_SDCARD = 1<<20;
+    public static final int FLAG_EXTERNAL_STORAGE = 1<<20;
 
     /**
      * Value for {@link #flags}: Set to true if the application is
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 663d9e6..9736b01 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1503,7 +1503,7 @@
         }
 
         if ((flags & PARSE_ON_SDCARD) != 0) {
-            ai.flags |= ApplicationInfo.FLAG_ON_SDCARD;
+            ai.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
         }
 
         if (sa.getBoolean(
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 2344c42..2b78d2d 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -102,6 +102,12 @@
     private static final int TOUCH_SLOP = 16;
     
     /**
+     * Distance a touch can wander before we think the user is attempting a paged scroll
+     * (in dips)
+     */
+    private static final int PAGING_TOUCH_SLOP = TOUCH_SLOP * 3;
+    
+    /**
      * Distance between the first touch and second touch to still be considered a double tap
      */
     private static final int DOUBLE_TAP_SLOP = 100;
@@ -140,6 +146,7 @@
     private final int mMaximumFlingVelocity;
     private final int mScrollbarSize;
     private final int mTouchSlop;
+    private final int mPagingTouchSlop;
     private final int mDoubleTapSlop;
     private final int mWindowTouchSlop;
     private final int mMaximumDrawingCacheSize;
@@ -158,6 +165,7 @@
         mMaximumFlingVelocity = MAXIMUM_FLING_VELOCITY;
         mScrollbarSize = SCROLL_BAR_SIZE;
         mTouchSlop = TOUCH_SLOP;
+        mPagingTouchSlop = PAGING_TOUCH_SLOP;
         mDoubleTapSlop = DOUBLE_TAP_SLOP;
         mWindowTouchSlop = WINDOW_TOUCH_SLOP;
         //noinspection deprecation
@@ -184,6 +192,7 @@
         mMaximumFlingVelocity = (int) (density * MAXIMUM_FLING_VELOCITY + 0.5f);
         mScrollbarSize = (int) (density * SCROLL_BAR_SIZE + 0.5f);
         mTouchSlop = (int) (density * TOUCH_SLOP + 0.5f);
+        mPagingTouchSlop = (int) (density * PAGING_TOUCH_SLOP + 0.5f);
         mDoubleTapSlop = (int) (density * DOUBLE_TAP_SLOP + 0.5f);
         mWindowTouchSlop = (int) (density * WINDOW_TOUCH_SLOP + 0.5f);
 
@@ -339,6 +348,14 @@
     public int getScaledTouchSlop() {
         return mTouchSlop;
     }
+    
+    /**
+     * @return Distance a touch can wander before we think the user is scrolling a full page
+     *         in dips
+     */
+    public int getScaledPagingTouchSlop() {
+        return mPagingTouchSlop;
+    }
 
     /**
      * @return Distance between the first touch and second touch to still be
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 6f6ee1d..6f2d070 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2199,14 +2199,15 @@
     // Sets r to be our visible rectangle in content coordinates
     private void calcOurContentVisibleRect(Rect r) {
         calcOurVisibleRect(r);
-        r.left = viewToContentX(r.left);
+        // since we might overscroll, pin the rect to the bounds of the content
+        r.left = Math.max(viewToContentX(r.left), 0);
         // viewToContentY will remove the total height of the title bar.  Add
         // the visible height back in to account for the fact that if the title
         // bar is partially visible, the part of the visible rect which is
         // displaying our content is displaced by that amount.
-        r.top = viewToContentY(r.top + getVisibleTitleHeight());
-        r.right = viewToContentX(r.right);
-        r.bottom = viewToContentY(r.bottom);
+        r.top = Math.max(viewToContentY(r.top + getVisibleTitleHeight()), 0);
+        r.right = Math.min(viewToContentX(r.right), mContentWidth);
+        r.bottom = Math.min(viewToContentY(r.bottom), mContentHeight);
     }
 
     static class ViewSizeData {
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 9965fe5..b6f3997 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -331,12 +331,14 @@
 // i.e. dynamically allocated, since its lifetime may exceed the current stack
 // frame.
 static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding,
-                        jobject options, bool allowPurgeable) {
+                        jobject options, bool allowPurgeable,
+                        bool forcePurgeable = false) {
     int sampleSize = 1;
     SkImageDecoder::Mode mode = SkImageDecoder::kDecodePixels_Mode;
     SkBitmap::Config prefConfig = SkBitmap::kNo_Config;
     bool doDither = true;
-    bool isPurgeable = allowPurgeable && optionsPurgeable(env, options);
+    bool isPurgeable = forcePurgeable ||
+                        (allowPurgeable && optionsPurgeable(env, options));
     bool reportSizeToVM = optionsReportSizeToVM(env, options);
     
     if (NULL != options) {
@@ -568,8 +570,10 @@
                                  jobject options) { // BitmapFactory$Options
     SkStream* stream;
     Asset* asset = reinterpret_cast<Asset*>(native_asset);
+    // assets can always be rebuilt, so force this
+    bool forcePurgeable = true;
 
-    if (optionsPurgeable(env, options)) {
+    if (forcePurgeable || optionsPurgeable(env, options)) {
         // if we could "ref/reopen" the asset, we may not need to copy it here
         // and we could assume optionsShareable, since assets are always RO
         stream = copyAssetToStream(asset);
@@ -582,7 +586,7 @@
         stream = new AssetStreamAdaptor(asset);
     }
     SkAutoUnref aur(stream);
-    return doDecode(env, stream, padding, options, true);
+    return doDecode(env, stream, padding, options, true, forcePurgeable);
 }
 
 static jobject nativeDecodeByteArray(JNIEnv* env, jobject, jbyteArray byteArray,
diff --git a/include/media/stagefright/StagefrightMediaScanner.h b/include/media/stagefright/StagefrightMediaScanner.h
index af125dc..4437eee 100644
--- a/include/media/stagefright/StagefrightMediaScanner.h
+++ b/include/media/stagefright/StagefrightMediaScanner.h
@@ -22,7 +22,7 @@
 
 namespace android {
 
-struct StagefrightMetadataRetriever;
+struct MediaMetadataRetriever;
 
 struct StagefrightMediaScanner : public MediaScanner {
     StagefrightMediaScanner();
@@ -35,7 +35,7 @@
     virtual char *extractAlbumArt(int fd);
 
 private:
-    sp<StagefrightMetadataRetriever> mRetriever;
+    sp<MediaMetadataRetriever> mRetriever;
 
     StagefrightMediaScanner(const StagefrightMediaScanner &);
     StagefrightMediaScanner &operator=(const StagefrightMediaScanner &);
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index d2cec0c..f623295b 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -104,7 +104,8 @@
     { // scope for the lock
         Mutex::Autolock _l(mLock);
 
-        if ( !( mCurrentState & ( MEDIA_PLAYER_IDLE | MEDIA_PLAYER_STATE_ERROR ) ) ) {
+        if ( !( (mCurrentState & MEDIA_PLAYER_IDLE) ||
+                (mCurrentState == MEDIA_PLAYER_STATE_ERROR ) ) ) {
             LOGE("setDataSource called in state %d", mCurrentState);
             return INVALID_OPERATION;
         }
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index b1eca2b..34fb2bc 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -20,7 +20,8 @@
 
 #include <media/stagefright/StagefrightMediaScanner.h>
 
-#include "include/StagefrightMetadataRetriever.h"
+#include <media/mediametadataretriever.h>
+#include <private/media/VideoFrame.h>
 
 // Sonivox includes
 #include <libsonivox/eas.h>
@@ -32,7 +33,7 @@
 namespace android {
 
 StagefrightMediaScanner::StagefrightMediaScanner()
-    : mRetriever(new StagefrightMetadataRetriever) {
+    : mRetriever(new MediaMetadataRetriever) {
 }
 
 StagefrightMediaScanner::~StagefrightMediaScanner() {}
@@ -146,6 +147,8 @@
 status_t StagefrightMediaScanner::processFile(
         const char *path, const char *mimeType,
         MediaScannerClient &client) {
+    LOGV("processFile '%s'.", path);
+
     client.setLocale(locale());
     client.beginFile();
 
@@ -218,6 +221,8 @@
 }
 
 char *StagefrightMediaScanner::extractAlbumArt(int fd) {
+    LOGV("extractAlbumArt %d", fd);
+
     off_t size = lseek(fd, 0, SEEK_END);
     if (size < 0) {
         return NULL;
@@ -227,15 +232,14 @@
     if (mRetriever->setDataSource(fd, 0, size) == OK
             && mRetriever->setMode(
                 METADATA_MODE_FRAME_CAPTURE_ONLY) == OK) {
-        MediaAlbumArt *art = mRetriever->extractAlbumArt();
+        sp<IMemory> mem = mRetriever->extractAlbumArt();
 
-        if (art != NULL) {
+        if (mem != NULL) {
+            MediaAlbumArt *art = static_cast<MediaAlbumArt *>(mem->pointer());
+
             char *data = (char *)malloc(art->mSize + 4);
             *(int32_t *)data = art->mSize;
-            memcpy(&data[4], art->mData, art->mSize);
-
-            delete art;
-            art = NULL;
+            memcpy(&data[4], &art[1], art->mSize);
 
             return data;
         }
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 371fa37..4c1356b 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -4589,7 +4589,7 @@
                         } else {
                             // When replacing apps make sure we honour
                             // the existing app location if not overwritten by other options
-                            boolean prevOnSd = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_ON_SDCARD) != 0;
+                            boolean prevOnSd = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
                             if (onSd) {
                                 // Install flag overrides everything.
                                 return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
@@ -5995,7 +5995,7 @@
         // Delete application code and resources
         if (deleteCodeAndResources) {
             // TODO can pick up from PackageSettings as well
-            int installFlags = ((p.applicationInfo.flags & ApplicationInfo.FLAG_ON_SDCARD)!=0) ?
+            int installFlags = ((p.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE)!=0) ?
                     PackageManager.INSTALL_EXTERNAL : 0;
             installFlags |= ((p.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK)!=0) ?
                     PackageManager.INSTALL_FORWARD_LOCK : 0;
@@ -7214,7 +7214,7 @@
         void setFlags(int pkgFlags) {
             this.pkgFlags = (pkgFlags & ApplicationInfo.FLAG_SYSTEM) |
             (pkgFlags & ApplicationInfo.FLAG_FORWARD_LOCK) |
-            (pkgFlags & ApplicationInfo.FLAG_ON_SDCARD) |
+            (pkgFlags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) |
             (pkgFlags & ApplicationInfo.FLAG_NEVER_ENCRYPT);
         }
     }
@@ -9058,7 +9058,7 @@
                return false;
            }
            mMediaMounted = mediaStatus;
-           Set<String> appList = mSettings.findPackagesWithFlag(ApplicationInfo.FLAG_ON_SDCARD);
+           Set<String> appList = mSettings.findPackagesWithFlag(ApplicationInfo.FLAG_EXTERNAL_STORAGE);
            ret = appList != null && appList.size() > 0;
        }
        // Queue up an async operation since the package installation may take a little while.
@@ -9107,7 +9107,7 @@
                    if (DEBUG_SD_INSTALL) Log.i(TAG, "Looking for pkg : " + pkgName);
                    PackageSetting ps = mSettings.mPackages.get(pkgName);
                    if (ps != null && ps.codePathString != null &&
-                           (ps.pkgFlags & ApplicationInfo.FLAG_ON_SDCARD) != 0) {
+                           (ps.pkgFlags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
                        if (DEBUG_SD_INSTALL) Log.i(TAG, "Container : " + cid +
                                " corresponds to pkg : " + pkgName +
                                " at code path: " + ps.codePathString);
@@ -9333,7 +9333,7 @@
                } else {
                    newFlags = (flags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0 ?
                            PackageManager.INSTALL_EXTERNAL : 0;
-                   currFlags = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_ON_SDCARD) != 0 ?
+                   currFlags = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0 ?
                            PackageManager.INSTALL_EXTERNAL : 0;
                    if (newFlags == currFlags) {
                        Log.w(TAG, "No move required. Trying to move to same location");
@@ -9400,9 +9400,9 @@
                                ps.resourcePathString = ps.resourcePath.getPath();
                                // Set the application info flag correctly.
                                if ((mp.flags & PackageManager.INSTALL_EXTERNAL) != 0) {
-                                   pkg.applicationInfo.flags |= ApplicationInfo.FLAG_ON_SDCARD;
+                                   pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
                                } else {
-                                   pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_ON_SDCARD;
+                                   pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_EXTERNAL_STORAGE;
                                }
                                ps.setFlags(pkg.applicationInfo.flags);
                                mAppDirs.remove(oldCodePath);
diff --git a/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java b/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
index 0b69020..d4435d3 100755
--- a/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
@@ -315,9 +315,9 @@
             if (!getInstallLoc(flags, expInstallLocation)) {
                 assertEquals(srcPath, appInstallPath);
                 assertEquals(publicSrcPath, appInstallPath);
-                assertFalse((info.flags & ApplicationInfo.FLAG_ON_SDCARD) != 0);
+                assertFalse((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
             } else {
-                assertTrue((info.flags & ApplicationInfo.FLAG_ON_SDCARD) != 0);
+                assertTrue((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
                 assertTrue(srcPath.startsWith(SECURE_CONTAINERS_PREFIX));
                 assertTrue(publicSrcPath.startsWith(SECURE_CONTAINERS_PREFIX));
             }
@@ -1172,9 +1172,9 @@
                 ApplicationInfo info = getPm().getApplicationInfo(ip.pkg.packageName, 0);
                 assertNotNull(info);
                 if ((moveFlags & PackageManager.MOVE_INTERNAL) != 0) {
-                    assertTrue((info.flags & ApplicationInfo.FLAG_ON_SDCARD) == 0);
+                    assertTrue((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0);
                 } else if ((moveFlags & PackageManager.MOVE_EXTERNAL_MEDIA) != 0){
-                    assertTrue((info.flags & ApplicationInfo.FLAG_ON_SDCARD) != 0);
+                    assertTrue((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
                 }
             } else {
                 assertFalse(retCode);