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

Commit 96fc0a49 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Revert "Have AssetFileDescriptor.AutoCloseInputStream use pread"" into...

Merge "Revert "Have AssetFileDescriptor.AutoCloseInputStream use pread"" into udc-dev am: 138683c1

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/22378297



Change-Id: I9c5b79353f4e37d172d80aa5c5a302a885e00468
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 96d25e70 138683c1
Loading
Loading
Loading
Loading
+33 −201
Original line number Original line Diff line number Diff line
@@ -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;
            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;
                return res;
            } catch (ErrnoException e) {
                throw new IOException(e);
            }
            }

            return super.read(buffer, offset, count);
        }
        }


        @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);
            }
        }
        }
    }
    }