summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/provider/DocumentsProvider.java26
-rw-r--r--core/java/android/provider/MetadataReader.java42
-rw-r--r--core/java/com/android/internal/content/FileSystemProvider.java24
-rw-r--r--packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java4
-rw-r--r--packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java35
-rw-r--r--packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java3
-rw-r--r--packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java6
7 files changed, 82 insertions, 58 deletions
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 2298134d469b..81b1921dd809 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -66,8 +66,6 @@ import android.util.Log;
import libcore.io.IoUtils;
import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
import java.util.LinkedList;
import java.util.Objects;
@@ -635,30 +633,6 @@ public abstract class DocumentsProvider extends ContentProvider {
}
/**
- * Returns metadata for arbitrary file given its stream and mimetype.
- *
- * <p><b>Note: Providers should only call this with streams for locally cached resources.
- * Use of network backed streams is inadvisable for performance reasons.
- *
- * @param stream The input stream. Should be backed by locally cached content.
- * Client retains ownership of the stream.
- * @param mimeType The mime type of the file.
- * @param tags The list of tags to load, if known. Pass null to get a default set.
- * @return Bundle containing any metadata found.
- * @throws IOException in the event of an error reading metadata.
- *
- * @hide
- */
- protected Bundle getDocumentMetadataFromStream(InputStream stream, String mimeType)
- throws IOException {
- Bundle metadata = new Bundle();
- // TODO: Remove the last null arg from MetadataReader. It was the "tags" value,
- // the has been removed from the getDocumentMetadata method.
- MetadataReader.getMetadata(metadata, stream, mimeType, null);
- return metadata;
- }
-
- /**
* Return concrete MIME type of the requested document. Must match the value
* of {@link Document#COLUMN_MIME_TYPE} for this document. The default
* implementation queries {@link #queryDocument(String, String[])}, so
diff --git a/core/java/android/provider/MetadataReader.java b/core/java/android/provider/MetadataReader.java
index 5aa5f72ab788..2d23c4eee130 100644
--- a/core/java/android/provider/MetadataReader.java
+++ b/core/java/android/provider/MetadataReader.java
@@ -36,29 +36,31 @@ import java.util.Map;
*/
public final class MetadataReader {
- private MetadataReader() {
- }
+ private MetadataReader() {}
private static final String[] DEFAULT_EXIF_TAGS = {
- ExifInterface.TAG_IMAGE_WIDTH,
- ExifInterface.TAG_IMAGE_LENGTH,
+ ExifInterface.TAG_APERTURE,
+ ExifInterface.TAG_COPYRIGHT,
ExifInterface.TAG_DATETIME,
+ ExifInterface.TAG_EXPOSURE_TIME,
+ ExifInterface.TAG_F_NUMBER,
ExifInterface.TAG_GPS_LATITUDE,
ExifInterface.TAG_GPS_LATITUDE_REF,
ExifInterface.TAG_GPS_LONGITUDE,
ExifInterface.TAG_GPS_LONGITUDE_REF,
+ ExifInterface.TAG_IMAGE_WIDTH,
+ ExifInterface.TAG_IMAGE_LENGTH,
ExifInterface.TAG_MAKE,
ExifInterface.TAG_MODEL,
- ExifInterface.TAG_APERTURE,
- ExifInterface.TAG_SHUTTER_SPEED_VALUE
+ ExifInterface.TAG_ORIENTATION,
+ ExifInterface.TAG_SHUTTER_SPEED_VALUE,
};
- private static final Map<String, Integer> TYPE_MAPPING = new HashMap<>();
- private static final String[] ALL_KNOWN_EXIF_KEYS;
private static final int TYPE_INT = 0;
private static final int TYPE_DOUBLE = 1;
private static final int TYPE_STRING = 2;
+ private static final Map<String, Integer> TYPE_MAPPING = new HashMap<>();
static {
// TODO: Move this over to ExifInterface.java
// Since each ExifInterface item has a type, and there's currently no way to get the type
@@ -198,11 +200,19 @@ public final class MetadataReader {
TYPE_MAPPING.put(ExifInterface.TAG_RW2_SENSOR_RIGHT_BORDER, TYPE_INT);
TYPE_MAPPING.put(ExifInterface.TAG_RW2_SENSOR_TOP_BORDER, TYPE_INT);
TYPE_MAPPING.put(ExifInterface.TAG_RW2_ISO, TYPE_INT);
- ALL_KNOWN_EXIF_KEYS = TYPE_MAPPING.keySet().toArray(new String[TYPE_MAPPING.size()]);
}
private static final String JPG_MIME_TYPE = "image/jpg";
private static final String JPEG_MIME_TYPE = "image/jpeg";
+
+ /**
+ * Returns true if caller can generally expect to get metadata results
+ * for the supplied mimetype.
+ */
+ public static boolean isSupportedMimeType(String mimeType) {
+ return JPG_MIME_TYPE.equals(mimeType) || JPEG_MIME_TYPE.equals(mimeType);
+ }
+
/**
* Generic metadata retrieval method that can retrieve any available metadata from a given doc
* Currently only functions for exifdata
@@ -228,10 +238,9 @@ public final class MetadataReader {
*/
public static void getMetadata(Bundle metadata, InputStream stream, String mimeType,
@Nullable String[] tags) throws IOException {
- List<String> metadataTypes = new ArrayList();
- if (mimeType.equals(JPG_MIME_TYPE) || mimeType.equals(JPEG_MIME_TYPE)) {
- ExifInterface exifInterface = new ExifInterface(stream);
- Bundle exifData = getExifData(exifInterface, tags);
+ List<String> metadataTypes = new ArrayList<>();
+ if (isSupportedMimeType(mimeType)) {
+ Bundle exifData = getExifData(stream, tags);
if (exifData.size() > 0) {
metadata.putBundle(DocumentsContract.METADATA_EXIF, exifData);
metadataTypes.add(DocumentsContract.METADATA_EXIF);
@@ -246,8 +255,7 @@ public final class MetadataReader {
/**
* Helper method that is called if getMetadata is called for an image mimeType.
*
- * @param exif the bundle to which we add exif data.
- * @param exifInterface an ExifInterface for an image
+ * @param stream the input stream from which to extra data.
* @param tags a list of ExifInterface tags that are used to retrieve data.
* if null, returns a default set of data from the following keys:
* ExifInterface.TAG_IMAGE_WIDTH,
@@ -262,11 +270,13 @@ public final class MetadataReader {
* ExifInterface.TAG_APERTURE,
* ExifInterface.TAG_SHUTTER_SPEED_VALUE
*/
- private static Bundle getExifData(ExifInterface exifInterface, @Nullable String[] tags)
+ private static Bundle getExifData(InputStream stream, @Nullable String[] tags)
throws IOException {
if (tags == null) {
tags = DEFAULT_EXIF_TAGS;
}
+
+ ExifInterface exifInterface = new ExifInterface(stream);
Bundle exif = new Bundle();
for (String tag : tags) {
if (TYPE_MAPPING.get(tag).equals(TYPE_INT)) {
diff --git a/core/java/com/android/internal/content/FileSystemProvider.java b/core/java/com/android/internal/content/FileSystemProvider.java
index 8c805accfbc5..e3a9b7e41d5b 100644
--- a/core/java/com/android/internal/content/FileSystemProvider.java
+++ b/core/java/com/android/internal/content/FileSystemProvider.java
@@ -28,7 +28,6 @@ import android.database.MatrixCursor.RowBuilder;
import android.graphics.Point;
import android.net.Uri;
import android.os.Binder;
-import android.os.Build;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.FileObserver;
@@ -39,6 +38,7 @@ import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsProvider;
import android.provider.MediaStore;
+import android.provider.MetadataReader;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
@@ -52,6 +52,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
@@ -120,26 +121,31 @@ public abstract class FileSystemProvider extends DocumentsProvider {
if (!file.isFile()) {
Log.w(TAG, "Can't stream non-regular file. Returning empty metadata.");
- return Bundle.EMPTY;
+ return null;
}
if (!file.canRead()) {
Log.w(TAG, "Can't stream non-readable file. Returning empty metadata.");
- return Bundle.EMPTY;
+ return null;
}
- String filePath = file.getAbsolutePath();
- FileInputStream stream = new FileInputStream(filePath);
+ String mimeType = getTypeForFile(file);
+ if (!MetadataReader.isSupportedMimeType(mimeType)) {
+ return null;
+ }
+ InputStream stream = null;
try {
- return getDocumentMetadataFromStream(stream, getTypeForFile(file));
+ Bundle metadata = new Bundle();
+ stream = new FileInputStream(file.getAbsolutePath());
+ MetadataReader.getMetadata(metadata, stream, mimeType, null);
+ return metadata;
} catch (IOException e) {
Log.e(TAG, "An error occurred retrieving the metadata", e);
+ return null;
} finally {
IoUtils.closeQuietly(stream);
}
-
- return null;
}
protected final List<String> findDocumentPath(File parent, File doc)
@@ -502,7 +508,7 @@ public abstract class FileSystemProvider extends DocumentsProvider {
}
protected boolean typeSupportsMetadata(String mimeType) {
- return MIMETYPE_JPG.equals(mimeType) || MIMETYPE_JPEG.equals(mimeType);
+ return MetadataReader.isSupportedMimeType(mimeType);
}
private static String getTypeForName(String name) {
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
index 9b5982b96e31..f243b51d6769 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
@@ -34,6 +34,7 @@ import android.mtp.MtpConstants;
import android.mtp.MtpObjectInfo;
import android.net.Uri;
import android.provider.DocumentsContract;
+import android.provider.MetadataReader;
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Root;
@@ -900,6 +901,9 @@ class MtpDatabase {
protectionState == MtpConstants.PROTECTION_STATUS_NONE) {
flag |= Document.FLAG_DIR_SUPPORTS_CREATE;
}
+ if (MetadataReader.isSupportedMimeType(mimeType)) {
+ flag |= Document.FLAG_SUPPORTS_METADATA;
+ }
if (thumbnailSize > 0) {
flag |= Document.FLAG_SUPPORTS_THUMBNAIL;
}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
index eb2d8aa71955..8c8116bd342a 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
@@ -16,6 +16,7 @@
package com.android.mtp;
+import android.annotation.Nullable;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
@@ -37,11 +38,12 @@ import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
import android.os.ProxyFileDescriptorCallback;
import android.os.storage.StorageManager;
+import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Path;
import android.provider.DocumentsContract.Root;
-import android.provider.DocumentsContract;
import android.provider.DocumentsProvider;
+import android.provider.MetadataReader;
import android.provider.Settings;
import android.system.ErrnoException;
import android.system.OsConstants;
@@ -50,14 +52,16 @@ import android.util.Log;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import libcore.io.IoUtils;
+
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.io.InputStream;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeoutException;
-import libcore.io.IoUtils;
/**
* DocumentsProvider for MTP devices.
@@ -107,7 +111,7 @@ public class MtpDocumentsProvider extends DocumentsProvider {
mResources = getContext().getResources();
mMtpManager = new MtpManager(getContext());
mResolver = getContext().getContentResolver();
- mDeviceToolkits = new HashMap<Integer, DeviceToolkit>();
+ mDeviceToolkits = new HashMap<>();
mDatabase = new MtpDatabase(getContext(), MtpDatabaseConstants.FLAG_DATABASE_IN_FILE);
mRootScanner = new RootScanner(mResolver, mMtpManager, mDatabase);
mIntentSender = new ServiceIntentSender(getContext());
@@ -151,7 +155,7 @@ public class MtpDocumentsProvider extends DocumentsProvider {
mResources = resources;
mMtpManager = mtpManager;
mResolver = resolver;
- mDeviceToolkits = new HashMap<Integer, DeviceToolkit>();
+ mDeviceToolkits = new HashMap<>();
mDatabase = database;
mRootScanner = new RootScanner(mResolver, mMtpManager, mDatabase);
mIntentSender = intentSender;
@@ -548,6 +552,29 @@ public class MtpDocumentsProvider extends DocumentsProvider {
}
}
+ @Override
+ public @Nullable Bundle getDocumentMetadata(String docId) throws FileNotFoundException {
+ String mimeType = getDocumentType(docId);
+
+ if (!MetadataReader.isSupportedMimeType(mimeType)) {
+ return null;
+ }
+
+ InputStream stream = null;
+ try {
+ stream = new ParcelFileDescriptor.AutoCloseInputStream(
+ openDocument(docId, "r", null));
+ Bundle metadata = new Bundle();
+ MetadataReader.getMetadata(metadata, stream, mimeType, null);
+ return metadata;
+ } catch (IOException e) {
+ Log.e(TAG, "An error occurred retrieving the metadata", e);
+ return null;
+ } finally {
+ IoUtils.closeQuietly(stream);
+ }
+ }
+
void openDevice(int deviceId) throws IOException {
synchronized (mDeviceListLock) {
if (mDeviceToolkits.containsKey(deviceId)) {
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
index 7fe6cb963522..32b169e6fa9f 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
@@ -237,7 +237,8 @@ public class MtpDatabaseTest extends AndroidTestCase {
assertEquals(
COLUMN_FLAGS,
DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
- DocumentsContract.Document.FLAG_SUPPORTS_WRITE,
+ DocumentsContract.Document.FLAG_SUPPORTS_WRITE |
+ DocumentsContract.Document.FLAG_SUPPORTS_METADATA,
cursor.getInt(9));
assertEquals(2 * 1024 * 1024, getInt(cursor, COLUMN_SIZE));
assertEquals(
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
index 3fa5eb581ef7..65c86dfb6d4c 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
@@ -329,7 +329,8 @@ public class MtpDocumentsProviderTest extends AndroidTestCase {
assertEquals(
DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
DocumentsContract.Document.FLAG_SUPPORTS_WRITE |
- DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL,
+ DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL |
+ DocumentsContract.Document.FLAG_SUPPORTS_METADATA,
cursor.getInt(4));
assertEquals(1024 * 1024 * 5, cursor.getInt(5));
}
@@ -474,7 +475,8 @@ public class MtpDocumentsProviderTest extends AndroidTestCase {
assertEquals("image/jpeg", cursor.getString(1));
assertEquals("image.jpg", cursor.getString(2));
assertEquals(0, cursor.getLong(3));
- assertEquals(Document.FLAG_SUPPORTS_THUMBNAIL, cursor.getInt(4));
+ assertEquals(Document.FLAG_SUPPORTS_THUMBNAIL
+ | Document.FLAG_SUPPORTS_METADATA, cursor.getInt(4));
assertEquals(1024 * 1024 * 5, cursor.getInt(5));
cursor.close();