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

4 Uncaught Fatal Exceptions in TakePictureTask & GetCapabilitiesTask on Galaxy Nexus #69

Closed
jpribble opened this issue Jul 27, 2017 · 8 comments
Assignees
Labels
Milestone

Comments

@jpribble
Copy link
Contributor

Four fatal, uncaught exceptions were found while testing on the Galaxy Nexus. These crashes are occurring in background threads that the caller cannot catch. Can you please help catch these exceptions and return them to the caller via the cameraErrorCallback? Thank you.

1) Galaxy Nexus running 4.2.2 - Crash while taking picture:
07-21 14:55:24.170 3552-3580/? E/AndroidRuntime: FATAL EXCEPTION: pool-3-thread-1
Process: com.example.gbs131.fotoapparat, PID: 3552
java.lang.RuntimeException: java.util.concurrent.ExecutionException: java.util.concurrent.ExecutionException: java.lang.RuntimeException: takePicture failed
at io.fotoapparat.result.PendingResult.getResultUnsafe(PendingResult.java:129)
at io.fotoapparat.result.PendingResult.access$100(PendingResult.java:20)
at io.fotoapparat.result.PendingResult$2.run(PendingResult.java:98)
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)
Caused by: java.util.concurrent.ExecutionException: java.util.concurrent.ExecutionException: java.lang.RuntimeException: takePicture failed
at java.util.concurrent.FutureTask.report(FutureTask.java:93)
at java.util.concurrent.FutureTask.get(FutureTask.java:163)
at io.fotoapparat.result.PendingResult.getResultUnsafe(PendingResult.java:127)
at io.fotoapparat.result.PendingResult.access$100(PendingResult.java:20) 
at io.fotoapparat.result.PendingResult$2.run(PendingResult.java:98) 
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) 
Caused by: java.util.concurrent.ExecutionException: java.lang.RuntimeException: takePicture failed
at java.util.concurrent.FutureTask.report(FutureTask.java:93)
at java.util.concurrent.FutureTask.get(FutureTask.java:163)
at io.fotoapparat.result.PendingResult$1.call(PendingResult.java:56)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
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) 
Caused by: java.lang.RuntimeException: takePicture failed
at android.hardware.Camera.native_takePicture(Native Method)
at android.hardware.Camera.takePicture(Camera.java:1436)
at io.fotoapparat.hardware.v1.Camera1.takePicture(Camera1.java:258)
at io.fotoapparat.routine.picture.TakePictureTask$1.call(TakePictureTask.java:24)
at io.fotoapparat.routine.picture.TakePictureTask$1.call(TakePictureTask.java:19)
at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
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) 

