Merge "Make sure the OMX component is synchronously shutdown before we try to instantiate another one. Also properly cleanup the software AVC decoder to avoid leaking memory."
diff --git a/core/res/res/drawable-hdpi/search_plate_global.9.png b/core/res/res/drawable-hdpi/search_plate_global.9.png
index 32c6dc3..e9f4f12 100644
--- a/core/res/res/drawable-hdpi/search_plate_global.9.png
+++ b/core/res/res/drawable-hdpi/search_plate_global.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/search_source_selector_indicator.png b/core/res/res/drawable-hdpi/search_source_selector_indicator.png
index b93a0c0..e81d9ac 100644
--- a/core/res/res/drawable-hdpi/search_source_selector_indicator.png
+++ b/core/res/res/drawable-hdpi/search_source_selector_indicator.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/search_plate_global.9.png b/core/res/res/drawable-mdpi/search_plate_global.9.png
index 1cad902..bb7400e 100644
--- a/core/res/res/drawable-mdpi/search_plate_global.9.png
+++ b/core/res/res/drawable-mdpi/search_plate_global.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/search_source_selector_indicator.png b/core/res/res/drawable-mdpi/search_source_selector_indicator.png
index 26bf18a..b3efef2 100644
--- a/core/res/res/drawable-mdpi/search_source_selector_indicator.png
+++ b/core/res/res/drawable-mdpi/search_source_selector_indicator.png
Binary files differ
diff --git a/core/res/res/layout/search_bar.xml b/core/res/res/layout/search_bar.xml
index 12285fd..2e93a39 100644
--- a/core/res/res/layout/search_bar.xml
+++ b/core/res/res/layout/search_bar.xml
@@ -33,10 +33,9 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:orientation="vertical"
-        android:paddingLeft="12dip"
-        android:paddingRight="12dip"
-        android:paddingTop="7dip"
-        android:paddingBottom="16dip"
+        android:paddingLeft="4dip"
+        android:paddingRight="4dip"
+        android:paddingTop="4dip"
         android:background="@drawable/search_plate_global" >
 
         <!-- This is actually used for the badge icon *or* the badge label (or neither) -->
@@ -63,10 +62,11 @@
 
             <view class="android.app.SearchDialog$SearchAutoComplete"
                 android:id="@+id/search_src_text"
-                android:background="@drawable/textfield_search"
+                android:background="@drawable/edit_text"
                 android:layout_height="wrap_content"
                 android:layout_width="0dip"
                 android:layout_weight="1.0"
+                android:layout_marginLeft="4dip"
                 android:paddingLeft="8dip"
                 android:paddingRight="6dip"
                 android:drawablePadding="2dip"
@@ -86,13 +86,15 @@
                 android:background="@drawable/btn_search_dialog"
                 android:layout_width="wrap_content"
                 android:layout_height="match_parent"
+                android:visibility="gone"
             />
 
             <ImageButton
                 android:id="@+id/search_voice_btn"
                 android:layout_width="wrap_content"
                 android:layout_height="match_parent"
-                android:layout_marginLeft="8dip"
+                android:layout_marginLeft="4dip"
+                android:layout_marginBottom="4dip"
                 android:background="@drawable/btn_search_dialog_voice"
                 android:src="@android:drawable/ic_btn_speak_now"
             />
diff --git a/core/res/res/layout/search_source_selector.xml b/core/res/res/layout/search_source_selector.xml
index c69dfc0..9312b08 100644
--- a/core/res/res/layout/search_source_selector.xml
+++ b/core/res/res/layout/search_source_selector.xml
@@ -16,10 +16,11 @@
 
 <FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="48dip"
+    android:layout_width="42dip"
     android:layout_height="match_parent"
+    android:layout_marginBottom="2dip"
     android:foreground="@drawable/search_source_selector_indicator"
-    android:foregroundGravity="bottom|right"
+    android:foregroundGravity="bottom|center_horizontal"
     >
 
     <ImageButton
@@ -27,6 +28,7 @@
         android:background="@drawable/search_source_selector_background"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
+        android:layout_marginBottom="6dip"
         android:scaleType="centerInside"
         android:focusable="true"
         android:clickable="true"
diff --git a/media/libstagefright/HTTPDataSource.cpp b/media/libstagefright/HTTPDataSource.cpp
index 5564886..e1ddfef 100644
--- a/media/libstagefright/HTTPDataSource.cpp
+++ b/media/libstagefright/HTTPDataSource.cpp
@@ -274,6 +274,9 @@
     ssize_t contentLength = 0;
     if (mFirstRequest || offset != mBufferOffset + mBufferLength) {
         if (!mFirstRequest) {
+            LOGV("new range offset=%ld (old=%ld)",
+                 offset, mBufferOffset + mBufferLength);
+
             mHttp->disconnect();
         }
         mFirstRequest = false;
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index ed12b6d..5370c39 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -84,6 +84,112 @@
     MPEG4Source &operator=(const MPEG4Source &);
 };
 
