From 59a00a38c983eae27470102d967b1adfcbed24cd Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Wed, 16 Sep 2015 18:00:04 -0700 Subject: [PATCH] Limit box art assets to 5 MB each to prevent OOM crashes --- .../grid/assets/DiskAssetLoader.java | 19 ++++++++++++++++++- .../java/com/limelight/utils/CacheHelper.java | 14 +++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/limelight/grid/assets/DiskAssetLoader.java b/app/src/main/java/com/limelight/grid/assets/DiskAssetLoader.java index 353c08b0..98c01fe8 100644 --- a/app/src/main/java/com/limelight/grid/assets/DiskAssetLoader.java +++ b/app/src/main/java/com/limelight/grid/assets/DiskAssetLoader.java @@ -13,6 +13,9 @@ import java.io.InputStream; import java.io.OutputStream; public class DiskAssetLoader { + // 5 MB + private final long MAX_ASSET_SIZE = 5 * 1024 * 1024; + private final File cacheDir; public DiskAssetLoader(File cacheDir) { @@ -27,6 +30,13 @@ public class DiskAssetLoader { InputStream in = null; Bitmap bmp = null; try { + // Make sure the cached asset doesn't exceed the maximum size + if (CacheHelper.getFileSize(cacheDir, "boxart", tuple.computer.uuid.toString(), tuple.app.getAppId() + ".png") > MAX_ASSET_SIZE) { + LimeLog.warning("Removing cached tuple exceeding size threshold: "+tuple); + CacheHelper.deleteCacheFile(cacheDir, "boxart", tuple.computer.uuid.toString(), tuple.app.getAppId() + ".png"); + return null; + } + in = CacheHelper.openCacheFileForInput(cacheDir, "boxart", tuple.computer.uuid.toString(), tuple.app.getAppId() + ".png"); BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = sampleSize; @@ -51,9 +61,11 @@ public class DiskAssetLoader { public void populateCacheWithStream(CachedAppAssetLoader.LoaderTuple tuple, InputStream input) { OutputStream out = null; + boolean success = false; try { out = CacheHelper.openCacheFileForOutput(cacheDir, "boxart", tuple.computer.uuid.toString(), tuple.app.getAppId() + ".png"); - CacheHelper.writeInputStreamToOutputStream(input, out); + CacheHelper.writeInputStreamToOutputStream(input, out, MAX_ASSET_SIZE); + success = true; } catch (IOException e) { e.printStackTrace(); } finally { @@ -62,6 +74,11 @@ public class DiskAssetLoader { out.close(); } catch (IOException ignored) {} } + + if (!success) { + LimeLog.warning("Unable to populate cache with tuple: "+tuple); + CacheHelper.deleteCacheFile(cacheDir, "boxart", tuple.computer.uuid.toString(), tuple.app.getAppId() + ".png"); + } } } } diff --git a/app/src/main/java/com/limelight/utils/CacheHelper.java b/app/src/main/java/com/limelight/utils/CacheHelper.java index 3cf26e91..52d42aec 100644 --- a/app/src/main/java/com/limelight/utils/CacheHelper.java +++ b/app/src/main/java/com/limelight/utils/CacheHelper.java @@ -30,6 +30,14 @@ public class CacheHelper { return f; } + public static long getFileSize(File root, String... path) { + return openPath(false, root, path).length(); + } + + public static boolean deleteCacheFile(File root, String... path) { + return openPath(false, root, path).delete(); + } + public static boolean cacheFileExists(File root, String... path) { return openPath(false, root, path).exists(); } @@ -42,11 +50,15 @@ public class CacheHelper { return new BufferedOutputStream(new FileOutputStream(openPath(true, root, path))); } - public static void writeInputStreamToOutputStream(InputStream in, OutputStream out) throws IOException { + public static void writeInputStreamToOutputStream(InputStream in, OutputStream out, long maxLength) throws IOException { byte[] buf = new byte[4096]; int bytesRead; while ((bytesRead = in.read(buf)) != -1) { + maxLength -= bytesRead; + if (maxLength <= 0) { + throw new IOException("Stream exceeded max size"); + } out.write(buf, 0, bytesRead); } }