2) Galaxy Nexus running 4.2.2 - Crash when first launching MainActivity:
07-25 14:17:37.097 13588-13617/com.example.gbs131.fotoapparat E/AndroidRuntime: FATAL EXCEPTION: pool-2-thread-1
java.lang.RuntimeException: java.util.concurrent.ExecutionException: java.lang.NullPointerException
at io.fotoapparat.result.PendingResult.getResultUnsafe(PendingResult.java:129)
at io.fotoapparat.result.PendingResult.access$100(PendingResult.java:20)
at io.fotoapparat.result.PendingResult$2.run(PendingResult.java:98)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
at java.lang.Thread.run(Thread.java:856)
Caused by: java.util.concurrent.ExecutionException: java.lang.NullPointerException
at java.util.concurrent.FutureTask.report(FutureTask.java:94)
at java.util.concurrent.FutureTask.get(FutureTask.java:160)
at io.fotoapparat.result.PendingResult.getResultUnsafe(PendingResult.java:127)
at io.fotoapparat.result.PendingResult.access$100(PendingResult.java:20)
at io.fotoapparat.result.PendingResult$2.run(PendingResult.java:98)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
at java.lang.Thread.run(Thread.java:856)
Caused by: java.lang.NullPointerException
at io.fotoapparat.hardware.v1.Camera1.getCapabilities(Camera1.java:237)
at io.fotoapparat.parameter.provider.GetCapabilitiesTask$1.call(GetCapabilitiesTask.java:18)
at io.fotoapparat.parameter.provider.GetCapabilitiesTask$1.call(GetCapabilitiesTask.java:15)
at java.util.concurrent.FutureTask.run(FutureTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
at java.lang.Thread.run(Thread.java:856)

3) Galaxy Nexus running 5.1.1 (Cyanogenmod) - Crash when returning to MainActivity after viewing image in separate Activity:
07-25 10:04:12.490 3030-3049/com.example.gbs131.fotoapparat E/AndroidRuntime: FATAL EXCEPTION: pool-3-thread-1
Process: com.example.gbs131.fotoapparat, PID: 3030
java.lang.RuntimeException: java.util.concurrent.ExecutionException: java.lang.RuntimeException: getParameters failed (empty parameters)
at io.fotoapparat.result.PendingResult.getResultUnsafe(PendingResult.java:129)
at io.fotoapparat.result.PendingResult.access$100(PendingResult.java:20)
at io.fotoapparat.result.PendingResult$2.run(PendingResult.java:98)
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)
Caused by: java.util.concurrent.ExecutionException: java.lang.RuntimeException: getParameters failed (empty parameters)
at java.util.concurrent.FutureTask.report(FutureTask.java:93)
at java.util.concurrent.FutureTask.get(FutureTask.java:163)
at io.fotoapparat.result.PendingResult.getResultUnsafe(PendingResult.java:127)
at io.fotoapparat.result.PendingResult.access$100(PendingResult.java:20) 
at io.fotoapparat.result.PendingResult$2.run(PendingResult.java:98) 
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) 
Caused by: java.lang.RuntimeException: getParameters failed (empty parameters)
at android.hardware.Camera.native_getParameters(Native Method)
at android.hardware.Camera.getParameters(Camera.java:1984)
at io.fotoapparat.hardware.v1.Camera1.getCapabilities(Camera1.java:237)
at io.fotoapparat.parameter.provider.GetCapabilitiesTask$1.call(GetCapabilitiesTask.java:18)
at io.fotoapparat.parameter.provider.GetCapabilitiesTask$1.call(GetCapabilitiesTask.java:15)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
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) 

4) Galaxy Nexus running 5.1.1 (Cyanogenmod) - Crash when taking a picture:
07-25 14:29:54.191 17530-22811/com.example.gbs131.fotoapparat E/AndroidRuntime: FATAL EXCEPTION: pool-2-thread-1
java.lang.RuntimeException: java.util.concurrent.ExecutionException: java.util.concurrent.ExecutionException: java.lang.NullPointerException
at io.fotoapparat.result.PendingResult.getResultUnsafe(PendingResult.java:129)
at io.fotoapparat.result.PendingResult.access$100(PendingResult.java:20)
at io.fotoapparat.result.PendingResult$2.run(PendingResult.java:98)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
at java.lang.Thread.run(Thread.java:856)
Caused by: java.util.concurrent.ExecutionException: java.util.concurrent.ExecutionException: java.lang.NullPointerException
at java.util.concurrent.FutureTask.report(FutureTask.java:94)
at java.util.concurrent.FutureTask.get(FutureTask.java:160)
at io.fotoapparat.result.PendingResult.getResultUnsafe(PendingResult.java:127)
at io.fotoapparat.result.PendingResult.access$100(PendingResult.java:20) 
at io.fotoapparat.result.PendingResult$2.run(PendingResult.java:98) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) 
at java.lang.Thread.run(Thread.java:856) 
Caused by: java.util.concurrent.ExecutionException: java.lang.NullPointerException
at java.util.concurrent.FutureTask.report(FutureTask.java:94)
at java.util.concurrent.FutureTask.get(FutureTask.java:160)
at io.fotoapparat.result.PendingResult$1.call(PendingResult.java:56)
at java.util.concurrent.FutureTask.run(FutureTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) 
at java.lang.Thread.run(Thread.java:856) 
Caused by: java.lang.NullPointerException
at io.fotoapparat.hardware.v1.Camera1.takePicture(Camera1.java:258)
at io.fotoapparat.routine.picture.TakePictureTask$1.call(TakePictureTask.java:24)
at io.fotoapparat.routine.picture.TakePictureTask$1.call(TakePictureTask.java:19)
at java.util.concurrent.FutureTask.run(FutureTask.java:234) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573) 
at java.lang.Thread.run(Thread.java:856) 
07-25 14:29:54.996 17530-17558/com.example.gbs131.fotoapparat D/Fotoapparat: stopPreview
07-25 14:29:54.996 17530-17558/com.example.gbs131.fotoapparat D/Fotoapparat: close
07-25 14:31:51.840 17530-22811/? I/Process: Sending signal. PID: 17530 SIG: 9

