Merge "MTP: Add MTP Thumbnail feature"
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index a828e2d..e6962a1 100755
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -27,7 +27,9 @@
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
+import android.graphics.Bitmap;
import android.media.ExifInterface;
+import android.media.ThumbnailUtils;
import android.net.Uri;
import android.os.BatteryManager;
import android.os.RemoteException;
@@ -49,6 +51,7 @@
import com.google.android.collect.Sets;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
@@ -71,6 +74,7 @@
*/
public class MtpDatabase implements AutoCloseable {
private static final String TAG = MtpDatabase.class.getSimpleName();
+ private static final int MAX_THUMB_SIZE = (200 * 1024);
private final Context mContext;
private final ContentProviderClient mMediaProvider;
@@ -803,6 +807,28 @@
return obj.getFormat();
}
+ private byte[] getThumbnailProcess(String path, Bitmap bitmap) {
+ try {
+ if (bitmap == null) {
+ Log.d(TAG, "getThumbnailProcess: Fail to generate thumbnail. Probably unsupported or corrupted image");
+ return null;
+ }
+
+ ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+ bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteStream);
+
+ if (byteStream.size() > MAX_THUMB_SIZE)
+ return null;
+
+ byte[] byteArray = byteStream.toByteArray();
+
+ return byteArray;
+ } catch (OutOfMemoryError oomEx) {
+ Log.w(TAG, "OutOfMemoryError:" + oomEx);
+ }
+ return null;
+ }
+
@VisibleForNative
private boolean getThumbnailInfo(int handle, long[] outLongs) {
MtpStorageManager.MtpObject obj = mManager.getObject(handle);
@@ -825,6 +851,16 @@
} catch (IOException e) {
// ignore and fall through
}
+
+// Note: above formats will fall through and go on below thumbnail generation if Exif processing fails
+ case MtpConstants.FORMAT_PNG:
+ case MtpConstants.FORMAT_GIF:
+ case MtpConstants.FORMAT_BMP:
+ outLongs[0] = MAX_THUMB_SIZE;
+ // only non-zero Width & Height needed. Actual size will be retrieved upon getThumbnailData by Host
+ outLongs[1] = 320;
+ outLongs[2] = 240;
+ return true;
}
return false;
}
@@ -847,6 +883,17 @@
} catch (IOException e) {
// ignore and fall through
}
+
+// Note: above formats will fall through and go on below thumbnail generation if Exif processing fails
+ case MtpConstants.FORMAT_PNG:
+ case MtpConstants.FORMAT_GIF:
+ case MtpConstants.FORMAT_BMP:
+ {
+ Bitmap bitmap = ThumbnailUtils.createImageThumbnail(path, MediaStore.Images.Thumbnails.MINI_KIND);
+ byte[] byteArray = getThumbnailProcess(path, bitmap);
+
+ return byteArray;
+ }
}
return null;
}
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 0a3b47b..17189fd 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -820,7 +820,10 @@
switch (info.mFormat) {
case MTP_FORMAT_EXIF_JPEG:
case MTP_FORMAT_HEIF:
- case MTP_FORMAT_JFIF: {
+ case MTP_FORMAT_JFIF:
+ case MTP_FORMAT_PNG:
+ case MTP_FORMAT_BMP:
+ case MTP_FORMAT_GIF: {
env = AndroidRuntime::getJNIEnv();
if (env->CallBooleanMethod(
mDatabase, method_getThumbnailInfo, (jint)handle, mLongBuffer)) {
@@ -881,7 +884,10 @@
switch (format) {
case MTP_FORMAT_EXIF_JPEG:
case MTP_FORMAT_HEIF:
- case MTP_FORMAT_JFIF: {
+ case MTP_FORMAT_JFIF:
+ case MTP_FORMAT_PNG:
+ case MTP_FORMAT_BMP:
+ case MTP_FORMAT_GIF: {
JNIEnv* env = AndroidRuntime::getJNIEnv();
jbyteArray thumbData = (jbyteArray) env->CallObjectMethod(
mDatabase, method_getThumbnailData, (jint)handle);