am 963cd006: Allow creating AssetFileDescriptors for MemoryFiles.

Merge commit '963cd006c45716b034f656bf7e7179e6476f7e4d'

* commit '963cd006c45716b034f656bf7e7179e6476f7e4d':
  Allow creating AssetFileDescriptors for MemoryFiles.
This commit is contained in:
Bjorn Bringert
2009-06-03 04:56:49 -07:00
committed by The Android Open Source Project
7 changed files with 575 additions and 12 deletions

View File

@@ -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
@@ -123,6 +126,13 @@ public class AssetFileDescriptor implements Parcelable {
mFd.close();
}
/**
* 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
@@ -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);
}
@@ -261,6 +277,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
@@ -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());
}
}