Enable early termination of the prefetcher's preparation phase.

Change-Id: I929ac9b0fd0b6ebd98c1bc56be18ac8f8378d48c
related-to-bug: 2537407
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 407fd57..05e23d1 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -1106,6 +1106,13 @@
     mPreparedCondition.broadcast();
 }
 
+// static
+bool AwesomePlayer::ContinuePreparation(void *cookie) {
+    AwesomePlayer *me = static_cast<AwesomePlayer *>(cookie);
+
+    return (me->mFlags & PREPARE_CANCELLED) == 0;
+}
+
 void AwesomePlayer::onPrepareAsyncEvent() {
     sp<Prefetcher> prefetcher;
 
@@ -1161,10 +1168,22 @@
         }
 
         LOGI("calling prefetcher->prepare()");
-        prefetcher->prepare();
-        LOGV("prefetcher is done preparing");
+        status_t result =
+            prefetcher->prepare(&AwesomePlayer::ContinuePreparation, this);
 
         prefetcher.clear();
+
+        if (result == OK) {
+            LOGV("prefetcher is done preparing");
+        } else {
+            Mutex::Autolock autoLock(mLock);
+
+            CHECK_EQ(result, -EINTR);
+
+            LOGI("prefetcher->prepare() was cancelled early.");
+            abortPrepare(UNKNOWN_ERROR);
+            return;
+        }
     }
 
     Mutex::Autolock autoLock(mLock);
diff --git a/media/libstagefright/Prefetcher.cpp b/media/libstagefright/Prefetcher.cpp
index debb60d..944a0c1 100644
--- a/media/libstagefright/Prefetcher.cpp
+++ b/media/libstagefright/Prefetcher.cpp
@@ -220,12 +220,19 @@
     return minCacheDurationUs < 0 ? 0 : minCacheDurationUs;
 }
 
-status_t Prefetcher::prepare() {
+status_t Prefetcher::prepare(
+        bool (*continueFunc)(void *cookie), void *cookie) {
     // Fill the cache.
 
     int64_t duration;
     bool noMoreData;
     do {
+        usleep(100000);
+
+        if (continueFunc && !(*continueFunc)(cookie)) {
+            return -EINTR;
+        }
+
         duration = getCachedDurationUs(&noMoreData);
     } while (!noMoreData && duration < 2000000ll);
 
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 32c28c1..610f913 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -222,6 +222,8 @@
 
     status_t finishSetDataSource_l();
 
+    static bool ContinuePreparation(void *cookie);
+
     AwesomePlayer(const AwesomePlayer &);
     AwesomePlayer &operator=(const AwesomePlayer &);
 };
diff --git a/media/libstagefright/include/Prefetcher.h b/media/libstagefright/include/Prefetcher.h
index d227864..b411d1b 100644
--- a/media/libstagefright/include/Prefetcher.h
+++ b/media/libstagefright/include/Prefetcher.h
@@ -36,7 +36,12 @@
 
     int64_t getCachedDurationUs(bool *noMoreData = NULL);
 
-    status_t prepare();
+    // If provided (non-NULL), "continueFunc" will be called repeatedly
+    // while preparing and preparation will finish early if it returns
+    // false. In this case "-EINTR" is returned as a result.
+    status_t prepare(
+            bool (*continueFunc)(void *cookie) = NULL,
+            void *cookie = NULL);
 
 protected:
     virtual ~Prefetcher();