HTTPStream and HTTPDataSource now support cancellation of the connection process, AwesomePlayer takes advantage of this in cases where ::reset() or ::suspend() is called while in the preparation phase to bail out early. Also fixes in issue where the audio codec was not properly stopped if no audio player object ever took ownership.

Change-Id: I6d73defe6d276693853a469db267bb2668d07af5
related-to-bugs: 2475845,2414536
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index e00ba470..10b7be3 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -26,6 +26,7 @@
 
 #include <binder/IPCThreadState.h>
 #include <media/stagefright/AudioPlayer.h>
+#include <media/stagefright/CachingDataSource.h>
 #include <media/stagefright/DataSource.h>
 #include <media/stagefright/FileSource.h>
 #include <media/stagefright/MediaBuffer.h>
@@ -318,6 +319,14 @@
 }
 
 void AwesomePlayer::reset_l() {
+    if (mFlags & PREPARING) {
+        mFlags |= PREPARE_CANCELLED;
+        if (mConnectingDataSource != NULL) {
+            LOGI("interrupting the connection process");
+            mConnectingDataSource->disconnect();
+        }
+    }
+
     while (mFlags & PREPARING) {
         mPreparedCondition.wait(mLock);
     }
@@ -337,6 +346,12 @@
     // If we did this later, audio would continue playing while we
     // shutdown the video-related resources and the player appear to
     // not be as responsive to a reset request.
+    if (mAudioPlayer == NULL && mAudioSource != NULL) {
+        // If we had an audio player, it would have effectively
+        // taken possession of the audio source and stopped it when
+        // _it_ is stopped. Otherwise this is still our responsibility.
+        mAudioSource->stop();
+    }
     mAudioSource.clear();
 
     if (mTimeSource != mAudioPlayer) {
@@ -1039,8 +1054,29 @@
 }
 
 status_t AwesomePlayer::finishSetDataSource_l() {
-    sp<DataSource> dataSource =
-        DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
+    sp<DataSource> dataSource;
+
+    if (!strncasecmp("http://", mUri.string(), 7)) {
+        mConnectingDataSource = new HTTPDataSource(mUri, &mUriHeaders);
+
+        mLock.unlock();
+        status_t err = mConnectingDataSource->connect();
+        mLock.lock();
+
+        if (err != OK) {
+            mConnectingDataSource.clear();
+
+            LOGI("mConnectingDataSource->connect() returned %d", err);
+            return err;
+        }
+
+        dataSource = new CachingDataSource(
+                mConnectingDataSource, 32 * 1024, 20);
+
+        mConnectingDataSource.clear();
+    } else {
+        dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
+    }
 
     if (dataSource == NULL) {
         return UNKNOWN_ERROR;
@@ -1067,7 +1103,7 @@
     }
 
     mPrepareResult = err;
-    mFlags &= ~PREPARING;
+    mFlags &= ~(PREPARING|PREPARE_CANCELLED);
     mAsyncPrepareEvent = NULL;
     mPreparedCondition.broadcast();
 }
@@ -1078,6 +1114,12 @@
     {
         Mutex::Autolock autoLock(mLock);
 
+        if (mFlags & PREPARE_CANCELLED) {
+            LOGI("prepare was cancelled before doing anything");
+            abortPrepare(UNKNOWN_ERROR);
+            return;
+        }
+
         if (mUri.size() > 0) {
             status_t err = finishSetDataSource_l();
 
@@ -1109,7 +1151,19 @@
     }
 
     if (prefetcher != NULL) {
+        {
+            Mutex::Autolock autoLock(mLock);
+            if (mFlags & PREPARE_CANCELLED) {
+                LOGI("prepare was cancelled before preparing the prefetcher");
+                abortPrepare(UNKNOWN_ERROR);
+                return;
+            }
+        }
+
+        LOGI("calling prefetcher->prepare()");
         prefetcher->prepare();
+        LOGV("prefetcher is done preparing");
+
         prefetcher.clear();
     }
 
@@ -1126,20 +1180,28 @@
     }
 
     mPrepareResult = OK;
-    mFlags &= ~PREPARING;
+    mFlags &= ~(PREPARING|PREPARE_CANCELLED);
     mFlags |= PREPARED;
     mAsyncPrepareEvent = NULL;
     mPreparedCondition.broadcast();
 }
 
 status_t AwesomePlayer::suspend() {
-    LOGI("suspend");
+    LOGV("suspend");
     Mutex::Autolock autoLock(mLock);
 
     if (mSuspensionState != NULL) {
         return INVALID_OPERATION;
     }
 
+    if (mFlags & PREPARING) {
+        mFlags |= PREPARE_CANCELLED;
+        if (mConnectingDataSource != NULL) {
+            LOGI("interrupting the connection process");
+            mConnectingDataSource->disconnect();
+        }
+    }
+
     while (mFlags & PREPARING) {
         mPreparedCondition.wait(mLock);
     }
@@ -1180,7 +1242,7 @@
 }
 
 status_t AwesomePlayer::resume() {
-    LOGI("resume");
+    LOGV("resume");
     Mutex::Autolock autoLock(mLock);
 
     if (mSuspensionState == NULL) {