Merge "Fragmented mp4 extractor" into jb-mr1-dev
diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h
index 172975c..c4c37b6 100644
--- a/include/media/IMediaPlayerService.h
+++ b/include/media/IMediaPlayerService.h
@@ -34,6 +34,8 @@
 struct ICrypto;
 class IMediaRecorder;
 class IOMX;
+class IRemoteDisplay;
+class IRemoteDisplayClient;
 struct IStreamSource;
 
 class IMediaPlayerService: public IInterface
@@ -50,6 +52,16 @@
     virtual sp<IOMX>            getOMX() = 0;
     virtual sp<ICrypto>         makeCrypto() = 0;
 
+    // Connects to a remote display.
+    // 'iface' specifies the address of the local interface on which to listen for
+    // a connection from the remote display as an ip address and port number
+    // of the form "x.x.x.x:y".  The media server should call back into the provided remote
+    // display client when display connection, disconnection or errors occur.
+    // The assumption is that at most one remote display will be connected to the
+    // provided interface at a time.
+    virtual sp<IRemoteDisplay> listenForRemoteDisplay(const sp<IRemoteDisplayClient>& client,
+            const String8& iface) = 0;
+
     // If iface == NULL, disable remote display, otherwise
     // iface should be of the form "x.x.x.x:y", i.e. ip address
     // of the local interface to bind to and the port number
diff --git a/include/media/IRemoteDisplay.h b/include/media/IRemoteDisplay.h
new file mode 100644
index 0000000..f39286e
--- /dev/null
+++ b/include/media/IRemoteDisplay.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_IREMOTEDISPLAY_H
+#define ANDROID_IREMOTEDISPLAY_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+/*
+ * Represents a remote display, such as a Wifi display.
+ *
+ * When the remote display is created, it may not yet be connected to the
+ * display.  The remote display asynchronously reports events such as successful
+ * connection, disconnection and errors to an IRemoteDisplayClient interface provided by
+ * the client.
+ */
+class IRemoteDisplay : public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(RemoteDisplay);
+
+    // Disconnects the remote display.
+    // The remote display should respond back to the IRemoteDisplayClient with an
+    // onDisplayDisconnected() event when the disconnection is complete.
+    virtual status_t disconnect() = 0;
+};
+
+
+// ----------------------------------------------------------------------------
+
+class BnRemoteDisplay : public BnInterface<IRemoteDisplay>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif // ANDROID_IREMOTEDISPLAY_H
diff --git a/include/media/IRemoteDisplayClient.h b/include/media/IRemoteDisplayClient.h
new file mode 100644
index 0000000..38a0c9a
--- /dev/null
+++ b/include/media/IRemoteDisplayClient.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_IREMOTEDISPLAYCLIENT_H
+#define ANDROID_IREMOTEDISPLAYCLIENT_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+class ISurfaceTexture;
+
+class IRemoteDisplayClient : public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(RemoteDisplayClient);
+
+    enum {
+        // Flag: The remote display is using a secure transport protocol such as HDCP.
+        kDisplayFlagSecure = 1 << 0,
+    };
+
+    enum {
+        // Error: An unknown / generic error occurred.
+        kErrorUnknown = 0,
+        // Error: The connection was dropped unexpectedly.
+        kErrorConnectionDropped = 1,
+    };
+
+    // Indicates that the remote display has been connected successfully.
+    // Provides a surface texture that the client should use to stream buffers to
+    // the remote display.
+    virtual void onDisplayConnected(const sp<ISurfaceTexture>& surfaceTexture,
+            uint32_t width, uint32_t height, uint32_t flags) = 0; // one-way
+
+    // Indicates that the remote display has been disconnected normally.
+    // This method should only be called once the client has called 'disconnect()'.
+    // It is currently an error for the display to disconnect for any other reason.
+    virtual void onDisplayDisconnected() = 0; // one-way
+
+    // Indicates that a connection could not be established to the remote display
+    // or an unrecoverable error occurred and the connection was severed.
+    // The media server should continue listening for connection attempts from the
+    // remote display.
+    virtual void onDisplayError(int32_t error) = 0; // one-way
+};
+
+
+// ----------------------------------------------------------------------------
+
+class BnRemoteDisplayClient : public BnInterface<IRemoteDisplayClient>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif // ANDROID_IREMOTEDISPLAYCLIENT_H
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index bcce063..76308e8 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -27,6 +27,8 @@
     IMediaRecorderClient.cpp \
     IMediaPlayer.cpp \
     IMediaRecorder.cpp \
