diff options
-rwxr-xr-x | media/java/android/mtp/MtpDatabase.java | 50 | ||||
-rw-r--r-- | media/jni/Android.bp | 1 | ||||
-rw-r--r-- | media/jni/android_mtp_MtpDatabase.cpp | 124 |
3 files changed, 82 insertions, 93 deletions
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java index 4ac6d35e351f..16ba63bf031b 100755 --- a/media/java/android/mtp/MtpDatabase.java +++ b/media/java/android/mtp/MtpDatabase.java @@ -25,6 +25,7 @@ import android.content.IntentFilter; 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 dalvik.system.CloseGuard; 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 @@ public class MtpDatabase implements AutoCloseable { } @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 10f76b07c749..c49b1e496c66 100644 --- a/media/jni/Android.bp +++ b/media/jni/Android.bp @@ -47,7 +47,6 @@ cc_library_shared { "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 1f89d86947a1..0a3b47b6f901 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_setDeviceProperty; 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 @@ MtpDatabase::MtpDatabase(JNIEnv *env, jobject client) 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 @@ MtpResponseCode MtpDatabase::getObjectPropertyList(MtpObjectHandle handle, 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 @@ MtpResponseCode MtpDatabase::getObjectInfo(MtpObjectHandle handle, 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)) { + + 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; } - - 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); + env->ReleaseLongArrayElements(mLongBuffer, longValues, 0); } break; } @@ -941,22 +882,19 @@ void* MtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) { 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 @@ int register_android_mtp_MtpDatabase(JNIEnv *env) 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"); |