Chris Mumford | 1c12b3f | 2019-08-13 15:29:05 | [diff] [blame] | 1 | # Android WebView and the UI thread |
| 2 | |
| 3 | This document describes how the Chromium based Android WebView reconciles with |
| 4 | mismatching requirements and assumptions between Android and Chromium about the |
| 5 | UI thread. |
| 6 | |
| 7 | |
| 8 | ## The UI Thread in Chromium |
| 9 | |
| 10 | In Chromium, there is a single global **UI** thread in the browser process. It |
| 11 | is one of the explicitly named |
| 12 | [BrowserThreads](/content/public/browser/browser_thread.h). |
| 13 | The **UI** thread is generally where UI code runs, including input delivery from |
| 14 | the OS. |
| 15 | |
| 16 | The concept of “the one and only **UI** thread” is well established in content |
| 17 | layer and above. For example, all WebContents live on this **UI** thread. |
| 18 | |
| 19 | |
| 20 | ## View Threads in Android |
| 21 | |
Nate Fischer | 84c05a4 | 2021-11-29 22:29:39 | [diff] [blame] | 22 | A [Window](https://developer.android.com/reference/android/view/Window.html), |
| 23 | its view tree, and |
| 24 | [Views](https://developer.android.com/reference/android/view/View) in that tree |
| 25 | are all single threaded in general; for a particular View, call this the |
| 26 | **view** thread. It is possible to create separate Windows and view trees on |
| 27 | separate threads, as long as Views are not moved between them. So there can be |
| 28 | more than one **view** thread. |
Chris Mumford | 1c12b3f | 2019-08-13 15:29:05 | [diff] [blame] | 29 | |
| 30 | Most apps do not make use of this hidden feature; they use a single view tree on |
Nate Fischer | 84c05a4 | 2021-11-29 22:29:39 | [diff] [blame] | 31 | the [main thread](https://developer.android.com/reference/android/os/Looper#getMainLooper()) |
Chris Mumford | 1c12b3f | 2019-08-13 15:29:05 | [diff] [blame] | 32 | of the application. However, in general, it’s not safe to assume there’s only a |
| 33 | single **view** thread, or that the **view** thread and the **main** thread is |
| 34 | the same. |
| 35 | |
| 36 | |
| 37 | ## Best effort solution |
| 38 | |
| 39 | WebView’s solution is use the first **view** thread as the **UI** thread, then |
| 40 | post non-**UI** thread calls to the **UI** thread, and block if needed. |
| 41 | |
| 42 | Because Chromium initialization identifies the thread as the UI thread, parts of |
| 43 | this solution runs before Chromium is initialized. The implementation is in the |
| 44 | android webview glue layer, specifically in |
| 45 | [WebViewChromium](../glue/java/src/com/android/webview/chromium/WebViewChromium.java) |
| 46 | and [WebViewChromiumFactoryProvider](../glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java). |
| 47 | The idea is hold off initializing chromium until a **view** thread is identified. |
| 48 | |
| 49 | **View** thread can be identified by certain View methods. For example, |
Nate Fischer | 84c05a4 | 2021-11-29 22:29:39 | [diff] [blame] | 50 | [onAttachedToWindow](https://developer.android.com/reference/android/view/View.html#onAttachedToWindow()) |
Chris Mumford | 1c12b3f | 2019-08-13 15:29:05 | [diff] [blame] | 51 | is called by the view tree on the **view** thread. Of course this is not 100% |
| 52 | reliable since apps could call those methods as well. |
| 53 | |
| 54 | In case a method that cannot be held off is called before a view thread is |
| 55 | identified, the **main** thread is used as the **UI** thread. Methods calls that |
| 56 | are not held off include: |
| 57 | |
| 58 | * Methods with an immediate output with no meaningful defaults without initialization. |
| 59 | * onDraw: Need to draw into canvas parameter |
| 60 | * Any method with a return value, like getHttpAuthUsernamePassword. |
| 61 | * “Important” calls that should not be held off. This is a judgement call mostly. |
| 62 | * Currently only loadUrl and loadData family of calls |
| 63 | |
| 64 | |
| 65 | ## View is Single-Threaded |
| 66 | |
| 67 | Views in android are expected to be created and used on its single **view** |
| 68 | thread, unless otherwise noted in the API. For WebView, this is enforced for |
Nate Fischer | 02b3a9d | 2023-07-14 23:35:50 | [diff] [blame] | 69 | apps targeting JB MR2 or above. The code lives in |
| 70 | [WebView.java](https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/core/java/android/webkit/WebView.java). |
Chris Mumford | 1c12b3f | 2019-08-13 15:29:05 | [diff] [blame] | 71 | Note this is an orthogonal concern to the single **UI** thread described above, |
| 72 | as this check still allows different WebViews to be used on different **view** |
| 73 | threads. |