Handle the OOM error during image processing

The OOM should not crash the app,
redirect the OOM error to ImageCaptureException.

Bug: 235321365
Test: manually test CoreTestApp
Change-Id: If6a2fb42b71344c7fae096e6aea6cdba49787dc1
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageSaver.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageSaver.java
index 3ab6e95..947ac42f 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageSaver.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageSaver.java
@@ -123,7 +123,7 @@
 
         SaveError saveError = null;
         String errorMessage = null;
-        Exception exception = null;
+        Throwable throwable = null;
         try (ImageProxy imageToClose = mImage;
              FileOutputStream output = new FileOutputStream(tempFile)) {
             byte[] bytes = imageToJpegByteArray(mImage, mJpegQuality);
@@ -151,10 +151,14 @@
             }
 
             exif.save();
+        } catch (OutOfMemoryError e) {
+            saveError = SaveError.UNKNOWN;
+            errorMessage = "Processing failed due to low memory.";
+            throwable = e;
         } catch (IOException | IllegalArgumentException e) {
             saveError = SaveError.FILE_IO_FAILED;
             errorMessage = "Failed to write temp file";
-            exception = e;
+            throwable = e;
         } catch (CodecFailedException e) {
             switch (e.getFailureType()) {
                 case ENCODE_FAILED:
@@ -171,10 +175,10 @@
                     errorMessage = "Failed to transcode mImage";
                     break;
             }
-            exception = e;
+            throwable = e;
         }
         if (saveError != null) {
-            postError(saveError, errorMessage, exception);
+            postError(saveError, errorMessage, throwable);
             tempFile.delete();
             return null;
         }
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/imagecapture/ProcessingNode.java b/camera/camera-core/src/main/java/androidx/camera/core/imagecapture/ProcessingNode.java
index fbe5b37..6e815cb 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/imagecapture/ProcessingNode.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/imagecapture/ProcessingNode.java
@@ -142,6 +142,9 @@
             }
         } catch (ImageCaptureException e) {
             sendError(request, e);
+        } catch (OutOfMemoryError e) {
+            sendError(request, new ImageCaptureException(
+                    ERROR_UNKNOWN, "Processing failed due to low memory.", e));
         } catch (RuntimeException e) {
             // For unexpected exceptions, throw an ERROR_UNKNOWN ImageCaptureException.
             sendError(request, new ImageCaptureException(ERROR_UNKNOWN, "Processing failed.", e));