Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 04077d07 authored by Marco Nelissen's avatar Marco Nelissen Committed by Gerrit Code Review
Browse files

Merge "Remove libexif usage from libmedia_jni.so"

parents c4cedf7b 8cef1419
Loading
Loading
Loading
Loading
+48 −0
Original line number Diff line number Diff line
@@ -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.media.MediaScanner;
import android.net.Uri;
import android.os.BatteryManager;
@@ -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;
@@ -843,6 +845,52 @@ public class MtpDatabase implements AutoCloseable {
        return obj.getFormat();
    }

    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;
    }

    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;
    }

    private int beginDeleteObject(int handle) {
        MtpStorageManager.MtpObject obj = mManager.getObject(handle);
        if (obj == null) {
+0 −1
Original line number Diff line number Diff line
@@ -50,7 +50,6 @@ cc_library_shared {
        "libstagefright_foundation",
        "libcamera_client",
        "libmtp",
        "libexif",
        "libpiex",
        "libprocessgroup",
        "libandroidfw",
+32 −92
Original line number Diff line number Diff line
@@ -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)) {

                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;
                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 ? getLongFromExifEntry(w) : 0;
                info.mImagePixHeight = h ? getLongFromExifEntry(h) : 0;
                exif_data_unref(exifdata);
                    info.mImagePixWidth = w;
                    info.mImagePixHeight = h;
                }
                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);
                jsize thumbSize = env->GetArrayLength(thumbData);
                result = malloc(thumbSize);
                if (result) {
                            memcpy(result, exifdata->data, exifdata->size);
                            outThumbSize = exifdata->size;
                        }
                    }
                    exif_data_unref(exifdata);
                    env->GetByteArrayRegion(thumbData, 0, thumbSize, (jbyte*)result);
                    outThumbSize = thumbSize;
                }
                env->DeleteLocalRef(thumbData);
                break;
            }

@@ -1388,6 +1326,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");