199f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins/* 299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins * Copyright 2015 The Android Open Source Project 399f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins * 499f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins * Licensed under the Apache License, Version 2.0 (the "License"); 599f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins * you may not use this file except in compliance with the License. 699f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins * You may obtain a copy of the License at 799f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins * 899f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins * http://www.apache.org/licenses/LICENSE-2.0 999f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins * 1099f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins * Unless required by applicable law or agreed to in writing, software 1199f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins * distributed under the License is distributed on an "AS IS" BASIS, 1299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1399f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins * See the License for the specific language governing permissions and 1499f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins * limitations under the License. 1599f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins */ 1699f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 1799f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins//#define LOG_NDEBUG 0 1899f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins#define LOG_TAG "CallbackDataSource" 1999f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins#include <utils/Log.h> 2099f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 2199f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins#include "include/CallbackDataSource.h" 2299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 2399f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins#include <binder/IMemory.h> 2499f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins#include <media/IDataSource.h> 2599f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins#include <media/stagefright/foundation/ADebug.h> 2699f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 2799f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins#include <algorithm> 2899f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 2999f31604136d66ae10e20669fb6b5716f342bde0Chris Watkinsnamespace android { 3099f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 3199f31604136d66ae10e20669fb6b5716f342bde0Chris WatkinsCallbackDataSource::CallbackDataSource( 3299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins const sp<IDataSource>& binderDataSource) 33fbe7fcfe818b6f68e352c7c450d4fe15a543b801Marco Nelissen : mIDataSource(binderDataSource), 34fbe7fcfe818b6f68e352c7c450d4fe15a543b801Marco Nelissen mIsClosed(false) { 3599f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins // Set up the buffer to read into. 3699f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins mMemory = mIDataSource->getIMemory(); 3769d3d8a9540b0da787ea0beccad2517f057dd54dMarco Nelissen mName = String8::format("CallbackDataSource(%s)", mIDataSource->toString().string()); 3869d3d8a9540b0da787ea0beccad2517f057dd54dMarco Nelissen 3999f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins} 4099f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 4199f31604136d66ae10e20669fb6b5716f342bde0Chris WatkinsCallbackDataSource::~CallbackDataSource() { 4299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins ALOGV("~CallbackDataSource"); 43fbe7fcfe818b6f68e352c7c450d4fe15a543b801Marco Nelissen close(); 4499f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins} 4599f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 4699f31604136d66ae10e20669fb6b5716f342bde0Chris Watkinsstatus_t CallbackDataSource::initCheck() const { 4799f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins if (mMemory == NULL) { 4899f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins return UNKNOWN_ERROR; 4999f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins } 5099f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins return OK; 5199f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins} 5299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 5399f31604136d66ae10e20669fb6b5716f342bde0Chris Watkinsssize_t CallbackDataSource::readAt(off64_t offset, void* data, size_t size) { 54b6f77710f3355f256c831f2465a21a745e8f9a32Marco Nelissen if (mMemory == NULL || data == NULL) { 5599f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins return -1; 5699f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins } 5799f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 5899f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins // IDataSource can only read up to mMemory->size() bytes at a time, but this 5999f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins // method should be able to read any number of bytes, so read in a loop. 6099f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins size_t totalNumRead = 0; 6199f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins size_t numLeft = size; 6299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins const size_t bufferSize = mMemory->size(); 6399f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 6499f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins while (numLeft > 0) { 6599f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins size_t numToRead = std::min(numLeft, bufferSize); 6699f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins ssize_t numRead = 6799f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins mIDataSource->readAt(offset + totalNumRead, numToRead); 6899f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins // A negative return value represents an error. Pass it on. 6999f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins if (numRead < 0) { 7040a3f52cc7d4f657f963d9c2b47007fdfd3fc9ddRobert Shih return numRead == ERROR_END_OF_STREAM && totalNumRead > 0 ? totalNumRead : numRead; 7199f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins } 7299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins // A zero return value signals EOS. Return the bytes read so far. 7399f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins if (numRead == 0) { 7499f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins return totalNumRead; 7599f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins } 76da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins if ((size_t)numRead > numToRead) { 77da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins return ERROR_OUT_OF_RANGE; 78da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins } 79da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins CHECK(numRead >= 0 && (size_t)numRead <= bufferSize); 8099f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins memcpy(((uint8_t*)data) + totalNumRead, mMemory->pointer(), numRead); 8199f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins numLeft -= numRead; 8299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins totalNumRead += numRead; 8399f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins } 8499f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 8599f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins return totalNumRead; 8699f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins} 8799f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 8899f31604136d66ae10e20669fb6b5716f342bde0Chris Watkinsstatus_t CallbackDataSource::getSize(off64_t *size) { 8999f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins status_t err = mIDataSource->getSize(size); 9099f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins if (err != OK) { 9199f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins return err; 9299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins } 9399f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins if (*size < 0) { 9499f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins // IDataSource will set size to -1 to indicate unknown size, but 9599f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins // DataSource returns ERROR_UNSUPPORTED for that. 9699f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins return ERROR_UNSUPPORTED; 9799f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins } 9899f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins return OK; 9999f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins} 10099f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 10110551fcd58b3807fc7351d88e6127ec227b993d1Wei Jiauint32_t CallbackDataSource::flags() { 10210551fcd58b3807fc7351d88e6127ec227b993d1Wei Jia return mIDataSource->getFlags(); 10310551fcd58b3807fc7351d88e6127ec227b993d1Wei Jia} 10410551fcd58b3807fc7351d88e6127ec227b993d1Wei Jia 105fbe7fcfe818b6f68e352c7c450d4fe15a543b801Marco Nelissenvoid CallbackDataSource::close() { 106fbe7fcfe818b6f68e352c7c450d4fe15a543b801Marco Nelissen if (!mIsClosed) { 107fbe7fcfe818b6f68e352c7c450d4fe15a543b801Marco Nelissen mIDataSource->close(); 108fbe7fcfe818b6f68e352c7c450d4fe15a543b801Marco Nelissen mIsClosed = true; 109fbe7fcfe818b6f68e352c7c450d4fe15a543b801Marco Nelissen } 110fbe7fcfe818b6f68e352c7c450d4fe15a543b801Marco Nelissen} 111fbe7fcfe818b6f68e352c7c450d4fe15a543b801Marco Nelissen 1122a5e49c984befa066e966cd9af2303a54976f163Wei Jiasp<DecryptHandle> CallbackDataSource::DrmInitialization(const char *mime) { 1132a5e49c984befa066e966cd9af2303a54976f163Wei Jia return mIDataSource->DrmInitialization(mime); 1142a5e49c984befa066e966cd9af2303a54976f163Wei Jia} 1152a5e49c984befa066e966cd9af2303a54976f163Wei Jia 116d49dbd6b625cddb82f3f7bbeac62d48ef338ef0fAndy Hungsp<IDataSource> CallbackDataSource::getIDataSource() const { 117d49dbd6b625cddb82f3f7bbeac62d48ef338ef0fAndy Hung return mIDataSource; 118d49dbd6b625cddb82f3f7bbeac62d48ef338ef0fAndy Hung} 119d49dbd6b625cddb82f3f7bbeac62d48ef338ef0fAndy Hung 120da7e453e1d1c77959822cf9602ddfed1c50be445Chris WatkinsTinyCacheSource::TinyCacheSource(const sp<DataSource>& source) 121da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins : mSource(source), mCachedOffset(0), mCachedSize(0) { 12269d3d8a9540b0da787ea0beccad2517f057dd54dMarco Nelissen mName = String8::format("TinyCacheSource(%s)", mSource->toString().string()); 123da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins} 124da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins 125da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkinsstatus_t TinyCacheSource::initCheck() const { 126da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins return mSource->initCheck(); 127da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins} 128da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins 129da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkinsssize_t TinyCacheSource::readAt(off64_t offset, void* data, size_t size) { 130da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins if (size >= kCacheSize) { 131da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins return mSource->readAt(offset, data, size); 132da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins } 133da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins 134da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins // Check if the cache satisfies the read. 13571ec3dfc1d8d53bdc8f99b69286b60ecb926d7ffWonsik Kim if (mCachedOffset <= offset 13671ec3dfc1d8d53bdc8f99b69286b60ecb926d7ffWonsik Kim && offset < (off64_t) (mCachedOffset + mCachedSize)) { 13706ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim if (offset + size <= mCachedOffset + mCachedSize) { 13806ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim memcpy(data, &mCache[offset - mCachedOffset], size); 13906ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim return size; 14006ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim } else { 14106ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim // If the cache hits only partially, flush the cache and read the 14206ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim // remainder. 14306ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim 14406ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim // This value is guaranteed to be greater than 0 because of the 14506ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim // enclosing if statement. 14606ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim const ssize_t remaining = mCachedOffset + mCachedSize - offset; 14706ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim memcpy(data, &mCache[offset - mCachedOffset], remaining); 14806ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim const ssize_t readMore = readAt(offset + remaining, 14906ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim (uint8_t*)data + remaining, size - remaining); 15006ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim if (readMore < 0) { 15106ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim return readMore; 15206ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim } 15306ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim return remaining + readMore; 15406ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim } 155da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins } 156da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins 1572a5e49c984befa066e966cd9af2303a54976f163Wei Jia 158da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins // Fill the cache and copy to the caller. 159da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins const ssize_t numRead = mSource->readAt(offset, mCache, kCacheSize); 160da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins if (numRead <= 0) { 1612a5e49c984befa066e966cd9af2303a54976f163Wei Jia // Flush cache on error 1622a5e49c984befa066e966cd9af2303a54976f163Wei Jia mCachedSize = 0; 1632a5e49c984befa066e966cd9af2303a54976f163Wei Jia mCachedOffset = 0; 164da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins return numRead; 165da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins } 166da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins if ((size_t)numRead > kCacheSize) { 1672a5e49c984befa066e966cd9af2303a54976f163Wei Jia // Flush cache on error 1682a5e49c984befa066e966cd9af2303a54976f163Wei Jia mCachedSize = 0; 1692a5e49c984befa066e966cd9af2303a54976f163Wei Jia mCachedOffset = 0; 170da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins return ERROR_OUT_OF_RANGE; 171da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins } 172da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins 173da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins mCachedSize = numRead; 174da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins mCachedOffset = offset; 175da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins CHECK(mCachedSize <= kCacheSize && mCachedOffset >= 0); 176da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins const size_t numToReturn = std::min(size, (size_t)numRead); 177da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins memcpy(data, mCache, numToReturn); 178da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins 179da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins return numToReturn; 180da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins} 181da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins 182da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkinsstatus_t TinyCacheSource::getSize(off64_t *size) { 183da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins return mSource->getSize(size); 184da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins} 185da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins 186da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkinsuint32_t TinyCacheSource::flags() { 187da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins return mSource->flags(); 188da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins} 189da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins 1902a5e49c984befa066e966cd9af2303a54976f163Wei Jiasp<DecryptHandle> TinyCacheSource::DrmInitialization(const char *mime) { 1912a5e49c984befa066e966cd9af2303a54976f163Wei Jia // flush cache when DrmInitialization occurs since decrypted 1922a5e49c984befa066e966cd9af2303a54976f163Wei Jia // data may differ from what is in cache. 1932a5e49c984befa066e966cd9af2303a54976f163Wei Jia mCachedOffset = 0; 1942a5e49c984befa066e966cd9af2303a54976f163Wei Jia mCachedSize = 0; 1952a5e49c984befa066e966cd9af2303a54976f163Wei Jia return mSource->DrmInitialization(mime); 1962a5e49c984befa066e966cd9af2303a54976f163Wei Jia} 197d49dbd6b625cddb82f3f7bbeac62d48ef338ef0fAndy Hung 198d49dbd6b625cddb82f3f7bbeac62d48ef338ef0fAndy Hungsp<IDataSource> TinyCacheSource::getIDataSource() const { 199d49dbd6b625cddb82f3f7bbeac62d48ef338ef0fAndy Hung return mSource->getIDataSource(); 200d49dbd6b625cddb82f3f7bbeac62d48ef338ef0fAndy Hung} 201d49dbd6b625cddb82f3f7bbeac62d48ef338ef0fAndy Hung 20299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins} // namespace android 203