Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash in Fotoapparat.start(): IOException: setPreviewTexture failed #178

Closed
jpribble opened this issue Jan 11, 2018 · 11 comments · Fixed by #189
Closed

Crash in Fotoapparat.start(): IOException: setPreviewTexture failed #178

jpribble opened this issue Jan 11, 2018 · 11 comments · Fixed by #189
Assignees
Labels

Comments

@jpribble
Copy link
Contributor

What are you trying to achieve or the steps to reproduce?

This crash was observed on a Samsung Galaxy Grand Prime running Android 5.1.1. It occurred when the camera activity was destroyed immediately after being resumed. Here is the scenario:

  1. CameraActivity takes a picture and launches an ImageReviewActivity.
  2. If the user accepts the image, ImageReviewActivity closes and returns success to CameraActivity.
  3. CameraActivity resumes, save the image to disk, and exits immediately.

During step 3 above, CameraActivity's onStart() (calls camera.start()), onStop() (call camera.stop()), and onDestroy() are all called in less than 1 second.

What was the result you received?

Fatal crash due to an uncaught IOException: setPreviewTexture failed in Fotoapparat's startRoutine.

Logs:

01-11 14:31:34.480 9246-9246 D/Fotoapparat: Fotoapparat: start
01-11 14:31:34.480 9246-11084 D/Fotoapparat: Device: selectCamera
01-11 14:31:34.480 9246-9246 D/Fotoapparat: Fotoapparat: getCurrentParameters
01-11 14:31:34.480 9246-11084 D/Fotoapparat: CameraDevice: open
01-11 14:31:34.480 9246-9246 D/Fotoapparat: Fotoapparat: getCapabilities
01-11 14:31:34.490 9246-11679 D/Fotoapparat: CameraDevice: getParameters$suspendImpl
01-11 14:31:34.490 9246-11679 D/Fotoapparat: CameraDevice: getCapabilities$suspendImpl
01-11 14:31:34.630 9246-11084 D/Fotoapparat: CameraDevice: getCapabilities$suspendImpl
01-11 14:31:34.630 9246-11084 D/Fotoapparat: CameraDevice: updateParameters$suspendImpl
01-11 14:31:34.630 9246-11084 D/Fotoapparat: New camera parameters are: […]
01-11 14:31:34.640 9246-11084 D/Fotoapparat: CameraDevice: updateFrameProcessor
01-11 14:31:34.640 9246-11084 D/Fotoapparat: CameraDevice: setDisplayOrientation
01-11 14:31:34.640 9246-11084 D/Fotoapparat: Image Rotation is: 270. Display rotation is: 90
01-11 14:31:34.650 9246-11084 D/Fotoapparat: CameraDevice: getPreviewResolution
01-11 14:31:34.650 9246-11084 D/Fotoapparat: Preview resolution is: Resolution(width=720, height=1280)
01-11 14:31:34.650 9246-11084 D/Fotoapparat: CameraDevice: setDisplaySurface
01-11 14:31:34.650 9246-11084 E/BufferQueueProducer: [unnamed-9246-0] connect(P): BufferQueue has been abandoned
01-11 14:31:34.650 9246-11084 E/AndroidRuntime: FATAL EXCEPTION: pool-4-thread-1
Process: [redacted], PID: 9246
java.lang.Error: java.io.IOException: setPreviewTexture failed
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1118)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.io.IOException: setPreviewTexture failed
at android.hardware.Camera.setPreviewTexture(Native Method)
at io.fotoapparat.hardware.CameraDeviceKt.setDisplaySurface(CameraDevice.kt:402)
at io.fotoapparat.hardware.CameraDeviceKt.access$setDisplaySurface(CameraDevice.kt:1)
at io.fotoapparat.hardware.CameraDevice.setDisplaySurface(CameraDevice.kt:251)
at io.fotoapparat.routine.camera.StartRoutineKt.start(StartRoutine.kt:67)
at io.fotoapparat.routine.camera.StartRoutineKt.bootStart(StartRoutine.kt:22)
at io.fotoapparat.Fotoapparat$start$1.invoke(Fotoapparat.kt:89)
at io.fotoapparat.Fotoapparat$start$1.invoke(Fotoapparat.kt:41)
at io.fotoapparat.hardware.ExecutorKt$sam$Runnable$ffbfbfd0.run(Executor.kt)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
at java.lang.Thread.run(Thread.java:818) 

What did you expect?

