Android camera crash

Hi,

I’m trying to use the camera on my android phone (Samsung S7). I call this code:

void open() {
    CameraDevice::openDeviceAsync(0, [this] (CameraDevice *device, const String &) {

        if(!device)
            return;

        device->onErrorOccurred = [] (const String &errorMessage) {
            std::cout << errorMessage << std::endl;
        };

        setPreview(device->createViewerComponent());
    });
}


void setPreview(Component *preview) {

    if(!preview)
        return;

    preview->setBounds(getLocalBounds());
    addChildAndTakeOwnerShip(preview);
}

The error callback is not called. First I got the following stacktrace. Then I checked out the recent commit from the development branch. Now it just crashes without breaking at a crash point in debug.

tgkill 0x0000007a624ab410 abort 0x0000007a6245dbd4 art::Runtime::Abort(char const*) 0x0000007a5f8337e4 art::Runtime::Aborter(char const*) 0x0000007a5f833ef4 android::base::LogMessage::~LogMessage() 0x0000007a5f91ea40 art::JavaVMExt::JniAbort(char const*, char const*) 0x0000007a5f6d1c88 art::JavaVMExt::JniAbortV(char const*, char const*, std::__va_list) 0x0000007a5f6d1e64 art::ScopedCheck::AbortF(char const*, …) 0x0000007a5f504ab4 art::ScopedCheck::CheckThread(_JNIEnv*) 0x0000007a5f5045e0 art::ScopedCheck::Check(art::ScopedObjectAccess&, bool, char const*, art::JniValueType*) 0x0000007a5f502a7c art::CheckJNI::NewPrimitiveArray(char const*, _JNIEnv*, int, art::Primitive::Type) 0x0000007a5f50d120 _JNIEnv::NewIntArray(int) jni.h:875 juce::AndroidComponentPeer::getScreenPosition() const juce_android_Windowing.cpp:470 juce::AndroidComponentPeer::globalToLocal(juce::Point<float>) juce_android_Windowing.cpp:487 juce::MouseInputSourceInternal::findComponentAt(juce::Point<float>) juce_MouseInputSource.cpp:78 juce::MouseInputSourceInternal::setScreenPos(juce::Point<float>, juce::Time, bool) juce_MouseInputSource.cpp:270 juce::MouseInputSourceInternal::handleAsyncUpdate() juce_MouseInputSource.cpp:431 juce::AsyncUpdater::AsyncUpdaterMessage::messageCallback() juce_AsyncUpdater.cpp:34 juce::AndroidMessageQueue::run() juce_android_Messaging.cpp:104 juce::Android::Runnable::invoke(_jobject*, _jobject*, _jobjectArray*) juce_android_Messaging.cpp:42 juce::juce_invokeImplementer(_JNIEnv*, _jobject*, long, _jobject*, _jobject*, _jobjectArray*) juce_android_JNIHelpers.cpp:400 art_quick_generic_jni_trampoline 0x0000007a5f90d304 art_quick_invoke_stub 0x0000007a5f903f88 art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*) 0x0000007a5f4d44f8 art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::DexFile::CodeItem const*, art::ShadowFrame*, art::JValue*) 0x0000007a5f67e15c bool art::interpreter::DoCall<true, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x0000007a5f679694 bool art::interpreter::DoInvoke<(art::InvokeType)1, true, false>(art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x0000007a5f6a44dc art::JValue art::interpreter::ExecuteSwitchImpl<false, false>(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue, bool) 0x0000007a5f69f808 art::interpreter::Execute(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue, bool) 0x0000007a5f659604 art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame*, art::JValue*) 0x0000007a5f65fca0 bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x0000007a5f678804 bool art::interpreter::DoInvoke<(art::InvokeType)4, false, false>(art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x0000007a5f6a4c98 art::JValue art::interpreter::ExecuteSwitchImpl<false, false>(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue, bool) 0x0000007a5f69dfe0 art::interpreter::Execute(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue, bool) 0x0000007a5f659604 artQuickToInterpreterBridge 0x0000007a5f8df75c art_quick_to_interpreter_bridge 0x0000007a5f90d420 art_quick_invoke_static_stub 0x0000007a5f90423c art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*) 0x0000007a5f4d4534 art::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, art::ArgArray*, art::JValue*, char const*) 0x0000007a5f82c820 art::InvokeWithJValues(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jmethodID*, jvalue*) 0x0000007a5f82d5a0 art::JNI::CallStaticObjectMethodA(_JNIEnv*, _jclass*, _jmethodID*, jvalue*) 0x0000007a5f737410 art::CheckJNI::CallMethodA(char const*, _JNIEnv*, _jobject*, _jclass*, _jmethodID*, jvalue*, art::Primitive::Type, art::InvokeType) 0x0000007a5f508cf4 art::InvokeProxyInvocationHandler(art::ScopedObjectAccessAlreadyRunnable&, char const*, _jobject*, _jobject*, std::__1::vector<jvalue, std::__1::allocator<jvalue> >&) 0x0000007a5f8c2d80 artQuickProxyInvokeHandler 0x0000007a5f8e01a4 art_quick_proxy_invoke_handler 0x0000007a5f90cf20 art_quick_invoke_stub 0x0000007a5f903f88 art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*) 0x0000007a5f4d44f8 art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::DexFile::CodeItem const*, art::ShadowFrame*, art::JValue*) 0x0000007a5f67e15c bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x0000007a5f678824 bool art::interpreter::DoInvoke<(art::InvokeType)4, false, false>(art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x0000007a5f6a4c98 art::JValue art::interpreter::ExecuteSwitchImpl<false, false>(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue, bool) 0x0000007a5f69dfe0 art::interpreter::Execute(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue, bool) 0x0000007a5f659604 art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame*, art::JValue*) 0x0000007a5f65fca0 bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x0000007a5f678804 bool art::interpreter::DoInvoke<(art::InvokeType)0, false, false>(art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x0000007a5f6a5738 art::JValue art::interpreter::ExecuteSwitchImpl<false, false>(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue, bool) 0x0000007a5f69cd14 art::interpreter::Execute(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue, bool) 0x0000007a5f659604 art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame*, art::JValue*) 0x0000007a5f65fca0 bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x0000007a5f678804 bool art::interpreter::DoInvoke<(art::InvokeType)2, false, false>(art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x0000007a5f6a2abc art::JValue art::interpreter::ExecuteSwitchImpl<false, false>(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue, bool) 0x0000007a5f6a0558 art::interpreter::Execute(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue, bool) 0x0000007a5f659604 art::interpreter::ArtInterpreterToInterpreterBridge(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame*, art::JValue*) 0x0000007a5f65fca0 bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x0000007a5f678804 MterpInvokeStatic 0x0000007a5f8ece00 ExecuteMterpImpl 0x0000007a5f8f5b98 art::interpreter::Execute(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue, bool) 0x0000007a5f6595a0 artQuickToInterpreterBridge 0x0000007a5f8df75c art_quick_to_interpreter_bridge 0x0000007a5f90d420 art_quick_invoke_static_stub 0x0000007a5f90423c art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*) 0x0000007a5f4d4534 art::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, art::ArgArray*, art::JValue*, char const*) 0x0000007a5f82c820 art::InvokeMethod(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jobject*, _jobject*, unsigned long) 0x0000007a5f82e378 art::Method_invoke(_JNIEnv*, _jobject*, _jobject*, _jobject*) 0x0000007a5f7b7a24 invoke 0x0000000070c9cf78 art_quick_invoke_stub 0x0000007a5f903f88 art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*) 0x0000007a5f4d44f8 art::interpreter::ArtInterpreterToCompiledCodeBridge(art::Thread*, art::ArtMethod*, art::DexFile::CodeItem const*, art::ShadowFrame*, art::JValue*) 0x0000007a5f67e15c bool art::interpreter::DoCall<false, false>(art::ArtMethod*, art::Thread*, art::ShadowFrame&, art::Instruction const*, unsigned short, art::JValue*) 0x0000007a5f678824 MterpInvokeVirtual 0x0000007a5f8eb7dc ExecuteMterpImpl 0x0000007a5f8f5a18 art::interpreter::Execute(art::Thread*, art::DexFile::CodeItem const*, art::ShadowFrame&, art::JValue, bool) 0x0000007a5f6595a0 artQuickToInterpreterBridge 0x0000007a5f8df75c art_quick_to_interpreter_bridge 0x0000007a5f90d420 main 0x0000000073142f6c art_quick_invoke_static_stub 0x0000007a5f90423c art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*) 0x0000007a5f4d4534 art::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, art::ArgArray*, art::JValue*, char const*) 0x0000007a5f82c820 art::InvokeWithVarArgs(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jmethodID*, std::__va_list) 0x0000007a5f82c47c art::JNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, std::__va_list) 0x0000007a5f7427a0 ___lldb_unnamed_symbol275$$libandroid_runtime.so 0x0000007a61afbb74 android::AndroidRuntime::start(char const*, android::Vector<android::String8> const&, bool) 0x0000007a61afde64 ___lldb_unnamed_symbol2$$app_process64 0x0000007a64c665c4 __libc_init 0x0000007a6245b8b0 ___lldb_unnamed_symbol1$$app_process64 0x0000007a64c65ecc __dl__start 0x0000007a64b27868

