diff options
| -rw-r--r-- | core/java/android/content/res/AssetFileDescriptor.java | 234 |
1 files changed, 33 insertions, 201 deletions
diff --git a/core/java/android/content/res/AssetFileDescriptor.java b/core/java/android/content/res/AssetFileDescriptor.java index d2a6f03cc1a1..ac65933db136 100644 --- a/core/java/android/content/res/AssetFileDescriptor.java +++ b/core/java/android/content/res/AssetFileDescriptor.java @@ -21,20 +21,12 @@ import android.os.Bundle; import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.Parcelable; -import android.system.ErrnoException; -import android.system.Os; import java.io.Closeable; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileOutputStream; 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 @@ -211,26 +203,19 @@ public class AssetFileDescriptor implements Parcelable, Closeable { */ public static class AutoCloseInputStream extends ParcelFileDescriptor.AutoCloseInputStream { - /** Size of current file. */ - 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; + private long mRemaining; public AutoCloseInputStream(AssetFileDescriptor fd) throws IOException { super(fd.getParcelFileDescriptor()); - mTotalSize = fd.getLength(); - mFileOffset = fd.getStartOffset(); + super.skip(fd.getStartOffset()); + mRemaining = (int) fd.getLength(); } @Override public int available() throws IOException { - long available = mTotalSize - mOffset; - return available >= 0 - ? (available < 0x7fffffff ? (int) available : 0x7fffffff) - : 0; + return mRemaining >= 0 + ? (mRemaining < 0x7fffffff ? (int) mRemaining : 0x7fffffff) + : super.available(); } @Override @@ -242,24 +227,15 @@ public class AssetFileDescriptor implements Parcelable, Closeable { @Override public int read(byte[] buffer, int offset, int count) throws IOException { - int available = available(); - if (available <= 0) { - return -1; - } - - if (count > available) count = available; - 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); - } + if (mRemaining >= 0) { + if (mRemaining == 0) return -1; + if (count > mRemaining) count = (int) mRemaining; + int res = super.read(buffer, offset, count); + if (res >= 0) mRemaining -= res; return res; - } catch (ErrnoException e) { - throw new IOException(e); } + + return super.read(buffer, offset, count); } @Override @@ -269,185 +245,41 @@ public class AssetFileDescriptor implements Parcelable, Closeable { @Override public long skip(long count) throws IOException { - int available = available(); - if (available <= 0) { - return -1; + if (mRemaining >= 0) { + if (mRemaining == 0) return -1; + if (count > mRemaining) count = mRemaining; + long res = super.skip(count); + if (res >= 0) mRemaining -= res; + return res; } - if (count > available) count = available; - mOffset += count; - updateChannelPosition(mOffset + mFileOffset); - return count; + return super.skip(count); } @Override public void mark(int readlimit) { - // Not supported. - return; + if (mRemaining >= 0) { + // Not supported. + return; + } + super.mark(readlimit); } @Override public boolean markSupported() { - return false; + if (mRemaining >= 0) { + return false; + } + return super.markSupported(); } @Override public synchronized void reset() throws IOException { - // Not supported. - return; - } - - @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); + if (mRemaining >= 0) { + // Not supported. + return; } + super.reset(); } } |