summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRuben Brunk <rubenbrunk@google.com>2013-02-20 22:45:55 -0800
committerRuben Brunk <rubenbrunk@google.com>2013-02-21 12:55:46 -0800
commit2d5b41f229ee8d19a9a092ba15e925a22bc97190 (patch)
tree6e5ad0023b1777a7e28eab641fa7a6af69d5a149
parent098f37afd29e0d61ae32a23ae65e1e0d2cd533ec (diff)
downloadandroid_packages_apps_Snap-2d5b41f229ee8d19a9a092ba15e925a22bc97190.tar.gz
android_packages_apps_Snap-2d5b41f229ee8d19a9a092ba15e925a22bc97190.tar.bz2
android_packages_apps_Snap-2d5b41f229ee8d19a9a092ba15e925a22bc97190.zip
Temporary handling when running out of heap in filtershow.
Bug: 8233895 Change-Id: Id078d2a4b387127c0d230bc5d9de4590f0e9f72b
-rw-r--r--src/com/android/gallery3d/filtershow/cache/ImageLoader.java125
-rw-r--r--src/com/android/gallery3d/filtershow/tools/SaveCopyTask.java72
2 files changed, 153 insertions, 44 deletions
diff --git a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
index 698992ac9..42e72e665 100644
--- a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
+++ b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java
@@ -91,6 +91,7 @@ public class ImageLoader {
public static final int ORI_TRANSPOSE = ExifInterface.ORIENTATION_TRANSPOSE;
public static final int ORI_TRANSVERSE = ExifInterface.ORIENTATION_TRANSVERSE;
+ private static final int BITMAP_LOAD_BACKOUT_ATTEMPTS = 5;
private Context mContext = null;
private Uri mUri = null;
@@ -406,28 +407,97 @@ public class ImageLoader {
public static Bitmap loadMutableBitmap(Context context, Uri sourceUri) {
BitmapFactory.Options options = new BitmapFactory.Options();
+ return loadMutableBitmap(context, sourceUri, options);
+ }
+
+ public static Bitmap loadMutableBitmap(Context context, Uri sourceUri,
+ BitmapFactory.Options options) {
// TODO: on <3.x we need a copy of the bitmap (inMutable doesn't
// exist)
options.inMutable = true;
+ Bitmap bitmap = decodeUriWithBackouts(context, sourceUri, options);
+ if (bitmap == null) {
+ return null;
+ }
+ int orientation = ImageLoader.getOrientation(context, sourceUri);
+ bitmap = ImageLoader.rotateToPortrait(bitmap, orientation);
+ return bitmap;
+ }
+
+ public static Bitmap decodeUriWithBackouts(Context context, Uri sourceUri,
+ BitmapFactory.Options options) {
+ boolean noBitmap = true;
+ int num_tries = 0;
+ InputStream is = getInputStream(context, sourceUri);
+
+ if (options.inSampleSize < 1) {
+ options.inSampleSize = 1;
+ }
+ // Stopgap fix for low-memory devices.
+ Bitmap bmap = null;
+ while (noBitmap) {
+ if (is == null) {
+ return null;
+ }
+ try {
+ // Try to decode, downsample if low-memory.
+ bmap = BitmapFactory.decodeStream(is, null, options);
+ noBitmap = false;
+ } catch (java.lang.OutOfMemoryError e) {
+ // Try 5 times before failing for good.
+ if (++num_tries >= BITMAP_LOAD_BACKOUT_ATTEMPTS) {
+ throw e;
+ }
+ is = null;
+ bmap = null;
+ System.gc();
+ is = getInputStream(context, sourceUri);
+ options.inSampleSize *= 2;
+ }
+ }
+ Utils.closeSilently(is);
+ return bmap;
+ }
+
+ private static InputStream getInputStream(Context context, Uri sourceUri) {
InputStream is = null;
- Bitmap bitmap = null;
try {
is = context.getContentResolver().openInputStream(sourceUri);
- bitmap = BitmapFactory.decodeStream(is, null, options);
} catch (FileNotFoundException e) {
Log.w(LOGTAG, "could not load bitmap ", e);
- is = null;
- bitmap = null;
- } finally {
Utils.closeSilently(is);
+ is = null;
}
- if (bitmap == null) {
- return null;
+ return is;
+ }
+
+ public static Bitmap decodeResourceWithBackouts(Resources res, BitmapFactory.Options options,
+ int id) {
+ boolean noBitmap = true;
+ int num_tries = 0;
+ if (options.inSampleSize < 1) {
+ options.inSampleSize = 1;
}
- int orientation = ImageLoader.getOrientation(context, sourceUri);
- bitmap = ImageLoader.rotateToPortrait(bitmap, orientation);
- return bitmap;
+ // Stopgap fix for low-memory devices.
+ Bitmap bmap = null;
+ while (noBitmap) {
+ try {
+ // Try to decode, downsample if low-memory.
+ bmap = BitmapFactory.decodeResource(
+ res, id, options);
+ noBitmap = false;
+ } catch (java.lang.OutOfMemoryError e) {
+ // Try 5 times before failing for good.
+ if (++num_tries >= BITMAP_LOAD_BACKOUT_ATTEMPTS) {
+ throw e;
+ }
+ bmap = null;
+ System.gc();
+ options.inSampleSize *= 2;
+ }
+ }
+ return bmap;
}
public void returnFilteredResult(ImagePreset preset,
@@ -451,13 +521,36 @@ public class ImageLoader {
if (param == null || mUri == null) {
return null;
}
- Bitmap bitmap = loadMutableBitmap(mContext, mUri);
- if (bitmap == null) {
- Log.w(LOGTAG, "Failed to save image!");
- return null;
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ boolean noBitmap = true;
+ int num_tries = 0;
+ if (options.inSampleSize < 1) {
+ options.inSampleSize = 1;
}
- bitmap = param.applyGeometry(bitmap);
- return param.apply(bitmap);
+ Bitmap bitmap = null;
+ // Stopgap fix for low-memory devices.
+ while (noBitmap) {
+ try {
+ // Try to do bitmap operations, downsample if low-memory
+ bitmap = loadMutableBitmap(mContext, mUri, options);
+ if (bitmap == null) {
+ Log.w(LOGTAG, "Failed to save image!");
+ return null;
+ }
+ bitmap = param.applyGeometry(bitmap);
+ bitmap = param.apply(bitmap);
+ noBitmap = false;
+ } catch (java.lang.OutOfMemoryError e) {
+ // Try 5 times before failing for good.
+ if (++num_tries >= 5) {
+ throw e;
+ }
+ bitmap = null;
+ System.gc();
+ options.inSampleSize *= 2;
+ }
+ }
+ return bitmap;
}
};
diff --git a/src/com/android/gallery3d/filtershow/tools/SaveCopyTask.java b/src/com/android/gallery3d/filtershow/tools/SaveCopyTask.java
index e378fe2b7..89cfa6bdf 100644
--- a/src/com/android/gallery3d/filtershow/tools/SaveCopyTask.java
+++ b/src/com/android/gallery3d/filtershow/tools/SaveCopyTask.java
@@ -22,6 +22,7 @@ import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
+import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;
@@ -173,37 +174,52 @@ public class SaveCopyTask extends AsyncTask<ImagePreset, Void, Uri> {
}
ImagePreset preset = params[0];
InputStream is = null;
- try {
- Bitmap bitmap = ImageLoader.loadMutableBitmap(context, sourceUri);
- if (bitmap == null) {
- return null;
- }
- bitmap = preset.applyGeometry(bitmap);
- bitmap = preset.apply(bitmap);
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ boolean noBitmap = true;
+ int num_tries = 0;
+ // Stopgap fix for low-memory devices.
+ while(noBitmap) {
+ try {
+ // Try to do bitmap operations, downsample if low-memory
+ Bitmap bitmap = ImageLoader.loadMutableBitmap(context, sourceUri, options);
+ if (bitmap == null) {
+ return null;
+ }
+ bitmap = preset.applyGeometry(bitmap);
+ bitmap = preset.apply(bitmap);
- Object xmp = null;
- if (preset.isPanoramaSafe()) {
- is = context.getContentResolver().openInputStream(sourceUri);
- xmp = XmpUtilHelper.extractXMPMeta(is);
- }
- ExifData exif = getExifData(sourceUri);
- if (exif != null) {
- exif.addDateTimeStampTag(ExifTag.TAG_DATE_TIME, System.currentTimeMillis(),
- TimeZone.getDefault());
- // Since the image has been modified, set the orientation to normal.
- exif.addTag(ExifTag.TAG_ORIENTATION).setValue(ExifTag.Orientation.TOP_LEFT);
+ Object xmp = null;
+ if (preset.isPanoramaSafe()) {
+ is = context.getContentResolver().openInputStream(sourceUri);
+ xmp = XmpUtilHelper.extractXMPMeta(is);
+ }
+ ExifData exif = getExifData(sourceUri);
+ if (exif != null) {
+ exif.addDateTimeStampTag(ExifTag.TAG_DATE_TIME, System.currentTimeMillis(),
+ TimeZone.getDefault());
+ // Since the image has been modified, set the orientation to normal.
+ exif.addTag(ExifTag.TAG_ORIENTATION).setValue(ExifTag.Orientation.TOP_LEFT);
+ }
+ saveBitmap(bitmap, this.destinationFile, xmp, exif);
+ bitmap.recycle();
+ noBitmap = false;
+ } catch (FileNotFoundException ex) {
+ Log.w(LOGTAG, "Failed to save image!", ex);
+ return null;
+ } catch (java.lang.OutOfMemoryError e) {
+ // Try 5 times before failing for good.
+ if (++num_tries >= 5) {
+ throw e;
+ }
+ System.gc();
+ options.inSampleSize *= 2;
+ } finally {
+ Utils.closeSilently(is);
}
- saveBitmap(bitmap, this.destinationFile, xmp, exif);
-
- Uri uri = insertContent(context, sourceUri, this.destinationFile, saveFileName);
- bitmap.recycle();
- return uri;
- } catch (FileNotFoundException ex) {
- Log.w(LOGTAG, "Failed to save image!", ex);
- return null;
- } finally {
- Utils.closeSilently(is);
}
+ Uri uri = insertContent(context, sourceUri, this.destinationFile, saveFileName);
+ return uri;
+
}
@Override