NuCachedSource2.cpp revision 9d2f386dd2885eaffa11fd494ae258bb09fe6397
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 24a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber#include <cutils/properties.h> 255994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber#include <media/stagefright/foundation/ADebug.h> 265994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber#include <media/stagefright/foundation/AMessage.h> 275994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber#include <media/stagefright/MediaErrors.h> 285994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 295994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubernamespace android { 305994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 315994b4798b01f3dd340577c9ea9657f09093a770Andreas Huberstruct PageCache { 325994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber PageCache(size_t pageSize); 335994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber ~PageCache(); 345994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 355994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber struct Page { 365994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber void *mData; 375994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber size_t mSize; 385994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber }; 395994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 405994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber Page *acquirePage(); 415994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber void releasePage(Page *page); 425994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 435994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber void appendPage(Page *page); 445994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber size_t releaseFromStart(size_t maxBytes); 455994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 465994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber size_t totalSize() const { 475994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber return mTotalSize; 485994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } 495994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 505994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber void copy(size_t from, void *data, size_t size); 515994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 525994b4798b01f3dd340577c9ea9657f09093a770Andreas Huberprivate: 535994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber size_t mPageSize; 545994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber size_t mTotalSize; 555994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 565994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber List<Page *> mActivePages; 575994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber List<Page *> mFreePages; 585994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 595994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber void freePages(List<Page *> *list); 605994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 615994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber DISALLOW_EVIL_CONSTRUCTORS(PageCache); 625994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber}; 635994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 645994b4798b01f3dd340577c9ea9657f09093a770Andreas HuberPageCache::PageCache(size_t pageSize) 655994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber : mPageSize(pageSize), 665994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mTotalSize(0) { 675994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber} 685994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 695994b4798b01f3dd340577c9ea9657f09093a770Andreas HuberPageCache::~PageCache() { 705994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber freePages(&mActivePages); 715994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber freePages(&mFreePages); 725994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber} 735994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 745994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubervoid PageCache::freePages(List<Page *> *list) { 755994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber List<Page *>::iterator it = list->begin(); 765994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber while (it != list->end()) { 775994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber Page *page = *it; 785994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 795994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber free(page->mData); 805994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber delete page; 815994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber page = NULL; 825994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 835994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber ++it; 845994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } 855994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber} 865994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 875994b4798b01f3dd340577c9ea9657f09093a770Andreas HuberPageCache::Page *PageCache::acquirePage() { 885994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber if (!mFreePages.empty()) { 895994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber List<Page *>::iterator it = mFreePages.begin(); 905994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber Page *page = *it; 915994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mFreePages.erase(it); 925994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 935994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber return page; 945994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } 955994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 965994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber Page *page = new Page; 975994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber page->mData = malloc(mPageSize); 985994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber page->mSize = 0; 995994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 1005994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber return page; 1015994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber} 1025994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 1035994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubervoid PageCache::releasePage(Page *page) { 1045994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber page->mSize = 0; 1055994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mFreePages.push_back(page); 1065994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber} 1075994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 1085994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubervoid PageCache::appendPage(Page *page) { 1095994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mTotalSize += page->mSize; 1105994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mActivePages.push_back(page); 1115994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber} 1125994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 1135994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubersize_t PageCache::releaseFromStart(size_t maxBytes) { 1145994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber size_t bytesReleased = 0; 1155994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 1165994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber while (maxBytes > 0 && !mActivePages.empty()) { 1175994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber List<Page *>::iterator it = mActivePages.begin(); 1185994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 1195994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber Page *page = *it; 1205994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 1215994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber if (maxBytes < page->mSize) { 1225994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber break; 1235994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } 1245994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 1255994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mActivePages.erase(it); 1265994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 1275994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber maxBytes -= page->mSize; 1285994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber bytesReleased += page->mSize; 1295994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 1305994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber releasePage(page); 1315994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } 1325994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 1335994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mTotalSize -= bytesReleased; 1345994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber return bytesReleased; 1355994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber} 1365994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 1375994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubervoid PageCache::copy(size_t from, void *data, size_t size) { 1383856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("copy from %d size %d", from, size); 1395994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 140310962976d575c0a97ec7a768e9cca0b2361daeaAndreas Huber if (size == 0) { 141310962976d575c0a97ec7a768e9cca0b2361daeaAndreas Huber return; 142310962976d575c0a97ec7a768e9cca0b2361daeaAndreas Huber } 143310962976d575c0a97ec7a768e9cca0b2361daeaAndreas Huber 1445994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber CHECK_LE(from + size, mTotalSize); 1455994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 1465994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber size_t offset = 0; 1475994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber List<Page *>::iterator it = mActivePages.begin(); 1485994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber while (from >= offset + (*it)->mSize) { 1495994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber offset += (*it)->mSize; 1505994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber ++it; 1515994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } 1525994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 1535994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber size_t delta = from - offset; 1545994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber size_t avail = (*it)->mSize - delta; 1555994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 1565994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber if (avail >= size) { 1575994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber memcpy(data, (const uint8_t *)(*it)->mData + delta, size); 1585994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber return; 1595994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } 1605994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 1615994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber memcpy(data, (const uint8_t *)(*it)->mData + delta, avail); 1625994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber ++it; 1635994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber data = (uint8_t *)data + avail; 1645994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber size -= avail; 1655994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 1665994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber while (size > 0) { 1675994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber size_t copy = (*it)->mSize; 1685994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber if (copy > size) { 1695994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber copy = size; 1705994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } 1715994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber memcpy(data, (*it)->mData, copy); 1725994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber data = (uint8_t *)data + copy; 1735994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber size -= copy; 1745994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber ++it; 1755994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } 1765994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber} 1775994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 1785994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber//////////////////////////////////////////////////////////////////////////////// 1795994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 18049c59815369616b0fd5451ccabd377e8fe1dc3faAndreas HuberNuCachedSource2::NuCachedSource2( 18149c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber const sp<DataSource> &source, 18249c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber const char *cacheConfig, 18349c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber bool disconnectAtHighwatermark) 1845994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber : mSource(source), 1855994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mReflector(new AHandlerReflector<NuCachedSource2>(this)), 1865994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mLooper(new ALooper), 1875994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mCache(new PageCache(kPageSize)), 1885994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mCacheOffset(0), 1895994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mFinalStatus(OK), 1905994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mLastAccessPos(0), 191a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber mFetching(true), 1920683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber mLastFetchTimeUs(-1), 193a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber mNumRetriesLeft(kMaxNumRetries), 194a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber mHighwaterThresholdBytes(kDefaultHighWaterThreshold), 195a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber mLowwaterThresholdBytes(kDefaultLowWaterThreshold), 19649c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber mKeepAliveIntervalUs(kDefaultKeepAliveIntervalUs), 19749c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber mDisconnectAtHighwatermark(disconnectAtHighwatermark) { 19849c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber // We are NOT going to support disconnect-at-highwatermark indefinitely 19949c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber // and we are not guaranteeing support for client-specified cache 20049c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber // parameters. Both of these are temporary measures to solve a specific 20149c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber // problem that will be solved in a better way going forward. 20249c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber 203a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber updateCacheParamsFromSystemProperty(); 204a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber 20549c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber if (cacheConfig != NULL) { 20649c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber updateCacheParamsFromString(cacheConfig); 20749c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber } 20849c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber 20949c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber if (mDisconnectAtHighwatermark) { 21049c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber // Makes no sense to disconnect and do keep-alives... 21149c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber mKeepAliveIntervalUs = 0; 21249c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber } 21349c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber 214a814c1fdc2acf0ed2ee3b175110f6039be7c4873Andreas Huber mLooper->setName("NuCachedSource2"); 2155994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mLooper->registerHandler(mReflector); 2165994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mLooper->start(); 2175994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 2185994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber Mutex::Autolock autoLock(mLock); 2195994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber (new AMessage(kWhatFetchMore, mReflector->id()))->post(); 2205994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber} 2215994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 2225994b4798b01f3dd340577c9ea9657f09093a770Andreas HuberNuCachedSource2::~NuCachedSource2() { 2235994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mLooper->stop(); 2245994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mLooper->unregisterHandler(mReflector->id()); 2255994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 2265994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber delete mCache; 2275994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mCache = NULL; 2285994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber} 2295994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 2305b1b8a93a07326f1cbc627f09e02988375189e0aJames Dongstatus_t NuCachedSource2::getEstimatedBandwidthKbps(int32_t *kbps) { 231b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong if (mSource->flags() & kIsHTTPBasedSource) { 232b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong HTTPBase* source = static_cast<HTTPBase *>(mSource.get()); 233b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong return source->getEstimatedBandwidthKbps(kbps); 234b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong } 235b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong return ERROR_UNSUPPORTED; 2365b1b8a93a07326f1cbc627f09e02988375189e0aJames Dong} 2375b1b8a93a07326f1cbc627f09e02988375189e0aJames Dong 2385b1b8a93a07326f1cbc627f09e02988375189e0aJames Dongstatus_t NuCachedSource2::setCacheStatCollectFreq(int32_t freqMs) { 239b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong if (mSource->flags() & kIsHTTPBasedSource) { 240b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong HTTPBase *source = static_cast<HTTPBase *>(mSource.get()); 241b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong return source->setBandwidthStatCollectFreq(freqMs); 242b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong } 243b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong return ERROR_UNSUPPORTED; 2445b1b8a93a07326f1cbc627f09e02988375189e0aJames Dong} 2455b1b8a93a07326f1cbc627f09e02988375189e0aJames Dong 2465994b4798b01f3dd340577c9ea9657f09093a770Andreas Huberstatus_t NuCachedSource2::initCheck() const { 2475994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber return mSource->initCheck(); 2485994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber} 2495994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 250c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t NuCachedSource2::getSize(off64_t *size) { 2515994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber return mSource->getSize(size); 2525994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber} 2535994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 2545994b4798b01f3dd340577c9ea9657f09093a770Andreas Huberuint32_t NuCachedSource2::flags() { 255b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong // Remove HTTP related flags since NuCachedSource2 is not HTTP-based. 256b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong uint32_t flags = mSource->flags() & ~(kWantsPrefetching | kIsHTTPBasedSource); 257b33d2ac90cfce0fe6db8c3e979e7ae2bbfc28163James Dong return (flags | kIsCachingDataSource); 2585994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber} 2595994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 2605994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubervoid NuCachedSource2::onMessageReceived(const sp<AMessage> &msg) { 2615994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber switch (msg->what()) { 2625994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber case kWhatFetchMore: 2635994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber { 2645994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber onFetch(); 2655994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber break; 2665994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } 2675994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 2685994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber case kWhatRead: 2695994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber { 2705994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber onRead(msg); 2715994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber break; 2725994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } 2735994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 2745994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber default: 2755994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber TRESPASS(); 2765994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } 2775994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber} 2785994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 2795994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubervoid NuCachedSource2::fetchInternal() { 2803856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("fetchInternal"); 2815994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 28295c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber bool reconnect = false; 28395c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber 2840683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber { 2850683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber Mutex::Autolock autoLock(mLock); 2860683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber CHECK(mFinalStatus == OK || mNumRetriesLeft > 0); 2870683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber 2880683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber if (mFinalStatus != OK) { 2890683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber --mNumRetriesLeft; 2900683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber 29195c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber reconnect = true; 29295c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber } 29395c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber } 29495c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber 29595c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber if (reconnect) { 29695c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber status_t err = 29795c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber mSource->reconnectAtOffset(mCacheOffset + mCache->totalSize()); 29895c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber 29995c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber Mutex::Autolock autoLock(mLock); 3000683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber 30195c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber if (err == ERROR_UNSUPPORTED) { 30295c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber mNumRetriesLeft = 0; 30395c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber return; 30495c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber } else if (err != OK) { 305df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("The attempt to reconnect failed, %d retries remaining", 30695c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber mNumRetriesLeft); 3070683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber 30895c4d6034dc356f70c6293ea53d4858415b2d020Andreas Huber return; 3090683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber } 3100683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber } 3115994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 3125994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber PageCache::Page *page = mCache->acquirePage(); 3135994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 3145994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber ssize_t n = mSource->readAt( 3155994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mCacheOffset + mCache->totalSize(), page->mData, kPageSize); 3165994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 3175994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber Mutex::Autolock autoLock(mLock); 3185994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 3195994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber if (n < 0) { 32029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("source returned error %ld, %d retries left", n, mNumRetriesLeft); 3215994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mFinalStatus = n; 3225994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mCache->releasePage(page); 3235994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } else if (n == 0) { 324df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("ERROR_END_OF_STREAM"); 3250683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber 3260683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber mNumRetriesLeft = 0; 3275994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mFinalStatus = ERROR_END_OF_STREAM; 3280683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber 3295994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mCache->releasePage(page); 3305994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } else { 3310683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber if (mFinalStatus != OK) { 332df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("retrying a previously failed read succeeded."); 3330683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber } 3340683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber mNumRetriesLeft = kMaxNumRetries; 3350683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber mFinalStatus = OK; 3360683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber 3375994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber page->mSize = n; 3385994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mCache->appendPage(page); 3395994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } 3405994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber} 3415994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 3425994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubervoid NuCachedSource2::onFetch() { 3433856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("onFetch"); 3445994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 3450683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber if (mFinalStatus != OK && mNumRetriesLeft == 0) { 3463856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("EOS reached, done prefetching for now"); 3475994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mFetching = false; 3485994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } 3495994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 350a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber bool keepAlive = 351a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber !mFetching 352a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber && mFinalStatus == OK 353a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber && mKeepAliveIntervalUs > 0 354a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber && ALooper::GetNowUs() >= mLastFetchTimeUs + mKeepAliveIntervalUs; 355a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber 356a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber if (mFetching || keepAlive) { 357a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber if (keepAlive) { 358df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Keep alive"); 359a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber } 360a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber 3615994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber fetchInternal(); 3625994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 363a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber mLastFetchTimeUs = ALooper::GetNowUs(); 364a5273ebd1746368662a597643d6701a5046d5c7bAndreas Huber 365a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber if (mFetching && mCache->totalSize() >= mHighwaterThresholdBytes) { 366df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("Cache full, done prefetching for now"); 3675994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mFetching = false; 36849c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber 36949c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber if (mDisconnectAtHighwatermark 37049c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber && (mSource->flags() & DataSource::kIsHTTPBasedSource)) { 3713856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Disconnecting at high watermark"); 37249c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber static_cast<HTTPBase *>(mSource.get())->disconnect(); 37349c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber } 3745994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } 375a44153c1a57202fb538659eb50706e60454d6273Andreas Huber } else { 376d17875a226491e3de60fa32d764a4cc92de7f949Andreas Huber Mutex::Autolock autoLock(mLock); 3775994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber restartPrefetcherIfNecessary_l(); 3785994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } 3795994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 3800683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber int64_t delayUs; 3810683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber if (mFetching) { 3820683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber if (mFinalStatus != OK && mNumRetriesLeft > 0) { 3830683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber // We failed this time and will try again in 3 seconds. 3840683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber delayUs = 3000000ll; 3850683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber } else { 3860683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber delayUs = 0; 3870683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber } 3880683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber } else { 3890683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber delayUs = 100000ll; 3900683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber } 3910683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber 3920683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber (new AMessage(kWhatFetchMore, mReflector->id()))->post(delayUs); 3935994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber} 3945994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 3955994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubervoid NuCachedSource2::onRead(const sp<AMessage> &msg) { 3963856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("onRead"); 3975994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 3985994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber int64_t offset; 3995994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber CHECK(msg->findInt64("offset", &offset)); 4005994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 4015994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber void *data; 4025994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber CHECK(msg->findPointer("data", &data)); 4035994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 4045994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber size_t size; 4055994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber CHECK(msg->findSize("size", &size)); 4065994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 4075994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber ssize_t result = readInternal(offset, data, size); 4085994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 4095994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber if (result == -EAGAIN) { 4105994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber msg->post(50000); 4115994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber return; 4125994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } 4135994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 4145994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber Mutex::Autolock autoLock(mLock); 4155994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 4165994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber CHECK(mAsyncResult == NULL); 4175994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 4185994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mAsyncResult = new AMessage; 4195994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mAsyncResult->setInt32("result", result); 4205994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 4215994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mCondition.signal(); 4225994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber} 4235994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 42434ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Hubervoid NuCachedSource2::restartPrefetcherIfNecessary_l( 4257bf8413f91fc072452f315a91618aeef2574d420Andreas Huber bool ignoreLowWaterThreshold, bool force) { 4266ee94582e3ce7bdd9625345e7564e3176a51a2f3James Dong static const size_t kGrayArea = 1024 * 1024; 4275994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 4280683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber if (mFetching || (mFinalStatus != OK && mNumRetriesLeft == 0)) { 4295994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber return; 4305994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } 4315994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 4327bf8413f91fc072452f315a91618aeef2574d420Andreas Huber if (!ignoreLowWaterThreshold && !force 43334ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber && mCacheOffset + mCache->totalSize() - mLastAccessPos 434a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber >= mLowwaterThresholdBytes) { 4355994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber return; 4365994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } 4375994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 4385994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber size_t maxBytes = mLastAccessPos - mCacheOffset; 4395994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 4407bf8413f91fc072452f315a91618aeef2574d420Andreas Huber if (!force) { 4417bf8413f91fc072452f315a91618aeef2574d420Andreas Huber if (maxBytes < kGrayArea) { 4427bf8413f91fc072452f315a91618aeef2574d420Andreas Huber return; 4437bf8413f91fc072452f315a91618aeef2574d420Andreas Huber } 4447bf8413f91fc072452f315a91618aeef2574d420Andreas Huber 4457bf8413f91fc072452f315a91618aeef2574d420Andreas Huber maxBytes -= kGrayArea; 4467bf8413f91fc072452f315a91618aeef2574d420Andreas Huber } 4475994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 4485994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber size_t actualBytes = mCache->releaseFromStart(maxBytes); 4495994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mCacheOffset += actualBytes; 4505994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 451df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("restarting prefetcher, totalSize = %d", mCache->totalSize()); 4525994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mFetching = true; 4535994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber} 4545994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 455c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongssize_t NuCachedSource2::readAt(off64_t offset, void *data, size_t size) { 4565994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber Mutex::Autolock autoSerializer(mSerializer); 4575994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 4583856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("readAt offset %lld, size %d", offset, size); 4595994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 4605994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber Mutex::Autolock autoLock(mLock); 4615994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 4625994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber // If the request can be completely satisfied from the cache, do so. 4635994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 4645994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber if (offset >= mCacheOffset 4655994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber && offset + size <= mCacheOffset + mCache->totalSize()) { 4665994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber size_t delta = offset - mCacheOffset; 4675994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mCache->copy(delta, data, size); 4685994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 4695994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mLastAccessPos = offset + size; 4705994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 4715994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber return size; 4725994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } 4735994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 4745994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber sp<AMessage> msg = new AMessage(kWhatRead, mReflector->id()); 4755994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber msg->setInt64("offset", offset); 4765994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber msg->setPointer("data", data); 4775994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber msg->setSize("size", size); 4785994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 4795994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber CHECK(mAsyncResult == NULL); 4805994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber msg->post(); 4815994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 4825994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber while (mAsyncResult == NULL) { 4835994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mCondition.wait(mLock); 4845994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } 4855994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 4865994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber int32_t result; 4875994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber CHECK(mAsyncResult->findInt32("result", &result)); 4885994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 4895994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mAsyncResult.clear(); 4905994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 4915994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber if (result > 0) { 4925994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mLastAccessPos = offset + result; 4935994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } 4945994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 4955994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber return (ssize_t)result; 4965994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber} 4975994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 4985994b4798b01f3dd340577c9ea9657f09093a770Andreas Hubersize_t NuCachedSource2::cachedSize() { 4995994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber Mutex::Autolock autoLock(mLock); 5005994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber return mCacheOffset + mCache->totalSize(); 5015994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber} 5025994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 5031bd233ce7e1aa7730bc18d46ffd57791391738cdBryan Mawhinneysize_t NuCachedSource2::approxDataRemaining(status_t *finalStatus) { 5045994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber Mutex::Autolock autoLock(mLock); 5051bd233ce7e1aa7730bc18d46ffd57791391738cdBryan Mawhinney return approxDataRemaining_l(finalStatus); 5065994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber} 5075994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 5081bd233ce7e1aa7730bc18d46ffd57791391738cdBryan Mawhinneysize_t NuCachedSource2::approxDataRemaining_l(status_t *finalStatus) { 5091bd233ce7e1aa7730bc18d46ffd57791391738cdBryan Mawhinney *finalStatus = mFinalStatus; 5100683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber 5110683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber if (mFinalStatus != OK && mNumRetriesLeft > 0) { 5120683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber // Pretend that everything is fine until we're out of retries. 5130683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber *finalStatus = OK; 5140683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber } 5150683eba6b35c396c21f10e926709f2f8fc05f090Andreas Huber 516c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t lastBytePosCached = mCacheOffset + mCache->totalSize(); 5175994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber if (mLastAccessPos < lastBytePosCached) { 5185994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber return lastBytePosCached - mLastAccessPos; 5195994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } 5205994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber return 0; 5215994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber} 5225994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 523c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongssize_t NuCachedSource2::readInternal(off64_t offset, void *data, size_t size) { 524a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber CHECK_LE(size, (size_t)mHighwaterThresholdBytes); 5257bf8413f91fc072452f315a91618aeef2574d420Andreas Huber 5263856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("readInternal offset %lld size %d", offset, size); 5275994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 5285994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber Mutex::Autolock autoLock(mLock); 5295994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 5307bf8413f91fc072452f315a91618aeef2574d420Andreas Huber if (!mFetching) { 5317bf8413f91fc072452f315a91618aeef2574d420Andreas Huber mLastAccessPos = offset; 5327bf8413f91fc072452f315a91618aeef2574d420Andreas Huber restartPrefetcherIfNecessary_l( 5337bf8413f91fc072452f315a91618aeef2574d420Andreas Huber false, // ignoreLowWaterThreshold 5347bf8413f91fc072452f315a91618aeef2574d420Andreas Huber true); // force 5357bf8413f91fc072452f315a91618aeef2574d420Andreas Huber } 5367bf8413f91fc072452f315a91618aeef2574d420Andreas Huber 5375994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber if (offset < mCacheOffset 538c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong || offset >= (off64_t)(mCacheOffset + mCache->totalSize())) { 5396ee94582e3ce7bdd9625345e7564e3176a51a2f3James Dong static const off64_t kPadding = 256 * 1024; 5405994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 5415994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber // In the presence of multiple decoded streams, once of them will 5425994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber // trigger this seek request, the other one will request data "nearby" 5435994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber // soon, adjust the seek position so that that subsequent request 5445994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber // does not trigger another seek. 545c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t seekOffset = (offset > kPadding) ? offset - kPadding : 0; 5465994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 5475994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber seekInternal_l(seekOffset); 5485994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } 5495994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 5505994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber size_t delta = offset - mCacheOffset; 5515994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 5525994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber if (mFinalStatus != OK) { 5535994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber if (delta >= mCache->totalSize()) { 5545994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber return mFinalStatus; 5555994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } 5565994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 5576f5aae1bcba130d5b8092a19fca3627aa565df56Andreas Huber size_t avail = mCache->totalSize() - delta; 55867802977b6f0aa8d6f14f85dadcf32a3cadb9c07Andreas Huber 55967802977b6f0aa8d6f14f85dadcf32a3cadb9c07Andreas Huber if (avail > size) { 56067802977b6f0aa8d6f14f85dadcf32a3cadb9c07Andreas Huber avail = size; 56167802977b6f0aa8d6f14f85dadcf32a3cadb9c07Andreas Huber } 56267802977b6f0aa8d6f14f85dadcf32a3cadb9c07Andreas Huber 5635994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mCache->copy(delta, data, avail); 5645994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 5655994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber return avail; 5665994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } 5675994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 5685994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber if (offset + size <= mCacheOffset + mCache->totalSize()) { 5695994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mCache->copy(delta, data, size); 5705994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 5715994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber return size; 5725994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } 5735994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 5743856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("deferring read"); 5755994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 5765994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber return -EAGAIN; 5775994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber} 5785994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 579c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t NuCachedSource2::seekInternal_l(off64_t offset) { 5805994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mLastAccessPos = offset; 5815994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 5825994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber if (offset >= mCacheOffset 583c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong && offset <= (off64_t)(mCacheOffset + mCache->totalSize())) { 5845994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber return OK; 5855994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber } 5865994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 587df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("new range: offset= %lld", offset); 5885994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 5895994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mCacheOffset = offset; 5905994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 5915994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber size_t totalSize = mCache->totalSize(); 5925994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber CHECK_EQ(mCache->releaseFromStart(totalSize), totalSize); 5935994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 5945994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mFinalStatus = OK; 5955994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber mFetching = true; 5965994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 5975994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber return OK; 5985994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber} 5995994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber 60034ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Hubervoid NuCachedSource2::resumeFetchingIfNecessary() { 60134ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber Mutex::Autolock autoLock(mLock); 60234ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber 60334ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber restartPrefetcherIfNecessary_l(true /* ignore low water threshold */); 60434ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber} 60534ef0f32c8fc0186236a27e07405328cc1f7c56dAndreas Huber 6069d2f386dd2885eaffa11fd494ae258bb09fe6397James Dongsp<DecryptHandle> NuCachedSource2::DrmInitialization(const char* mime) { 6079d2f386dd2885eaffa11fd494ae258bb09fe6397James Dong return mSource->DrmInitialization(mime); 608b371426ce4cf2fa6d8c3d1903b61322feb165d35Gloria Wang} 609b371426ce4cf2fa6d8c3d1903b61322feb165d35Gloria Wang 610b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wangvoid NuCachedSource2::getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client) { 611b371426ce4cf2fa6d8c3d1903b61322feb165d35Gloria Wang mSource->getDrmInfo(handle, client); 612b371426ce4cf2fa6d8c3d1903b61322feb165d35Gloria Wang} 613b371426ce4cf2fa6d8c3d1903b61322feb165d35Gloria Wang 614771b85d9245a24273497792a2515d88d31c99e1eGloria WangString8 NuCachedSource2::getUri() { 615771b85d9245a24273497792a2515d88d31c99e1eGloria Wang return mSource->getUri(); 616771b85d9245a24273497792a2515d88d31c99e1eGloria Wang} 617ac05c317cd818701535c5d72ce90da98c4bae75bAndreas Huber 6186511c9755c3a3360ba869772600c7aae048a7ffcAndreas HuberString8 NuCachedSource2::getMIMEType() const { 6196511c9755c3a3360ba869772600c7aae048a7ffcAndreas Huber return mSource->getMIMEType(); 6206511c9755c3a3360ba869772600c7aae048a7ffcAndreas Huber} 6216511c9755c3a3360ba869772600c7aae048a7ffcAndreas Huber 622a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Hubervoid NuCachedSource2::updateCacheParamsFromSystemProperty() { 623a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber char value[PROPERTY_VALUE_MAX]; 624a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber if (!property_get("media.stagefright.cache-params", value, NULL)) { 625a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber return; 626a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber } 627a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber 628a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber updateCacheParamsFromString(value); 629a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber} 630a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber 631a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Hubervoid NuCachedSource2::updateCacheParamsFromString(const char *s) { 632a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber ssize_t lowwaterMarkKb, highwaterMarkKb; 6330b8cd8b0cf1489f8f7c0b2c4d7ea8fea70ca93a1Andreas Huber int keepAliveSecs; 634a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber 6350b8cd8b0cf1489f8f7c0b2c4d7ea8fea70ca93a1Andreas Huber if (sscanf(s, "%ld/%ld/%d", 6360b8cd8b0cf1489f8f7c0b2c4d7ea8fea70ca93a1Andreas Huber &lowwaterMarkKb, &highwaterMarkKb, &keepAliveSecs) != 3) { 63729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Failed to parse cache parameters from '%s'.", s); 638a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber return; 639a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber } 640a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber 641a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber if (lowwaterMarkKb >= 0) { 642a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber mLowwaterThresholdBytes = lowwaterMarkKb * 1024; 643a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber } else { 644a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber mLowwaterThresholdBytes = kDefaultLowWaterThreshold; 645a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber } 646a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber 647a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber if (highwaterMarkKb >= 0) { 648a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber mHighwaterThresholdBytes = highwaterMarkKb * 1024; 649a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber } else { 650a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber mHighwaterThresholdBytes = kDefaultHighWaterThreshold; 651a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber } 652a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber 6530b8cd8b0cf1489f8f7c0b2c4d7ea8fea70ca93a1Andreas Huber if (mLowwaterThresholdBytes >= mHighwaterThresholdBytes) { 65429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Illegal low/highwater marks specified, reverting to defaults."); 6550b8cd8b0cf1489f8f7c0b2c4d7ea8fea70ca93a1Andreas Huber 6560b8cd8b0cf1489f8f7c0b2c4d7ea8fea70ca93a1Andreas Huber mLowwaterThresholdBytes = kDefaultLowWaterThreshold; 6570b8cd8b0cf1489f8f7c0b2c4d7ea8fea70ca93a1Andreas Huber mHighwaterThresholdBytes = kDefaultHighWaterThreshold; 6580b8cd8b0cf1489f8f7c0b2c4d7ea8fea70ca93a1Andreas Huber } 6590b8cd8b0cf1489f8f7c0b2c4d7ea8fea70ca93a1Andreas Huber 6600b8cd8b0cf1489f8f7c0b2c4d7ea8fea70ca93a1Andreas Huber if (keepAliveSecs >= 0) { 6610b8cd8b0cf1489f8f7c0b2c4d7ea8fea70ca93a1Andreas Huber mKeepAliveIntervalUs = keepAliveSecs * 1000000ll; 6620b8cd8b0cf1489f8f7c0b2c4d7ea8fea70ca93a1Andreas Huber } else { 6630b8cd8b0cf1489f8f7c0b2c4d7ea8fea70ca93a1Andreas Huber mKeepAliveIntervalUs = kDefaultKeepAliveIntervalUs; 6640b8cd8b0cf1489f8f7c0b2c4d7ea8fea70ca93a1Andreas Huber } 665a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber 6663856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("lowwater = %d bytes, highwater = %d bytes, keepalive = %lld us", 667a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber mLowwaterThresholdBytes, 668a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber mHighwaterThresholdBytes, 669a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber mKeepAliveIntervalUs); 670a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber} 671a045cb0e77097120e86e367e1cab5494ce2a5d5eAndreas Huber 67249c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber// static 67349c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Hubervoid NuCachedSource2::RemoveCacheSpecificHeaders( 67449c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber KeyedVector<String8, String8> *headers, 67549c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber String8 *cacheConfig, 67649c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber bool *disconnectAtHighwatermark) { 67749c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber *cacheConfig = String8(); 67849c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber *disconnectAtHighwatermark = false; 67949c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber 68049c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber if (headers == NULL) { 68149c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber return; 68249c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber } 68349c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber 68449c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber ssize_t index; 68549c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber if ((index = headers->indexOfKey(String8("x-cache-config"))) >= 0) { 68649c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber *cacheConfig = headers->valueAt(index); 68749c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber 68849c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber headers->removeItemsAt(index); 68949c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber 6903856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Using special cache config '%s'", cacheConfig->string()); 69149c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber } 69249c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber 69349c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber if ((index = headers->indexOfKey( 69449c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber String8("x-disconnect-at-highwatermark"))) >= 0) { 69549c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber *disconnectAtHighwatermark = true; 69649c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber headers->removeItemsAt(index); 69749c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber 6983856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Client requested disconnection at highwater mark"); 69949c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber } 70049c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber} 70149c59815369616b0fd5451ccabd377e8fe1dc3faAndreas Huber 7025994b4798b01f3dd340577c9ea9657f09093a770Andreas Huber} // namespace android 703