diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/ActivityResultStreamHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/ActivityResultStreamHandler.kt index 8d7c272cf..7736d8058 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/ActivityResultStreamHandler.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/ActivityResultStreamHandler.kt @@ -188,7 +188,7 @@ class ActivityResultStreamHandler(private val activity: Activity, arguments: Any } private fun pickCollectionFilters() { - val initialFilters = (args["initialFilters"] as List<*>?)?.mapNotNull { if (it is String) it else null } ?: listOf() + val initialFilters = (args["initialFilters"] as? List<*>)?.mapNotNull { if (it is String) it else null } ?: listOf() val intent = Intent(MainActivity.INTENT_ACTION_PICK_COLLECTION_FILTERS, null, activity, MainActivity::class.java) .putExtra(MainActivity.EXTRA_KEY_FILTERS_ARRAY, initialFilters.toTypedArray()) .putExtra(MainActivity.EXTRA_KEY_FILTERS_STRING, initialFilters.joinToString(MainActivity.EXTRA_STRING_ARRAY_SEPARATOR)) diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/metadataextractor/SafePngMetadataReader.kt b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/metadataextractor/SafePngMetadataReader.kt index b0baa7973..1f2cc1dd5 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/metadataextractor/SafePngMetadataReader.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/metadataextractor/SafePngMetadataReader.kt @@ -28,7 +28,7 @@ object SafePngMetadataReader { private val LOG_TAG = LogUtils.createTag() // arbitrary size to detect chunks that may yield an OOM - private const val chunkSizeDangerThreshold = SafeXmpReader.segmentTypeSizeDangerThreshold + private const val chunkSizeDangerThreshold = SafeXmpReader.SEGMENT_TYPE_SIZE_DANGER_THRESHOLD private val latin1Encoding = Charsets.ISO_8859_1 private val desiredChunkTypes: Set = hashSetOf( diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/metadataextractor/SafeXmpReader.kt b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/metadataextractor/SafeXmpReader.kt index 4be65a348..28115aa14 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/metadataextractor/SafeXmpReader.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/metadataextractor/SafeXmpReader.kt @@ -48,7 +48,7 @@ class SafeXmpReader : XmpReader() { extendedXMPBuffer?.let { xmpBytes -> val totalSize = xmpBytes.size - if (totalSize > segmentTypeSizeDangerThreshold) { + if (totalSize > SEGMENT_TYPE_SIZE_DANGER_THRESHOLD) { logError(metadata, totalSize) } else { extract(xmpBytes, metadata) @@ -111,7 +111,7 @@ class SafeXmpReader : XmpReader() { val chunkOffset = reader.uInt32.toInt() if (extendedXMPBuffer == null) { // TLAD insert start - if (fullLength > segmentTypeSizeDangerThreshold) { + if (fullLength > SEGMENT_TYPE_SIZE_DANGER_THRESHOLD) { logError(metadata, fullLength) return null } @@ -147,7 +147,7 @@ class SafeXmpReader : XmpReader() { private val LOG_TAG = LogUtils.createTag() // arbitrary size to detect extended XMP that may yield an OOM - const val segmentTypeSizeDangerThreshold = 3 * (1 shl 20) // MB + const val SEGMENT_TYPE_SIZE_DANGER_THRESHOLD = 3 * (1 shl 20) // MB // tighter node limits for faster loading val PARSE_OPTIONS: ParseOptions = ParseOptions().setXMPNodesToLimit( diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/utils/BitmapUtils.kt b/android/app/src/main/kotlin/deckers/thibault/aves/utils/BitmapUtils.kt index 8a07860de..e1893729b 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/utils/BitmapUtils.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/utils/BitmapUtils.kt @@ -14,6 +14,9 @@ object BitmapUtils { private val LOG_TAG = LogUtils.createTag() private const val INITIAL_BUFFER_SIZE = 2 shl 17 // 256kB + // arbitrary size to detect buffer that may yield an OOM + private const val BUFFER_SIZE_DANGER_THRESHOLD = 10 * (1 shl 20) // MB + private val freeBaos = ArrayList() private val mutex = Mutex() @@ -39,6 +42,15 @@ object BitmapUtils { this.compress(Bitmap.CompressFormat.JPEG, quality, stream) } if (recycle) this.recycle() + + val bufferSize = stream.size() + if (bufferSize > BUFFER_SIZE_DANGER_THRESHOLD) { + val availHeapSize = Runtime.getRuntime().let { it.maxMemory() - (it.totalMemory() - it.freeMemory()) } + if (bufferSize > availHeapSize) { + throw Exception("compressed bitmap to $bufferSize bytes, which cannot be allocated to a new byte array, with only $availHeapSize free bytes") + } + } + val byteArray = stream.toByteArray() stream.reset() mutex.withLock { @@ -59,7 +71,7 @@ object BitmapUtils { } fun centerSquareCrop(context: Context, bitmap: Bitmap?, size: Int): Bitmap? { - bitmap ?: return bitmap + bitmap ?: return null return TransformationUtils.centerCrop(getBitmapPool(context), bitmap, size, size) } diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/utils/ContextUtils.kt b/android/app/src/main/kotlin/deckers/thibault/aves/utils/ContextUtils.kt index 0dd235137..a0683f388 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/utils/ContextUtils.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/utils/ContextUtils.kt @@ -24,7 +24,7 @@ object ContextUtils { } fun Context.isMyServiceRunning(serviceClass: Class): Boolean { - val am = this.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager? + val am = this.getSystemService(Context.ACTIVITY_SERVICE) as? ActivityManager am ?: return false @Suppress("deprecation") return am.getRunningServices(Integer.MAX_VALUE).any { it.service.className == serviceClass.name }