If there is an exception inside Fotoapparat's async routines, it should be caught and, if it's fatal, be sent to the cameraErrorCallback.
I could work around this by optimizing the code not to call camera.start() when it's about to be destroyed but I still wanted to report this uncaught exception since it may affect others.

Context:

  • FA version: 2.1.2
  • Devices/APIs affected: Samsung Galaxy Grand Prime running Android 5.1.1
@Diolor Diolor added the bug label Jan 11, 2018
@Diolor
Copy link
Member

Diolor commented Jan 11, 2018

Correct me if wrong. So ways to reproduce are instantly call: start() & stop()? Or is it because also there is a onDestroy() ?

@jpribble
Copy link
Contributor Author

Yes, just quickly calling start() then stop() should reproduce it. The crash occurs before onDestroy() so you can ignore that.

@Diolor
Copy link
Member

Diolor commented Jan 11, 2018

Calling fotoapparat.start(), fotoapparat.stop() one after each other cannot reproduce it (since they run in a single thread).
Should be some other reason causing this.

Camera#setPreviewTexture(..) doc:
     * @throws IOException if the method fails (for example, if the surface
     *     texture is unavailable or unsuitable).

Maybe surface becomes/was never unavailable onStop() 🤔

@ghost
Copy link

ghost commented Jan 13, 2018

I have the same bug here :

E/AndroidRuntime: FATAL EXCEPTION: pool-2-thread-1
                                                                                     Process: .... PID: 16702
                                                                                     java.lang.Error: java.io.IOException: setPreviewTexture failed
                                                                                         at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1119)
                                                                                         at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
                                                                                         at java.lang.Thread.run(Thread.java:818)
                                                                                      Caused by: java.io.IOException: setPreviewTexture failed
                                                                                         at android.hardware.Camera.setPreviewTexture(Native Method)
                                                                                         at io.fotoapparat.hardware.CameraDeviceKt.setDisplaySurface(CameraDevice.kt:402)
                                                                                         at io.fotoapparat.hardware.CameraDeviceKt.access$setDisplaySurface(CameraDevice.kt:1)
                                                                                         at io.fotoapparat.hardware.CameraDevice.setDisplaySurface(CameraDevice.kt:251)
                                                                                         at io.fotoapparat.routine.camera.StartRoutineKt.start(StartRoutine.kt:67)
                                                                                         at io.fotoapparat.routine.camera.StartRoutineKt.bootStart(StartRoutine.kt:22)
                                                                                         at io.fotoapparat.Fotoapparat$start$1.invoke(Fotoapparat.kt:89)
                                                                                         at io.fotoapparat.Fotoapparat$start$1.invoke(Fotoapparat.kt:41)
                                                                                         at io.fotoapparat.hardware.ExecutorKt$sam$Runnable$ffbfbfd0.run(Executor.kt)
                                                                                         at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
                                                                                         at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
                                                                                         at java.lang.Thread.run(Thread.java:818) 

this problem happens when I hit back button in any second activity to return to cameraactivity.
Problem happened in Emulator android api level 23

@Diolor
Copy link
Member

Diolor commented Jan 14, 2018

thanks for the reproduction steps @Kim24

@Diolor Diolor self-assigned this Jan 16, 2018
@Diolor
Copy link
Member

Diolor commented Jan 16, 2018

I cannot reproduce it. Can you please provide some more info, code with replicating example etc...?

Things I tried, both work fine (on pixel 2):

    • call start() / stop() after each other
    • call start() inside onStart()
    • click to enter a new activity with a result
    • stop() called inside onStop() because of the new activity, camera closes fine
    • interact to new activity
    • return to first activity and inside onActivityResult call finish(), no start or stop are ofc called here

@jpribble
Copy link
Contributor Author

I think this issue only occurs on certain devices. I found it after only a few tests on the Samsung Galaxy Grand Prime but it never occurred in 100+ tests on a Samsung Galaxy S8.

@matej-svejda
Copy link

I can also reproduce this error with the following code

public class MainActivity extends AppCompatActivity
{
	private Fotoapparat fotoapparat;

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		CameraView cameraView = findViewById(R.id.camera_view);
		fotoapparat = Fotoapparat
			.with(this)
			.into(cameraView)
			.lensPosition(back())
			.focusMode(firstAvailable(
				continuousFocusPicture(),
				autoFocus(),
				fixed()
			))
			.flash(off())
			.build();
	}

	@Override
	protected void onResume()
	{
		super.onResume();
		fotoapparat.start();
	}

	@Override
	protected void onPause()
	{
		fotoapparat.stop();
		super.onPause();
	}
}