XML layout:


<io.fotoapparat.view.CameraView
android:id="@+id/camera"
android:layout_width="match_parent"
android:layout_height="match_parent"/>

Source code initialization:

private Fotoapparat fotoapparat;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    fotoapparat = Fotoapparat
            .with(this)
            .into((CameraView) findViewById(R.id.camera))
            .previewScaleType(ScaleType.CENTER_CROP)
            .photoSize(smallestSize())
            .lensPosition(firstAvailable(
                    back(),
                    front(),
                    external()
            ))
            .focusMode(firstAvailable(
                    continuousFocus(),
                    autoFocus(),
                    fixed()
            ))
            .flash(firstAvailable(
                    torch(),
                    on(),
                    autoFlash(),
                    off()
            ))
            .logger(logcat())
            .build();
}

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

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

public void takePicture(View v) {
    fotoapparat.takePicture()
            .toBitmap()
            .whenAvailable(new PendingResult.Callback<BitmapPhoto>() {
                @Override
                public void onResult(BitmapPhoto result) {
                    ...
                }
            });
}

Using library version 1.2.0

@dmitry-zaitsev
Copy link
Member

It looks like there is a racing condition and picture is being taken while the camera is stopping. Will dig deeper into that to check why it happens.

@kphil
Copy link
Contributor

kphil commented Sep 20, 2017

+1 for catching these exceptions and return them to the caller via the cameraErrorCallback. Especially for calls on the camera instance like takePicture and getParameters. These often result in NPE's for no reason on some devices.

I have the same crashes with 1.3.0, for example 1) described here and the one in issue #98 .

Exception java.lang.RuntimeException: java.util.concurrent.ExecutionException: java.util.concurrent.ExecutionException: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.hardware.Camera.takePicture([REDACTED_DOMAIN_NAME]$ShutterCallback, [REDACTED_DOMAIN_NAME]$PictureCallback, [REDACTED_DOMAIN_NAME]$PictureCallback, [REDACTED_DOMAIN_NAME]$PictureCallback)' on a null object reference
io.fotoapparat.result.PendingResult.getResultUnsafe (PendingResult.java:129)
io.fotoapparat.result.PendingResult.access$100 (PendingResult.java:20)
io.fotoapparat.result.PendingResult$2.run (PendingResult.java:98)
java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1115)
java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:590)
java.lang.Thread.run (Thread.java:818)

Caused by java.util.concurrent.ExecutionException: java.util.concurrent.ExecutionException: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.hardware.Camera.takePicture([REDACTED_DOMAIN_NAME]$ShutterCallback, [REDACTED_DOMAIN_NAME]$PictureCallback, [REDACTED_DOMAIN_NAME]$PictureCallback, [REDACTED_DOMAIN_NAME]$PictureCallback)' on a null object reference
java.util.concurrent.FutureTask.report (FutureTask.java:93)
java.util.concurrent.FutureTask.get (FutureTask.java:163)
io.fotoapparat.result.PendingResult.getResultUnsafe (PendingResult.java:127)
io.fotoapparat.result.PendingResult.access$100 (PendingResult.java:20)
io.fotoapparat.result.PendingResult$2.run (PendingResult.java:98)
java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1115)
java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:590)
java.lang.Thread.run (Thread.java:818)

