Remove libexif usage from libmedia_jni.so
Test: manual, connect with MTP and PTP Change-Id: I33128db25b8aae60df7854c61fc2a3873a1bced9 (cherry picked from commitf7ec16802c) (cherry picked from commitefb865ace2)
This commit is contained in:
@@ -25,6 +25,7 @@ import android.content.IntentFilter;
|
|||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.media.ExifInterface;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.BatteryManager;
|
import android.os.BatteryManager;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
@@ -47,6 +48,7 @@ import dalvik.system.CloseGuard;
|
|||||||
import com.google.android.collect.Sets;
|
import com.google.android.collect.Sets;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -798,6 +800,54 @@ public class MtpDatabase implements AutoCloseable {
|
|||||||
return obj.getFormat();
|
return obj.getFormat();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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
|
@VisibleForNative
|
||||||
private int beginDeleteObject(int handle) {
|
private int beginDeleteObject(int handle) {
|
||||||
MtpStorageManager.MtpObject obj = mManager.getObject(handle);
|
MtpStorageManager.MtpObject obj = mManager.getObject(handle);
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ cc_library_shared {
|
|||||||
"libstagefright_foundation",
|
"libstagefright_foundation",
|
||||||
"libcamera_client",
|
"libcamera_client",
|
||||||
"libmtp",
|
"libmtp",
|
||||||
"libexif",
|
|
||||||
"libpiex",
|
"libpiex",
|
||||||
"libprocessgroup",
|
"libprocessgroup",
|
||||||
"libandroidfw",
|
"libandroidfw",
|
||||||
|
|||||||
@@ -30,13 +30,6 @@
|
|||||||
#include "src/piex_types.h"
|
#include "src/piex_types.h"
|
||||||
#include "src/piex.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/AndroidRuntime.h>
|
||||||
#include <android_runtime/Log.h>
|
#include <android_runtime/Log.h>
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
@@ -70,6 +63,8 @@ static jmethodID method_setDeviceProperty;
|
|||||||
static jmethodID method_getObjectPropertyList;
|
static jmethodID method_getObjectPropertyList;
|
||||||
static jmethodID method_getObjectInfo;
|
static jmethodID method_getObjectInfo;
|
||||||
static jmethodID method_getObjectFilePath;
|
static jmethodID method_getObjectFilePath;
|
||||||
|
static jmethodID method_getThumbnailInfo;
|
||||||
|
static jmethodID method_getThumbnailData;
|
||||||
static jmethodID method_beginDeleteObject;
|
static jmethodID method_beginDeleteObject;
|
||||||
static jmethodID method_endDeleteObject;
|
static jmethodID method_endDeleteObject;
|
||||||
static jmethodID method_beginMoveObject;
|
static jmethodID method_beginMoveObject;
|
||||||
@@ -219,7 +214,7 @@ MtpDatabase::MtpDatabase(JNIEnv *env, jobject client)
|
|||||||
return; // Already threw.
|
return; // Already threw.
|
||||||
}
|
}
|
||||||
mIntBuffer = (jintArray)env->NewGlobalRef(intArray);
|
mIntBuffer = (jintArray)env->NewGlobalRef(intArray);
|
||||||
jlongArray longArray = env->NewLongArray(2);
|
jlongArray longArray = env->NewLongArray(3);
|
||||||
if (!longArray) {
|
if (!longArray) {
|
||||||
return; // Already threw.
|
return; // Already threw.
|
||||||
}
|
}
|
||||||
@@ -780,57 +775,6 @@ MtpResponseCode MtpDatabase::getObjectPropertyList(MtpObjectHandle handle,
|
|||||||
return result;
|
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,
|
MtpResponseCode MtpDatabase::getObjectInfo(MtpObjectHandle handle,
|
||||||
MtpObjectInfo& info) {
|
MtpObjectInfo& info) {
|
||||||
MtpStringBuffer path;
|
MtpStringBuffer path;
|
||||||
@@ -877,26 +821,23 @@ MtpResponseCode MtpDatabase::getObjectInfo(MtpObjectHandle handle,
|
|||||||
case MTP_FORMAT_EXIF_JPEG:
|
case MTP_FORMAT_EXIF_JPEG:
|
||||||
case MTP_FORMAT_HEIF:
|
case MTP_FORMAT_HEIF:
|
||||||
case MTP_FORMAT_JFIF: {
|
case MTP_FORMAT_JFIF: {
|
||||||
ExifData *exifdata;
|
env = AndroidRuntime::getJNIEnv();
|
||||||
if (info.mFormat == MTP_FORMAT_HEIF) {
|
if (env->CallBooleanMethod(
|
||||||
exifdata = getExifFromExtractor(path);
|
mDatabase, method_getThumbnailInfo, (jint)handle, mLongBuffer)) {
|
||||||
} else {
|
|
||||||
exifdata = exif_data_new_from_file(path);
|
|
||||||
}
|
|
||||||
if (exifdata) {
|
|
||||||
if ((false)) {
|
|
||||||
exif_data_foreach_content(exifdata, foreachcontent, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
ExifEntry *w = exif_content_get_entry(
|
jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
|
||||||
exifdata->ifd[EXIF_IFD_EXIF], EXIF_TAG_PIXEL_X_DIMENSION);
|
jlong size = longValues[0];
|
||||||
ExifEntry *h = exif_content_get_entry(
|
jlong w = longValues[1];
|
||||||
exifdata->ifd[EXIF_IFD_EXIF], EXIF_TAG_PIXEL_Y_DIMENSION);
|
jlong h = longValues[2];
|
||||||
info.mThumbCompressedSize = exifdata->data ? exifdata->size : 0;
|
if (size > 0 && size <= UINT32_MAX &&
|
||||||
info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
|
w > 0 && w <= UINT32_MAX &&
|
||||||
info.mImagePixWidth = w ? getLongFromExifEntry(w) : 0;
|
h > 0 && h <= UINT32_MAX) {
|
||||||
info.mImagePixHeight = h ? getLongFromExifEntry(h) : 0;
|
info.mThumbCompressedSize = size;
|
||||||
exif_data_unref(exifdata);
|
info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
|
||||||
|
info.mImagePixWidth = w;
|
||||||
|
info.mImagePixHeight = h;
|
||||||
|
}
|
||||||
|
env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -941,22 +882,19 @@ void* MtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) {
|
|||||||
case MTP_FORMAT_EXIF_JPEG:
|
case MTP_FORMAT_EXIF_JPEG:
|
||||||
case MTP_FORMAT_HEIF:
|
case MTP_FORMAT_HEIF:
|
||||||
case MTP_FORMAT_JFIF: {
|
case MTP_FORMAT_JFIF: {
|
||||||
ExifData *exifdata;
|
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||||
if (format == MTP_FORMAT_HEIF) {
|
jbyteArray thumbData = (jbyteArray) env->CallObjectMethod(
|
||||||
exifdata = getExifFromExtractor(path);
|
mDatabase, method_getThumbnailData, (jint)handle);
|
||||||
} else {
|
if (thumbData == NULL) {
|
||||||
exifdata = exif_data_new_from_file(path);
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (exifdata) {
|
jsize thumbSize = env->GetArrayLength(thumbData);
|
||||||
if (exifdata->data) {
|
result = malloc(thumbSize);
|
||||||
result = malloc(exifdata->size);
|
if (result) {
|
||||||
if (result) {
|
env->GetByteArrayRegion(thumbData, 0, thumbSize, (jbyte*)result);
|
||||||
memcpy(result, exifdata->data, exifdata->size);
|
outThumbSize = thumbSize;
|
||||||
outThumbSize = exifdata->size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exif_data_unref(exifdata);
|
|
||||||
}
|
}
|
||||||
|
env->DeleteLocalRef(thumbData);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1389,6 +1327,8 @@ int register_android_mtp_MtpDatabase(JNIEnv *env)
|
|||||||
GET_METHOD_ID(getObjectPropertyList, clazz, "(IIIII)Landroid/mtp/MtpPropertyList;");
|
GET_METHOD_ID(getObjectPropertyList, clazz, "(IIIII)Landroid/mtp/MtpPropertyList;");
|
||||||
GET_METHOD_ID(getObjectInfo, clazz, "(I[I[C[J)Z");
|
GET_METHOD_ID(getObjectInfo, clazz, "(I[I[C[J)Z");
|
||||||
GET_METHOD_ID(getObjectFilePath, clazz, "(I[C[J)I");
|
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(beginDeleteObject, clazz, "(I)I");
|
||||||
GET_METHOD_ID(endDeleteObject, clazz, "(IZ)V");
|
GET_METHOD_ID(endDeleteObject, clazz, "(IZ)V");
|
||||||
GET_METHOD_ID(beginMoveObject, clazz, "(III)I");
|
GET_METHOD_ID(beginMoveObject, clazz, "(III)I");
|
||||||
|
|||||||
Reference in New Issue
Block a user