Loading _docs/history.html +1 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ FIXED Photos would sometimes fail to save on some devices with Storage Access options were enabled (options like DRO, HDR, auto-level, photostamp that require post-processing; custom Exif tags like artist or copyright; or when using geotagging with Camera2 API). FIXED Corrupt videos could be left over if video failed to start. FIXED Possible problem taking photos on some devices with LIMITED Camera2 API support. FIXED Possible problem with default edge mode and noise reduction mode behaviours on some devices with LIMITED Camera2 API support. Loading app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java +44 −0 Original line number Diff line number Diff line Loading @@ -6207,6 +6207,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv } int exp_n_new_files = 0; boolean failed_to_start = false; if( mPreview.isVideoRecording() ) { assertEquals((int) (Integer) takePhotoButton.getTag(), net.sourceforge.opencamera.R.drawable.take_video_recording); assertEquals((int) (Integer) switchVideoButton.getTag(), net.sourceforge.opencamera.R.drawable.take_photo); Loading Loading @@ -6305,6 +6306,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv else { Log.d(TAG, "didn't start video"); assertTrue(allow_failure); failed_to_start = true; } if( mPreview.usingCamera2API() ) { Loading @@ -6319,6 +6321,10 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv // if quick, should have deleted corrupt video - but may be device dependent, sometimes we manage to record a video anyway! assertTrue(n_new_files == 0 || n_new_files == 1); } else if( failed_to_start ) { // if video recording failed to start, we should have deleted any file created! assertEquals(0, n_new_files); } else { assertEquals(n_non_video_files+1, n_new_files); } Loading Loading @@ -7347,6 +7353,44 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv subTestTakeVideo(false, false, true, false, null, 5000, false, 0); } public void testTakeVideoForceFailureSAF() throws InterruptedException { Log.d(TAG, "testTakeVideoForceFailureSAF"); if( Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP ) { Log.d(TAG, "SAF requires Android Lollipop or better"); return; } setToDefault(); SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(mActivity); SharedPreferences.Editor editor = settings.edit(); editor.putBoolean(PreferenceKeys.UsingSAFPreferenceKey, true); editor.putString(PreferenceKeys.SaveLocationSAFPreferenceKey, "content://com.android.externalstorage.documents/tree/primary%3ADCIM%2FOpenCamera"); editor.apply(); updateForSettings(); mActivity.getPreview().test_video_failure = true; subTestTakeVideo(false, false, true, false, null, 5000, false, 0); } public void testTakeVideoForceIOException() throws InterruptedException { Log.d(TAG, "testTakeVideoForceIOException"); setToDefault(); mActivity.getPreview().test_video_ioexception = true; subTestTakeVideo(false, false, true, false, null, 5000, false, 0); } public void testTakeVideoForceCameraControllerException() throws InterruptedException { Log.d(TAG, "testTakeVideoForceCameraControllerException"); setToDefault(); mActivity.getPreview().test_video_cameracontrollerexception = true; subTestTakeVideo(false, false, true, false, null, 5000, false, 0); } /* Test can be reliable on some devices, test no longer run as part of test suites. */ public void testTakeVideo4K() throws InterruptedException { Loading app/src/androidTest/java/net/sourceforge/opencamera/test/VideoTests.java +3 −0 Original line number Diff line number Diff line Loading @@ -59,6 +59,9 @@ public class VideoTests { } suite.addTest(TestSuite.createTest(MainActivityTest.class, "testTakeVideoTimeLapse")); suite.addTest(TestSuite.createTest(MainActivityTest.class, "testTakeVideoForceFailure")); suite.addTest(TestSuite.createTest(MainActivityTest.class, "testTakeVideoForceFailureSAF")); suite.addTest(TestSuite.createTest(MainActivityTest.class, "testTakeVideoForceIOException")); suite.addTest(TestSuite.createTest(MainActivityTest.class, "testTakeVideoForceCameraControllerException")); if( MainActivityTest.test_camera2 ) { suite.addTest(TestSuite.createTest(MainActivityTest.class, "testVideoLogProfile")); suite.addTest(TestSuite.createTest(MainActivityTest.class, "testVideoJTLogProfile")); Loading app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +27 −5 Original line number Diff line number Diff line Loading @@ -392,6 +392,8 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu public volatile int count_cameraContinuousFocusMoving; public volatile boolean test_fail_open_camera; public volatile boolean test_video_failure; public volatile boolean test_video_ioexception; public volatile boolean test_video_cameracontrollerexception; public volatile boolean test_ticker_called; // set from MySurfaceView or CanvasView public volatile boolean test_called_next_output_file; public volatile boolean test_started_next_output_file; Loading Loading @@ -5515,14 +5517,33 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu local_video_recorder.setOrientationHint(getImageVideoRotation()); if( MyDebug.LOG ) Log.d(TAG, "about to prepare video recorder"); local_video_recorder.prepare(); if( test_video_ioexception ) { if( MyDebug.LOG ) Log.d(TAG, "test_video_ioexception is true"); throw new IOException(); } boolean want_photo_video_recording = supportsPhotoVideoRecording() && applicationInterface.usePhotoVideoRecording(); camera_controller.initVideoRecorderPostPrepare(local_video_recorder, want_photo_video_recording); if( test_video_cameracontrollerexception ) { if( MyDebug.LOG ) Log.d(TAG, "test_video_cameracontrollerexception is true"); throw new CameraControllerException(); } if( MyDebug.LOG ) Log.d(TAG, "about to start video recorder"); try { local_video_recorder.start(); if( test_video_failure ) { if( MyDebug.LOG ) Log.d(TAG, "test_video_failure is true"); throw new RuntimeException(); } this.video_recorder = local_video_recorder; videoRecordingStarted(max_filesize_restart); } Loading Loading @@ -5588,6 +5609,8 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu video_recorder.release(); video_recorder = null; video_recorder_is_paused = false; applicationInterface.deleteUnusedVideo(videoFileInfo.video_method, videoFileInfo.video_uri, videoFileInfo.video_filename); videoFileInfo = new VideoFileInfo(); applicationInterface.cameraInOperation(false, true); this.reconnectCamera(true); } Loading @@ -5613,6 +5636,8 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu video_recorder.release(); video_recorder = null; video_recorder_is_paused = false; applicationInterface.deleteUnusedVideo(videoFileInfo.video_method, videoFileInfo.video_uri, videoFileInfo.video_filename); videoFileInfo = new VideoFileInfo(); applicationInterface.cameraInOperation(false, true); this.reconnectCamera(true); this.showToast(null, R.string.video_no_free_space); Loading @@ -5633,11 +5658,6 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu faces_detected = null; } if( test_video_failure ) { if( MyDebug.LOG ) Log.d(TAG, "test_video_failure is true"); throw new RuntimeException(); } video_start_time = System.currentTimeMillis(); video_start_time_set = true; applicationInterface.startedVideo(); Loading Loading @@ -5734,6 +5754,8 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu video_recorder.release(); video_recorder = null; video_recorder_is_paused = false; applicationInterface.deleteUnusedVideo(videoFileInfo.video_method, videoFileInfo.video_uri, videoFileInfo.video_filename); videoFileInfo = new VideoFileInfo(); applicationInterface.cameraInOperation(false, true); this.reconnectCamera(true); } Loading Loading
_docs/history.html +1 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ FIXED Photos would sometimes fail to save on some devices with Storage Access options were enabled (options like DRO, HDR, auto-level, photostamp that require post-processing; custom Exif tags like artist or copyright; or when using geotagging with Camera2 API). FIXED Corrupt videos could be left over if video failed to start. FIXED Possible problem taking photos on some devices with LIMITED Camera2 API support. FIXED Possible problem with default edge mode and noise reduction mode behaviours on some devices with LIMITED Camera2 API support. Loading
app/src/androidTest/java/net/sourceforge/opencamera/test/MainActivityTest.java +44 −0 Original line number Diff line number Diff line Loading @@ -6207,6 +6207,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv } int exp_n_new_files = 0; boolean failed_to_start = false; if( mPreview.isVideoRecording() ) { assertEquals((int) (Integer) takePhotoButton.getTag(), net.sourceforge.opencamera.R.drawable.take_video_recording); assertEquals((int) (Integer) switchVideoButton.getTag(), net.sourceforge.opencamera.R.drawable.take_photo); Loading Loading @@ -6305,6 +6306,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv else { Log.d(TAG, "didn't start video"); assertTrue(allow_failure); failed_to_start = true; } if( mPreview.usingCamera2API() ) { Loading @@ -6319,6 +6321,10 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv // if quick, should have deleted corrupt video - but may be device dependent, sometimes we manage to record a video anyway! assertTrue(n_new_files == 0 || n_new_files == 1); } else if( failed_to_start ) { // if video recording failed to start, we should have deleted any file created! assertEquals(0, n_new_files); } else { assertEquals(n_non_video_files+1, n_new_files); } Loading Loading @@ -7347,6 +7353,44 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv subTestTakeVideo(false, false, true, false, null, 5000, false, 0); } public void testTakeVideoForceFailureSAF() throws InterruptedException { Log.d(TAG, "testTakeVideoForceFailureSAF"); if( Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP ) { Log.d(TAG, "SAF requires Android Lollipop or better"); return; } setToDefault(); SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(mActivity); SharedPreferences.Editor editor = settings.edit(); editor.putBoolean(PreferenceKeys.UsingSAFPreferenceKey, true); editor.putString(PreferenceKeys.SaveLocationSAFPreferenceKey, "content://com.android.externalstorage.documents/tree/primary%3ADCIM%2FOpenCamera"); editor.apply(); updateForSettings(); mActivity.getPreview().test_video_failure = true; subTestTakeVideo(false, false, true, false, null, 5000, false, 0); } public void testTakeVideoForceIOException() throws InterruptedException { Log.d(TAG, "testTakeVideoForceIOException"); setToDefault(); mActivity.getPreview().test_video_ioexception = true; subTestTakeVideo(false, false, true, false, null, 5000, false, 0); } public void testTakeVideoForceCameraControllerException() throws InterruptedException { Log.d(TAG, "testTakeVideoForceCameraControllerException"); setToDefault(); mActivity.getPreview().test_video_cameracontrollerexception = true; subTestTakeVideo(false, false, true, false, null, 5000, false, 0); } /* Test can be reliable on some devices, test no longer run as part of test suites. */ public void testTakeVideo4K() throws InterruptedException { Loading
app/src/androidTest/java/net/sourceforge/opencamera/test/VideoTests.java +3 −0 Original line number Diff line number Diff line Loading @@ -59,6 +59,9 @@ public class VideoTests { } suite.addTest(TestSuite.createTest(MainActivityTest.class, "testTakeVideoTimeLapse")); suite.addTest(TestSuite.createTest(MainActivityTest.class, "testTakeVideoForceFailure")); suite.addTest(TestSuite.createTest(MainActivityTest.class, "testTakeVideoForceFailureSAF")); suite.addTest(TestSuite.createTest(MainActivityTest.class, "testTakeVideoForceIOException")); suite.addTest(TestSuite.createTest(MainActivityTest.class, "testTakeVideoForceCameraControllerException")); if( MainActivityTest.test_camera2 ) { suite.addTest(TestSuite.createTest(MainActivityTest.class, "testVideoLogProfile")); suite.addTest(TestSuite.createTest(MainActivityTest.class, "testVideoJTLogProfile")); Loading
app/src/main/java/net/sourceforge/opencamera/preview/Preview.java +27 −5 Original line number Diff line number Diff line Loading @@ -392,6 +392,8 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu public volatile int count_cameraContinuousFocusMoving; public volatile boolean test_fail_open_camera; public volatile boolean test_video_failure; public volatile boolean test_video_ioexception; public volatile boolean test_video_cameracontrollerexception; public volatile boolean test_ticker_called; // set from MySurfaceView or CanvasView public volatile boolean test_called_next_output_file; public volatile boolean test_started_next_output_file; Loading Loading @@ -5515,14 +5517,33 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu local_video_recorder.setOrientationHint(getImageVideoRotation()); if( MyDebug.LOG ) Log.d(TAG, "about to prepare video recorder"); local_video_recorder.prepare(); if( test_video_ioexception ) { if( MyDebug.LOG ) Log.d(TAG, "test_video_ioexception is true"); throw new IOException(); } boolean want_photo_video_recording = supportsPhotoVideoRecording() && applicationInterface.usePhotoVideoRecording(); camera_controller.initVideoRecorderPostPrepare(local_video_recorder, want_photo_video_recording); if( test_video_cameracontrollerexception ) { if( MyDebug.LOG ) Log.d(TAG, "test_video_cameracontrollerexception is true"); throw new CameraControllerException(); } if( MyDebug.LOG ) Log.d(TAG, "about to start video recorder"); try { local_video_recorder.start(); if( test_video_failure ) { if( MyDebug.LOG ) Log.d(TAG, "test_video_failure is true"); throw new RuntimeException(); } this.video_recorder = local_video_recorder; videoRecordingStarted(max_filesize_restart); } Loading Loading @@ -5588,6 +5609,8 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu video_recorder.release(); video_recorder = null; video_recorder_is_paused = false; applicationInterface.deleteUnusedVideo(videoFileInfo.video_method, videoFileInfo.video_uri, videoFileInfo.video_filename); videoFileInfo = new VideoFileInfo(); applicationInterface.cameraInOperation(false, true); this.reconnectCamera(true); } Loading @@ -5613,6 +5636,8 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu video_recorder.release(); video_recorder = null; video_recorder_is_paused = false; applicationInterface.deleteUnusedVideo(videoFileInfo.video_method, videoFileInfo.video_uri, videoFileInfo.video_filename); videoFileInfo = new VideoFileInfo(); applicationInterface.cameraInOperation(false, true); this.reconnectCamera(true); this.showToast(null, R.string.video_no_free_space); Loading @@ -5633,11 +5658,6 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu faces_detected = null; } if( test_video_failure ) { if( MyDebug.LOG ) Log.d(TAG, "test_video_failure is true"); throw new RuntimeException(); } video_start_time = System.currentTimeMillis(); video_start_time_set = true; applicationInterface.startedVideo(); Loading Loading @@ -5734,6 +5754,8 @@ public class Preview implements SurfaceHolder.Callback, TextureView.SurfaceTextu video_recorder.release(); video_recorder = null; video_recorder_is_paused = false; applicationInterface.deleteUnusedVideo(videoFileInfo.video_method, videoFileInfo.video_uri, videoFileInfo.video_filename); videoFileInfo = new VideoFileInfo(); applicationInterface.cameraInOperation(false, true); this.reconnectCamera(true); } Loading