Caused by java.util.concurrent.ExecutionException: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.hardware.Camera.takePicture([REDACTED_DOMAIN_NAME]$ShutterCallback, [REDACTED_DOMAIN_NAME]$PictureCallback, [REDACTED_DOMAIN_NAME]$PictureCallback, [REDACTED_DOMAIN_NAME]$PictureCallback)' on a null object reference
java.util.concurrent.FutureTask.report (FutureTask.java:93)
java.util.concurrent.FutureTask.get (FutureTask.java:163)
io.fotoapparat.result.PendingResult$1.call (PendingResult.java:56)
java.util.concurrent.FutureTask.run (FutureTask.java:237)
java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1115)
java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:590)
java.lang.Thread.run (Thread.java:818)

Caused by java.lang.NullPointerException: Attempt to invoke virtual method 'void android.hardware.Camera.takePicture([REDACTED_DOMAIN_NAME]$ShutterCallback, [REDACTED_DOMAIN_NAME]$PictureCallback, [REDACTED_DOMAIN_NAME]$PictureCallback, [REDACTED_DOMAIN_NAME]$PictureCallback)' on a null object reference
io.fotoapparat.hardware.v1.Camera1.takePicture (Camera1.java:277)
io.fotoapparat.routine.picture.TakePictureTask$1.call (TakePictureTask.java:24)
io.fotoapparat.routine.picture.TakePictureTask$1.call (TakePictureTask.java:19)
java.util.concurrent.FutureTask.run (FutureTask.java:237)
java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1115)
java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:590)
java.lang.Thread.run (Thread.java:818)

Happened on the following devices:

Xiaomi

  • Xiaomi Redmi 2 Prime (HM 2LTE-IN)
  • Redmi Note 3
  • Redmi 4A
  • Redmi Note 4G (HM NOTE 1LTETD)
  • Mi 4i
  • Redmi Note 4
  • Redmi 3S
  • Redmi Note 3G/4G (HM NOTE 1S CT)
  • Redmi 4
  • Redmi 2 (2014819)
  • Redmi 2 Global (2014818)

Oppo

  • F1s (A1601)
  • A33f
  • A37 (A37fw-International)
  • F1 Plus (X9009)
  • F1 (F1w)
  • A 37 (A37fw)

Samsung

  • Galaxy Note2 (GT-N7100)
  • Galaxy Grand Prime (SM-G531F ,SM-G530BT)
  • Galaxy Win
  • Galaxy Core
  • Galaxy Core Prime
  • Galaxy Core Prime Duos (SM-G360H)

Lenovo

  • Tab 2 A8-50
  • A6000

Intex

  • Aqua 4.5E

Coolpad

  • Mega 2.5D (Y83-I00)
  • Note 5 (3600I)

HTC

  • Desire 816G dual sim
  • Desire 326G dual sim

Motorola

  • Moto G (5S)

Sony

  • Xperia M4 Aqua (E2306)

Condor

  • PLUME P6 (PGN517)

Heres a crash similar to 2) from post above, trying to call getParameters:

Exception java.lang.NullPointerException: Attempt to invoke virtual method '[REDACTED_DOMAIN_NAME]$Parameters android.hardware.Camera.getParameters()' on a null object reference
io.fotoapparat.hardware.v1.Camera1.getCapabilities (Camera1.java:252)
io.fotoapparat.routine.parameter.UpdateParametersRoutine.updateParameters (UpdateParametersRoutine.java:32)
io.fotoapparat.Fotoapparat$1.run (Fotoapparat.java:237)
java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1112)
java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:587)
java.lang.Thread.run (Thread.java:818)