When pausing/resuming the app really fast a couple of times on a Galaxy S6 running Android 6.0.1 I get the following crash:

 Process: com.navvis.fotoapparattest, PID: 24056
  java.lang.Error: java.io.IOException: setPreviewTexture failed
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1119)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
      at java.lang.Thread.run(Thread.java:818)
   Caused by: java.io.IOException: setPreviewTexture failed
      at android.hardware.Camera.setPreviewTexture(Native Method)
      at io.fotoapparat.hardware.CameraDeviceKt.setDisplaySurface(CameraDevice.kt:402)
      at io.fotoapparat.hardware.CameraDeviceKt.access$setDisplaySurface(CameraDevice.kt:1)
      at io.fotoapparat.hardware.CameraDevice.setDisplaySurface(CameraDevice.kt:251)
      at io.fotoapparat.routine.camera.StartRoutineKt.start(StartRoutine.kt:67)
      at io.fotoapparat.routine.camera.StartRoutineKt.bootStart(StartRoutine.kt:22)
      at io.fotoapparat.Fotoapparat$start$1.invoke(Fotoapparat.kt:89)
      at io.fotoapparat.Fotoapparat$start$1.invoke(Fotoapparat.kt:41)
      at io.fotoapparat.hardware.ExecutorKt$sam$Runnable$ffbfbfd0.run(Executor.kt)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
      at java.lang.Thread.run(Thread.java:818) 

.

@dmitry-zaitsev dmitry-zaitsev self-assigned this Jan 20, 2018
@dmitry-zaitsev
Copy link
Member

Since IOException is a checked exception we should always be ready for it. In this particular case, we could just catch and ignore it.

@jpribble
Copy link
Contributor Author

Thanks for the fix! It no longer crashes but I'm seeing that this can leave the device in a state where the camera preview is black and no frames are passed to the frame processor. Do you think this should be propagated to the cameraErrorCallback instead of ignoring it?
Here are the logs from a Samsung GS7 with the black camera preview:

