Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9d035221 authored by Jeremy Meyer's avatar Jeremy Meyer
Browse files

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
parent 00b3b61f
Loading
Loading
Loading
Loading
+36 −35
Original line number Diff line number Diff line
@@ -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;
            }

            return super.read(buffer, offset, count);
            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);
            }
        }

        @Override
@@ -245,42 +256,32 @@ 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);
        }

        @Override
        public boolean markSupported() {
            if (mRemaining >= 0) {
            return false;
        }
            return super.markSupported();
        }

        @Override
        public synchronized void reset() throws IOException {
            if (mRemaining >= 0) {
            // Not supported.
            return;
        }
            super.reset();
        }
    }

    /**