diff options
Diffstat (limited to 'core/java/android/content')
| -rw-r--r-- | core/java/android/content/res/AssetFileDescriptor.java | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/core/java/android/content/res/AssetFileDescriptor.java b/core/java/android/content/res/AssetFileDescriptor.java index 231e3e2..a37e4e8 100644 --- a/core/java/android/content/res/AssetFileDescriptor.java +++ b/core/java/android/content/res/AssetFileDescriptor.java @@ -16,6 +16,7 @@ package android.content.res; +import android.os.MemoryFile; import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.Parcelable; @@ -24,6 +25,8 @@ import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; +import java.nio.channels.FileChannel; /** * File descriptor of an entry in the AssetManager. This provides your own @@ -124,6 +127,13 @@ public class AssetFileDescriptor implements Parcelable { } /** + * Checks whether this file descriptor is for a memory file. + */ + private boolean isMemoryFile() throws IOException { + return MemoryFile.isMemoryFile(mFd.getFileDescriptor()); + } + + /** * Create and return a new auto-close input stream for this asset. This * will either return a full asset {@link AutoCloseInputStream}, or * an underlying {@link ParcelFileDescriptor.AutoCloseInputStream @@ -132,6 +142,12 @@ public class AssetFileDescriptor implements Parcelable { * should only call this once for a particular asset. */ public FileInputStream createInputStream() throws IOException { + if (isMemoryFile()) { + if (mLength > Integer.MAX_VALUE) { + throw new IOException("File length too large for a memory file: " + mLength); + } + return new AutoCloseMemoryFileInputStream(mFd, (int)mLength); + } if (mLength < 0) { return new ParcelFileDescriptor.AutoCloseInputStream(mFd); } @@ -262,6 +278,66 @@ public class AssetFileDescriptor implements Parcelable { } /** + * An input stream that reads from a MemoryFile and closes it when the stream is closed. + * This extends FileInputStream just because {@link #createInputStream} returns + * a FileInputStream. All the FileInputStream methods are + * overridden to use the MemoryFile instead. + */ + private static class AutoCloseMemoryFileInputStream extends FileInputStream { + private ParcelFileDescriptor mParcelFd; + private MemoryFile mFile; + private InputStream mStream; + + public AutoCloseMemoryFileInputStream(ParcelFileDescriptor fd, int length) + throws IOException { + super(fd.getFileDescriptor()); + mParcelFd = fd; + mFile = new MemoryFile(fd.getFileDescriptor(), length, "r"); + mStream = mFile.getInputStream(); + } + + @Override + public int available() throws IOException { + return mStream.available(); + } + + @Override + public void close() throws IOException { + mParcelFd.close(); // must close ParcelFileDescriptor, not just the file descriptor, + // since it could be a subclass of ParcelFileDescriptor. + // E.g. ContentResolver.ParcelFileDescriptorInner.close() releases + // a content provider + mFile.close(); // to unmap the memory file from the address space. + mStream.close(); // doesn't actually do anything + } + + @Override + public FileChannel getChannel() { + return null; + } + + @Override + public int read() throws IOException { + return mStream.read(); + } + + @Override + public int read(byte[] buffer, int offset, int count) throws IOException { + return mStream.read(buffer, offset, count); + } + + @Override + public int read(byte[] buffer) throws IOException { + return mStream.read(buffer); + } + + @Override + public long skip(long count) throws IOException { + return mStream.skip(count); + } + } + + /** * An OutputStream you can create on a ParcelFileDescriptor, which will * take care of calling {@link ParcelFileDescriptor#close * ParcelFileDescritor.close()} for you when the stream is closed. @@ -345,4 +421,16 @@ public class AssetFileDescriptor implements Parcelable { return new AssetFileDescriptor[size]; } }; + + /** + * Creates an AssetFileDescriptor from a memory file. + * + * @hide + */ + public static AssetFileDescriptor fromMemoryFile(MemoryFile memoryFile) + throws IOException { + ParcelFileDescriptor fd = memoryFile.getParcelFileDescriptor(); + return new AssetFileDescriptor(fd, 0, memoryFile.length()); + } + } |
