Merge "Revert "Have AssetFileDescriptor.AutoCloseInputStream use pread"" into udc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
138683c165
@@ -21,20 +21,12 @@ import android.os.Bundle;
|
|||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.system.ErrnoException;
|
|
||||||
import android.system.Os;
|
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.MappedByteBuffer;
|
|
||||||
import java.nio.channels.FileChannel;
|
|
||||||
import java.nio.channels.FileLock;
|
|
||||||
import java.nio.channels.ReadableByteChannel;
|
|
||||||
import java.nio.channels.WritableByteChannel;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File descriptor of an entry in the AssetManager. This provides your own
|
* File descriptor of an entry in the AssetManager. This provides your own
|
||||||
@@ -211,26 +203,19 @@ public class AssetFileDescriptor implements Parcelable, Closeable {
|
|||||||
*/
|
*/
|
||||||
public static class AutoCloseInputStream
|
public static class AutoCloseInputStream
|
||||||
extends ParcelFileDescriptor.AutoCloseInputStream {
|
extends ParcelFileDescriptor.AutoCloseInputStream {
|
||||||
/** Size of current file. */
|
private long mRemaining;
|
||||||
private long mTotalSize;
|
|
||||||
/** The absolute position of current file start point. */
|
|
||||||
private final long mFileOffset;
|
|
||||||
/** The relative position where input stream is against mFileOffset. */
|
|
||||||
private long mOffset;
|
|
||||||
private OffsetCorrectFileChannel mOffsetCorrectFileChannel;
|
|
||||||
|
|
||||||
public AutoCloseInputStream(AssetFileDescriptor fd) throws IOException {
|
public AutoCloseInputStream(AssetFileDescriptor fd) throws IOException {
|
||||||
super(fd.getParcelFileDescriptor());
|
super(fd.getParcelFileDescriptor());
|
||||||
mTotalSize = fd.getLength();
|
super.skip(fd.getStartOffset());
|
||||||
mFileOffset = fd.getStartOffset();
|
mRemaining = (int) fd.getLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int available() throws IOException {
|
public int available() throws IOException {
|
||||||
long available = mTotalSize - mOffset;
|
return mRemaining >= 0
|
||||||
return available >= 0
|
? (mRemaining < 0x7fffffff ? (int) mRemaining : 0x7fffffff)
|
||||||
? (available < 0x7fffffff ? (int) available : 0x7fffffff)
|
: super.available();
|
||||||
: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -242,24 +227,15 @@ public class AssetFileDescriptor implements Parcelable, Closeable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(byte[] buffer, int offset, int count) throws IOException {
|
public int read(byte[] buffer, int offset, int count) throws IOException {
|
||||||
int available = available();
|
if (mRemaining >= 0) {
|
||||||
if (available <= 0) {
|
if (mRemaining == 0) return -1;
|
||||||
return -1;
|
if (count > mRemaining) count = (int) mRemaining;
|
||||||
|
int res = super.read(buffer, offset, count);
|
||||||
|
if (res >= 0) mRemaining -= res;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count > available) count = available;
|
return super.read(buffer, offset, count);
|
||||||
try {
|
|
||||||
int res = Os.pread(getFD(), buffer, offset, count, mFileOffset + mOffset);
|
|
||||||
// pread returns 0 at end of file, while java's InputStream interface requires -1
|
|
||||||
if (res == 0) res = -1;
|
|
||||||
if (res > 0) {
|
|
||||||
mOffset += res;
|
|
||||||
updateChannelPosition(mOffset + mFileOffset);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
} catch (ErrnoException e) {
|
|
||||||
throw new IOException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -269,185 +245,41 @@ public class AssetFileDescriptor implements Parcelable, Closeable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long skip(long count) throws IOException {
|
public long skip(long count) throws IOException {
|
||||||
int available = available();
|
if (mRemaining >= 0) {
|
||||||
if (available <= 0) {
|
if (mRemaining == 0) return -1;
|
||||||
return -1;
|
if (count > mRemaining) count = mRemaining;
|
||||||
|
long res = super.skip(count);
|
||||||
|
if (res >= 0) mRemaining -= res;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count > available) count = available;
|
return super.skip(count);
|
||||||
mOffset += count;
|
|
||||||
updateChannelPosition(mOffset + mFileOffset);
|
|
||||||
return count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mark(int readlimit) {
|
public void mark(int readlimit) {
|
||||||
|
if (mRemaining >= 0) {
|
||||||
// Not supported.
|
// Not supported.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
super.mark(readlimit);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean markSupported() {
|
public boolean markSupported() {
|
||||||
|
if (mRemaining >= 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
return super.markSupported();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void reset() throws IOException {
|
public synchronized void reset() throws IOException {
|
||||||
|
if (mRemaining >= 0) {
|
||||||
// Not supported.
|
// Not supported.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
super.reset();
|
||||||
@Override
|
|
||||||
public FileChannel getChannel() {
|
|
||||||
if (mOffsetCorrectFileChannel == null) {
|
|
||||||
mOffsetCorrectFileChannel = new OffsetCorrectFileChannel(super.getChannel());
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
updateChannelPosition(mOffset + mFileOffset);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
return mOffsetCorrectFileChannel;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the position of mOffsetCorrectFileChannel only after it is constructed.
|
|
||||||
*
|
|
||||||
* @param newPosition The absolute position mOffsetCorrectFileChannel needs to be moved to.
|
|
||||||
*/
|
|
||||||
private void updateChannelPosition(long newPosition) throws IOException {
|
|
||||||
if (mOffsetCorrectFileChannel != null) {
|
|
||||||
mOffsetCorrectFileChannel.position(newPosition);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A FileChannel wrapper that will update mOffset of the AutoCloseInputStream
|
|
||||||
* to correct position when using FileChannel to read. All occurrence of position
|
|
||||||
* should be using absolute solution and each override method just do Delegation
|
|
||||||
* besides additional check. All methods related to write mode have been disabled
|
|
||||||
* and will throw UnsupportedOperationException with customized message.
|
|
||||||
*/
|
|
||||||
private class OffsetCorrectFileChannel extends FileChannel {
|
|
||||||
private final FileChannel mDelegate;
|
|
||||||
private static final String METHOD_NOT_SUPPORTED_MESSAGE =
|
|
||||||
"This Method is not supported in AutoCloseInputStream FileChannel.";
|
|
||||||
|
|
||||||
OffsetCorrectFileChannel(FileChannel fc) {
|
|
||||||
mDelegate = fc;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int read(ByteBuffer dst) throws IOException {
|
|
||||||
if (available() <= 0) return -1;
|
|
||||||
int bytesRead = mDelegate.read(dst);
|
|
||||||
if (bytesRead != -1) mOffset += bytesRead;
|
|
||||||
return bytesRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long read(ByteBuffer[] dsts, int offset, int length) throws IOException {
|
|
||||||
if (available() <= 0) return -1;
|
|
||||||
if (mOffset + length > mTotalSize) {
|
|
||||||
length = (int) (mTotalSize - mOffset);
|
|
||||||
}
|
|
||||||
long bytesRead = mDelegate.read(dsts, offset, length);
|
|
||||||
if (bytesRead != -1) mOffset += bytesRead;
|
|
||||||
return bytesRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
/**The only read method that does not move channel position*/
|
|
||||||
public int read(ByteBuffer dst, long position) throws IOException {
|
|
||||||
if (position - mFileOffset > mTotalSize) return -1;
|
|
||||||
return mDelegate.read(dst, position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long position() throws IOException {
|
|
||||||
return mDelegate.position();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FileChannel position(long newPosition) throws IOException {
|
|
||||||
mOffset = newPosition - mFileOffset;
|
|
||||||
return mDelegate.position(newPosition);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long size() throws IOException {
|
|
||||||
return mTotalSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long transferTo(long position, long count, WritableByteChannel target)
|
|
||||||
throws IOException {
|
|
||||||
if (position - mFileOffset > mTotalSize) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (position - mFileOffset + count > mTotalSize) {
|
|
||||||
count = mTotalSize - (position - mFileOffset);
|
|
||||||
}
|
|
||||||
return mDelegate.transferTo(position, count, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MappedByteBuffer map(MapMode mode, long position, long size) throws IOException {
|
|
||||||
if (position - mFileOffset > mTotalSize) {
|
|
||||||
throw new IOException(
|
|
||||||
"Cannot map to buffer because position exceed current file size.");
|
|
||||||
}
|
|
||||||
if (position - mFileOffset + size > mTotalSize) {
|
|
||||||
size = mTotalSize - (position - mFileOffset);
|
|
||||||
}
|
|
||||||
return mDelegate.map(mode, position, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void implCloseChannel() throws IOException {
|
|
||||||
mDelegate.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int write(ByteBuffer src) throws IOException {
|
|
||||||
throw new UnsupportedOperationException(METHOD_NOT_SUPPORTED_MESSAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long write(ByteBuffer[] srcs, int offset, int length) throws IOException {
|
|
||||||
throw new UnsupportedOperationException(METHOD_NOT_SUPPORTED_MESSAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int write(ByteBuffer src, long position) throws IOException {
|
|
||||||
throw new UnsupportedOperationException(METHOD_NOT_SUPPORTED_MESSAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long transferFrom(ReadableByteChannel src, long position, long count)
|
|
||||||
throws IOException {
|
|
||||||
throw new UnsupportedOperationException(METHOD_NOT_SUPPORTED_MESSAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FileChannel truncate(long size) throws IOException {
|
|
||||||
throw new UnsupportedOperationException(METHOD_NOT_SUPPORTED_MESSAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void force(boolean metaData) throws IOException {
|
|
||||||
throw new UnsupportedOperationException(METHOD_NOT_SUPPORTED_MESSAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FileLock lock(long position, long size, boolean shared) throws IOException {
|
|
||||||
throw new UnsupportedOperationException(METHOD_NOT_SUPPORTED_MESSAGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FileLock tryLock(long position, long size, boolean shared) throws IOException {
|
|
||||||
throw new UnsupportedOperationException(METHOD_NOT_SUPPORTED_MESSAGE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user