Remove libexif usage from libmedia_jni.so
Test: manual, connect with MTP and PTP
Change-Id: I33128db25b8aae60df7854c61fc2a3873a1bced9
(cherry picked from commit f7ec16802c0ff22feeaed9d4011c4a18c9d0dd96)
(cherry picked from commit efb865ace2885723d37e0ef9e6bae695d6dcabb0)
(cherry picked from commit 5954d210d324bd97fc585b6a238a15d1d52e64a1)
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index 4ac6d35..16ba63b 100755
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -25,6 +25,7 @@
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
+import android.media.ExifInterface;
import android.net.Uri;
import android.os.BatteryManager;
import android.os.RemoteException;
@@ -47,6 +48,7 @@
import com.google.android.collect.Sets;
import java.io.File;
+import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
@@ -799,6 +801,54 @@
}
@VisibleForNative
+ private boolean getThumbnailInfo(int handle, long[] outLongs) {
+ MtpStorageManager.MtpObject obj = mManager.getObject(handle);
+ if (obj == null) {
+ return false;
+ }
+
+ String path = obj.getPath().toString();
+ switch (obj.getFormat()) {
+ case MtpConstants.FORMAT_HEIF:
+ case MtpConstants.FORMAT_EXIF_JPEG:
+ case MtpConstants.FORMAT_JFIF:
+ try {
+ ExifInterface exif = new ExifInterface(path);
+ long[] thumbOffsetAndSize = exif.getThumbnailRange();
+ outLongs[0] = thumbOffsetAndSize != null ? thumbOffsetAndSize[1] : 0;
+ outLongs[1] = exif.getAttributeInt(ExifInterface.TAG_PIXEL_X_DIMENSION, 0);
+ outLongs[2] = exif.getAttributeInt(ExifInterface.TAG_PIXEL_Y_DIMENSION, 0);
+ return true;
+ } catch (IOException e) {
+ // ignore and fall through
+ }
+ }
+ return false;
+ }
+
+ @VisibleForNative
+ private byte[] getThumbnailData(int handle) {
+ MtpStorageManager.MtpObject obj = mManager.getObject(handle);
+ if (obj == null) {
+ return null;
+ }
+
+ String path = obj.getPath().toString();
+ switch (obj.getFormat()) {
+ case MtpConstants.FORMAT_HEIF:
+ case MtpConstants.FORMAT_EXIF_JPEG:
+ case MtpConstants.FORMAT_JFIF:
+ try {
+ ExifInterface exif = new ExifInterface(path);
+ return exif.getThumbnail();
+ } catch (IOException e) {
+ // ignore and fall through
+ }
+ }
+ return null;
+ }
+
+ @VisibleForNative
private int beginDeleteObject(int handle) {
MtpStorageManager.MtpObject obj = mManager.getObject(handle);
if (obj == null) {
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index 10f76b0..c49b1e4 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -47,7 +47,6 @@
"libstagefright_foundation",
"libcamera_client",
"libmtp",
- "libexif",
"libpiex",
"libprocessgroup",
"libandroidfw",
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 1f89d86..0a3b47b 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -30,13 +30,6 @@
#include "src/piex_types.h"
#include "src/piex.h"
-extern "C" {
-#include "libexif/exif-content.h"
-#include "libexif/exif-data.h"
-#include "libexif/exif-tag.h"
-#include "libexif/exif-utils.h"
-}
-
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/Log.h>
#include <jni.h>
@@ -70,6 +63,8 @@
static jmethodID method_getObjectPropertyList;
static jmethodID method_getObjectInfo;
static jmethodID method_getObjectFilePath;
+static jmethodID method_getThumbnailInfo;
+static jmethodID method_getThumbnailData;
static jmethodID method_beginDeleteObject;
static jmethodID method_endDeleteObject;
static jmethodID method_beginMoveObject;
@@ -219,7 +214,7 @@
return; // Already threw.
}
mIntBuffer = (jintArray)env->NewGlobalRef(intArray);
- jlongArray longArray = env->NewLongArray(2);
+ jlongArray longArray = env->NewLongArray(3);
if (!longArray) {
return; // Already threw.
}
@@ -780,57 +775,6 @@
return result;
}
-static void foreachentry(ExifEntry *entry, void* /* user */) {
- char buf[1024];
- ALOGI("entry %x, format %d, size %d: %s",
- entry->tag, entry->format, entry->size, exif_entry_get_value(entry, buf, sizeof(buf)));
-}
-
-static void foreachcontent(ExifContent *content, void *user) {
- ALOGI("content %d", exif_content_get_ifd(content));
- exif_content_foreach_entry(content, foreachentry, user);
-}
-
-static long getLongFromExifEntry(ExifEntry *e) {
- ExifByteOrder o = exif_data_get_byte_order(e->parent->parent);
- return exif_get_long(e->data, o);
-}
-
-static ExifData *getExifFromExtractor(const char *path) {
- std::unique_ptr<uint8_t[]> exifBuf;
- ExifData *exifdata = NULL;
-
- FILE *fp = fopen (path, "rb");
- if (!fp) {
- ALOGE("failed to open file");
- return NULL;
- }
-
- sp<NuMediaExtractor> extractor = new NuMediaExtractor();
- fseek(fp, 0L, SEEK_END);
- if (extractor->setDataSource(fileno(fp), 0, ftell(fp)) != OK) {
- ALOGE("failed to setDataSource");
- fclose(fp);
- return NULL;
- }
-
- off64_t offset;
- size_t size;
- if (extractor->getExifOffsetSize(&offset, &size) != OK) {
- fclose(fp);
- return NULL;
- }
-
- exifBuf.reset(new uint8_t[size]);
- fseek(fp, offset, SEEK_SET);
- if (fread(exifBuf.get(), 1, size, fp) == size) {
- exifdata = exif_data_new_from_data(exifBuf.get(), size);
- }
-
- fclose(fp);
- return exifdata;
-}
-
MtpResponseCode MtpDatabase::getObjectInfo(MtpObjectHandle handle,
MtpObjectInfo& info) {
MtpStringBuffer path;
@@ -877,26 +821,23 @@
case MTP_FORMAT_EXIF_JPEG:
case MTP_FORMAT_HEIF:
case MTP_FORMAT_JFIF: {
- ExifData *exifdata;
- if (info.mFormat == MTP_FORMAT_HEIF) {
- exifdata = getExifFromExtractor(path);
- } else {
- exifdata = exif_data_new_from_file(path);
- }
- if (exifdata) {
- if ((false)) {
- exif_data_foreach_content(exifdata, foreachcontent, NULL);
- }
+ env = AndroidRuntime::getJNIEnv();
+ if (env->CallBooleanMethod(
+ mDatabase, method_getThumbnailInfo, (jint)handle, mLongBuffer)) {
- ExifEntry *w = exif_content_get_entry(
- exifdata->ifd[EXIF_IFD_EXIF], EXIF_TAG_PIXEL_X_DIMENSION);
- ExifEntry *h = exif_content_get_entry(
- exifdata->ifd[EXIF_IFD_EXIF], EXIF_TAG_PIXEL_Y_DIMENSION);
- info.mThumbCompressedSize = exifdata->data ? exifdata->size : 0;
- info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
- info.mImagePixWidth = w ? getLongFromExifEntry(w) : 0;
- info.mImagePixHeight = h ? getLongFromExifEntry(h) : 0;
- exif_data_unref(exifdata);
+ jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
+ jlong size = longValues[0];
+ jlong w = longValues[1];
+ jlong h = longValues[2];
+ if (size > 0 && size <= UINT32_MAX &&
+ w > 0 && w <= UINT32_MAX &&
+ h > 0 && h <= UINT32_MAX) {
+ info.mThumbCompressedSize = size;
+ info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
+ info.mImagePixWidth = w;
+ info.mImagePixHeight = h;
+ }
+ env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
}
break;
}
@@ -941,22 +882,19 @@
case MTP_FORMAT_EXIF_JPEG:
case MTP_FORMAT_HEIF:
case MTP_FORMAT_JFIF: {
- ExifData *exifdata;
- if (format == MTP_FORMAT_HEIF) {
- exifdata = getExifFromExtractor(path);
- } else {
- exifdata = exif_data_new_from_file(path);
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ jbyteArray thumbData = (jbyteArray) env->CallObjectMethod(
+ mDatabase, method_getThumbnailData, (jint)handle);
+ if (thumbData == NULL) {
+ return nullptr;
}
- if (exifdata) {
- if (exifdata->data) {
- result = malloc(exifdata->size);
- if (result) {
- memcpy(result, exifdata->data, exifdata->size);
- outThumbSize = exifdata->size;
- }
- }
- exif_data_unref(exifdata);
+ jsize thumbSize = env->GetArrayLength(thumbData);
+ result = malloc(thumbSize);
+ if (result) {
+ env->GetByteArrayRegion(thumbData, 0, thumbSize, (jbyte*)result);
+ outThumbSize = thumbSize;
}
+ env->DeleteLocalRef(thumbData);
break;
}
@@ -1389,6 +1327,8 @@
GET_METHOD_ID(getObjectPropertyList, clazz, "(IIIII)Landroid/mtp/MtpPropertyList;");
GET_METHOD_ID(getObjectInfo, clazz, "(I[I[C[J)Z");
GET_METHOD_ID(getObjectFilePath, clazz, "(I[C[J)I");
+ GET_METHOD_ID(getThumbnailInfo, clazz, "(I[J)Z");
+ GET_METHOD_ID(getThumbnailData, clazz, "(I)[B");
GET_METHOD_ID(beginDeleteObject, clazz, "(I)I");
GET_METHOD_ID(endDeleteObject, clazz, "(IZ)V");
GET_METHOD_ID(beginMoveObject, clazz, "(III)I");