Support for a "preparation" state that can take care of lengthy

operations in NuPlayer and its sources. Sources also can publish their
flags now and the mediaplayer UI will be able to pick up on these.

Change-Id: I4f2b7e5d105dcb4b6c9132cd0e8799efa0c6a14b
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 0736fbe..78b94ba 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -112,6 +112,7 @@
 
 NuPlayer::NuPlayer()
     : mUIDValid(false),
+      mSourceFlags(0),
       mVideoIsAVC(false),
       mAudioEOS(false),
       mVideoEOS(false),
@@ -142,7 +143,7 @@
     mDriver = driver;
 }
 
-void NuPlayer::setDataSource(const sp<IStreamSource> &source) {
+void NuPlayer::setDataSourceAsync(const sp<IStreamSource> &source) {
     sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
 
     sp<AMessage> notify = new AMessage(kWhatSourceNotify, id());
@@ -174,7 +175,7 @@
     return false;
 }
 
-void NuPlayer::setDataSource(
+void NuPlayer::setDataSourceAsync(
         const char *url, const KeyedVector<String8, String8> *headers) {
     sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
     size_t len = strlen(url);
@@ -199,7 +200,7 @@
     msg->post();
 }
 
-void NuPlayer::setDataSource(int fd, int64_t offset, int64_t length) {
+void NuPlayer::setDataSourceAsync(int fd, int64_t offset, int64_t length) {
     sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
 
     sp<AMessage> notify = new AMessage(kWhatSourceNotify, id());
@@ -209,6 +210,10 @@
     msg->post();
 }
 
+void NuPlayer::prepareAsync() {
+    (new AMessage(kWhatPrepare, id()))->post();
+}
+
 void NuPlayer::setVideoSurfaceTextureAsync(
         const sp<IGraphicBufferProducer> &bufferProducer) {
     sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id());
@@ -287,6 +292,18 @@
             mSource = static_cast<Source *>(obj.get());
 
             looper()->registerHandler(mSource);
+
+            CHECK(mDriver != NULL);
+            sp<NuPlayerDriver> driver = mDriver.promote();
+            if (driver != NULL) {
+                driver->notifySetDataSourceCompleted(OK);
+            }
+            break;
+        }
+
+        case kWhatPrepare:
+        {
+            mSource->prepareAsync();
             break;
         }
 
@@ -403,9 +420,7 @@
                     && (mAudioDecoder != NULL || mVideoDecoder != NULL)) {
                 // This is the first time we've found anything playable.
 
-                uint32_t flags = mSource->flags();
-
-                if (flags & Source::FLAG_DYNAMIC_DURATION) {
+                if (mSourceFlags & Source::FLAG_DYNAMIC_DURATION) {
                     schedulePollDuration();
                 }
             }
@@ -730,7 +745,7 @@
 
         case kWhatSourceNotify:
         {
-            TRESPASS();  // TBD
+            onSourceNotify(msg);
             break;
         }
 
@@ -1233,8 +1248,76 @@
     }
 }
 
+void NuPlayer::onSourceNotify(const sp<AMessage> &msg) {
+    int32_t what;
+    CHECK(msg->findInt32("what", &what));
+
+    switch (what) {
+        case Source::kWhatPrepared:
+        {
+            sp<NuPlayerDriver> driver = mDriver.promote();
+            if (driver != NULL) {
+                driver->notifyPrepareCompleted(OK);
+            }
+            break;
+        }
+
+        case Source::kWhatFlagsChanged:
+        {
+            uint32_t flags;
+            CHECK(msg->findInt32("flags", (int32_t *)&flags));
+
+            if ((mSourceFlags & Source::FLAG_DYNAMIC_DURATION)
+                    && (!(flags & Source::FLAG_DYNAMIC_DURATION))) {
+                cancelPollDuration();
+            } else if (!(mSourceFlags & Source::FLAG_DYNAMIC_DURATION)
+                    && (flags & Source::FLAG_DYNAMIC_DURATION)
+                    && (mAudioDecoder != NULL || mVideoDecoder != NULL)) {
+                schedulePollDuration();
+            }
+
+            mSourceFlags = flags;
+            break;
+        }
+
+        case Source::kWhatVideoSizeChanged:
+        {
+            int32_t width, height;
+            CHECK(msg->findInt32("width", &width));
+            CHECK(msg->findInt32("height", &height));
+
+            notifyListener(MEDIA_SET_VIDEO_SIZE, width, height);
+            break;
+        }
+
+        default:
+            TRESPASS();
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
+void NuPlayer::Source::notifyFlagsChanged(uint32_t flags) {
+    sp<AMessage> notify = dupNotify();
+    notify->setInt32("what", kWhatFlagsChanged);
+    notify->setInt32("flags", flags);
+    notify->post();
+}
+
+void NuPlayer::Source::notifyVideoSizeChanged(int32_t width, int32_t height) {
+    sp<AMessage> notify = dupNotify();
+    notify->setInt32("what", kWhatVideoSizeChanged);
+    notify->setInt32("width", width);
+    notify->setInt32("height", height);
+    notify->post();
+}
+
+void NuPlayer::Source::notifyPrepared() {
+    sp<AMessage> notify = dupNotify();
+    notify->setInt32("what", kWhatPrepared);
+    notify->post();
+}
+
 void NuPlayer::Source::onMessageReceived(const sp<AMessage> &msg) {
     TRESPASS();
 }