Loading media/java/android/mtp/MtpDatabase.java +47 −0 Original line number Diff line number Diff line Loading @@ -27,7 +27,9 @@ import android.content.IntentFilter; 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; Loading @@ -49,6 +51,7 @@ import dalvik.system.CloseGuard; import com.google.android.collect.Sets; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.nio.file.Path; Loading @@ -71,6 +74,7 @@ import java.util.stream.IntStream; */ 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; Loading Loading @@ -803,6 +807,28 @@ public class MtpDatabase implements AutoCloseable { 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); Loading @@ -825,6 +851,16 @@ public class MtpDatabase implements AutoCloseable { } 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; } Loading @@ -847,6 +883,17 @@ public class MtpDatabase implements AutoCloseable { } 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; } Loading media/jni/android_mtp_MtpDatabase.cpp +8 −2 Original line number Diff line number Diff line Loading @@ -820,7 +820,10 @@ MtpResponseCode MtpDatabase::getObjectInfo(MtpObjectHandle handle, 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)) { Loading Loading @@ -881,7 +884,10 @@ void* MtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) { 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); Loading Loading
media/java/android/mtp/MtpDatabase.java +47 −0 Original line number Diff line number Diff line Loading @@ -27,7 +27,9 @@ import android.content.IntentFilter; 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; Loading @@ -49,6 +51,7 @@ import dalvik.system.CloseGuard; import com.google.android.collect.Sets; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.nio.file.Path; Loading @@ -71,6 +74,7 @@ import java.util.stream.IntStream; */ 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; Loading Loading @@ -803,6 +807,28 @@ public class MtpDatabase implements AutoCloseable { 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); Loading @@ -825,6 +851,16 @@ public class MtpDatabase implements AutoCloseable { } 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; } Loading @@ -847,6 +883,17 @@ public class MtpDatabase implements AutoCloseable { } 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; } Loading
media/jni/android_mtp_MtpDatabase.cpp +8 −2 Original line number Diff line number Diff line Loading @@ -820,7 +820,10 @@ MtpResponseCode MtpDatabase::getObjectInfo(MtpObjectHandle handle, 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)) { Loading Loading @@ -881,7 +884,10 @@ void* MtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) { 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); Loading