15994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber/*
25994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber * Copyright (C) 2010 The Android Open Source Project
35994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber *
45994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
55994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber * you may not use this file except in compliance with the License.
65994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber * You may obtain a copy of the License at
75994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber *
85994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
95994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber *
105994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber * Unless required by applicable law or agreed to in writing, software
115994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
125994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber * See the License for the specific language governing permissions and
145994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber * limitations under the License.
155994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber */
165994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
17a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <inttypes.h>
18a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn
19ac05c317cd818701535c5d72ce90da98c4bae75bAndreas Huber//#define LOG_NDEBUG 0
205994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber#define LOG_TAG "NuCachedSource2"
215994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber#include <utils/Log.h>
225994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
235994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber#include "include/NuCachedSource2.h"
245b1b8a93a07326f1cbc627f09e02988375189e0aJames Dong#include "include/HTTPBase.h"
255994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
26a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber#include <cutils/properties.h>
275994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber#include <media/stagefright/foundation/ADebug.h>
285994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber#include <media/stagefright/foundation/AMessage.h>
295994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber#include <media/stagefright/MediaErrors.h>
305994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
315994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubernamespace android {
325994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
335994b4798b01f3dd340577c9ea9657f09093a770Andreas Huberstruct PageCache {
345994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    PageCache(size_t pageSize);
355994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    ~PageCache();
365994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
375994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    struct Page {
385994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        void *mData;
395994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        size_t mSize;
405994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    };
415994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
425994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    Page *acquirePage();
435994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    void releasePage(Page *page);
445994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
455994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    void appendPage(Page *page);
465994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    size_t releaseFromStart(size_t maxBytes);
475994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
485994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    size_t totalSize() const {
495994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        return mTotalSize;
505994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
515994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
525994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    void copy(size_t from, void *data, size_t size);
535994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
545994b4798b01f3dd340577c9ea9657f09093a770Andreas Huberprivate:
555994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    size_t mPageSize;
565994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    size_t mTotalSize;
575994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
585994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    List<Page *> mActivePages;
595994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    List<Page *> mFreePages;
605994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
615994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    void freePages(List<Page *> *list);
625994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
635994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(PageCache);
645994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber};
655994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
665994b4798b01f3dd340577c9ea9657f09093a770Andreas HuberPageCache::PageCache(size_t pageSize)
675994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    : mPageSize(pageSize),
685994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber      mTotalSize(0) {
695994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
705994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
715994b4798b01f3dd340577c9ea9657f09093a770Andreas HuberPageCache::~PageCache() {
725994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    freePages(&mActivePages);
735994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    freePages(&mFreePages);
745994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
755994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
765994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubervoid PageCache::freePages(List<Page *> *list) {
775994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    List<Page *>::iterator it = list->begin();
785994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    while (it != list->end()) {
795994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        Page *page = *it;
805994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
815994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        free(page->mData);
825994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        delete page;
835994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        page = NULL;
845994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
855994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        ++it;
865994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
875994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
885994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
895994b4798b01f3dd340577c9ea9657f09093a770Andreas HuberPageCache::Page *PageCache::acquirePage() {
905994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    if (!mFreePages.empty()) {
915994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        List<Page *>::iterator it = mFreePages.begin();
925994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        Page *page = *it;
935994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        mFreePages.erase(it);
945994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
955994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        return page;
965994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
975994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
985994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    Page *page = new Page;
995994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    page->mData = malloc(mPageSize);
1005994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    page->mSize = 0;
1015994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1025994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    return page;
1035994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
1045994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1055994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubervoid PageCache::releasePage(Page *page) {
1065994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    page->mSize = 0;
1075994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mFreePages.push_back(page);
1085994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
1095994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1105994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubervoid PageCache::appendPage(Page *page) {
1115994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mTotalSize += page->mSize;
1125994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mActivePages.push_back(page);
1135994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
1145994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1155994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubersize_t PageCache::releaseFromStart(size_t maxBytes) {
1165994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    size_t bytesReleased = 0;
1175994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1185994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    while (maxBytes > 0 && !mActivePages.empty()) {
1195994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        List<Page *>::iterator it = mActivePages.begin();
1205994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1215994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        Page *page = *it;
1225994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1235994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        if (maxBytes < page->mSize) {
1245994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber            break;
1255994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        }
1265994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1275994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        mActivePages.erase(it);
1285994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1295994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        maxBytes -= page->mSize;
1305994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        bytesReleased += page->mSize;
1315994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1325994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        releasePage(page);
1335994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
1345994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1355994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mTotalSize -= bytesReleased;
1365994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    return bytesReleased;
1375994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
1385994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1395994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubervoid PageCache::copy(size_t from, void *data, size_t size) {
140a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGV("copy from %zu size %zu", from, size);
1415994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
142310962976d575c0a97ec7a768e9cca0b2361daeaAndreas Huber    if (size == 0) {
143310962976d575c0a97ec7a768e9cca0b2361daeaAndreas Huber        return;
144310962976d575c0a97ec7a768e9cca0b2361daeaAndreas Huber    }
145310962976d575c0a97ec7a768e9cca0b2361daeaAndreas Huber
1465994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    CHECK_LE(from + size, mTotalSize);
1475994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1485994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    size_t offset = 0;
1495994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    List<Page *>::iterator it = mActivePages.begin();
1505994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    while (from >= offset + (*it)->mSize) {
1515994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        offset += (*it)->mSize;
1525994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        ++it;
1535994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
1545994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1555994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    size_t delta = from - offset;
1565994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    size_t avail = (*it)->mSize - delta;
1575994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1585994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    if (avail >= size) {
1595994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        memcpy(data, (const uint8_t *)(*it)->mData + delta, size);
1605994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        return;
1615994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
1625994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1635994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    memcpy(data, (const uint8_t *)(*it)->mData + delta, avail);
1645994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    ++it;
1655994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    data = (uint8_t *)data + avail;
1665994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    size -= avail;
1675994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1685994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    while (size > 0) {
1695994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        size_t copy = (*it)->mSize;
1705994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        if (copy > size) {
1715994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber            copy = size;
1725994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        }
1735994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        memcpy(data, (*it)->mData, copy);
1745994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        data = (uint8_t *)data + copy;
1755994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        size -= copy;
1765994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        ++it;
1775994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
1785994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
1795994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1805994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber////////////////////////////////////////////////////////////////////////////////
1815994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
18249c59815369616b0fd5451ccabd377e8fe1dc3faAndreas HuberNuCachedSource2::NuCachedSource2(
18349c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber        const sp<DataSource> &source,
18449c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber        const char *cacheConfig,
18549c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber        bool disconnectAtHighwatermark)
1865994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    : mSource(source),
1875994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber      mReflector(new AHandlerReflector<NuCachedSource2>(this)),
1885994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber      mLooper(new ALooper),
1895994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber      mCache(new PageCache(kPageSize)),
1905994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber      mCacheOffset(0),
1915994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber      mFinalStatus(OK),
1925994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber      mLastAccessPos(0),
193a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber      mFetching(true),
19448296b792a8d68358de74141fa80bd5bd84d0307Chong Zhang      mDisconnecting(false),
1950683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber      mLastFetchTimeUs(-1),
196a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber      mNumRetriesLeft(kMaxNumRetries),
197a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber      mHighwaterThresholdBytes(kDefaultHighWaterThreshold),
198a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber      mLowwaterThresholdBytes(kDefaultLowWaterThreshold),
19949c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber      mKeepAliveIntervalUs(kDefaultKeepAliveIntervalUs),
20049c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber      mDisconnectAtHighwatermark(disconnectAtHighwatermark) {
20149c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber    // We are NOT going to support disconnect-at-highwatermark indefinitely
20249c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber    // and we are not guaranteeing support for client-specified cache
20349c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber    // parameters. Both of these are temporary measures to solve a specific
20449c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber    // problem that will be solved in a better way going forward.
20549c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber
206a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber    updateCacheParamsFromSystemProperty();
207a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber
20849c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber    if (cacheConfig != NULL) {
20949c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber        updateCacheParamsFromString(cacheConfig);
21049c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber    }
21149c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber
21249c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber    if (mDisconnectAtHighwatermark) {
21349c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber        // Makes no sense to disconnect and do keep-alives...
21449c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber        mKeepAliveIntervalUs = 0;
21549c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber    }
21649c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber
217a814c1fdc2acf0ed2ee3b175110f6039be7c4873Andreas Huber    mLooper->setName("NuCachedSource2");
2185994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mLooper->registerHandler(mReflector);
2191b86fe063badb5f28c467ade39be0f4008688947Andreas Huber
2201b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    // Since it may not be obvious why our looper thread needs to be
2211b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    // able to call into java since it doesn't appear to do so at all...
2221b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    // IMediaHTTPConnection may be (and most likely is) implemented in JAVA
2231b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    // and a local JAVA IBinder will call directly into JNI methods.
2241b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    // So whenever we call DataSource::readAt it may end up in a call to
2251b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    // IMediaHTTPConnection::readAt and therefore call back into JAVA.
2261b86fe063badb5f28c467ade39be0f4008688947Andreas Huber    mLooper->start(false /* runOnCallingThread */, true /* canCallJava */);
22769d3d8a9540b0da787ea0beccad2517f057dd54dMarco Nelissen
22869d3d8a9540b0da787ea0beccad2517f057dd54dMarco Nelissen    mName = String8::format("NuCachedSource2(%s)", mSource->toString().string());
2295994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
2305994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
2315994b4798b01f3dd340577c9ea9657f09093a770Andreas HuberNuCachedSource2::~NuCachedSource2() {
2325994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mLooper->stop();
2335994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mLooper->unregisterHandler(mReflector->id());
2345994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
2355994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    delete mCache;
2365994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mCache = NULL;
2375994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
2385994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
239316c3d929ffb004b0150d515e82aede02208ce97Wonsik Kim// static
240316c3d929ffb004b0150d515e82aede02208ce97Wonsik Kimsp<NuCachedSource2> NuCachedSource2::Create(
241316c3d929ffb004b0150d515e82aede02208ce97Wonsik Kim        const sp<DataSource> &source,
242316c3d929ffb004b0150d515e82aede02208ce97Wonsik Kim        const char *cacheConfig,
243316c3d929ffb004b0150d515e82aede02208ce97Wonsik Kim        bool disconnectAtHighwatermark) {
244316c3d929ffb004b0150d515e82aede02208ce97Wonsik Kim    sp<NuCachedSource2> instance = new NuCachedSource2(
245316c3d929ffb004b0150d515e82aede02208ce97Wonsik Kim            source, cacheConfig, disconnectAtHighwatermark);
246316c3d929ffb004b0150d515e82aede02208ce97Wonsik Kim    Mutex::Autolock autoLock(instance->mLock);
247316c3d929ffb004b0150d515e82aede02208ce97Wonsik Kim    (new AMessage(kWhatFetchMore, instance->mReflector))->post();
248316c3d929ffb004b0150d515e82aede02208ce97Wonsik Kim    return instance;
249316c3d929ffb004b0150d515e82aede02208ce97Wonsik Kim}
250316c3d929ffb004b0150d515e82aede02208ce97Wonsik Kim
2515b1b8a93a07326f1cbc627f09e02988375189e0aJames Dongstatus_t NuCachedSource2::getEstimatedBandwidthKbps(int32_t *kbps) {
252b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong    if (mSource->flags() & kIsHTTPBasedSource) {
253b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong        HTTPBase* source = static_cast<HTTPBase *>(mSource.get());
254b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong        return source->getEstimatedBandwidthKbps(kbps);
255b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong    }
256b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong    return ERROR_UNSUPPORTED;
2575b1b8a93a07326f1cbc627f09e02988375189e0aJames Dong}
2585b1b8a93a07326f1cbc627f09e02988375189e0aJames Dong
25948296b792a8d68358de74141fa80bd5bd84d0307Chong Zhangvoid NuCachedSource2::disconnect() {
26048296b792a8d68358de74141fa80bd5bd84d0307Chong Zhang    if (mSource->flags() & kIsHTTPBasedSource) {
26148296b792a8d68358de74141fa80bd5bd84d0307Chong Zhang        ALOGV("disconnecting HTTPBasedSource");
26248296b792a8d68358de74141fa80bd5bd84d0307Chong Zhang
26348296b792a8d68358de74141fa80bd5bd84d0307Chong Zhang        {
26448296b792a8d68358de74141fa80bd5bd84d0307Chong Zhang            Mutex::Autolock autoLock(mLock);
26548296b792a8d68358de74141fa80bd5bd84d0307Chong Zhang            // set mDisconnecting to true, if a fetch returns after
26648296b792a8d68358de74141fa80bd5bd84d0307Chong Zhang            // this, the source will be marked as EOS.
26748296b792a8d68358de74141fa80bd5bd84d0307Chong Zhang            mDisconnecting = true;
2689f3d1cffe3bbec35c1fb7fc7e206428728ac234eChong Zhang
2699f3d1cffe3bbec35c1fb7fc7e206428728ac234eChong Zhang            // explicitly signal mCondition so that the pending readAt()
2709f3d1cffe3bbec35c1fb7fc7e206428728ac234eChong Zhang            // will immediately return
2719f3d1cffe3bbec35c1fb7fc7e206428728ac234eChong Zhang            mCondition.signal();
27248296b792a8d68358de74141fa80bd5bd84d0307Chong Zhang        }
27348296b792a8d68358de74141fa80bd5bd84d0307Chong Zhang
27448296b792a8d68358de74141fa80bd5bd84d0307Chong Zhang        // explicitly disconnect from the source, to allow any
27548296b792a8d68358de74141fa80bd5bd84d0307Chong Zhang        // pending reads to return more promptly
27648296b792a8d68358de74141fa80bd5bd84d0307Chong Zhang        static_cast<HTTPBase *>(mSource.get())->disconnect();
27748296b792a8d68358de74141fa80bd5bd84d0307Chong Zhang    }
27848296b792a8d68358de74141fa80bd5bd84d0307Chong Zhang}
27948296b792a8d68358de74141fa80bd5bd84d0307Chong Zhang
2805b1b8a93a07326f1cbc627f09e02988375189e0aJames Dongstatus_t NuCachedSource2::setCacheStatCollectFreq(int32_t freqMs) {
281b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong    if (mSource->flags() & kIsHTTPBasedSource) {
282b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong        HTTPBase *source = static_cast<HTTPBase *>(mSource.get());
283b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong        return source->setBandwidthStatCollectFreq(freqMs);
284b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong    }
285b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong    return ERROR_UNSUPPORTED;
2865b1b8a93a07326f1cbc627f09e02988375189e0aJames Dong}
2875b1b8a93a07326f1cbc627f09e02988375189e0aJames Dong
2885994b4798b01f3dd340577c9ea9657f09093a770Andreas Huberstatus_t NuCachedSource2::initCheck() const {
2895994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    return mSource->initCheck();
2905994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
2915994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
292c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t NuCachedSource2::getSize(off64_t *size) {
2935994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    return mSource->getSize(size);
2945994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
2955994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
2965994b4798b01f3dd340577c9ea9657f09093a770Andreas Huberuint32_t NuCachedSource2::flags() {
297b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong    // Remove HTTP related flags since NuCachedSource2 is not HTTP-based.
298b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong    uint32_t flags = mSource->flags() & ~(kWantsPrefetching | kIsHTTPBasedSource);
299b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong    return (flags | kIsCachingDataSource);
3005994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
3015994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
3025994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubervoid NuCachedSource2::onMessageReceived(const sp<AMessage> &msg) {
3035994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    switch (msg->what()) {
3045994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        case kWhatFetchMore:
3055994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        {
3065994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber            onFetch();
3075994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber            break;
3085994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        }
3095994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
3105994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        case kWhatRead:
3115994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        {
3125994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber            onRead(msg);
3135994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber            break;
3145994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        }
3155994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
3165994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        default:
3175994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber            TRESPASS();
3185994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
3195994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
3205994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
3215994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubervoid NuCachedSource2::fetchInternal() {
3223856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("fetchInternal");
3235994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
32495c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber    bool reconnect = false;
32595c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber
3260683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber    {
3270683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        Mutex::Autolock autoLock(mLock);
3280683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        CHECK(mFinalStatus == OK || mNumRetriesLeft > 0);
3290683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber
3300683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        if (mFinalStatus != OK) {
3310683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber            --mNumRetriesLeft;
3320683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber
33395c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber            reconnect = true;
33495c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber        }
33595c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber    }
33695c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber
33795c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber    if (reconnect) {
33895c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber        status_t err =
33995c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber            mSource->reconnectAtOffset(mCacheOffset + mCache->totalSize());
34095c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber
34195c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber        Mutex::Autolock autoLock(mLock);
3420683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber
3439f3d1cffe3bbec35c1fb7fc7e206428728ac234eChong Zhang        if (mDisconnecting) {
3449f3d1cffe3bbec35c1fb7fc7e206428728ac234eChong Zhang            mNumRetriesLeft = 0;
3459f3d1cffe3bbec35c1fb7fc7e206428728ac234eChong Zhang            mFinalStatus = ERROR_END_OF_STREAM;
3469f3d1cffe3bbec35c1fb7fc7e206428728ac234eChong Zhang            return;
3479f3d1cffe3bbec35c1fb7fc7e206428728ac234eChong Zhang        } else if (err == ERROR_UNSUPPORTED || err == -EPIPE) {
348a7607a7f97b3136d5e61c0bca63760bf9fc05b19Andreas Huber            // These are errors that are not likely to go away even if we
349a7607a7f97b3136d5e61c0bca63760bf9fc05b19Andreas Huber            // retry, i.e. the server doesn't support range requests or similar.
35095c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber            mNumRetriesLeft = 0;
35195c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber            return;
35295c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber        } else if (err != OK) {
353df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block            ALOGI("The attempt to reconnect failed, %d retries remaining",
35495c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber                 mNumRetriesLeft);
3550683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber
35695c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber            return;
3570683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        }
3580683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber    }
3595994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
3605994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    PageCache::Page *page = mCache->acquirePage();
3615994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
3625994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    ssize_t n = mSource->readAt(
3635994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber            mCacheOffset + mCache->totalSize(), page->mData, kPageSize);
3645994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
3655994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    Mutex::Autolock autoLock(mLock);
3665994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
36748296b792a8d68358de74141fa80bd5bd84d0307Chong Zhang    if (n == 0 || mDisconnecting) {
368efbb61950db36a5eb789be83f077246172507c67Chong Zhang        ALOGI("caching reached eos.");
36948296b792a8d68358de74141fa80bd5bd84d0307Chong Zhang
37048296b792a8d68358de74141fa80bd5bd84d0307Chong Zhang        mNumRetriesLeft = 0;
37148296b792a8d68358de74141fa80bd5bd84d0307Chong Zhang        mFinalStatus = ERROR_END_OF_STREAM;
37248296b792a8d68358de74141fa80bd5bd84d0307Chong Zhang
37348296b792a8d68358de74141fa80bd5bd84d0307Chong Zhang        mCache->releasePage(page);
37448296b792a8d68358de74141fa80bd5bd84d0307Chong Zhang    } else if (n < 0) {
3755994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        mFinalStatus = n;
376a7607a7f97b3136d5e61c0bca63760bf9fc05b19Andreas Huber        if (n == ERROR_UNSUPPORTED || n == -EPIPE) {
377a7607a7f97b3136d5e61c0bca63760bf9fc05b19Andreas Huber            // These are errors that are not likely to go away even if we
378a7607a7f97b3136d5e61c0bca63760bf9fc05b19Andreas Huber            // retry, i.e. the server doesn't support range requests or similar.
379a7607a7f97b3136d5e61c0bca63760bf9fc05b19Andreas Huber            mNumRetriesLeft = 0;
380a7607a7f97b3136d5e61c0bca63760bf9fc05b19Andreas Huber        }
381a7607a7f97b3136d5e61c0bca63760bf9fc05b19Andreas Huber
382a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn        ALOGE("source returned error %zd, %d retries left", n, mNumRetriesLeft);
3835994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        mCache->releasePage(page);
3845994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    } else {
3850683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        if (mFinalStatus != OK) {
386df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block            ALOGI("retrying a previously failed read succeeded.");
3870683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        }
3880683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        mNumRetriesLeft = kMaxNumRetries;
3890683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        mFinalStatus = OK;
3900683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber
3915994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        page->mSize = n;
3925994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        mCache->appendPage(page);
3935994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
3945994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
3955994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
3965994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubervoid NuCachedSource2::onFetch() {
3973856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("onFetch");
3985994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
3990683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber    if (mFinalStatus != OK && mNumRetriesLeft == 0) {
4003856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("EOS reached, done prefetching for now");
4015994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        mFetching = false;
4025994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
4035994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
404a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber    bool keepAlive =
405a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber        !mFetching
406a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber            && mFinalStatus == OK
407a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber            && mKeepAliveIntervalUs > 0
408a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber            && ALooper::GetNowUs() >= mLastFetchTimeUs + mKeepAliveIntervalUs;
409a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber
410a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber    if (mFetching || keepAlive) {
411a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber        if (keepAlive) {
412df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block            ALOGI("Keep alive");
413a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber        }
414a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber
4155994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        fetchInternal();
4165994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
417a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber        mLastFetchTimeUs = ALooper::GetNowUs();
418a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber
419a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber        if (mFetching && mCache->totalSize() >= mHighwaterThresholdBytes) {
420df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block            ALOGI("Cache full, done prefetching for now");
4215994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber            mFetching = false;
42249c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber
42349c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber            if (mDisconnectAtHighwatermark
42449c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber                    && (mSource->flags() & DataSource::kIsHTTPBasedSource)) {
4253856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("Disconnecting at high watermark");
42649c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber                static_cast<HTTPBase *>(mSource.get())->disconnect();
42740a4e1440869b2e3981f261b0d301cd16c0cf0aaBryan Mawhinney                mFinalStatus = -EAGAIN;
42849c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber            }
4295994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        }
430a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
431d17875a226491e3de60fa32d764a4cc92de7f949Andreas Huber        Mutex::Autolock autoLock(mLock);
4325994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        restartPrefetcherIfNecessary_l();
4335994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
4345994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4350683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber    int64_t delayUs;
4360683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber    if (mFetching) {
4370683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        if (mFinalStatus != OK && mNumRetriesLeft > 0) {
4380683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber            // We failed this time and will try again in 3 seconds.
4390683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber            delayUs = 3000000ll;
4400683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        } else {
4410683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber            delayUs = 0;
4420683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        }
4430683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber    } else {
4440683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        delayUs = 100000ll;
4450683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber    }
4460683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber
4471d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatFetchMore, mReflector))->post(delayUs);
4485994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
4495994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4505994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubervoid NuCachedSource2::onRead(const sp<AMessage> &msg) {
4513856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("onRead");
4525994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4535994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    int64_t offset;
4545994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    CHECK(msg->findInt64("offset", &offset));
4555994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4565994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    void *data;
4575994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    CHECK(msg->findPointer("data", &data));
4585994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4595994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    size_t size;
4605994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    CHECK(msg->findSize("size", &size));
4615994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4625994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    ssize_t result = readInternal(offset, data, size);
4635994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4645994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    if (result == -EAGAIN) {
4655994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        msg->post(50000);
4665994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        return;
4675994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
4685994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4695994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    Mutex::Autolock autoLock(mLock);
4704f17dadd3cfd9940893ea042ca8883c6aa6ada07Robert Shih    if (mDisconnecting) {
4714f17dadd3cfd9940893ea042ca8883c6aa6ada07Robert Shih        mCondition.signal();
4724f17dadd3cfd9940893ea042ca8883c6aa6ada07Robert Shih        return;
4734f17dadd3cfd9940893ea042ca8883c6aa6ada07Robert Shih    }
4745994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4755994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    CHECK(mAsyncResult == NULL);
4765994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4775994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mAsyncResult = new AMessage;
4785994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mAsyncResult->setInt32("result", result);
4795994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4805994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mCondition.signal();
4815994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
4825994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
48334ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Hubervoid NuCachedSource2::restartPrefetcherIfNecessary_l(
4847bf8413f91fc072452f315a91618aeef2574d420Andreas Huber        bool ignoreLowWaterThreshold, bool force) {
4856ee94582e3ce7bdd9625345e7564e3176a51a2f3James Dong    static const size_t kGrayArea = 1024 * 1024;
4865994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4870683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber    if (mFetching || (mFinalStatus != OK && mNumRetriesLeft == 0)) {
4885994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        return;
4895994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
4905994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4917bf8413f91fc072452f315a91618aeef2574d420Andreas Huber    if (!ignoreLowWaterThreshold && !force
49234ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber            && mCacheOffset + mCache->totalSize() - mLastAccessPos
493a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber                >= mLowwaterThresholdBytes) {
4945994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        return;
4955994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
4965994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4975994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    size_t maxBytes = mLastAccessPos - mCacheOffset;
4985994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4997bf8413f91fc072452f315a91618aeef2574d420Andreas Huber    if (!force) {
5007bf8413f91fc072452f315a91618aeef2574d420Andreas Huber        if (maxBytes < kGrayArea) {
5017bf8413f91fc072452f315a91618aeef2574d420Andreas Huber            return;
5027bf8413f91fc072452f315a91618aeef2574d420Andreas Huber        }
5037bf8413f91fc072452f315a91618aeef2574d420Andreas Huber
5047bf8413f91fc072452f315a91618aeef2574d420Andreas Huber        maxBytes -= kGrayArea;
5057bf8413f91fc072452f315a91618aeef2574d420Andreas Huber    }
5065994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5075994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    size_t actualBytes = mCache->releaseFromStart(maxBytes);
5085994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mCacheOffset += actualBytes;
5095994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
510a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn    ALOGI("restarting prefetcher, totalSize = %zu", mCache->totalSize());
5115994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mFetching = true;
5125994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
5135994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
514c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongssize_t NuCachedSource2::readAt(off64_t offset, void *data, size_t size) {
5155994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    Mutex::Autolock autoSerializer(mSerializer);
5165994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
517ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar    ALOGV("readAt offset %lld, size %zu", (long long)offset, size);
5185994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5195994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    Mutex::Autolock autoLock(mLock);
5204f17dadd3cfd9940893ea042ca8883c6aa6ada07Robert Shih    if (mDisconnecting) {
5214f17dadd3cfd9940893ea042ca8883c6aa6ada07Robert Shih        return ERROR_END_OF_STREAM;
5224f17dadd3cfd9940893ea042ca8883c6aa6ada07Robert Shih    }
5235994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5245994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    // If the request can be completely satisfied from the cache, do so.
5255994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5265994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    if (offset >= mCacheOffset
5275994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber            && offset + size <= mCacheOffset + mCache->totalSize()) {
5285994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        size_t delta = offset - mCacheOffset;
5295994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        mCache->copy(delta, data, size);
5305994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5315994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        mLastAccessPos = offset + size;
5325994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5335994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        return size;
5345994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
5355994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5361d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatRead, mReflector);
5375994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    msg->setInt64("offset", offset);
5385994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    msg->setPointer("data", data);
5395994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    msg->setSize("size", size);
5405994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5415994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    CHECK(mAsyncResult == NULL);
5425994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    msg->post();
5435994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5449f3d1cffe3bbec35c1fb7fc7e206428728ac234eChong Zhang    while (mAsyncResult == NULL && !mDisconnecting) {
5455994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        mCondition.wait(mLock);
5465994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
5475994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5489f3d1cffe3bbec35c1fb7fc7e206428728ac234eChong Zhang    if (mDisconnecting) {
5494f17dadd3cfd9940893ea042ca8883c6aa6ada07Robert Shih        mAsyncResult.clear();
5509f3d1cffe3bbec35c1fb7fc7e206428728ac234eChong Zhang        return ERROR_END_OF_STREAM;
5519f3d1cffe3bbec35c1fb7fc7e206428728ac234eChong Zhang    }
5529f3d1cffe3bbec35c1fb7fc7e206428728ac234eChong Zhang
5535994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    int32_t result;
5545994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    CHECK(mAsyncResult->findInt32("result", &result));
5555994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5565994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mAsyncResult.clear();
5575994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5585994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    if (result > 0) {
5595994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        mLastAccessPos = offset + result;
5605994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
5615994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5625994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    return (ssize_t)result;
5635994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
5645994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5655994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubersize_t NuCachedSource2::cachedSize() {
5665994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    Mutex::Autolock autoLock(mLock);
5675994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    return mCacheOffset + mCache->totalSize();
5685994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
5695994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
570a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Hubersize_t NuCachedSource2::approxDataRemaining(status_t *finalStatus) const {
5715994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    Mutex::Autolock autoLock(mLock);
5721bd233ce7e1aa7730bc18d46ffd57791391738cdBryan Mawhinney    return approxDataRemaining_l(finalStatus);
5735994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
5745994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
575a53d87c7b1428fe02f535c31dafd64cb1362fde9Andreas Hubersize_t NuCachedSource2::approxDataRemaining_l(status_t *finalStatus) const {
5761bd233ce7e1aa7730bc18d46ffd57791391738cdBryan Mawhinney    *finalStatus = mFinalStatus;
5770683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber
5780683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber    if (mFinalStatus != OK && mNumRetriesLeft > 0) {
5790683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        // Pretend that everything is fine until we're out of retries.
5800683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        *finalStatus = OK;
5810683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber    }
5820683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber
583c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t lastBytePosCached = mCacheOffset + mCache->totalSize();
5845994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    if (mLastAccessPos < lastBytePosCached) {
5855994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        return lastBytePosCached - mLastAccessPos;
5865994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
5875994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    return 0;
5885994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
5895994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
590c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongssize_t NuCachedSource2::readInternal(off64_t offset, void *data, size_t size) {
591a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber    CHECK_LE(size, (size_t)mHighwaterThresholdBytes);
5927bf8413f91fc072452f315a91618aeef2574d420Andreas Huber
593ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar    ALOGV("readInternal offset %lld size %zu", (long long)offset, size);
5945994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5955994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    Mutex::Autolock autoLock(mLock);
5965994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5972c878cfdf36b896abb99e62a37188cc92cd4fe6eChong Zhang    // If we're disconnecting, return EOS and don't access *data pointer.
5982c878cfdf36b896abb99e62a37188cc92cd4fe6eChong Zhang    // data could be on the stack of the caller to NuCachedSource2::readAt(),
5992c878cfdf36b896abb99e62a37188cc92cd4fe6eChong Zhang    // which may have exited already.
6002c878cfdf36b896abb99e62a37188cc92cd4fe6eChong Zhang    if (mDisconnecting) {
6012c878cfdf36b896abb99e62a37188cc92cd4fe6eChong Zhang        return ERROR_END_OF_STREAM;
6022c878cfdf36b896abb99e62a37188cc92cd4fe6eChong Zhang    }
6032c878cfdf36b896abb99e62a37188cc92cd4fe6eChong Zhang
6047bf8413f91fc072452f315a91618aeef2574d420Andreas Huber    if (!mFetching) {
6057bf8413f91fc072452f315a91618aeef2574d420Andreas Huber        mLastAccessPos = offset;
6067bf8413f91fc072452f315a91618aeef2574d420Andreas Huber        restartPrefetcherIfNecessary_l(
6077bf8413f91fc072452f315a91618aeef2574d420Andreas Huber                false, // ignoreLowWaterThreshold
6087bf8413f91fc072452f315a91618aeef2574d420Andreas Huber                true); // force
6097bf8413f91fc072452f315a91618aeef2574d420Andreas Huber    }
6107bf8413f91fc072452f315a91618aeef2574d420Andreas Huber
6115994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    if (offset < mCacheOffset
612c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            || offset >= (off64_t)(mCacheOffset + mCache->totalSize())) {
6136ee94582e3ce7bdd9625345e7564e3176a51a2f3James Dong        static const off64_t kPadding = 256 * 1024;
6145994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
6155994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        // In the presence of multiple decoded streams, once of them will
6165994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        // trigger this seek request, the other one will request data "nearby"
6175994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        // soon, adjust the seek position so that that subsequent request
6185994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        // does not trigger another seek.
619c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t seekOffset = (offset > kPadding) ? offset - kPadding : 0;
6205994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
6215994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        seekInternal_l(seekOffset);
6225994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
6235994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
6245994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    size_t delta = offset - mCacheOffset;
6255994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
62640a4e1440869b2e3981f261b0d301cd16c0cf0aaBryan Mawhinney    if (mFinalStatus != OK && mNumRetriesLeft == 0) {
6275994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        if (delta >= mCache->totalSize()) {
6285994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber            return mFinalStatus;
6295994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        }
6305994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
6316f5aae1bcba130d5b8092a19fca3627aa565df56Andreas Huber        size_t avail = mCache->totalSize() - delta;
63267802977b6f0aa8d6f14f85dadcf32a3cadb9c07Andreas Huber
63367802977b6f0aa8d6f14f85dadcf32a3cadb9c07Andreas Huber        if (avail > size) {
63467802977b6f0aa8d6f14f85dadcf32a3cadb9c07Andreas Huber            avail = size;
63567802977b6f0aa8d6f14f85dadcf32a3cadb9c07Andreas Huber        }
63667802977b6f0aa8d6f14f85dadcf32a3cadb9c07Andreas Huber
6375994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        mCache->copy(delta, data, avail);
6385994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
6395994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        return avail;
6405994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
6415994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
6425994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    if (offset + size <= mCacheOffset + mCache->totalSize()) {
6435994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        mCache->copy(delta, data, size);
6445994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
6455994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        return size;
6465994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
6475994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
6483856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("deferring read");
6495994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
6505994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    return -EAGAIN;
6515994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
6525994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
653c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t NuCachedSource2::seekInternal_l(off64_t offset) {
6545994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mLastAccessPos = offset;
6555994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
6565994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    if (offset >= mCacheOffset
657c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            && offset <= (off64_t)(mCacheOffset + mCache->totalSize())) {
6585994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        return OK;
6595994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
6605994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
661ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar    ALOGI("new range: offset= %lld", (long long)offset);
6625994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
6635994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mCacheOffset = offset;
6645994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
6655994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    size_t totalSize = mCache->totalSize();
6665994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    CHECK_EQ(mCache->releaseFromStart(totalSize), totalSize);
6675994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
66840a4e1440869b2e3981f261b0d301cd16c0cf0aaBryan Mawhinney    mNumRetriesLeft = kMaxNumRetries;
6695994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mFetching = true;
6705994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
6715994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    return OK;
6725994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
6735994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
67434ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Hubervoid NuCachedSource2::resumeFetchingIfNecessary() {
67534ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber    Mutex::Autolock autoLock(mLock);
67634ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber
67734ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber    restartPrefetcherIfNecessary_l(true /* ignore low water threshold */);
67834ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber}
67934ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber
6809d2f386dd2885eaffa11fd494ae258bb09fe6397James Dongsp<DecryptHandle> NuCachedSource2::DrmInitialization(const char* mime) {
6819d2f386dd2885eaffa11fd494ae258bb09fe6397James Dong    return mSource->DrmInitialization(mime);
682b371426ce4cf2fa6d8c3d1903b61322feb165d35Gloria Wang}
683b371426ce4cf2fa6d8c3d1903b61322feb165d35Gloria Wang
684b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wangvoid NuCachedSource2::getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client) {
685b371426ce4cf2fa6d8c3d1903b61322feb165d35Gloria Wang    mSource->getDrmInfo(handle, client);
686b371426ce4cf2fa6d8c3d1903b61322feb165d35Gloria Wang}
687b371426ce4cf2fa6d8c3d1903b61322feb165d35Gloria Wang
688771b85d9245a24273497792a2515d88d31c99e1eGloria WangString8 NuCachedSource2::getUri() {
689771b85d9245a24273497792a2515d88d31c99e1eGloria Wang    return mSource->getUri();
690771b85d9245a24273497792a2515d88d31c99e1eGloria Wang}
691ac05c317cd818701535c5d72ce90da98c4bae75bAndreas Huber
6926511c9755c3a3360ba869772600c7aae048a7ffcAndreas HuberString8 NuCachedSource2::getMIMEType() const {
6936511c9755c3a3360ba869772600c7aae048a7ffcAndreas Huber    return mSource->getMIMEType();
6946511c9755c3a3360ba869772600c7aae048a7ffcAndreas Huber}
6956511c9755c3a3360ba869772600c7aae048a7ffcAndreas Huber
696a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Hubervoid NuCachedSource2::updateCacheParamsFromSystemProperty() {
697a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber    char value[PROPERTY_VALUE_MAX];
698a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber    if (!property_get("media.stagefright.cache-params", value, NULL)) {
699a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber        return;
700a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber    }
701a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber
702a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber    updateCacheParamsFromString(value);
703a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber}
704a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber
705a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Hubervoid NuCachedSource2::updateCacheParamsFromString(const char *s) {
706a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber    ssize_t lowwaterMarkKb, highwaterMarkKb;
7070b8cd8b0cf1489f8f7c0b2c4d7ea8fea70ca93a1Andreas Huber    int keepAliveSecs;
708a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber
709db43b34c3428e480f8c4c66e7e88f4001f37f91eMark Salyzyn    if (sscanf(s, "%zd/%zd/%d",
7100b8cd8b0cf1489f8f7c0b2c4d7ea8fea70ca93a1Andreas Huber               &lowwaterMarkKb, &highwaterMarkKb, &keepAliveSecs) != 3) {
71129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Failed to parse cache parameters from '%s'.", s);
712a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber        return;
713a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber    }
714a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber
715a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber    if (lowwaterMarkKb >= 0) {
716a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber        mLowwaterThresholdBytes = lowwaterMarkKb * 1024;
717a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber    } else {
718a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber        mLowwaterThresholdBytes = kDefaultLowWaterThreshold;
719a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber    }
720a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber
721a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber    if (highwaterMarkKb >= 0) {
722a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber        mHighwaterThresholdBytes = highwaterMarkKb * 1024;
723a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber    } else {
724a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber        mHighwaterThresholdBytes = kDefaultHighWaterThreshold;
725a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber    }
726a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber
7270b8cd8b0cf1489f8f7c0b2c4d7ea8fea70ca93a1Andreas Huber    if (mLowwaterThresholdBytes >= mHighwaterThresholdBytes) {
72829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Illegal low/highwater marks specified, reverting to defaults.");
7290b8cd8b0cf1489f8f7c0b2c4d7ea8fea70ca93a1Andreas Huber
7300b8cd8b0cf1489f8f7c0b2c4d7ea8fea70ca93a1Andreas Huber        mLowwaterThresholdBytes = kDefaultLowWaterThreshold;
7310b8cd8b0cf1489f8f7c0b2c4d7ea8fea70ca93a1Andreas Huber        mHighwaterThresholdBytes = kDefaultHighWaterThreshold;
7320b8cd8b0cf1489f8f7c0b2c4d7ea8fea70ca93a1Andreas Huber    }
7330b8cd8b0cf1489f8f7c0b2c4d7ea8fea70ca93a1Andreas Huber
7340b8cd8b0cf1489f8f7c0b2c4d7ea8fea70ca93a1Andreas Huber    if (keepAliveSecs >= 0) {
7350b8cd8b0cf1489f8f7c0b2c4d7ea8fea70ca93a1Andreas Huber        mKeepAliveIntervalUs = keepAliveSecs * 1000000ll;
7360b8cd8b0cf1489f8f7c0b2c4d7ea8fea70ca93a1Andreas Huber    } else {
7370b8cd8b0cf1489f8f7c0b2c4d7ea8fea70ca93a1Andreas Huber        mKeepAliveIntervalUs = kDefaultKeepAliveIntervalUs;
7380b8cd8b0cf1489f8f7c0b2c4d7ea8fea70ca93a1Andreas Huber    }
739a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber
740ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar    ALOGV("lowwater = %zu bytes, highwater = %zu bytes, keepalive = %lld us",
741a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber         mLowwaterThresholdBytes,
742a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber         mHighwaterThresholdBytes,
743ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar         (long long)mKeepAliveIntervalUs);
744a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber}
745a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber
74649c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber// static
74749c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Hubervoid NuCachedSource2::RemoveCacheSpecificHeaders(
74849c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber        KeyedVector<String8, String8> *headers,
74949c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber        String8 *cacheConfig,
75049c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber        bool *disconnectAtHighwatermark) {
75149c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber    *cacheConfig = String8();
75249c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber    *disconnectAtHighwatermark = false;
75349c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber
75449c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber    if (headers == NULL) {
75549c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber        return;
75649c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber    }
75749c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber
75849c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber    ssize_t index;
75949c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber    if ((index = headers->indexOfKey(String8("x-cache-config"))) >= 0) {
76049c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber        *cacheConfig = headers->valueAt(index);
76149c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber
76249c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber        headers->removeItemsAt(index);
76349c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber
7643856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Using special cache config '%s'", cacheConfig->string());
76549c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber    }
76649c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber
76749c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber    if ((index = headers->indexOfKey(
76849c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber                    String8("x-disconnect-at-highwatermark"))) >= 0) {
76949c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber        *disconnectAtHighwatermark = true;
77049c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber        headers->removeItemsAt(index);
77149c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber
7723856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Client requested disconnection at highwater mark");
77349c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber    }
77449c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber}
77549c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber
7765994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}  // namespace android
777