RTSP now properly publishes its "seekable" flags after connection

has successfully completed and only then signals that preparation is
complete.

Change-Id: I1a60f718e673fe1462c69369c40eafbed6a14326
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 78b94ba..bcefe63 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -1255,9 +1255,12 @@
     switch (what) {
         case Source::kWhatPrepared:
         {
+            int32_t err;
+            CHECK(msg->findInt32("err", &err));
+
             sp<NuPlayerDriver> driver = mDriver.promote();
             if (driver != NULL) {
-                driver->notifyPrepareCompleted(OK);
+                driver->notifyPrepareCompleted(err);
             }
             break;
         }
@@ -1312,9 +1315,10 @@
     notify->post();
 }
 
-void NuPlayer::Source::notifyPrepared() {
+void NuPlayer::Source::notifyPrepared(status_t err) {
     sp<AMessage> notify = dupNotify();
     notify->setInt32("what", kWhatPrepared);
+    notify->setInt32("err", err);
     notify->post();
 }
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index ab7b4e8..3c63e80 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -31,6 +31,7 @@
 
 NuPlayerDriver::NuPlayerDriver()
     : mState(STATE_IDLE),
+      mIsAsyncPrepare(false),
       mAsyncResult(UNKNOWN_ERROR),
       mSetSurfaceInProgress(false),
       mDurationUs(-1),
@@ -160,6 +161,11 @@
     switch (mState) {
         case STATE_UNPREPARED:
             mState = STATE_PREPARING;
+
+            // Make sure we're not posting any notifications, success or
+            // failure information is only communicated through our result
+            // code.
+            mIsAsyncPrepare = false;
             mPlayer->prepareAsync();
             while (mState == STATE_PREPARING) {
                 mCondition.wait(mLock);
@@ -176,6 +182,7 @@
     switch (mState) {
         case STATE_UNPREPARED:
             mState = STATE_PREPARING;
+            mIsAsyncPrepare = true;
             mPlayer->prepareAsync();
             return OK;
         default:
@@ -500,9 +507,14 @@
     mAsyncResult = err;
 
     if (err == OK) {
-        notifyListener(MEDIA_PREPARED);
+        if (mIsAsyncPrepare) {
+            notifyListener(MEDIA_PREPARED);
+        }
         mState = STATE_PREPARED;
     } else {
+        if (mIsAsyncPrepare) {
+            notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
+        }
         mState = STATE_UNPREPARED;
     }
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index 49b8ed2..5df0cfb 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -92,6 +92,7 @@
 
     State mState;
 
+    bool mIsAsyncPrepare;
     status_t mAsyncResult;
 
     // The following are protected through "mLock"
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
index 53c7c12..f5d4c38 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
@@ -81,7 +81,7 @@
 
     void notifyFlagsChanged(uint32_t flags);
     void notifyVideoSizeChanged(int32_t width, int32_t height);
-    void notifyPrepared();
+    void notifyPrepared(status_t err = OK);
 
 private:
     sp<AMessage> mNotify;
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index e4d72d9..d787647 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -96,16 +96,6 @@
 
         mHandler->connect();
     }
-
-    notifyVideoSizeChanged(0, 0);
-
-    notifyFlagsChanged(
-            FLAG_CAN_PAUSE
-            | FLAG_CAN_SEEK_BACKWARD
-            | FLAG_CAN_SEEK_FORWARD
-            | FLAG_CAN_SEEK);
-
-    notifyPrepared();
 }
 
 void NuPlayer::RTSPSource::start() {
@@ -270,12 +260,31 @@
 
     switch (what) {
         case MyHandler::kWhatConnected:
+        {
             onConnected();
+
+            notifyVideoSizeChanged(0, 0);
+
+            uint32_t flags = 0;
+
+            if (mHandler->isSeekable()) {
+                flags = FLAG_CAN_PAUSE | FLAG_CAN_SEEK;
+
+                // Seeking 10secs forward or backward is a very expensive
+                // operation for rtsp, so let's not enable that.
+                // The user can always use the seek bar.
+            }
+
+            notifyFlagsChanged(flags);
+            notifyPrepared();
             break;
+        }
 
         case MyHandler::kWhatDisconnected:
+        {
             onDisconnected(msg);
             break;
+        }
 
         case MyHandler::kWhatSeekDone:
         {
@@ -520,6 +529,12 @@
     }
 
     if (err != OK) {
+        if (mState == CONNECTING) {
+            // We're still in the preparation phase, signal that it
+            // failed.
+            notifyPrepared(err);
+        }
+
         mState = DISCONNECTED;
         mFinalResult = err;
 
@@ -537,6 +552,12 @@
     mLooper->unregisterHandler(mHandler->id());
     mHandler.clear();
 
+    if (mState == CONNECTING) {
+        // We're still in the preparation phase, signal that it
+        // failed.
+        notifyPrepared(err);
+    }
+
     mState = DISCONNECTED;
     mFinalResult = err;
 
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index cdd00e4..aa64060 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -195,6 +195,10 @@
         msg->post();
     }
 
+    bool isSeekable() const {
+        return mSeekable;
+    }
+
     static void addRR(const sp<ABuffer> &buf) {
         uint8_t *ptr = buf->data() + buf->size();
         ptr[0] = 0x80 | 0;