When I still got the crash break, it was on this line:
https://github.com/WeAreROLI/JUCE/blob/master/modules/juce_gui_basics/native/juce_android_Windowing.cpp#L466

I can run this code on my Mac. It opens the webcam and displays a preview. My phone is running Android 8.0.0, API 26.

Ok and before I send this I now found the CameraDemo. This crashes the same. (and btw: The “Camera required” setting is not enabled by default in the demo).

Also crashing on Samsung J5 with Android 8.1.0. (my App and CameraDemo).

Edit: Ok so it is working with a Huawei Mate20 and Android 9.
Edit2: And also working on iPad mini (although I again had to activate the camera request in Projucer first) Is it possible this is a Samsung specific problem? I don’t have any more devices to test with.

I’ve tested the CameraDemo on a Moto G6 Plus running Android 8 and a Samsung Galaxy S5 Neo running Android 6 and neither are crashing.

The callstack isn’t much use for debugging Android devices, can you paste the output of the Logcat window instead?

That looks more promising:

2019-03-07 15:44:06.232 31480-31480/com.juce.camerademo E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.juce.camerademo, PID: 31480
    java.lang.IllegalArgumentException: CaptureRequest contains unconfigured Input/Output Surface!
        at android.hardware.camera2.CaptureRequest.convertSurfaceToStreamId(CaptureRequest.java:582)
        at android.hardware.camera2.impl.CameraDeviceImpl.submitCaptureRequest(CameraDeviceImpl.java:938)
        at android.hardware.camera2.impl.CameraDeviceImpl.setRepeatingRequest(CameraDeviceImpl.java:984)
        at android.hardware.camera2.impl.CameraCaptureSessionImpl.setRepeatingRequest(CameraCaptureSessionImpl.java:238)
        at com.roli.juce.JuceInvocationHandler.dispatchInvoke(Native Method)
        at com.roli.juce.JuceInvocationHandler.invoke(Unknown Source:14)
        at java.lang.reflect.Proxy.invoke(Proxy.java:913)
        at $Proxy1.run(Unknown Source)
        at android.os.Handler.handleCallback(Handler.java:789)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6944)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

The problem is probably related to this:

Seems like it’s a known problem with Samsung devices running Android 8. I’ll add investigating this further to our backlog but I’m afraid it’s not particularly high priority at the moment.