Merge "stagefright: Fix port-reconfiguration & output-buffer-filled race condition" into jb-mr2-dev
diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h
index 182d563..fef7af2 100644
--- a/include/media/IMediaPlayerService.h
+++ b/include/media/IMediaPlayerService.h
@@ -89,6 +89,9 @@
 
     virtual void addBatteryData(uint32_t params) = 0;
     virtual status_t pullBatteryData(Parcel* reply) = 0;
+
+    virtual status_t updateProxyConfig(
+            const char *host, int32_t port, const char *exclusionList) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index 8fc72c3..9a75f81 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -198,6 +198,11 @@
         return INVALID_OPERATION;
     }
 
+    virtual status_t updateProxyConfig(
+            const char *host, int32_t port, const char *exclusionList) {
+        return INVALID_OPERATION;
+    }
+
 private:
     friend class MediaPlayerService;
 
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index e5aa033..14381c7 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -232,6 +232,9 @@
             status_t        setRetransmitEndpoint(const char* addrString, uint16_t port);
             status_t        setNextMediaPlayer(const sp<MediaPlayer>& player);
 
+            status_t updateProxyConfig(
+                    const char *host, int32_t port, const char *exclusionList);
+
 private:
             void            clear_l();
             status_t        seekTo_l(int msec);
diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp
index e1ce5a9..74f574d 100644
--- a/media/libmedia/IMediaPlayerService.cpp
+++ b/media/libmedia/IMediaPlayerService.cpp
@@ -48,6 +48,7 @@
     ADD_BATTERY_DATA,
     PULL_BATTERY_DATA,
     LISTEN_FOR_REMOTE_DISPLAY,
+    UPDATE_PROXY_CONFIG,
 };
 
 class BpMediaPlayerService: public BpInterface<IMediaPlayerService>
@@ -163,6 +164,25 @@
         remote()->transact(LISTEN_FOR_REMOTE_DISPLAY, data, &reply);
         return interface_cast<IRemoteDisplay>(reply.readStrongBinder());
     }
+
+    virtual status_t updateProxyConfig(
+            const char *host, int32_t port, const char *exclusionList) {
+        Parcel data, reply;
+
+        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
+        if (host == NULL) {
+            data.writeInt32(0);
+        } else {
+            data.writeInt32(1);
+            data.writeCString(host);
+            data.writeInt32(port);
+            data.writeCString(exclusionList);
+        }
+
+        remote()->transact(UPDATE_PROXY_CONFIG, data, &reply);
+
+        return reply.readInt32();
+    }
 };
 
 IMPLEMENT_META_INTERFACE(MediaPlayerService, "android.media.IMediaPlayerService");
@@ -267,6 +287,24 @@
             reply->writeStrongBinder(display->asBinder());
             return NO_ERROR;
         } break;
+        case UPDATE_PROXY_CONFIG:
+        {
+            CHECK_INTERFACE(IMediaPlayerService, data, reply);
+
+            const char *host = NULL;
+            int32_t port = 0;
+            const char *exclusionList = NULL;
+
+            if (data.readInt32()) {
+                host = data.readCString();
+                port = data.readInt32();
+                exclusionList = data.readCString();
+            }
+
+            reply->writeInt32(updateProxyConfig(host, port, exclusionList));
+
+            return OK;
+        }
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 4a34233..68cbdf5 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -814,4 +814,15 @@
     return mPlayer->setNextPlayer(next == NULL ? NULL : next->mPlayer);
 }
 
+status_t MediaPlayer::updateProxyConfig(
+        const char *host, int32_t port, const char *exclusionList) {
+    const sp<IMediaPlayerService>& service = getMediaPlayerService();
+
+    if (service != NULL) {
+        return service->updateProxyConfig(host, port, exclusionList);
+    }
+
+    return INVALID_OPERATION;
+}
+
 }; // namespace android
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index ec6ace1..acff958 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -74,6 +74,7 @@
 #include "Crypto.h"
 #include "Drm.h"
 #include "HDCP.h"
+#include "HTTPBase.h"
 #include "RemoteDisplay.h"
 
 namespace {
@@ -303,6 +304,11 @@
     return new RemoteDisplay(client, iface.string());
 }
 
+status_t MediaPlayerService::updateProxyConfig(
+        const char *host, int32_t port, const char *exclusionList) {
+    return HTTPBase::UpdateProxyConfig(host, port, exclusionList);
+}
+
 status_t MediaPlayerService::AudioCache::dump(int fd, const Vector<String16>& args) const
 {
     const size_t SIZE = 256;
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 82dc29b..b33805d 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -256,6 +256,9 @@
             const String8& iface);
     virtual status_t            dump(int fd, const Vector<String16>& args);
 
+    virtual status_t        updateProxyConfig(
+            const char *host, int32_t port, const char *exclusionList);
+
             void                removeClient(wp<Client> client);
 
     // For battery usage tracking purpose