+    IRemoteDisplay.cpp \
+    IRemoteDisplayClient.cpp \
     IStreamSource.cpp \
     Metadata.cpp \
     mediarecorder.cpp \
diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp
index d3e2e19..c2ec439 100644
--- a/media/libmedia/IMediaPlayerService.cpp
+++ b/media/libmedia/IMediaPlayerService.cpp
@@ -24,9 +24,12 @@
 #include <media/IMediaPlayerService.h>
 #include <media/IMediaRecorder.h>
 #include <media/IOMX.h>
+#include <media/IRemoteDisplay.h>
+#include <media/IRemoteDisplayClient.h>
 #include <media/IStreamSource.h>
 
 #include <utils/Errors.h>  // for status_t
+#include <utils/String8.h>
 
 namespace android {
 
@@ -40,7 +43,8 @@
     MAKE_CRYPTO,
     ENABLE_REMOTE_DISPLAY,
     ADD_BATTERY_DATA,
-    PULL_BATTERY_DATA
+    PULL_BATTERY_DATA,
+    LISTEN_FOR_REMOTE_DISPLAY,
 };
 
 class BpMediaPlayerService: public BpInterface<IMediaPlayerService>
@@ -148,6 +152,17 @@
         data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
         return remote()->transact(PULL_BATTERY_DATA, data, reply);
     }
+
+    virtual sp<IRemoteDisplay> listenForRemoteDisplay(const sp<IRemoteDisplayClient>& client,
+            const String8& iface)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
+        data.writeStrongBinder(client->asBinder());
+        data.writeString8(iface);
+        remote()->transact(LISTEN_FOR_REMOTE_DISPLAY, data, &reply);
+        return interface_cast<IRemoteDisplay>(reply.readStrongBinder());
+    }
 };
 
 IMPLEMENT_META_INTERFACE(MediaPlayerService, "android.media.IMediaPlayerService");
@@ -242,6 +257,15 @@
             pullBatteryData(reply);
             return NO_ERROR;
         } break;
