Viktor Sehr
Viktor Sehr

Reputation: 13099

DetachCurrentThread crashes sometimes in NDK

I excuse for asking a quite vague question, but, I have a pure native NDK application which is supposed to execute in Immersive Mode (i.e fullscreen).

The immersive mode JNI snippet is executed when the app is resumed via APP_CMD_RESUME. This works most of the time, but, every now and then the command activity->vm->DetachCurrentThread() in my SetImmersiveMode() snippet crashes with a fatal exception:

FATAL EXCEPTION: Thread-10
Process: com.toppluva.portis.LocalDebug, PID: 5474
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:7380)
at android.view.ViewRootImpl.recomputeViewAttributes(ViewRootImpl.java:3478)
at android.view.View.setSystemUiVisibility(View.java:22587)

This really boggles me, mainly because it happens every now and then, how can I detect if I'm executing from this original thread?

Note that according to the documentation APP_CMD_RESUME executes from main thread.

Upvotes: 4

Views: 1978

Answers (1)

Alex Cohn
Alex Cohn

Reputation: 57163

View.setSystemUiVisibility() should be called from the main thread only. Without seeing your code, it's hard to tell if DetachCurrentThread() plays any role in this.

documentation, ANativeActivity::env is JNI context for the main thread of the app.

You should call DetachCurrentThread() before terminating a native thread that you attached to JVM.

You should not call DetachCurrentThread) on a thread born in Java, e.g. the UI thread.

Note that you may call AttachCurrentThread() at any time and on any thread. It will be equivalent to NOP on a Java thread or on an attached thread.

These attach/detach are not paired like parentheses. Any number of attach calls is reversed by single detach. The recommended practice:

use pthread_key_create to define a destructor function that will be called before the thread exits, and call DetachCurrentThread from there. (Use that key with pthread_setspecific to store the JNIEnv in thread-local-storage; that way it'll be passed into your destructor as the argument.)

See how WebRTC handles attach/detach in their git Web repo.

Upvotes: 4

Related Questions