| # Android WebView and the UI thread |
| |
| This document describes how the Chromium based Android WebView reconciles with |
| mismatching requirements and assumptions between Android and Chromium about the |
| UI thread. |
| |
| |
| ## The UI Thread in Chromium |
| |
| In Chromium, there is a single global **UI** thread in the browser process. It |
| is one of the explicitly named |
| [BrowserThreads](/content/public/browser/browser_thread.h). |
| The **UI** thread is generally where UI code runs, including input delivery from |
| the OS. |
| |
| The concept of “the one and only **UI** thread” is well established in content |
| layer and above. For example, all WebContents live on this **UI** thread. |
| |
| |
| ## View Threads in Android |
| |
| A [Window](https://developer.android.com/reference/android/view/Window.html), |
| its view tree, and |
| [Views](https://developer.android.com/reference/android/view/View) in that tree |
| are all single threaded in general; for a particular View, call this the |
| **view** thread. It is possible to create separate Windows and view trees on |
| separate threads, as long as Views are not moved between them. So there can be |
| more than one **view** thread. |
| |
| Most apps do not make use of this hidden feature; they use a single view tree on |
| the [main thread](https://developer.android.com/reference/android/os/Looper#getMainLooper()) |
| of the application. However, in general, it’s not safe to assume there’s only a |
| single **view** thread, or that the **view** thread and the **main** thread is |
| the same. |
| |
| |
| ## Best effort solution |
| |
| WebView’s solution is use the first **view** thread as the **UI** thread, then |
| post non-**UI** thread calls to the **UI** thread, and block if needed. |
| |
| Because Chromium initialization identifies the thread as the UI thread, parts of |
| this solution runs before Chromium is initialized. The implementation is in the |
| android webview glue layer, specifically in |
| [WebViewChromium](../glue/java/src/com/android/webview/chromium/WebViewChromium.java) |
| and [WebViewChromiumFactoryProvider](../glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java). |
| The idea is hold off initializing chromium until a **view** thread is identified. |
| |
| **View** thread can be identified by certain View methods. For example, |
| [onAttachedToWindow](https://developer.android.com/reference/android/view/View.html#onAttachedToWindow()) |
| is called by the view tree on the **view** thread. Of course this is not 100% |
| reliable since apps could call those methods as well. |
| |
| In case a method that cannot be held off is called before a view thread is |
| identified, the **main** thread is used as the **UI** thread. Methods calls that |
| are not held off include: |
| |
| * Methods with an immediate output with no meaningful defaults without initialization. |
| * onDraw: Need to draw into canvas parameter |
| * Any method with a return value, like getHttpAuthUsernamePassword. |
| * “Important” calls that should not be held off. This is a judgement call mostly. |
| * Currently only loadUrl and loadData family of calls |
| |
| |
| ## View is Single-Threaded |
| |
| Views in android are expected to be created and used on its single **view** |
| thread, unless otherwise noted in the API. For WebView, this is enforced for |
| apps targeting JB MR2 or above. The code lives in |
| [WebView.java](https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/core/java/android/webkit/WebView.java). |
| Note this is an orthogonal concern to the single **UI** thread described above, |
| as this check still allows different WebViews to be used on different **view** |
| threads. |