+// This custom data source wraps an existing one and satisfies requests
+// falling entirely within a cached range from the cache while forwarding
+// all remaining requests to the wrapped datasource.
+// This is used to cache the full sampletable metadata for a single track,
+// possibly wrapping multiple times to cover all tracks, i.e.
+// Each MPEG4DataSource caches the sampletable metadata for a single track.
+
+struct MPEG4DataSource : public DataSource {
+    MPEG4DataSource(const sp<DataSource> &source);
+
+    virtual status_t initCheck() const;
+    virtual ssize_t readAt(off_t offset, void *data, size_t size);
+    virtual status_t getSize(off_t *size);
+    virtual uint32_t flags();
+
+    status_t setCachedRange(off_t offset, size_t size);
+
+protected:
+    virtual ~MPEG4DataSource();
+
+private:
+    Mutex mLock;
+
+    sp<DataSource> mSource;
+    off_t mCachedOffset;
+    size_t mCachedSize;
+    uint8_t *mCache;
+
+    void clearCache();
+
+    MPEG4DataSource(const MPEG4DataSource &);
+    MPEG4DataSource &operator=(const MPEG4DataSource &);
+};
+
+MPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source)
+    : mSource(source),
+      mCachedOffset(0),
+      mCachedSize(0),
+      mCache(NULL) {
+}
+
+MPEG4DataSource::~MPEG4DataSource() {
+    clearCache();
+}
+
+void MPEG4DataSource::clearCache() {
+    if (mCache) {
+        free(mCache);
+        mCache = NULL;
+    }
+
+    mCachedOffset = 0;
+    mCachedSize = 0;
+}
+
+status_t MPEG4DataSource::initCheck() const {
+    return mSource->initCheck();
+}
+
+ssize_t MPEG4DataSource::readAt(off_t offset, void *data, size_t size) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (offset >= mCachedOffset
+            && offset + size <= mCachedOffset + mCachedSize) {
+        memcpy(data, &mCache[offset - mCachedOffset], size);
+        return size;
+    }
+
+    return mSource->readAt(offset, data, size);
+}
+
+status_t MPEG4DataSource::getSize(off_t *size) {
+    return mSource->getSize(size);
+}
+
+uint32_t MPEG4DataSource::flags() {
+    return mSource->flags();
+}
+
+status_t MPEG4DataSource::setCachedRange(off_t offset, size_t size) {
+    Mutex::Autolock autoLock(mLock);
+
+    clearCache();
+
+    mCache = (uint8_t *)malloc(size);
+
+    if (mCache == NULL) {
+        return -ENOMEM;
+    }
+
+    mCachedOffset = offset;
+    mCachedSize = size;
+
+    ssize_t err = mSource->readAt(mCachedOffset, mCache, mCachedSize);
+
+    if (err < (ssize_t)size) {
+        clearCache();
+
+        return ERROR_IO;
+    }
+
+    return OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
 static void hexdump(const void *_data, size_t size) {
     const uint8_t *data = (const uint8_t *)_data;
     size_t offset = 0;
@@ -374,6 +480,19 @@
         case FOURCC('u', 'd', 't', 'a'):
         case FOURCC('i', 'l', 's', 't'):
         {
+            if (chunk_type == FOURCC('s', 't', 'b', 'l')) {
+                LOGV("sampleTable chunk is %d bytes long.", (size_t)chunk_size);
+
+                if (mDataSource->flags() & DataSource::kWantsPrefetching) {
+                    sp<MPEG4DataSource> cachedSource =
+                        new MPEG4DataSource(mDataSource);
+
+                    if (cachedSource->setCachedRange(*offset, chunk_size) == OK) {
+                        mDataSource = cachedSource;
+                    }
+                }
+            }
+
             off_t stop_offset = *offset + chunk_size;
             *offset = data_offset;
             while (*offset < stop_offset) {
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 3ffb8bf..cd4ae4cc 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -4369,18 +4369,13 @@
         String idxStr = "";
         int idx = 1;
         if (oldCodePath != null) {
-            int eidx = -1;
-            if (suffix != null) {
-                eidx = oldCodePath.indexOf(suffix);
+            String subStr = oldCodePath;
+            if (subStr.startsWith(prefix)) {
+                subStr = subStr.substring(prefix.length());
             }
-            if (eidx == -1) {
-                eidx = oldCodePath.length();
+            if (subStr.endsWith(suffix)) {
+                subStr = subStr.substring(0, subStr.length() - suffix.length());
             }
-            int sidx = oldCodePath.indexOf(prefix);
-            if (sidx == -1) {
-                sidx = 0;
-            }
-            String subStr = oldCodePath.substring(sidx + prefix.length(), eidx);
             if (subStr != null) {
                 if (subStr.startsWith("-")) {
                     subStr = subStr.substring(1);