1a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik/* 2a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik * Copyright (C) 2013 The Android Open Source Project 3a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik * 4a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik * Licensed under the Apache License, Version 2.0 (the "License"); 5a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik * you may not use this file except in compliance with the License. 6a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik * You may obtain a copy of the License at 7a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik * 8a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik * http://www.apache.org/licenses/LICENSE-2.0 9a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik * 10a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik * Unless required by applicable law or agreed to in writing, software 11a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik * distributed under the License is distributed on an "AS IS" BASIS, 12a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik * See the License for the specific language governing permissions and 14a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik * limitations under the License. 15a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik */ 16a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 17a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik#define LOG_TAG "Stream" 18a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 19a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik#include "Stream.h" 20a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 21a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik#include <string.h> 22a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 23a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik#include "JNIHelpers.h" 24a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik#include "utils/log.h" 25a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik#include "utils/math.h" 26a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 27a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craikstatic struct { 28a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik jmethodID read; 29a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik jmethodID reset; 30a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik} gInputStreamClassInfo; 31a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 32a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris CraikStream::Stream() 33a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik : mPeekBuffer(0) 34a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik , mPeekSize(0) 35a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik , mPeekOffset(0) { 36a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik} 37a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 38a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris CraikStream::~Stream() { 39a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik delete mPeekBuffer; 40a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik} 41a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 42a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craiksize_t Stream::peek(void* buffer, size_t size) { 43a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik size_t peek_remaining = mPeekSize - mPeekOffset; 44a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik if (size > peek_remaining) { 45a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik char* old_peek = mPeekBuffer; 46a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik mPeekBuffer = new char[size]; 47a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik if (old_peek) { 48a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik memcpy(mPeekBuffer, old_peek + mPeekOffset, peek_remaining); 49a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik delete old_peek; 50a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik } 51a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik size_t read = doRead(mPeekBuffer + mPeekOffset, size - peek_remaining); 52a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik mPeekOffset = 0; 53a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik mPeekSize = peek_remaining + read; 54a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik } 55a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik size = min(size, mPeekSize - mPeekOffset); 56a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik memcpy(buffer, mPeekBuffer + mPeekOffset, size); 57a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik return size; 58a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik} 59a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 60a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craiksize_t Stream::read(void* buffer, size_t size) { 61a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik size_t bytes_read = 0; 62a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik size_t peek_remaining = mPeekSize - mPeekOffset; 63a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik if (peek_remaining) { 64a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik bytes_read = min(size, peek_remaining); 65a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik memcpy(buffer, mPeekBuffer + mPeekOffset, bytes_read); 66a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik mPeekOffset += bytes_read; 67a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik if (mPeekOffset == mPeekSize) { 68a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik delete mPeekBuffer; 69a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik mPeekBuffer = 0; 70a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik mPeekOffset = 0; 71a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik mPeekSize = 0; 72a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik } 73a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik size -= bytes_read; 74a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik buffer = ((char*) buffer) + bytes_read; 75a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik } 76a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik if (size) { 77a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik bytes_read += doRead(buffer, size); 78a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik } 79a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik return bytes_read; 80a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik} 81a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 82a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craiksize_t MemoryStream::doRead(void* buffer, size_t size) { 83a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik size = min(size, mRemaining); 84a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik memcpy(buffer, mBuffer, size); 85a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik mBuffer += size; 86a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik mRemaining -= size; 87a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik return size; 88a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik} 89a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 90a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craiksize_t FileStream::doRead(void* buffer, size_t size) { 91a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik return fread(buffer, 1, size, mFd); 92a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik} 93a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 94a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craiksize_t JavaInputStream::doRead(void* dstBuffer, size_t size) { 95a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik size_t totalBytesRead = 0; 96a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 97a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik do { 98a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik size_t requested = min(size, mByteArrayLength); 99a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 100a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik jint bytesRead = mEnv->CallIntMethod(mInputStream, 101a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik gInputStreamClassInfo.read, mByteArray, 0, requested); 102a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik if (mEnv->ExceptionCheck() || bytesRead < 0) { 103a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik return 0; 104a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik } 105a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 106a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik mEnv->GetByteArrayRegion(mByteArray, 0, bytesRead, (jbyte*)dstBuffer); 107a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik dstBuffer = (char*)dstBuffer + bytesRead; 108a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik totalBytesRead += bytesRead; 109a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik size -= bytesRead; 110a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik } while (size > 0); 111a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 112a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik return totalBytesRead; 113a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik} 114a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik 115a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craikjint JavaStream_OnLoad(JNIEnv* env) { 116a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik // Skip the verbose logging on error for these, as they won't be subject 117a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik // to obfuscators or similar and are thus unlikely to ever fail 118a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik jclass inputStreamClazz = env->FindClass("java/io/InputStream"); 119a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik if (!inputStreamClazz) { 120a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik return -1; 121a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik } 122a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik gInputStreamClassInfo.read = env->GetMethodID(inputStreamClazz, "read", "([BII)I"); 123a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik gInputStreamClassInfo.reset = env->GetMethodID(inputStreamClazz, "reset", "()V"); 124a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik if (!gInputStreamClassInfo.read || !gInputStreamClassInfo.reset) { 125a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik return -1; 126a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik } 127a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik return 0; 128a1265c3d8a20e805e0c45083d5c7d728d4b70009Chris Craik} 129