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

Commit ab3fcf99 authored by Mark Harman's avatar Mark Harman
Browse files

Fix Camera2 crash if no photo/video/preview resolutions; improve switch camera...

Fix Camera2 crash if no photo/video/preview resolutions; improve switch camera behaviour if camera can't be opened.
parent 3fe88e6e
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -48,6 +48,13 @@
<p>&lt; <small><a href="index.html">Main Page.</a></small></p>

<pre>
Version 1.48.1 (Work in progress)

FIXED   Crash on devices with Camera2 API where camera reports no picture, video or preview
        resolutions, instead fail to open camera gracefully instead.
FIXED   Fix switch camera buttons behaviour if a camera with ID greater than 0 failed to open.
ADDED   If camera fails to open, display ID of current camera that we tried to open.

Version 1.48 (2020/04/22)

FIXED   Taking front camera photos with frontscreen torch was slow.
+17 −4
Original line number Diff line number Diff line
@@ -694,6 +694,18 @@ public class MainActivity extends Activity {
        return is_multi_cam;
    }

    /* Returns the camera Id in use by the preview - or the one we requested, if the camera failed
     * to open.
     * Needed as Preview.getCameraId() returns 0 if camera_controller==null, but if the camera
     * fails to open, we want the switch camera icons to still work as expected!
     */
    private int getActualCameraId() {
        if( preview.getCameraController() == null )
            return applicationInterface.getCameraIdPref();
        else
            return preview.getCameraId();
    }

    /** Whether the icon switch_multi_camera should be displayed. This is if the following are all
     *  true:
     *  - The device is a multi camera device (MainActivity.is_multi_cam==true).
@@ -704,7 +716,7 @@ public class MainActivity extends Activity {
     */
    public boolean showSwitchMultiCamIcon() {
        if( isMultiCamEnabled() ) {
            int cameraId = preview.getCameraId();
            int cameraId = getActualCameraId();
            switch( preview.getCameraControllerManager().getFacing(cameraId) ) {
                case FACING_BACK:
                    if( back_camera_ids.size() > 0 )
@@ -1628,7 +1640,7 @@ public class MainActivity extends Activity {
    public int getNextCameraId() {
        if( MyDebug.LOG )
            Log.d(TAG, "getNextCameraId");
        int cameraId = preview.getCameraId();
        int cameraId = getActualCameraId();
        if( MyDebug.LOG )
            Log.d(TAG, "current cameraId: " + cameraId);
        if( this.preview.canSwitchCamera() ) {
@@ -1677,7 +1689,8 @@ public class MainActivity extends Activity {
        }
        List<Integer> camera_set;
        // don't use preview.getCameraController(), as it may be null if user quickly switches between cameras
        switch( preview.getCameraControllerManager().getFacing(preview.getCameraId()) ) {
        int currCameraId = getActualCameraId();
        switch( preview.getCameraControllerManager().getFacing(currCameraId) ) {
            case FACING_BACK:
                camera_set = back_camera_ids;
                break;
@@ -1689,7 +1702,7 @@ public class MainActivity extends Activity {
                break;
        }
        int cameraId;
        int indx = camera_set.indexOf(preview.getCameraId());
        int indx = camera_set.indexOf(currCameraId);
        if( indx == -1 ) {
            Log.e(TAG, "camera id not in current camera set");
            // this shouldn't happen, but if it does, revert to the first camera id in the set
+47 −24
Original line number Diff line number Diff line
@@ -2411,6 +2411,8 @@ public class CameraController2 extends CameraController {
                        }
                    }
                    if( !found ) {
                        if( MyDebug.LOG )
                            Log.d(TAG, "high resolution [non-burst] picture size: " + camera_size.getWidth() + " x " + camera_size.getHeight());
                        CameraController.Size size = new CameraController.Size(camera_size.getWidth(), camera_size.getHeight());
                        size.supports_burst = false;
                        camera_features.picture_sizes.add(size);
@@ -2418,11 +2420,18 @@ public class CameraController2 extends CameraController {
                }
            }
        }
        if( camera_picture_sizes == null ) {
            // camera_picture_sizes is null on Samsung Galaxy Note 10+ and S20 for camera ID 4!
            Log.e(TAG, "no picture sizes returned by getOutputSizes");
            throw new CameraControllerException();
        }
        else {
            for(android.util.Size camera_size : camera_picture_sizes) {
                if( MyDebug.LOG )
                    Log.d(TAG, "picture size: " + camera_size.getWidth() + " x " + camera_size.getHeight());
                camera_features.picture_sizes.add(new CameraController.Size(camera_size.getWidth(), camera_size.getHeight()));
            }
        }
        // sizes are usually already sorted from high to low, but sort just in case
        // note some devices do have sizes in a not fully sorted order (e.g., Nokia 8)
        Collections.sort(camera_features.picture_sizes, new CameraController.SizeSorter());
@@ -2479,6 +2488,12 @@ public class CameraController2 extends CameraController {
        for(int[] r : this.ae_fps_ranges) {
            min_fps = Math.min(min_fps, r[0]);
        }
        if( camera_video_sizes == null ) {
            // camera_video_sizes is null on Samsung Galaxy Note 10+ and S20 for camera ID 4!
            Log.e(TAG, "no video sizes returned by getOutputSizes");
            throw new CameraControllerException();
        }
        else {
            for(android.util.Size camera_size : camera_video_sizes) {
                if( camera_size.getWidth() > 4096 || camera_size.getHeight() > 2160 )
                    continue; // Nexus 6 returns these, even though not supported?!
@@ -2492,6 +2507,7 @@ public class CameraController2 extends CameraController {
                    Log.d(TAG, "normal video size: " + normal_video_size);
                }
            }
        }
        Collections.sort(camera_features.video_sizes, new CameraController.SizeSorter());

        if( capabilities_high_speed_video ) {
@@ -2544,6 +2560,12 @@ public class CameraController2 extends CameraController {
            if( MyDebug.LOG )
                Log.d(TAG, "display_size: " + display_size.x + " x " + display_size.y);
        }
        if( camera_preview_sizes == null ) {
            // camera_preview_sizes is null on Samsung Galaxy Note 10+ and S20 for camera ID 4!
            Log.e(TAG, "no preview sizes returned by getOutputSizes");
            throw new CameraControllerException();
        }
        else {
            for(android.util.Size camera_size : camera_preview_sizes) {
                if( MyDebug.LOG )
                    Log.d(TAG, "preview size: " + camera_size.getWidth() + " x " + camera_size.getHeight());
@@ -2554,6 +2576,7 @@ public class CameraController2 extends CameraController {
                }
                camera_features.preview_sizes.add(new CameraController.Size(camera_size.getWidth(), camera_size.getHeight()));
            }
        }

        if( characteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE) ) {
            camera_features.supported_flash_values = new ArrayList<>();
+2 −0
Original line number Diff line number Diff line
@@ -7130,6 +7130,8 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu
        return supported_focus_values;
    }

    /** Returns the current camera ID, or 0 if the camera isn't opened.
     */
    public int getCameraId() {
        if( camera_controller == null )
            return 0;
+2 −0
Original line number Diff line number Diff line
@@ -2019,6 +2019,8 @@ public class DrawPreview {
                    canvas.drawText(getContext().getResources().getString(R.string.failed_to_open_camera_1), canvas.getWidth() / 2.0f, canvas.getHeight() / 2.0f, p);
                    canvas.drawText(getContext().getResources().getString(R.string.failed_to_open_camera_2), canvas.getWidth() / 2.0f, canvas.getHeight() / 2.0f + pixels_offset, p);
                    canvas.drawText(getContext().getResources().getString(R.string.failed_to_open_camera_3), canvas.getWidth() / 2.0f, canvas.getHeight() / 2.0f + 2 * pixels_offset, p);
                    // n.b., use applicationInterface.getCameraIdPref(), as preview.getCameraId() returns 0 if camera_controller==null
                    canvas.drawText(getContext().getResources().getString(R.string.camera_id) + ":" + applicationInterface.getCameraIdPref(), canvas.getWidth() / 2.0f, canvas.getHeight() / 2.0f + 3 * pixels_offset, p);
                }
            }
            else {