summaryrefslogtreecommitdiffstats
path: root/core/java/android/content
diff options
context:
space:
mode:
authorBjorn Bringert <bringert@android.com>2009-05-29 14:05:12 +0100
committerBjorn Bringert <bringert@android.com>2009-06-03 12:53:42 +0100
commit963cd006c45716b034f656bf7e7179e6476f7e4d (patch)
treefddf34e58d6cb5b7b8fb5afe0df3e98a76e7f959 /core/java/android/content
parent8dbe612dc60526d635e57257b58627b33a099678 (diff)
downloadframeworks_base-963cd006c45716b034f656bf7e7179e6476f7e4d.zip
frameworks_base-963cd006c45716b034f656bf7e7179e6476f7e4d.tar.gz
frameworks_base-963cd006c45716b034f656bf7e7179e6476f7e4d.tar.bz2
Allow creating AssetFileDescriptors for MemoryFiles.
This allows content providers to use in-memory data to implement ContentProvider.openAssetFile(), instead of just normal files and sockets as before. To test cross-process use of AssetFileDescriptors for MemoryFiles, a test content provider and a client for it are added to AndroidTests. Fixes http://b/issue?id=1871731
Diffstat (limited to 'core/java/android/content')
-rw-r--r--core/java/android/content/res/AssetFileDescriptor.java88
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());
+ }
+
}