Revert "Have AssetFileDescriptor.AutoCloseInputStream use pread"
Revert submission 20068774-b-168310122 Reason for revert: This caused b/263325931 Bug: b/263325931 Reverted changes: /q/submissionid:20068774-b-168310122 (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:f2ad1a434b34394a95c187e78998f2955d89efa5) Merged-In: I3af382c65d9b230901ff15575e394bdcb4e953ef Change-Id: I3af382c65d9b230901ff15575e394bdcb4e953ef
This commit is contained in:
@@ -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 (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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user