diff --git a/media/libstagefright/HTTPBase.cpp b/media/libstagefright/HTTPBase.cpp
index 40bfc55..d2cc6c2 100644
--- a/media/libstagefright/HTTPBase.cpp
+++ b/media/libstagefright/HTTPBase.cpp
@@ -58,6 +58,16 @@
     }
 }
 
+// static
+status_t HTTPBase::UpdateProxyConfig(
+        const char *host, int32_t port, const char *exclusionList) {
+#if CHROMIUM_AVAILABLE
+    return UpdateChromiumHTTPDataSourceProxyConfig(host, port, exclusionList);
+#else
+    return INVALID_OPERATION;
+#endif
+}
+
 void HTTPBase::addBandwidthMeasurement(
         size_t numBytes, int64_t delayUs) {
     Mutex::Autolock autoLock(mLock);
diff --git a/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
index 91ce175..a862d8b 100644
--- a/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
+++ b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
@@ -340,5 +340,11 @@
     return err;
 }
 
+// static
+status_t ChromiumHTTPDataSource::UpdateProxyConfig(
+        const char *host, int32_t port, const char *exclusionList) {
+    return SfDelegate::UpdateProxyConfig(host, port, exclusionList);
+}
+
 }  // namespace android
 
diff --git a/media/libstagefright/chromium_http/chromium_http_stub.cpp b/media/libstagefright/chromium_http/chromium_http_stub.cpp
index 560a61f..289f6de 100644
--- a/media/libstagefright/chromium_http/chromium_http_stub.cpp
+++ b/media/libstagefright/chromium_http/chromium_http_stub.cpp
@@ -26,6 +26,11 @@
     return new ChromiumHTTPDataSource(flags);
 }
 
+status_t UpdateChromiumHTTPDataSourceProxyConfig(
+        const char *host, int32_t port, const char *exclusionList) {
+    return ChromiumHTTPDataSource::UpdateProxyConfig(host, port, exclusionList);
+}
+
 DataSource *createDataUriSource(const char *uri) {
     return new DataUriSource(uri);
 }
diff --git a/media/libstagefright/chromium_http/support.cpp b/media/libstagefright/chromium_http/support.cpp
index 832e86d..741cb1d 100644
--- a/media/libstagefright/chromium_http/support.cpp
+++ b/media/libstagefright/chromium_http/support.cpp
@@ -44,7 +44,7 @@
 
 static Mutex gNetworkThreadLock;
 static base::Thread *gNetworkThread = NULL;
-static scoped_refptr<net::URLRequestContext> gReqContext;
+static scoped_refptr<SfRequestContext> gReqContext;
 static scoped_ptr<net::NetworkChangeNotifier> gNetworkChangeNotifier;
 
 bool logMessageHandler(
@@ -169,8 +169,10 @@
     set_ssl_config_service(
         net::SSLConfigService::CreateSystemSSLConfigService());
 
+    mProxyConfigService = new net::ProxyConfigServiceAndroid;
+
     set_proxy_service(net::ProxyService::CreateWithoutProxyResolver(
-        new net::ProxyConfigServiceAndroid, net_log()));
+        mProxyConfigService, net_log()));
 
     set_http_transaction_factory(new net::HttpCache(
             host_resolver(),
@@ -191,6 +193,31 @@
     return mUserAgent;
 }
 
+status_t SfRequestContext::updateProxyConfig(
+        const char *host, int32_t port, const char *exclusionList) {
+    Mutex::Autolock autoLock(mProxyConfigLock);
+
+    if (host == NULL || *host == '\0') {
+        MY_LOGV("updateProxyConfig NULL");
+
+        std::string proxy;
+        std::string exList;
+        mProxyConfigService->UpdateProxySettings(proxy, exList);
+    } else {
+#if !defined(LOG_NDEBUG) || LOG_NDEBUG == 0
+        LOG_PRI(ANDROID_LOG_VERBOSE, LOG_TAG,
+                "updateProxyConfig %s:%d, exclude '%s'",
+                host, port, exclusionList);
+#endif
+
+        std::string proxy = StringPrintf("%s:%d", host, port).c_str();
+        std::string exList = exclusionList;
+        mProxyConfigService->UpdateProxySettings(proxy, exList);
+    }
+
+    return OK;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
 SfNetworkLibrary::SfNetworkLibrary() {}
@@ -219,6 +246,14 @@
     CHECK(mURLRequest == NULL);
 }
 
+// static
+status_t SfDelegate::UpdateProxyConfig(
+        const char *host, int32_t port, const char *exclusionList) {
+    InitializeNetworkThreadIfNecessary();
+
+    return gReqContext->updateProxyConfig(host, port, exclusionList);
+}
+
 void SfDelegate::setOwner(ChromiumHTTPDataSource *owner) {
     mOwner = owner;
 }
diff --git a/media/libstagefright/chromium_http/support.h b/media/libstagefright/chromium_http/support.h
index d2c5bc0..975a1d3 100644
--- a/media/libstagefright/chromium_http/support.h
+++ b/media/libstagefright/chromium_http/support.h
@@ -27,8 +27,13 @@
 #include "net/base/io_buffer.h"
 
 #include <utils/KeyedVector.h>
+#include <utils/Mutex.h>
 #include <utils/String8.h>
 
+namespace net {
+    struct ProxyConfigServiceAndroid;
+};
+
 namespace android {
 
 struct SfNetLog : public net::NetLog {
@@ -55,8 +60,14 @@
 
     virtual const std::string &GetUserAgent(const GURL &url) const;
 
+    status_t updateProxyConfig(
+            const char *host, int32_t port, const char *exclusionList);
+
 private:
+    Mutex mProxyConfigLock;
+
     std::string mUserAgent;
+    net::ProxyConfigServiceAndroid *mProxyConfigService;
 
     DISALLOW_EVIL_CONSTRUCTORS(SfRequestContext);
 };
@@ -120,6 +131,9 @@
 
     virtual void OnReadCompleted(net::URLRequest *request, int bytes_read);
 
+    static status_t UpdateProxyConfig(
+            const char *host, int32_t port, const char *exclusionList);
+
 private:
     typedef Delegate inherited;
 
diff --git a/media/libstagefright/chromium_http_stub.cpp b/media/libstagefright/chromium_http_stub.cpp
index cbd8796..ed8a878 100644
--- a/media/libstagefright/chromium_http_stub.cpp
+++ b/media/libstagefright/chromium_http_stub.cpp
@@ -30,6 +30,9 @@
 HTTPBase *(*gLib_createChromiumHTTPDataSource)(uint32_t flags);
 DataSource *(*gLib_createDataUriSource)(const char *uri);
 
+status_t (*gLib_UpdateChromiumHTTPDataSourceProxyConfig)(
+        const char *host, int32_t port, const char *exclusionList);
+
 static bool load_libstagefright_chromium_http() {
     Mutex::Autolock autoLock(gLibMutex);
     void *sym;
@@ -59,6 +62,14 @@
     }
     gLib_createDataUriSource = (DataSource *(*)(const char *))sym;
 
+    sym = dlsym(gHandle, "UpdateChromiumHTTPDataSourceProxyConfig");
+    if (sym == NULL) {
+        gHandle = NULL;
+        return false;
+    }
+    gLib_UpdateChromiumHTTPDataSourceProxyConfig =
+        (status_t (*)(const char *, int32_t, const char *))sym;
+
     return true;
 }
 
@@ -70,6 +81,16 @@
     return gLib_createChromiumHTTPDataSource(flags);
 }
 
+status_t UpdateChromiumHTTPDataSourceProxyConfig(
+        const char *host, int32_t port, const char *exclusionList) {
+    if (!load_libstagefright_chromium_http()) {
+        return INVALID_OPERATION;
+    }
+
+    return gLib_UpdateChromiumHTTPDataSourceProxyConfig(
+            host, port, exclusionList);
+}
+
 DataSource *createDataUriSource(const char *uri) {
     if (!load_libstagefright_chromium_http()) {
         return NULL;
diff --git a/media/libstagefright/include/ChromiumHTTPDataSource.h b/media/libstagefright/include/ChromiumHTTPDataSource.h
index 82e08fd..785f939 100644
--- a/media/libstagefright/include/ChromiumHTTPDataSource.h
+++ b/media/libstagefright/include/ChromiumHTTPDataSource.h
@@ -53,6 +53,9 @@
 
     virtual status_t reconnectAtOffset(off64_t offset);
 
+    static status_t UpdateProxyConfig(
+            const char *host, int32_t port, const char *exclusionList);
+
 protected:
     virtual ~ChromiumHTTPDataSource();
 
diff --git a/media/libstagefright/include/HTTPBase.h b/media/libstagefright/include/HTTPBase.h
index b8e10f7..c2dc351 100644
--- a/media/libstagefright/include/HTTPBase.h
+++ b/media/libstagefright/include/HTTPBase.h
@@ -48,6 +48,9 @@
 
     virtual status_t setBandwidthStatCollectFreq(int32_t freqMs);
 
+    static status_t UpdateProxyConfig(
+            const char *host, int32_t port, const char *exclusionList);
+
     void setUID(uid_t uid);
     bool getUID(uid_t *uid) const;
 
diff --git a/media/libstagefright/include/chromium_http_stub.h b/media/libstagefright/include/chromium_http_stub.h
index 869d4ac..e0651a4 100644
--- a/media/libstagefright/include/chromium_http_stub.h
+++ b/media/libstagefright/include/chromium_http_stub.h
@@ -23,6 +23,10 @@
 namespace android {
 extern "C" {
 HTTPBase *createChromiumHTTPDataSource(uint32_t flags);
+
+status_t UpdateChromiumHTTPDataSourceProxyConfig(
+        const char *host, int32_t port, const char *exclusionList);
+
 DataSource *createDataUriSource(const char *uri);
 }
 }