01-25 10:55:50.141 22825-22825/ D/TakePictureActivity: onStart()
01-25 10:55:50.161 22825-22825/ D/Fotoapparat: Fotoapparat: start
01-25 10:55:50.161 22825-22825/ D/Fotoapparat: Fotoapparat: getCurrentParameters
01-25 10:55:50.161 22825-26832/ D/Fotoapparat: Device: selectCamera
01-25 10:55:50.161 22825-22825/ D/Fotoapparat: Fotoapparat: getCapabilities
01-25 10:55:50.161 22825-26832/ D/Fotoapparat: CameraDevice: open
01-25 10:55:50.211 22825-26832/ D/Fotoapparat: CameraDevice: getCapabilities$suspendImpl
01-25 10:55:50.211 22825-26832/ D/Fotoapparat: CameraDevice: updateParameters$suspendImpl
01-25 10:55:50.211 22825-26832/ D/Fotoapparat: New camera parameters are: CameraParameters
flashMode: io.fotoapparat.parameter.Flash$Off@c59cc10
focusMode: io.fotoapparat.parameter.FocusMode$ContinuousFocusPicture@7430d28
jpegQuality: 90
previewFpsRange: FpsRange(min=15000, max=30000)
antiBandingMode: io.fotoapparat.parameter.AntiBandingMode$Auto@a7efa41
sensorSensitivity: null
pictureResolution: Resolution(width=1280, height=720)
previewResolution: Resolution(width=1280, height=720)
01-25 10:55:50.211 22825-26832/ D/Fotoapparat: CameraDevice: updateFrameProcessor
01-25 10:55:50.211 22825-26832/ D/Fotoapparat: CameraDevice: setDisplayOrientation
01-25 10:55:50.211 22825-26832/ D/Fotoapparat: Image orientation is: io.fotoapparat.hardware.orientation.Orientation$Horizontal$ReverseLandscape@44fd3d4.
Display orientation is: io.fotoapparat.hardware.orientation.Orientation$Vertical$Portrait@27ff97d.
Preview orientation is: io.fotoapparat.hardware.orientation.Orientation$Vertical$Portrait@27ff97d.
01-25 10:55:50.211 22825-26832/ D/Fotoapparat: CameraDevice: getPreviewResolution
01-25 10:55:50.211 22825-26832/ D/Fotoapparat: Preview resolution is: Resolution(width=1280, height=720)
01-25 10:55:50.211 22825-26832/ D/Fotoapparat: CameraDevice: setDisplaySurface
01-25 10:55:50.211 22825-26832/ E/BufferQueueProducer: [SurfaceTexture-0-22825-2] connect(P): BufferQueue has been abandoned
01-25 10:55:50.211 22825-26832/ D/Fotoapparat: Can't start preview because of the exception: java.io.IOException: setPreviewTexture failed
01-25 10:55:50.221 22825-26832/ D/Fotoapparat: CameraDevice: getParameters$suspendImpl
01-25 10:55:50.221 22825-26832/ D/Fotoapparat: CameraDevice: getCapabilities$suspendImpl
01-25 10:55:50.221 22825-23138/ D/mali_winsys: new_window_surface returns 0x3000, [2560x1440]-format:1
01-25 10:55:50.231 22825-22825/ D/ViewRootImpl: MSG_RESIZED_REPORT: ci=Rect(0, 0 - 0, 0) vi=Rect(0, 0 - 0, 0) or=2
01-25 10:55:51.751 22825-26832/ D/Fotoapparat: CameraDevice: setDisplayOrientation
01-25 10:55:51.751 22825-26832/ D/Fotoapparat: Image orientation is: io.fotoapparat.hardware.orientation.Orientation$Vertical$Portrait@27ff97d.
Display orientation is: io.fotoapparat.hardware.orientation.Orientation$Vertical$Portrait@27ff97d.
Preview orientation is: io.fotoapparat.hardware.orientation.Orientation$Vertical$Portrait@27ff97d.
01-25 10:55:51.931 22825-26832/ D/Fotoapparat: CameraDevice: setDisplayOrientation
01-25 10:55:51.931 22825-26832/ D/Fotoapparat: Image orientation is: io.fotoapparat.hardware.orientation.Orientation$Horizontal$ReverseLandscape@44fd3d4.
Display orientation is: io.fotoapparat.hardware.orientation.Orientation$Vertical$Portrait@27ff97d.
Preview orientation is: io.fotoapparat.hardware.orientation.Orientation$Vertical$Portrait@27ff97d.
01-25 10:55:55.121 22825-26832/ D/Fotoapparat: CameraDevice: setDisplayOrientation
01-25 10:55:55.121 22825-26832/ D/Fotoapparat: Image orientation is: io.fotoapparat.hardware.orientation.Orientation$Vertical$ReversePortrait@f00ccf4.
Display orientation is: io.fotoapparat.hardware.orientation.Orientation$Vertical$Portrait@27ff97d.
Preview orientation is: io.fotoapparat.hardware.orientation.Orientation$Vertical$Portrait@27ff97d.
01-25 10:55:55.721 22825-26832/ D/Fotoapparat: CameraDevice: setDisplayOrientation
01-25 10:55:55.721 22825-26832/ D/Fotoapparat: Image orientation is: io.fotoapparat.hardware.orientation.Orientation$Horizontal$ReverseLandscape@44fd3d4.
Display orientation is: io.fotoapparat.hardware.orientation.Orientation$Vertical$Portrait@27ff97d.
Preview orientation is: io.fotoapparat.hardware.orientation.Orientation$Vertical$Portrait@27ff97d.
01-25 10:55:55.781 22825-26832/ D/Fotoapparat: CameraDevice: setDisplayOrientation
01-25 10:55:55.781 22825-26832/ D/Fotoapparat: Image orientation is: io.fotoapparat.hardware.orientation.Orientation$Vertical$ReversePortrait@f00ccf4.
Display orientation is: io.fotoapparat.hardware.orientation.Orientation$Vertical$Portrait@27ff97d.
Preview orientation is: io.fotoapparat.hardware.orientation.Orientation$Vertical$Portrait@27ff97d.
01-25 10:55:55.831 22825-26832/ D/Fotoapparat: CameraDevice: setDisplayOrientation
… (continues repeating ^)

@thuypt
Copy link

thuypt commented Apr 11, 2019

@jpribble Agree with you. All off exceptions if the lib cannot handle should be propagated to error callback instead of ignore and close the issue.

I also got this after open any camera app then get back to my app.

@dmitry-zaitsev Pls consider to return known exceptions in the error callback, and let us handle by our self, at least we can call recreate screen or show a error message.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants