am 963cd006: Allow creating AssetFileDescriptors for MemoryFiles.
Merge commit '963cd006c45716b034f656bf7e7179e6476f7e4d' * commit '963cd006c45716b034f656bf7e7179e6476f7e4d': Allow creating AssetFileDescriptors for MemoryFiles.
This commit is contained in:
committed by
The Android Open Source Project
commit
c0cbfda0fe
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user