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.
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.
Related
i know that the android app runs in the main thread means UI thread.I want to know what is need of main thread to run an app? What happens if we do not use the main thread to run app.Why main thread is necessary?
Well it needs a thread. Every app ever written has at least one- even the simplest Hello World app in the simplest language. A thread is just a series of instructions being run on the processor. So even if your app doesn't multithread at all, the one series of instructions it is running would be a thread- you could even call it the main thread if you wanted. So it would literally be impossible to have no main thread at all.
What makes the main thread special in Android is that you're only allowed to change visible elements on it. If Android didn't have that restriction, you'd have the possibility of race conditions and inconsistent UIs- the possibility that views are being changed on one thread while another is drawing to the screen. To prevent this you'd need to do a lot of manual locking. Instead, Android decided to only allow these changes on the main thread. That prevents a large class of timing bugs and race conditions (although not all, depending on how you implement your models).
From this link:
What is the need of main thread?
When an Android application is first started, the runtime system creates a single thread in which all application components will run by default. This thread is generally referred to as the main thread. The primary role of the main thread is to handle the user interface in terms of event handling and interaction with views in the user interface. Any additional components that are started within the application will, by default, also run on the main thread.
Why is main thread necessary?
Any component within an application that performs a time-consuming task using the main thread will cause the entire application to appear to lock up until the task is completed. This will typically result in the operating system displaying an “Application is unresponsive” warning to the user. Clearly, this is far from the desired behavior for any application. In such a situation, this can be avoided simply by launching the task to be performed in a separate thread, allowing the main thread to continue unhindered with other tasks.
Please refer to the link to understand more about main thread with an example.
For more details, you can follow this link.
I am processing UI instructions on a virtual machine (V8 actually) on Android in the main UI thread. This works fine. However, now I'm adding a JavaScript debugger into the mix (Stetho in my case). I can pause the UI thread when a breakpoint is hit, and even step through instructions. However, when an instruction changes the UI, the UI is not immediately updated. Instead, the view is invalidated and only when the main event loop continues processing will the updates render.
So my question is, can I force a redraw of the entire device from the UI thread without returning to the main loop? If I return to the main loop then I will blow my entire call stack, and pausing during debugging will no longer work.
I tried to get the main Looper, and I can even call Loop() on it (ideally to start processing the events), but then this will become the main loop (and you cannot quit the main looper). If anyone has any thoughts on how to simulate the main event loop, that would be greatly appreciated.
This is fun, I'm doing the same thing as you, creating a bridge between J2V8 and Stetho. The trick is to run the debugger in it's own thread. Since the debugger will have direct access to V8, it can easily manipulate the runtime, but commands going to Native code (like UI commands) will run on the main thread until they come back to the V8 runtime.
I have a combined Java/C++ app. When I want to diagnose issues I often print log messages from C++ with the __android_log_print() function. This works fine so long as the C++ was called from the main thread, but if called from another thread, I do not see the log data. The multithreaded nature of my app is crucial to its operation. Is there any way of viewing the logs, or perhaps even viewing diagnostic output via some different mechanism altogether?
__android_log_print() works amazingly well from any thread, be it main thread, Java worker thread, JNI attached thread, or purely native. The -v threadtime logcat parameter is very useful. You should look for some other reason. Is the thread running at all?
I am using libDispatch (GCD) opensource on Android platform.
So, most of the complex time consuming tasks are being done through NDK (where i am using libDispatch).
For some calls, I am using dispatch_async(get_main_queue)...This is where the problem is coming...
I am able to run tasks in the concurrent queues but not on main queue.
Since this requires dispatch_main() to be called which we cannot do on here as Java thread will be blocked in that case.
So, is it possible to run the Java UI on some secondary thread and hook the dispatch_main() to serve the dispatch_main_queue here?
OR : Do I need to keep serving the main_queue from JAva main UI thread through JNI ?
Look into _dispatch_main_queue_callback_4CF which is the function you can call to drain the main queue. It will return like a normal sensible function after executing the queued operations, instead of killing the thread like dispatch_main.
Note that you'll need to call _dispatch_main_queue_callback_4CF on a regular basis from your Java UI thread, possibly each iteration. The official Cocoa implementation uses _dispatch_queue_wakeup_main() which uses mach messages to kick the main thread out of any sleep states so it can guarantee the callback function is called quickly, but you'd have to do some work to enable that and build your own libDispatch port. In reality on Android I don't think the main UI thread is ever put to sleep while your app is active so it shouldn't be an issue.
There is a ticket open on the libDispatch site at https://libdispatch.macosforge.org/trac/ticket/38 to make _dispatch_main_queue_callback_4CF a public function. The ticket is marked "Accepted" but no word on if/when that will happen.
The Qt doc says,
As mentioned, each program has one thread when it is started. This
thread is called the "main thread" (also known as the "GUI thread" in
Qt applications). The Qt GUI must run in this thread.
The Android doc says,
Like activities and the other components, services run in the main
thread of the application process
And iOS,
It is strongly recommended not to update UI controls etc from a
background thread (e.g. a timer, comms etc). This can be the cause of
crashes which are sometimes very hard to identify. Instead use these
to force code to be executed on the UI thread (which is always the
“main” thread).
Why does they use a single threaded model to update UI ?
The short answer is, it's the only reasonable way to ensure that the display is not corrupted.
The long answer is that allowing multiple threads to update the UI results in deadlocks, race conditions, and all sorts of trouble. This was the painful lesson taught by Java's AWT (among other UI systems) that allows multiple threads to touch the UI. See, for instance, Multithreaded toolkits: A failed dream?. That post refers (via dead links) to Why Threads Are A Bad Idea and Threadaches.
iOS and Android force you to work with UI only from main thread. The reason is the same as a shared object, thread safe[About]... in multithread environment
Android example error
FATAL EXCEPTION: Thread-19449
E/AndroidRuntime: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views
iOS example error
This application is modifying the autolayout engine from a background thread" error?