NuCachedSource2.cpp revision 0683eba6b35c396c21f10e926709f2f8fc05f090
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
17ac05c317cd818701535c5d72ce90da98c4bae75bAndreas Huber//#define LOG_NDEBUG 0
185994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber#define LOG_TAG "NuCachedSource2"
195994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber#include <utils/Log.h>
205994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
215994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber#include "include/NuCachedSource2.h"
225b1b8a93a07326f1cbc627f09e02988375189e0aJames Dong#include "include/HTTPBase.h"
235994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
245994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber#include <media/stagefright/foundation/ADebug.h>
255994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber#include <media/stagefright/foundation/AMessage.h>
265994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber#include <media/stagefright/MediaErrors.h>
275994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
285994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubernamespace android {
295994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
305994b4798b01f3dd340577c9ea9657f09093a770Andreas Huberstruct PageCache {
315994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    PageCache(size_t pageSize);
325994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    ~PageCache();
335994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
345994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    struct Page {
355994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        void *mData;
365994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        size_t mSize;
375994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    };
385994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
395994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    Page *acquirePage();
405994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    void releasePage(Page *page);
415994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
425994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    void appendPage(Page *page);
435994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    size_t releaseFromStart(size_t maxBytes);
445994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
455994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    size_t totalSize() const {
465994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        return mTotalSize;
475994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
485994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
495994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    void copy(size_t from, void *data, size_t size);
505994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
515994b4798b01f3dd340577c9ea9657f09093a770Andreas Huberprivate:
525994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    size_t mPageSize;
535994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    size_t mTotalSize;
545994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
555994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    List<Page *> mActivePages;
565994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    List<Page *> mFreePages;
575994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
585994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    void freePages(List<Page *> *list);
595994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
605994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    DISALLOW_EVIL_CONSTRUCTORS(PageCache);
615994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber};
625994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
635994b4798b01f3dd340577c9ea9657f09093a770Andreas HuberPageCache::PageCache(size_t pageSize)
645994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    : mPageSize(pageSize),
655994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber      mTotalSize(0) {
665994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
675994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
685994b4798b01f3dd340577c9ea9657f09093a770Andreas HuberPageCache::~PageCache() {
695994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    freePages(&mActivePages);
705994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    freePages(&mFreePages);
715994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
725994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
735994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubervoid PageCache::freePages(List<Page *> *list) {
745994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    List<Page *>::iterator it = list->begin();
755994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    while (it != list->end()) {
765994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        Page *page = *it;
775994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
785994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        free(page->mData);
795994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        delete page;
805994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        page = NULL;
815994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
825994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        ++it;
835994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
845994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
855994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
865994b4798b01f3dd340577c9ea9657f09093a770Andreas HuberPageCache::Page *PageCache::acquirePage() {
875994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    if (!mFreePages.empty()) {
885994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        List<Page *>::iterator it = mFreePages.begin();
895994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        Page *page = *it;
905994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        mFreePages.erase(it);
915994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
925994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        return page;
935994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
945994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
955994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    Page *page = new Page;
965994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    page->mData = malloc(mPageSize);
975994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    page->mSize = 0;
985994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
995994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    return page;
1005994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
1015994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1025994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubervoid PageCache::releasePage(Page *page) {
1035994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    page->mSize = 0;
1045994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mFreePages.push_back(page);
1055994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
1065994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1075994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubervoid PageCache::appendPage(Page *page) {
1085994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mTotalSize += page->mSize;
1095994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mActivePages.push_back(page);
1105994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
1115994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1125994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubersize_t PageCache::releaseFromStart(size_t maxBytes) {
1135994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    size_t bytesReleased = 0;
1145994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1155994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    while (maxBytes > 0 && !mActivePages.empty()) {
1165994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        List<Page *>::iterator it = mActivePages.begin();
1175994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1185994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        Page *page = *it;
1195994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1205994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        if (maxBytes < page->mSize) {
1215994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber            break;
1225994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        }
1235994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1245994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        mActivePages.erase(it);
1255994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1265994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        maxBytes -= page->mSize;
1275994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        bytesReleased += page->mSize;
1285994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1295994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        releasePage(page);
1305994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
1315994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1325994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mTotalSize -= bytesReleased;
1335994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    return bytesReleased;
1345994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
1355994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1365994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubervoid PageCache::copy(size_t from, void *data, size_t size) {
1376e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber    LOGV("copy from %d size %d", from, size);
1385994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
139310962976d575c0a97ec7a768e9cca0b2361daeaAndreas Huber    if (size == 0) {
140310962976d575c0a97ec7a768e9cca0b2361daeaAndreas Huber        return;
141310962976d575c0a97ec7a768e9cca0b2361daeaAndreas Huber    }
142310962976d575c0a97ec7a768e9cca0b2361daeaAndreas Huber
1435994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    CHECK_LE(from + size, mTotalSize);
1445994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1455994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    size_t offset = 0;
1465994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    List<Page *>::iterator it = mActivePages.begin();
1475994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    while (from >= offset + (*it)->mSize) {
1485994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        offset += (*it)->mSize;
1495994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        ++it;
1505994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
1515994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1525994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    size_t delta = from - offset;
1535994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    size_t avail = (*it)->mSize - delta;
1545994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1555994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    if (avail >= size) {
1565994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        memcpy(data, (const uint8_t *)(*it)->mData + delta, size);
1575994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        return;
1585994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
1595994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1605994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    memcpy(data, (const uint8_t *)(*it)->mData + delta, avail);
1615994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    ++it;
1625994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    data = (uint8_t *)data + avail;
1635994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    size -= avail;
1645994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1655994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    while (size > 0) {
1665994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        size_t copy = (*it)->mSize;
1675994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        if (copy > size) {
1685994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber            copy = size;
1695994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        }
1705994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        memcpy(data, (*it)->mData, copy);
1715994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        data = (uint8_t *)data + copy;
1725994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        size -= copy;
1735994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        ++it;
1745994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
1755994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
1765994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1775994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber////////////////////////////////////////////////////////////////////////////////
1785994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1795994b4798b01f3dd340577c9ea9657f09093a770Andreas HuberNuCachedSource2::NuCachedSource2(const sp<DataSource> &source)
1805994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    : mSource(source),
1815994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber      mReflector(new AHandlerReflector<NuCachedSource2>(this)),
1825994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber      mLooper(new ALooper),
1835994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber      mCache(new PageCache(kPageSize)),
1845994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber      mCacheOffset(0),
1855994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber      mFinalStatus(OK),
1865994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber      mLastAccessPos(0),
187a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber      mFetching(true),
1880683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber      mLastFetchTimeUs(-1),
1890683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber      mNumRetriesLeft(kMaxNumRetries) {
190a814c1fdc2acf0ed2ee3b175110f6039be7c4873Andreas Huber    mLooper->setName("NuCachedSource2");
1915994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mLooper->registerHandler(mReflector);
1925994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mLooper->start();
1935994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1945994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    Mutex::Autolock autoLock(mLock);
1955994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    (new AMessage(kWhatFetchMore, mReflector->id()))->post();
1965994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
1975994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
1985994b4798b01f3dd340577c9ea9657f09093a770Andreas HuberNuCachedSource2::~NuCachedSource2() {
1995994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mLooper->stop();
2005994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mLooper->unregisterHandler(mReflector->id());
2015994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
2025994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    delete mCache;
2035994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mCache = NULL;
2045994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
2055994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
2065b1b8a93a07326f1cbc627f09e02988375189e0aJames Dongstatus_t NuCachedSource2::getEstimatedBandwidthKbps(int32_t *kbps) {
207b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong    if (mSource->flags() & kIsHTTPBasedSource) {
208b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong        HTTPBase* source = static_cast<HTTPBase *>(mSource.get());
209b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong        return source->getEstimatedBandwidthKbps(kbps);
210b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong    }
211b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong    return ERROR_UNSUPPORTED;
2125b1b8a93a07326f1cbc627f09e02988375189e0aJames Dong}
2135b1b8a93a07326f1cbc627f09e02988375189e0aJames Dong
2145b1b8a93a07326f1cbc627f09e02988375189e0aJames Dongstatus_t NuCachedSource2::setCacheStatCollectFreq(int32_t freqMs) {
215b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong    if (mSource->flags() & kIsHTTPBasedSource) {
216b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong        HTTPBase *source = static_cast<HTTPBase *>(mSource.get());
217b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong        return source->setBandwidthStatCollectFreq(freqMs);
218b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong    }
219b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong    return ERROR_UNSUPPORTED;
2205b1b8a93a07326f1cbc627f09e02988375189e0aJames Dong}
2215b1b8a93a07326f1cbc627f09e02988375189e0aJames Dong
2225994b4798b01f3dd340577c9ea9657f09093a770Andreas Huberstatus_t NuCachedSource2::initCheck() const {
2235994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    return mSource->initCheck();
2245994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
2255994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
226c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t NuCachedSource2::getSize(off64_t *size) {
2275994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    return mSource->getSize(size);
2285994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
2295994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
2305994b4798b01f3dd340577c9ea9657f09093a770Andreas Huberuint32_t NuCachedSource2::flags() {
231b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong    // Remove HTTP related flags since NuCachedSource2 is not HTTP-based.
232b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong    uint32_t flags = mSource->flags() & ~(kWantsPrefetching | kIsHTTPBasedSource);
233b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong    return (flags | kIsCachingDataSource);
2345994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
2355994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
2365994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubervoid NuCachedSource2::onMessageReceived(const sp<AMessage> &msg) {
2375994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    switch (msg->what()) {
2385994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        case kWhatFetchMore:
2395994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        {
2405994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber            onFetch();
2415994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber            break;
2425994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        }
2435994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
2445994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        case kWhatRead:
2455994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        {
2465994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber            onRead(msg);
2475994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber            break;
2485994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        }
2495994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
2505994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        default:
2515994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber            TRESPASS();
2525994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
2535994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
2545994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
2555994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubervoid NuCachedSource2::fetchInternal() {
2566e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber    LOGV("fetchInternal");
2575994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
2580683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber    {
2590683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        Mutex::Autolock autoLock(mLock);
2600683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        CHECK(mFinalStatus == OK || mNumRetriesLeft > 0);
2610683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber
2620683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        if (mFinalStatus != OK) {
2630683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber            --mNumRetriesLeft;
2640683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber
2650683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber            status_t err =
2660683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber                mSource->reconnectAtOffset(mCacheOffset + mCache->totalSize());
2670683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber
2680683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber            if (err == ERROR_UNSUPPORTED) {
2690683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber                mNumRetriesLeft = 0;
2700683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber                return;
2710683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber            } else if (err != OK) {
2720683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber                LOGI("The attempt to reconnect failed, %d retries remaining",
2730683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber                     mNumRetriesLeft);
2740683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber
2750683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber                return;
2760683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber            }
2770683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        }
2780683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber    }
2795994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
2805994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    PageCache::Page *page = mCache->acquirePage();
2815994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
2825994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    ssize_t n = mSource->readAt(
2835994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber            mCacheOffset + mCache->totalSize(), page->mData, kPageSize);
2845994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
2855994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    Mutex::Autolock autoLock(mLock);
2865994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
2875994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    if (n < 0) {
2880683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        LOGE("source returned error %ld, %d retries left", n, mNumRetriesLeft);
2895994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        mFinalStatus = n;
2905994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        mCache->releasePage(page);
2915994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    } else if (n == 0) {
2926e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber        LOGI("ERROR_END_OF_STREAM");
2930683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber
2940683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        mNumRetriesLeft = 0;
2955994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        mFinalStatus = ERROR_END_OF_STREAM;
2960683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber
2975994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        mCache->releasePage(page);
2985994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    } else {
2990683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        if (mFinalStatus != OK) {
3000683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber            LOGI("retrying a previously failed read succeeded.");
3010683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        }
3020683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        mNumRetriesLeft = kMaxNumRetries;
3030683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        mFinalStatus = OK;
3040683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber
3055994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        page->mSize = n;
3065994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        mCache->appendPage(page);
3075994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
3085994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
3095994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
3105994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubervoid NuCachedSource2::onFetch() {
3116e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber    LOGV("onFetch");
3125994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
3130683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber    if (mFinalStatus != OK && mNumRetriesLeft == 0) {
3146e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber        LOGV("EOS reached, done prefetching for now");
3155994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        mFetching = false;
3165994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
3175994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
318a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber    bool keepAlive =
319a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber        !mFetching
320a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber            && mFinalStatus == OK
321a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber            && ALooper::GetNowUs() >= mLastFetchTimeUs + kKeepAliveIntervalUs;
322a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber
323a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber    if (mFetching || keepAlive) {
324a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber        if (keepAlive) {
3256e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber            LOGI("Keep alive");
326a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber        }
327a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber
3285994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        fetchInternal();
3295994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
330a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber        mLastFetchTimeUs = ALooper::GetNowUs();
331a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber
332a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber        if (mFetching && mCache->totalSize() >= kHighWaterThreshold) {
3336e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber            LOGI("Cache full, done prefetching for now");
3345994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber            mFetching = false;
3355994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        }
336a44153c1a57202fb538659eb50706e60454d6273Andreas Huber    } else {
337d17875a226491e3de60fa32d764a4cc92de7f949Andreas Huber        Mutex::Autolock autoLock(mLock);
3385994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        restartPrefetcherIfNecessary_l();
3395994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
3405994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
3410683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber    int64_t delayUs;
3420683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber    if (mFetching) {
3430683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        if (mFinalStatus != OK && mNumRetriesLeft > 0) {
3440683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber            // We failed this time and will try again in 3 seconds.
3450683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber            delayUs = 3000000ll;
3460683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        } else {
3470683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber            delayUs = 0;
3480683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        }
3490683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber    } else {
3500683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        delayUs = 100000ll;
3510683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber    }
3520683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber
3530683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber    (new AMessage(kWhatFetchMore, mReflector->id()))->post(delayUs);
3545994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
3555994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
3565994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubervoid NuCachedSource2::onRead(const sp<AMessage> &msg) {
3576e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber    LOGV("onRead");
3585994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
3595994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    int64_t offset;
3605994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    CHECK(msg->findInt64("offset", &offset));
3615994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
3625994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    void *data;
3635994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    CHECK(msg->findPointer("data", &data));
3645994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
3655994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    size_t size;
3665994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    CHECK(msg->findSize("size", &size));
3675994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
3685994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    ssize_t result = readInternal(offset, data, size);
3695994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
3705994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    if (result == -EAGAIN) {
3715994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        msg->post(50000);
3725994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        return;
3735994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
3745994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
3755994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    Mutex::Autolock autoLock(mLock);
3765994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
3775994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    CHECK(mAsyncResult == NULL);
3785994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
3795994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mAsyncResult = new AMessage;
3805994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mAsyncResult->setInt32("result", result);
3815994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
3825994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mCondition.signal();
3835994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
3845994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
38534ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Hubervoid NuCachedSource2::restartPrefetcherIfNecessary_l(
3867bf8413f91fc072452f315a91618aeef2574d420Andreas Huber        bool ignoreLowWaterThreshold, bool force) {
3876ee94582e3ce7bdd9625345e7564e3176a51a2f3James Dong    static const size_t kGrayArea = 1024 * 1024;
3885994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
3890683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber    if (mFetching || (mFinalStatus != OK && mNumRetriesLeft == 0)) {
3905994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        return;
3915994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
3925994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
3937bf8413f91fc072452f315a91618aeef2574d420Andreas Huber    if (!ignoreLowWaterThreshold && !force
39434ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber            && mCacheOffset + mCache->totalSize() - mLastAccessPos
39534ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber                >= kLowWaterThreshold) {
3965994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        return;
3975994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
3985994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
3995994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    size_t maxBytes = mLastAccessPos - mCacheOffset;
4005994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4017bf8413f91fc072452f315a91618aeef2574d420Andreas Huber    if (!force) {
4027bf8413f91fc072452f315a91618aeef2574d420Andreas Huber        if (maxBytes < kGrayArea) {
4037bf8413f91fc072452f315a91618aeef2574d420Andreas Huber            return;
4047bf8413f91fc072452f315a91618aeef2574d420Andreas Huber        }
4057bf8413f91fc072452f315a91618aeef2574d420Andreas Huber
4067bf8413f91fc072452f315a91618aeef2574d420Andreas Huber        maxBytes -= kGrayArea;
4077bf8413f91fc072452f315a91618aeef2574d420Andreas Huber    }
4085994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4095994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    size_t actualBytes = mCache->releaseFromStart(maxBytes);
4105994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mCacheOffset += actualBytes;
4115994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4126e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber    LOGI("restarting prefetcher, totalSize = %d", mCache->totalSize());
4135994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mFetching = true;
4145994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
4155994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
416c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongssize_t NuCachedSource2::readAt(off64_t offset, void *data, size_t size) {
4175994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    Mutex::Autolock autoSerializer(mSerializer);
4185994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
419145e68fc778275963189b02a1adcbe27cce4d769Andreas Huber    LOGV("readAt offset %lld, size %d", offset, size);
4205994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4215994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    Mutex::Autolock autoLock(mLock);
4225994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4235994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    // If the request can be completely satisfied from the cache, do so.
4245994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4255994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    if (offset >= mCacheOffset
4265994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber            && offset + size <= mCacheOffset + mCache->totalSize()) {
4275994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        size_t delta = offset - mCacheOffset;
4285994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        mCache->copy(delta, data, size);
4295994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4305994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        mLastAccessPos = offset + size;
4315994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4325994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        return size;
4335994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
4345994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4355994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    sp<AMessage> msg = new AMessage(kWhatRead, mReflector->id());
4365994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    msg->setInt64("offset", offset);
4375994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    msg->setPointer("data", data);
4385994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    msg->setSize("size", size);
4395994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4405994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    CHECK(mAsyncResult == NULL);
4415994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    msg->post();
4425994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4435994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    while (mAsyncResult == NULL) {
4445994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        mCondition.wait(mLock);
4455994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
4465994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4475994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    int32_t result;
4485994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    CHECK(mAsyncResult->findInt32("result", &result));
4495994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4505994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mAsyncResult.clear();
4515994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4525994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    if (result > 0) {
4535994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        mLastAccessPos = offset + result;
4545994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
4555994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4565994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    return (ssize_t)result;
4575994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
4585994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4595994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubersize_t NuCachedSource2::cachedSize() {
4605994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    Mutex::Autolock autoLock(mLock);
4615994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    return mCacheOffset + mCache->totalSize();
4625994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
4635994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4641bd233ce7e1aa7730bc18d46ffd57791391738cdBryan Mawhinneysize_t NuCachedSource2::approxDataRemaining(status_t *finalStatus) {
4655994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    Mutex::Autolock autoLock(mLock);
4661bd233ce7e1aa7730bc18d46ffd57791391738cdBryan Mawhinney    return approxDataRemaining_l(finalStatus);
4675994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
4685994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4691bd233ce7e1aa7730bc18d46ffd57791391738cdBryan Mawhinneysize_t NuCachedSource2::approxDataRemaining_l(status_t *finalStatus) {
4701bd233ce7e1aa7730bc18d46ffd57791391738cdBryan Mawhinney    *finalStatus = mFinalStatus;
4710683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber
4720683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber    if (mFinalStatus != OK && mNumRetriesLeft > 0) {
4730683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        // Pretend that everything is fine until we're out of retries.
4740683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber        *finalStatus = OK;
4750683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber    }
4760683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber
477c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t lastBytePosCached = mCacheOffset + mCache->totalSize();
4785994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    if (mLastAccessPos < lastBytePosCached) {
4795994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        return lastBytePosCached - mLastAccessPos;
4805994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
4815994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    return 0;
4825994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
4835994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
484c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongssize_t NuCachedSource2::readInternal(off64_t offset, void *data, size_t size) {
4857bf8413f91fc072452f315a91618aeef2574d420Andreas Huber    CHECK_LE(size, (size_t)kHighWaterThreshold);
4867bf8413f91fc072452f315a91618aeef2574d420Andreas Huber
487145e68fc778275963189b02a1adcbe27cce4d769Andreas Huber    LOGV("readInternal offset %lld size %d", offset, size);
4885994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4895994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    Mutex::Autolock autoLock(mLock);
4905994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
4917bf8413f91fc072452f315a91618aeef2574d420Andreas Huber    if (!mFetching) {
4927bf8413f91fc072452f315a91618aeef2574d420Andreas Huber        mLastAccessPos = offset;
4937bf8413f91fc072452f315a91618aeef2574d420Andreas Huber        restartPrefetcherIfNecessary_l(
4947bf8413f91fc072452f315a91618aeef2574d420Andreas Huber                false, // ignoreLowWaterThreshold
4957bf8413f91fc072452f315a91618aeef2574d420Andreas Huber                true); // force
4967bf8413f91fc072452f315a91618aeef2574d420Andreas Huber    }
4977bf8413f91fc072452f315a91618aeef2574d420Andreas Huber
4985994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    if (offset < mCacheOffset
499c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            || offset >= (off64_t)(mCacheOffset + mCache->totalSize())) {
5006ee94582e3ce7bdd9625345e7564e3176a51a2f3James Dong        static const off64_t kPadding = 256 * 1024;
5015994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5025994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        // In the presence of multiple decoded streams, once of them will
5035994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        // trigger this seek request, the other one will request data "nearby"
5045994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        // soon, adjust the seek position so that that subsequent request
5055994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        // does not trigger another seek.
506c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t seekOffset = (offset > kPadding) ? offset - kPadding : 0;
5075994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5085994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        seekInternal_l(seekOffset);
5095994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
5105994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5115994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    size_t delta = offset - mCacheOffset;
5125994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5135994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    if (mFinalStatus != OK) {
5145994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        if (delta >= mCache->totalSize()) {
5155994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber            return mFinalStatus;
5165994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        }
5175994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5186f5aae1bcba130d5b8092a19fca3627aa565df56Andreas Huber        size_t avail = mCache->totalSize() - delta;
51967802977b6f0aa8d6f14f85dadcf32a3cadb9c07Andreas Huber
52067802977b6f0aa8d6f14f85dadcf32a3cadb9c07Andreas Huber        if (avail > size) {
52167802977b6f0aa8d6f14f85dadcf32a3cadb9c07Andreas Huber            avail = size;
52267802977b6f0aa8d6f14f85dadcf32a3cadb9c07Andreas Huber        }
52367802977b6f0aa8d6f14f85dadcf32a3cadb9c07Andreas Huber
5245994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        mCache->copy(delta, data, avail);
5255994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5265994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        return avail;
5275994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
5285994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5295994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    if (offset + size <= mCacheOffset + mCache->totalSize()) {
5305994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        mCache->copy(delta, data, size);
5315994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5325994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        return size;
5335994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
5345994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5356e4c5c499999c04c2477b987f9e64f3ff2bf1a06Andreas Huber    LOGV("deferring read");
5365994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5375994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    return -EAGAIN;
5385994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
5395994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
540c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t NuCachedSource2::seekInternal_l(off64_t offset) {
5415994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mLastAccessPos = offset;
5425994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5435994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    if (offset >= mCacheOffset
544c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            && offset <= (off64_t)(mCacheOffset + mCache->totalSize())) {
5455994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber        return OK;
5465994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    }
5475994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5487fe4ed1207fa587c65231f9a32374ae4b618d6c0Andreas Huber    LOGI("new range: offset= %lld", offset);
5495994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5505994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mCacheOffset = offset;
5515994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5525994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    size_t totalSize = mCache->totalSize();
5535994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    CHECK_EQ(mCache->releaseFromStart(totalSize), totalSize);
5545994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5555994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mFinalStatus = OK;
5565994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    mFetching = true;
5575994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
5585994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber    return OK;
5595994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}
5605994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber
56134ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Hubervoid NuCachedSource2::resumeFetchingIfNecessary() {
56234ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber    Mutex::Autolock autoLock(mLock);
56334ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber
56434ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber    restartPrefetcherIfNecessary_l(true /* ignore low water threshold */);
56534ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber}
56634ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber
567b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wangsp<DecryptHandle> NuCachedSource2::DrmInitialization() {
568889b340ec736a9d3e3e690256d305cc8740f0c4bGloria Wang    return mSource->DrmInitialization();
569b371426ce4cf2fa6d8c3d1903b61322feb165d35Gloria Wang}
570b371426ce4cf2fa6d8c3d1903b61322feb165d35Gloria Wang
571b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wangvoid NuCachedSource2::getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client) {
572b371426ce4cf2fa6d8c3d1903b61322feb165d35Gloria Wang    mSource->getDrmInfo(handle, client);
573b371426ce4cf2fa6d8c3d1903b61322feb165d35Gloria Wang}
574b371426ce4cf2fa6d8c3d1903b61322feb165d35Gloria Wang
575771b85d9245a24273497792a2515d88d31c99e1eGloria WangString8 NuCachedSource2::getUri() {
576771b85d9245a24273497792a2515d88d31c99e1eGloria Wang    return mSource->getUri();
577771b85d9245a24273497792a2515d88d31c99e1eGloria Wang}
578ac05c317cd818701535c5d72ce90da98c4bae75bAndreas Huber
5796511c9755c3a3360ba869772600c7aae048a7ffcAndreas HuberString8 NuCachedSource2::getMIMEType() const {
5806511c9755c3a3360ba869772600c7aae048a7ffcAndreas Huber    return mSource->getMIMEType();
5816511c9755c3a3360ba869772600c7aae048a7ffcAndreas Huber}
5826511c9755c3a3360ba869772600c7aae048a7ffcAndreas Huber
5835994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}  // namespace android
584