Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a9d512be authored by Avichal Rakesh's avatar Avichal Rakesh
Browse files

camera: Fix exception handling from ImageReader#detach

ImageReader has a bug where if detaching an Image from Surface fails, it
might throw a RuntimeException instead of an IllegalStateException as
stated in the javadoc. This can lead to CameraExtensionSessionImpl
crashing due to the unhandled exception. Changing ImageReader behavior
is difficult as it might break backwards compatibility.

To prevent crashes from expected exception, this CL adds exception
handling for RuntimeException when detaching images.

In addition, CameraExtensionSessionImpl caught generic `Exception` at
another place, which can lead to it consuming unintended exceptions.
This CL scopes in the exception handling to consume expected exceptions
only.

Bug: 236825255
Test: CtsCameraTestCases pass on Flame
Change-Id: I6fa81b7a19fb4017480074e33b09942aedcd2212
parent 4b0581da
Loading
Loading
Loading
Loading
+31 −3
Original line number Original line Diff line number Diff line
@@ -1737,6 +1737,20 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
                } catch (IllegalStateException e) {
                } catch (IllegalStateException e) {
                    // This is possible in case the client disconnects from the output surface
                    // This is possible in case the client disconnects from the output surface
                    // abruptly.
                    // abruptly.
                    Log.w(TAG, "Output surface likely abandoned, dropping buffer!");
                    img.close();
                } catch (RuntimeException e) {
                    // NOTE: This is intended to catch RuntimeException from ImageReader.detachImage
                    // ImageReader.detachImage is not supposed to throw RuntimeExceptions but the
                    // bug went unchecked for a few years and now its behavior cannot be changed
                    // without breaking backwards compatibility.

                    if (!e.getClass().equals(RuntimeException.class)) {
                        // re-throw any exceptions that aren't base RuntimeException since they are
                        // coming from elsewhere, and we shouldn't silently drop those.
                        throw e;
                    }

                    Log.w(TAG, "Output surface likely abandoned, dropping buffer!");
                    Log.w(TAG, "Output surface likely abandoned, dropping buffer!");
                    img.close();
                    img.close();
                }
                }
@@ -1773,9 +1787,23 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
                }
                }
                try {
                try {
                    reader.detachImage(img);
                    reader.detachImage(img);
                } catch (Exception e) {
                } catch (IllegalStateException e) {
                    Log.e(TAG,
                    Log.e(TAG, "Failed to detach image!");
                            "Failed to detach image!");
                    img.close();
                    return;
                } catch (RuntimeException e) {
                    // NOTE: This is intended to catch RuntimeException from ImageReader.detachImage
                    // ImageReader.detachImage is not supposed to throw RuntimeExceptions but the
                    // bug went unchecked for a few years and now its behavior cannot be changed
                    // without breaking backwards compatibility.

                    if (!e.getClass().equals(RuntimeException.class)) {
                        // re-throw any exceptions that aren't base RuntimeException since they are
                        // coming from elsewhere, and we shouldn't silently drop those.
                        throw e;
                    }

                    Log.e(TAG, "Failed to detach image!");
                    img.close();
                    img.close();
                    return;
                    return;
                }
                }