+        case LISTEN_FOR_REMOTE_DISPLAY: {
+            CHECK_INTERFACE(IMediaPlayerService, data, reply);
+            sp<IRemoteDisplayClient> client(
+                    interface_cast<IRemoteDisplayClient>(data.readStrongBinder()));
+            String8 iface(data.readString8());
+            sp<IRemoteDisplay> display(listenForRemoteDisplay(client, iface));
+            reply->writeStrongBinder(display->asBinder());
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libmedia/IRemoteDisplay.cpp b/media/libmedia/IRemoteDisplay.cpp
new file mode 100644
index 0000000..5d6ab34
--- /dev/null
+++ b/media/libmedia/IRemoteDisplay.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <media/IRemoteDisplay.h>
+
+namespace android {
+
+enum {
+    DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+class BpRemoteDisplay: public BpInterface<IRemoteDisplay>
+{
+public:
+    BpRemoteDisplay(const sp<IBinder>& impl)
+        : BpInterface<IRemoteDisplay>(impl)
+    {
+    }
+
+    status_t disconnect()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IRemoteDisplay::getInterfaceDescriptor());
+        remote()->transact(DISCONNECT, data, &reply);
+        return reply.readInt32();
+    }
+};
+
+IMPLEMENT_META_INTERFACE(RemoteDisplay, "android.media.IRemoteDisplay");
+
+// ----------------------------------------------------------------------
+
+status_t BnRemoteDisplay::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch (code) {
+        case DISCONNECT: {
+            CHECK_INTERFACE(IRemoteDisplay, data, reply);
+            reply->writeInt32(disconnect());
+            return NO_ERROR;
+        }
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+}; // namespace android
diff --git a/media/libmedia/IRemoteDisplayClient.cpp b/media/libmedia/IRemoteDisplayClient.cpp
new file mode 100644
index 0000000..4a1b570
--- /dev/null
+++ b/media/libmedia/IRemoteDisplayClient.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <media/IRemoteDisplayClient.h>
+#include <gui/ISurfaceTexture.h>
+#include <utils/String8.h>
+
+namespace android {
+
+enum {
+    ON_DISPLAY_CONNECTED = IBinder::FIRST_CALL_TRANSACTION,
+    ON_DISPLAY_DISCONNECTED,
+    ON_DISPLAY_ERROR,
+};
+
+class BpRemoteDisplayClient: public BpInterface<IRemoteDisplayClient>
+{
+public:
+    BpRemoteDisplayClient(const sp<IBinder>& impl)
+        : BpInterface<IRemoteDisplayClient>(impl)
+    {
+    }
+
+    void onDisplayConnected(const sp<ISurfaceTexture>& surfaceTexture,
+            uint32_t width, uint32_t height, uint32_t flags)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IRemoteDisplayClient::getInterfaceDescriptor());
+        data.writeStrongBinder(surfaceTexture->asBinder());
+        data.writeInt32(width);
+        data.writeInt32(height);
+        data.writeInt32(flags);
+        remote()->transact(ON_DISPLAY_CONNECTED, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+
+    void onDisplayDisconnected()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IRemoteDisplayClient::getInterfaceDescriptor());
+        remote()->transact(ON_DISPLAY_DISCONNECTED, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+
+    void onDisplayError(int32_t error)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IRemoteDisplayClient::getInterfaceDescriptor());
+        data.writeInt32(error);
+        remote()->transact(ON_DISPLAY_ERROR, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(RemoteDisplayClient, "android.media.IRemoteDisplayClient");
+
+// ----------------------------------------------------------------------
+
+status_t BnRemoteDisplayClient::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch (code) {
+        case ON_DISPLAY_CONNECTED: {
+            CHECK_INTERFACE(IRemoteDisplayClient, data, reply);
+            sp<ISurfaceTexture> surfaceTexture(
+                    interface_cast<ISurfaceTexture>(data.readStrongBinder()));
+            uint32_t width = data.readInt32();
+            uint32_t height = data.readInt32();
+            uint32_t flags = data.readInt32();
+            onDisplayConnected(surfaceTexture, width, height, flags);
+            return NO_ERROR;
+        }
+        case ON_DISPLAY_DISCONNECTED: {
+            CHECK_INTERFACE(IRemoteDisplayClient, data, reply);
+            onDisplayDisconnected();
+            return NO_ERROR;
+        }
+        case ON_DISPLAY_ERROR: {
+            CHECK_INTERFACE(IRemoteDisplayClient, data, reply);
+            int32_t error = data.readInt32();
+            onDisplayError(error);
+            return NO_ERROR;
+        }
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+}; // namespace android
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 166bae9..9005500 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -44,6 +44,8 @@
 #include <utils/SystemClock.h>
 #include <utils/Vector.h>
 
+#include <media/IRemoteDisplay.h>
+#include <media/IRemoteDisplayClient.h>
 #include <media/MediaPlayerInterface.h>
 #include <media/mediarecorder.h>
 #include <media/MediaMetadataRetrieverInterface.h>
@@ -279,6 +281,11 @@
     return new Crypto;
 }
 
+sp<IRemoteDisplay> MediaPlayerService::listenForRemoteDisplay(
+        const sp<IRemoteDisplayClient>& client, const String8& iface) {
+    return new RemoteDisplay(client, iface.string());;
+}
+
 status_t MediaPlayerService::enableRemoteDisplay(const char *iface) {
     Mutex::Autolock autoLock(mLock);
 
@@ -287,20 +294,12 @@
             return INVALID_OPERATION;
         }
 
-        mRemoteDisplay = new RemoteDisplay;
-
-        status_t err = mRemoteDisplay->start(iface);
-
-        if (err != OK) {
-            mRemoteDisplay.clear();
-            return err;
-        }
-
+        mRemoteDisplay = new RemoteDisplay(NULL /* client */, iface);
         return OK;
     }
 
     if (mRemoteDisplay != NULL) {
-        mRemoteDisplay->stop();
+        mRemoteDisplay->disconnect();
         mRemoteDisplay.clear();
     }
 
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 2577c58..ca8a96f 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -41,6 +41,8 @@
 class IMediaRecorder;
 class IMediaMetadataRetriever;
 class IOMX;
+class IRemoteDisplay;
+class IRemoteDisplayClient;
 class MediaRecorderClient;
 struct RemoteDisplay;
 
@@ -248,6 +250,9 @@
     virtual sp<IMemory>         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat);
     virtual sp<IOMX>            getOMX();
     virtual sp<ICrypto>         makeCrypto();