Happened on the following devices:

Xiaomi

  • Xiaomi Redmi 2 Prime (HM 2LTE-IN)
  • Redmi Note 3
  • Redmi Note 4G (HM NOTE 1LTETD)
  • Mi 4i
  • Redmi 2 Global (2014818)

Oppo

  • F1s (A1601)
  • A33f
  • A37 (A37fw-International)
  • F1 (F1w)

Coolpad

  • Mega 2.5D (Y83-I00)
  • Note 5 (3600I)

Sony

  • Xperia M4 Aqua (E2306)

My fotoapparat initialization is pretty simple, i see the problem mostly on the named devices camera hardware:
.previewScaleType(ScaleType.CENTER_CROP) .photoSize(firstAvailable( aspectRatio( 4f / 3f, CameraUtils.recommendedPictureSize() ), aspectRatio( 16f / 9f, CameraUtils.recommendedPictureSize() ))) .previewSize(firstAvailable( aspectRatio( 4f / 3f, CameraUtils.recommendedPreviewSize() ), aspectRatio( 16f / 9f, CameraUtils.recommendedPreviewSize() ))) .lensPosition(back()) .focusMode(firstAvailable( macro(), continuousFocus(), autoFocus(), fixed() )).flash(off())

I solved these issues for me by catching NPEs on camera.getParameters and camera.takePicture calls, throw an CameraException and passing it later to CameraErrorCallback. It's not very elegant, but if i can help out i would gladly provide a PR.

And thanks for the great camera library!

@dmitry-zaitsev dmitry-zaitsev self-assigned this Sep 26, 2017
@shtolik
Copy link

shtolik commented Oct 25, 2017

I see same crash reports from our users. Could the suggested fix be included in next version, please?

@Diolor
Copy link
Member

Diolor commented Oct 25, 2017

Hi @shtolik. Our time is pretty limited but we would be happy to merge a PR with the fix.

@kphil
Copy link
Contributor

kphil commented Oct 29, 2017

I would provide a PR, but i would take some feedback on best way to handle errors related to routines with tasks.

Currently CameraDevice implementations are catching RuntimeExceptions and throw a CameraException from that. The CameraException is than caught in the routine (currently only in StartCameraRoutine), which also has the CameraErrorCallback. In fact CameraErrorCallback is exclusivly passed to routines.
And if the routine catches a CameraException, we call the CameraErrorCallback. So i would go on and pass the CameraErrorCallback to other routines which are using camera and are likley to cause a RuntimeException and handle it the same way.

But routines like TakePictureRoutine involve a task (FutureTask) and a result. For TakePictureRoutine i did it the same way as described before, but had to go on and handle failing to take a picture in the transformer classes (passing an empty Photo) and make PendingResults Callback onResult nullable.
Or would it be better to just handle/pass FutureTasks ExecutionException inside PendingResult if something goes wrong with a task?

@Diolor
Copy link
Member

Diolor commented Dec 24, 2017

Hey guys, you may try 2.0.0-beta2 to check if it's still happening. The crash will for sure be caught internally in FA but if there is any funky behaviour feel free to report it.

Info: related reason: #104

@Diolor Diolor added this to the 2.0.0 milestone Dec 24, 2017
@Diolor
Copy link
Member

Diolor commented Dec 29, 2017

I am still not convinced if we should suppress these exceptions completely as the developers might want to retry an action or inform the user. 🤔

@Diolor Diolor closed this as completed Dec 31, 2017
@Diolor
Copy link
Member

Diolor commented Jan 3, 2018

Just for the sake of transparency:

  • rx converters will returns those errors in the onError
  • .await() will throw the relevant exceptions
  • .whenAvailable will fail more silently and return a null object

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

No branches or pull requests

5 participants