Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 49c59815 authored by Andreas Huber's avatar Andreas Huber
Browse files

YouTube can now request custom cache/prefetch parameters and disconnect-at-highwater

through the use of pseudo http headers specified in the setDataSource call.

x-cache-config: -1/-1/0
x-disconnect-at-highwatermark: 1

turns off keep-alives and disconnects every time the cache is full (will attempt
to reconnect once it run below lowwater mark)

related-to-bug: 5433309

Change-Id: Id2f942fc956e0e156834cfcd6bb08dae6a29fae1
parent e87a2f05
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -2005,6 +2005,11 @@ status_t AwesomePlayer::finishSetDataSource_l() {
            mConnectingDataSource->setUID(mUID);
        }

        String8 cacheConfig;
        bool disconnectAtHighwatermark;
        NuCachedSource2::RemoveCacheSpecificHeaders(
                &mUriHeaders, &cacheConfig, &disconnectAtHighwatermark);

        mLock.unlock();
        status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
        mLock.lock();
@@ -2024,7 +2029,10 @@ status_t AwesomePlayer::finishSetDataSource_l() {
                    new ThrottledSource(
                        mConnectingDataSource, 50 * 1024 /* bytes/sec */));
#else
            mCachedSource = new NuCachedSource2(mConnectingDataSource);
            mCachedSource = new NuCachedSource2(
                    mConnectingDataSource,
                    cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
                    disconnectAtHighwatermark);
#endif

            dataSource = mCachedSource;
+56 −2
Original line number Diff line number Diff line
@@ -177,7 +177,10 @@ void PageCache::copy(size_t from, void *data, size_t size) {

////////////////////////////////////////////////////////////////////////////////

NuCachedSource2::NuCachedSource2(const sp<DataSource> &source)
NuCachedSource2::NuCachedSource2(
        const sp<DataSource> &source,
        const char *cacheConfig,
        bool disconnectAtHighwatermark)
    : mSource(source),
      mReflector(new AHandlerReflector<NuCachedSource2>(this)),
      mLooper(new ALooper),
@@ -190,9 +193,24 @@ NuCachedSource2::NuCachedSource2(const sp<DataSource> &source)
      mNumRetriesLeft(kMaxNumRetries),
      mHighwaterThresholdBytes(kDefaultHighWaterThreshold),
      mLowwaterThresholdBytes(kDefaultLowWaterThreshold),
      mKeepAliveIntervalUs(kDefaultKeepAliveIntervalUs) {
      mKeepAliveIntervalUs(kDefaultKeepAliveIntervalUs),
      mDisconnectAtHighwatermark(disconnectAtHighwatermark) {
    // We are NOT going to support disconnect-at-highwatermark indefinitely
    // and we are not guaranteeing support for client-specified cache
    // parameters. Both of these are temporary measures to solve a specific
    // problem that will be solved in a better way going forward.

    updateCacheParamsFromSystemProperty();

    if (cacheConfig != NULL) {
        updateCacheParamsFromString(cacheConfig);
    }

    if (mDisconnectAtHighwatermark) {
        // Makes no sense to disconnect and do keep-alives...
        mKeepAliveIntervalUs = 0;
    }

    mLooper->setName("NuCachedSource2");
    mLooper->registerHandler(mReflector);
    mLooper->start();
@@ -339,6 +357,12 @@ void NuCachedSource2::onFetch() {
        if (mFetching && mCache->totalSize() >= mHighwaterThresholdBytes) {
            LOGI("Cache full, done prefetching for now");
            mFetching = false;

            if (mDisconnectAtHighwatermark
                    && (mSource->flags() & DataSource::kIsHTTPBasedSource)) {
                LOGV("Disconnecting at high watermark");
                static_cast<HTTPBase *>(mSource.get())->disconnect();
            }
        }
    } else {
        Mutex::Autolock autoLock(mLock);
@@ -637,4 +661,34 @@ void NuCachedSource2::updateCacheParamsFromString(const char *s) {
         mKeepAliveIntervalUs);
}

// static
void NuCachedSource2::RemoveCacheSpecificHeaders(
        KeyedVector<String8, String8> *headers,
        String8 *cacheConfig,
        bool *disconnectAtHighwatermark) {
    *cacheConfig = String8();
    *disconnectAtHighwatermark = false;

    if (headers == NULL) {
        return;
    }

    ssize_t index;
    if ((index = headers->indexOfKey(String8("x-cache-config"))) >= 0) {
        *cacheConfig = headers->valueAt(index);

        headers->removeItemsAt(index);

        LOGV("Using special cache config '%s'", cacheConfig->string());
    }

    if ((index = headers->indexOfKey(
                    String8("x-disconnect-at-highwatermark"))) >= 0) {
        *disconnectAtHighwatermark = true;
        headers->removeItemsAt(index);

        LOGV("Client requested disconnection at highwater mark");
    }
}

}  // namespace android
+11 −1
Original line number Diff line number Diff line
@@ -28,7 +28,10 @@ struct ALooper;
struct PageCache;

struct NuCachedSource2 : public DataSource {
    NuCachedSource2(const sp<DataSource> &source);
    NuCachedSource2(
            const sp<DataSource> &source,
            const char *cacheConfig = NULL,
            bool disconnectAtHighwatermark = false);

    virtual status_t initCheck() const;

@@ -56,6 +59,11 @@ struct NuCachedSource2 : public DataSource {
    status_t getEstimatedBandwidthKbps(int32_t *kbps);
    status_t setCacheStatCollectFreq(int32_t freqMs);

    static void RemoveCacheSpecificHeaders(
            KeyedVector<String8, String8> *headers,
            String8 *cacheConfig,
            bool *disconnectAtHighwatermark);

protected:
    virtual ~NuCachedSource2();

@@ -105,6 +113,8 @@ private:
    // If the keep-alive interval is 0, keep-alives are disabled.
    int64_t mKeepAliveIntervalUs;

    bool mDisconnectAtHighwatermark;

    void onMessageReceived(const sp<AMessage> &msg);
    void onFetch();
    void onRead(const sp<AMessage> &msg);