+
+    virtual sp<IRemoteDisplay> listenForRemoteDisplay(const sp<IRemoteDisplayClient>& client,
+            const String8& iface);
     virtual status_t            enableRemoteDisplay(const char *iface);
 
     virtual status_t            dump(int fd, const Vector<String16>& args);
diff --git a/media/libmediaplayerservice/RemoteDisplay.cpp b/media/libmediaplayerservice/RemoteDisplay.cpp
index 49f7278..1cc605e 100644
--- a/media/libmediaplayerservice/RemoteDisplay.cpp
+++ b/media/libmediaplayerservice/RemoteDisplay.cpp
@@ -19,29 +19,27 @@
 #include "ANetworkSession.h"
 #include "source/WifiDisplaySource.h"
 
+#include <media/IRemoteDisplayClient.h>
+
 namespace android {
 
-RemoteDisplay::RemoteDisplay()
-    : mInitCheck(NO_INIT),
-      mLooper(new ALooper),
+RemoteDisplay::RemoteDisplay(
+        const sp<IRemoteDisplayClient> &client, const char *iface)
+    : mLooper(new ALooper),
       mNetSession(new ANetworkSession),
-      mSource(new WifiDisplaySource(mNetSession)) {
+      mSource(new WifiDisplaySource(mNetSession, client)) {
     mLooper->registerHandler(mSource);
+
+    mNetSession->start();
+    mLooper->start();
+
+    mSource->start(iface);
 }
 
 RemoteDisplay::~RemoteDisplay() {
 }
 
-status_t RemoteDisplay::start(const char *iface) {
-    mNetSession->start();
-    mLooper->start();
-
-    mSource->start(iface);
-
-    return OK;
-}
-
-status_t RemoteDisplay::stop() {
+status_t RemoteDisplay::disconnect() {
     mSource->stop();
 
     mLooper->stop();
@@ -51,4 +49,3 @@
 }
 
 }  // namespace android
-
diff --git a/media/libmediaplayerservice/RemoteDisplay.h b/media/libmediaplayerservice/RemoteDisplay.h
index 3607d06..63c5286 100644
--- a/media/libmediaplayerservice/RemoteDisplay.h
+++ b/media/libmediaplayerservice/RemoteDisplay.h
@@ -18,6 +18,7 @@
 
 #define REMOTE_DISPLAY_H_
 
+#include <media/IRemoteDisplay.h>
 #include <media/stagefright/foundation/ABase.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
@@ -26,20 +27,18 @@
 
 struct ALooper;
 struct ANetworkSession;
+struct IRemoteDisplayClient;
 struct WifiDisplaySource;
 
-struct RemoteDisplay : public RefBase {
-    RemoteDisplay();
+struct RemoteDisplay : public BnRemoteDisplay {
+    RemoteDisplay(const sp<IRemoteDisplayClient> &client, const char *iface);
 
-    status_t start(const char *iface);
-    status_t stop();
+    virtual status_t disconnect();
 
 protected:
     virtual ~RemoteDisplay();
 
 private:
-    status_t mInitCheck;
-
     sp<ALooper> mNetLooper;
     sp<ALooper> mLooper;
     sp<ANetworkSession> mNetSession;
diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.cpp b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
index c9d6562..6c01c7b 100644
--- a/media/libstagefright/wifi-display/source/PlaybackSession.cpp
+++ b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
@@ -113,9 +113,11 @@
 
 WifiDisplaySource::PlaybackSession::PlaybackSession(
         const sp<ANetworkSession> &netSession,
-        const sp<AMessage> &notify)
+        const sp<AMessage> &notify,
+        bool legacyMode)
     : mNetSession(netSession),
       mNotify(notify),
+      mLegacyMode(legacyMode),
       mLastLifesignUs(),
       mTSQueue(new ABuffer(12 + kMaxNumTSPacketsPerRTPPacket * 188)),
       mPrevTimeUs(-1ll),
@@ -240,11 +242,6 @@
 
     mPacketizer.clear();
 
-    sp<IServiceManager> sm = defaultServiceManager();
-    sp<IBinder> binder = sm->getService(String16("SurfaceFlinger"));
-    sp<ISurfaceComposer> service = interface_cast<ISurfaceComposer>(binder);
-    CHECK(service != NULL);
-
     if (mSerializer != NULL) {
         mSerializer->stop();
 
@@ -257,7 +254,14 @@
         mSerializerLooper.clear();
     }
 
-    service->connectDisplay(NULL);
+    if (mLegacyMode) {
+        sp<IServiceManager> sm = defaultServiceManager();
+        sp<IBinder> binder = sm->getService(String16("SurfaceFlinger"));
+        sp<ISurfaceComposer> service = interface_cast<ISurfaceComposer>(binder);
+        CHECK(service != NULL);
+
+        service->connectDisplay(NULL);
+    }
 
     if (mRTCPSessionID != 0) {
         mNetSession->destroySession(mRTCPSessionID);
@@ -598,7 +602,7 @@
     SurfaceComposerClient::getDisplayInfo(0, &info);
 
     // sp<SurfaceMediaSource> source = new SurfaceMediaSource(info.w, info.h);
-    sp<SurfaceMediaSource> source = new SurfaceMediaSource(720, 1280);
+    sp<SurfaceMediaSource> source = new SurfaceMediaSource(width(), height());
 
 #if 0
     ssize_t index = mSerializer->addSource(source);
@@ -641,7 +645,11 @@
     err = source->setMaxAcquiredBufferCount(numInputBuffers + 1);
     CHECK_EQ(err, (status_t)OK);
 
-    service->connectDisplay(source->getBufferQueue());
+    mBufferQueue = source->getBufferQueue();
+
+    if (mLegacyMode) {
+        service->connectDisplay(mBufferQueue);
+    }
 #endif
 
 #if 0
@@ -673,6 +681,18 @@
     return OK;
 }
 
+sp<ISurfaceTexture> WifiDisplaySource::PlaybackSession::getSurfaceTexture() {
+    return mBufferQueue;
+}
+
+int32_t WifiDisplaySource::PlaybackSession::width() const {
+    return 720;
+}
+
+int32_t WifiDisplaySource::PlaybackSession::height() const {
+    return 1280;
+}
+
 void WifiDisplaySource::PlaybackSession::scheduleSendSR() {
     if (mSendSRPending) {
         return;
diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.h b/media/libstagefright/wifi-display/source/PlaybackSession.h
index a6c9f27..5c228f6 100644
--- a/media/libstagefright/wifi-display/source/PlaybackSession.h
+++ b/media/libstagefright/wifi-display/source/PlaybackSession.h
@@ -23,6 +23,8 @@
 namespace android {
 
 struct ABuffer;
+struct BufferQueue;
+struct ISurfaceTexture;
 struct Serializer;
 struct TSPacketizer;
 
@@ -32,7 +34,9 @@
 // display.
 struct WifiDisplaySource::PlaybackSession : public AHandler {
     PlaybackSession(
-            const sp<ANetworkSession> &netSession, const sp<AMessage> &notify);
+            const sp<ANetworkSession> &netSession,
+            const sp<AMessage> &notify,
+            bool legacyMode);
 
     status_t init(
             const char *clientIP, int32_t clientRtp, int32_t clientRtcp,
@@ -46,6 +50,10 @@
     status_t play();
     status_t pause();
 
+    sp<ISurfaceTexture> getSurfaceTexture();
+    int32_t width() const;
+    int32_t height() const;
+
     enum {
         kWhatSessionDead,
         kWhatBinaryData,
@@ -73,6 +81,7 @@
 
     sp<ANetworkSession> mNetSession;
     sp<AMessage> mNotify;
+    bool mLegacyMode;
 
     int64_t mLastLifesignUs;
 
@@ -80,6 +89,7 @@
     sp<Serializer> mSerializer;
     sp<TSPacketizer> mPacketizer;
     sp<ALooper> mCodecLooper;
+    sp<BufferQueue> mBufferQueue;
 
     KeyedVector<size_t, sp<Track> > mTracks;
 
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
index a998dcd..0786f2b 100644
--- a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
+++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp
@@ -22,6 +22,9 @@
 #include "PlaybackSession.h"
 #include "ParsedMessage.h"
 
+#include <gui/ISurfaceTexture.h>
+
+#include <media/IRemoteDisplayClient.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -32,8 +35,11 @@
 
 namespace android {
 
-WifiDisplaySource::WifiDisplaySource(const sp<ANetworkSession> &netSession)
+WifiDisplaySource::WifiDisplaySource(
+        const sp<ANetworkSession> &netSession,
+        const sp<IRemoteDisplayClient> &client)
     : mNetSession(netSession),
+      mClient(client),
       mSessionID(0),
       mReaperPending(false),
       mNextCSeq(1) {
@@ -201,6 +207,10 @@
                 mPlaybackSessions.removeItemsAt(i);
             }
 
+            if (mClient != NULL) {
+                mClient->onDisplayDisconnected();
+            }
+
             status_t err = OK;
 
             sp<AMessage> response = new AMessage;
@@ -768,7 +778,8 @@
     notify->setInt32("sessionID", sessionID);
 
     sp<PlaybackSession> playbackSession =
-        new PlaybackSession(mNetSession, notify);
+        new PlaybackSession(
+                mNetSession, notify, mClient == NULL /* legacyMode */);
 
     looper()->registerHandler(playbackSession);
 
@@ -869,6 +880,14 @@
 
     err = mNetSession->sendRequest(sessionID, response.c_str());
     CHECK_EQ(err, (status_t)OK);
+
+    if (mClient != NULL) {
+        mClient->onDisplayConnected(
+                playbackSession->getSurfaceTexture(),
+                playbackSession->width(),
+                playbackSession->height(),
+                0 /* flags */);
+    }
 }
 
 void WifiDisplaySource::onPauseRequest(
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.h b/media/libstagefright/wifi-display/source/WifiDisplaySource.h
index f56347d..99eb4f5 100644
--- a/media/libstagefright/wifi-display/source/WifiDisplaySource.h
+++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.h
@@ -24,6 +24,7 @@
 
 namespace android {
 
+struct IRemoteDisplayClient;
 struct ParsedMessage;
 
 // Represents the RTSP server acting as a wifi display source.
@@ -31,7 +32,9 @@
 struct WifiDisplaySource : public AHandler {
     static const unsigned kWifiDisplayDefaultPort = 7236;
 
-    WifiDisplaySource(const sp<ANetworkSession> &netSession);
+    WifiDisplaySource(
+            const sp<ANetworkSession> &netSession,
+            const sp<IRemoteDisplayClient> &client);
 
     status_t start(const char *iface);
     status_t stop();
@@ -74,6 +77,7 @@
         kPlaybackSessionTimeoutSecs * 1000000ll;
 
     sp<ANetworkSession> mNetSession;
+    sp<IRemoteDisplayClient> mClient;
     int32_t mSessionID;
 
     struct ClientInfo {