Merge "Apparently a MemoryHeapPMem must be slap()ed for SurfaceFlinger to use the contained buffers."
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 5090c39..b8a50bf 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -1064,6 +1064,8 @@
 }
 
 void AwesomePlayer::onPrepareAsyncEvent() {
+    sp<Prefetcher> prefetcher;
+
     {
         Mutex::Autolock autoLock(mLock);
 
@@ -1075,12 +1077,25 @@
                 return;
             }
         }
-    }
 
-    sp<Prefetcher> prefetcher;
+        if (mVideoTrack != NULL && mVideoSource == NULL) {
+            status_t err = initVideoDecoder();
 
-    {
-        Mutex::Autolock autoLock(mLock);
+            if (err != OK) {
+                abortPrepare(err);
+                return;
+            }
+        }
+
+        if (mAudioTrack != NULL && mAudioSource == NULL) {
+            status_t err = initAudioDecoder();
+
+            if (err != OK) {
+                abortPrepare(err);
+                return;
+            }
+        }
+
         prefetcher = mPrefetcher;
     }
 
@@ -1091,24 +1106,6 @@
 
     Mutex::Autolock autoLock(mLock);
 
-    if (mVideoTrack != NULL && mVideoSource == NULL) {
-        status_t err = initVideoDecoder();
-
-        if (err != OK) {
-            abortPrepare(err);
-            return;
-        }
-    }
-
-    if (mAudioTrack != NULL && mAudioSource == NULL) {
-        status_t err = initAudioDecoder();
-
-        if (err != OK) {
-            abortPrepare(err);
-            return;
-        }
-    }
-
     if (mIsAsyncPrepare) {
         if (mVideoWidth < 0 || mVideoHeight < 0) {
             notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
diff --git a/media/libstagefright/Prefetcher.cpp b/media/libstagefright/Prefetcher.cpp
index 9c73f4a..493570a 100644
--- a/media/libstagefright/Prefetcher.cpp
+++ b/media/libstagefright/Prefetcher.cpp
@@ -59,6 +59,7 @@
     int64_t mSeekTimeUs;
     int64_t mCacheDurationUs;
     bool mPrefetcherStopped;
+    bool mCurrentlyPrefetching;
 
     List<MediaBuffer *> mCachedBuffers;
 
@@ -205,10 +206,6 @@
             continue;
         }
 
-        if (cacheDurationUs >= kMaxCacheDurationUs) {
-            continue;
-        }
-
         if (minIndex < 0 || cacheDurationUs < minCacheDurationUs) {
             minCacheDurationUs = cacheDurationUs;
             minIndex = i;
@@ -223,13 +220,13 @@
 }
 
 status_t Prefetcher::prepare() {
-    // Buffer about 2 secs worth of data on prepare.
+    // Fill the cache.
 
     int64_t duration;
     bool noMoreData;
     do {
         duration = getCachedDurationUs(&noMoreData);
-    } while (!noMoreData && duration < 2000000);
+    } while (!noMoreData && duration < kMaxCacheDurationUs);
 
     return OK;
 }
@@ -245,7 +242,8 @@
       mReachedEOS(false),
       mSeekTimeUs(0),
       mCacheDurationUs(0),
-      mPrefetcherStopped(false) {
+      mPrefetcherStopped(false),
+      mCurrentlyPrefetching(false) {
 }
 
 PrefetchedSource::~PrefetchedSource() {
@@ -275,6 +273,10 @@
 
     Mutex::Autolock autoLock(mLock);
 
+    while (mCurrentlyPrefetching) {
+        mCondition.wait(mLock);
+    }
+
     clearCache_l();
 
     status_t err = mSource->stop();
@@ -344,15 +346,24 @@
         return;
     }
 
+    mCurrentlyPrefetching = true;
+
     if (mSeekTimeUs >= 0) {
         options.setSeekTo(mSeekTimeUs);
         mSeekTimeUs = -1;
     }
 
+    // Ensure our object does not go away while we're not holding
+    // the lock.
+    sp<PrefetchedSource> me = this;
+
+    mLock.unlock();
     MediaBuffer *buffer;
     status_t err = mSource->read(&buffer, &options);
+    mLock.lock();
 
     if (err != OK) {
+        mCurrentlyPrefetching = false;
         mReachedEOS = true;
         mFinalStatus = err;
         mCondition.signal();
@@ -380,6 +391,8 @@
 
     mCachedBuffers.push_back(copy);
     updateCacheDuration_l();
+
+    mCurrentlyPrefetching = false;
     mCondition.signal();
 }