Have AssetFileDescriptor.AutoCloseInputStream use pread
Previously two AssetFileDescriptors pointing to the same file could be using the same underlying file descriptor and reading from both would provide unexpected results since they would both modify the file offset in the kernel data structure. Test: Added testTwoFileDescriptorsWorkIndependently() to android.content.res.cts.AssetFileDescriptor_AutoCloseInputStreamTest Test: atest AssetFileDescriptor_AutoCloseInputStreamTest Fix: 168310122 Change-Id: I6c9f9d1de193992736bf39516ab9364af34a47cd
This commit is contained in:
@@ -21,6 +21,8 @@ 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;
|
||||
@@ -203,19 +205,22 @@ public class AssetFileDescriptor implements Parcelable, Closeable {
|
||||
*/
|
||||
public static class AutoCloseInputStream
|
||||
extends ParcelFileDescriptor.AutoCloseInputStream {
|
||||
private long mRemaining;
|
||||
private long mTotalSize;
|
||||
private final long mFileOffset;
|
||||
private long mOffset;
|
||||
|
||||
public AutoCloseInputStream(AssetFileDescriptor fd) throws IOException {
|
||||
super(fd.getParcelFileDescriptor());
|
||||
super.skip(fd.getStartOffset());
|
||||
mRemaining = (int)fd.getLength();
|
||||
mTotalSize = fd.getLength();
|
||||
mFileOffset = fd.getStartOffset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() throws IOException {
|
||||
return mRemaining >= 0
|
||||
? (mRemaining < 0x7fffffff ? (int)mRemaining : 0x7fffffff)
|
||||
: super.available();
|
||||
long available = mTotalSize - mOffset;
|
||||
return available >= 0
|
||||
? (available < 0x7fffffff ? (int) available : 0x7fffffff)
|
||||
: 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -227,15 +232,21 @@ public class AssetFileDescriptor implements Parcelable, Closeable {
|
||||
|
||||
@Override
|
||||
public int read(byte[] buffer, int offset, int count) throws IOException {
|
||||
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;
|
||||
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;
|
||||
return res;
|
||||
} catch (ErrnoException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
|
||||
return super.read(buffer, offset, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -245,41 +256,31 @@ public class AssetFileDescriptor implements Parcelable, Closeable {
|
||||
|
||||
@Override
|
||||
public long skip(long count) throws IOException {
|
||||
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;
|
||||
int available = available();
|
||||
if (available <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return super.skip(count);
|
||||
|
||||
if (count > available) count = available;
|
||||
mOffset += count;
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mark(int readlimit) {
|
||||
if (mRemaining >= 0) {
|
||||
// Not supported.
|
||||
return;
|
||||
}
|
||||
super.mark(readlimit);
|
||||
// Not supported.
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean markSupported() {
|
||||
if (mRemaining >= 0) {
|
||||
return false;
|
||||
}
|
||||
return super.markSupported();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void reset() throws IOException {
|
||||
if (mRemaining >= 0) {
|
||||
// Not supported.
|
||||
return;
|
||||
}
|
||||
super.reset();
|
||||
// Not supported.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user