AndroidWebView启动Chromium渲染引擎的过程分析_第1页
AndroidWebView启动Chromium渲染引擎的过程分析_第2页
AndroidWebView启动Chromium渲染引擎的过程分析_第3页
AndroidWebView启动Chromium渲染引擎的过程分析_第4页
AndroidWebView启动Chromium渲染引擎的过程分析_第5页
已阅读5页,还剩42页未读 继续免费阅读

付费下载

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Android WebView 启动 Chromium 渲染引擎的过程分析Android WebView 加载了 Chromium 动态库之后,就可以启动 Chromium 渲染引擎了。Chromium 渲染引擎由 Browser、Render 和 GPU 三端组成。其中,Browser 端负责将网页UI 合成在屏幕上,Render 端负责加载网页的 URL 和渲染网页的 UI,GPU 端负责执行Browser 端和 Render 端请求的 GPU 命令。本文接下来详细分析 Chromium 渲染引擎三端的启动过程。Android WebView 使用了单进程架构的 Chromium 来加载和渲染网页,因此它的 Browser端、Render 端和 GPU 端都不是以进程的形式存在的,而是以线程的形式存在。其中,Browser 端实现在 App 的 UI 线程中,Render 端实现在一个独立的线程中,而 GPU 端实现在 App 的 Render Thread 中。注意,这是针对 Android 5.0 及以上版本的。Android 在 4.4 版本引入基于 Chromium 实现的 WebView,那时候 GPU 端与 Browser 一样,都是实现在 App的 UI 线程中。接下来我们只讨论 Android WebView 在 Android 5.0 及以上版本的实现。Android WebView 启动 Chromium 渲染引擎三端的过程如图 1 所示:从前面一文可以知道,当我们在 App 的 UI 中嵌入一个 WebView 时,WebView 会在内部创建一个类型为 WebViewChromium 的 Provider。Android WebView 就是通过这个 Provider来启动和使用 Chromium 渲染引擎的。Chromium 里面有一个 android_webview 模块。这个模块提供了两个类AwBrowserProcess 和 AwContents,分别用来封装 Chromium 的 Content 层提供的两个接口类 BrowserStartupController 和 ContentViewCore,它们分别用来启动 Chromium 的 Browser端和 Render 端。Android WebView 启动 Chromium 的 Browser 端,实际上就是在 App 的 UI 线程创建一个 Browser Main Loop。Chromium 以后需要请求 Browser 端执行某一个操作时,就可以向这个 Browser Main Loop 发送一个 Task。这个 Task 最终会在 App 进程的 UI 线程中调度执行。Android WebView 启动 Chromium 的 Render 端,实际上就是在当前的 App 进程中创建一个线程。以后网页就由这个线程负责加载和渲染。这个线程称为 In-Process Renderer Thread。由于 Chromium 的 GPU 端实现在 App 的 Render Thread 中,这个 Render Thread 是由 App 负责启动的,因此 Chromium 无需启动它。不过, Chromium 里的 android_webview模块会启动一个 DeferredGpuCommandService 服务。当 Chromium 的 Browser 端和 Render端需要执行 GPU 操作时,就会向 DeferredGpuCommandService 服务发出请求。这时候DeferredGpuCommandService 服务又会通过 App 的 UI 线程将请求的 GPU 操作提交给 App的 Render Thread 执行。这一点可以参考前面一文的描述。我们在接下来的一篇文章也会对Chromium 的 Browser 端和 Render 端执行 GPU 操作的过程进行详细的分析。接下来我们就结合源码,分析 Android WebView 启动 Chromium 的 Browser 端和Render 端的过程。对于 GPU 端,我们仅仅分析与它相关的 DeferredGpuCommandService服务的启动过程。在接下来一篇文章分析 Android WebView 执行 GPU 命令的过程时,我们再对 GPU 端进行更详细的分析。我们首先分析 Android WebView 启动 Chromium 的 Browser 端的过程。前面提到,WebView 会在内部创建一个类型为 WebViewChromium 的 Provider。有了这个 Provider 之后,WebView 就可以调用它的成员函数 init 启动 Chromium 的 Browser 端,如下所示:java view plain copyclass WebViewChromium implements WebViewProvider, WebViewProvider.ScrollDelegate, WebViewProvider.ViewDelegate . public void init(final Map javaScriptInterfaces, final boolean privateBrowsing) . / We will defer real initialization until we know which thread to do it on, unless: / - we are on the main thread already (common case), / - the app is targeting = JB MR2, in which case checkThread enforces that all usage / comes from a single thread. (Note in JB MR2 this exception was in WebView.java). if (mAppTargetSdkVersion = Build.VERSION_CODES.JELLY_BEAN_MR2) mFactory.startYourEngines(false); checkThread(); else if (!mFactory.hasStarted() if (Looper.myLooper() = Looper.getMainLooper() mFactory.startYourEngines(true); . mRunQueue.addTask(new Runnable() Override public void run() initForReal(); . ); . 这个函数定义在文件frameworks/webview/chromium/java/com/android/webview/chromium/WebViewChromium.java中。WebViewChromium 类的成员变量 mFactory 指向的是一个WebViewChromiumFactoryProvider 对象。WebViewChromium 类的成员函数 init 通过调用这个 WebViewChromiumFactoryProvider 对象的成员函数 startYourEngines 启动 Chromium渲染引擎的 Browser 端。在 Android 4.3 之前, WebView 只能在 App 的 UI 线程中创建。相应地,WebView也只能在 App 的 UI 线程中启动 Chromium 渲染引擎的 Browser 端。这时候WebViewChromium 类的成员函数 init 会传递一个参数 true 给WebViewChromiumFactoryProvider 类的成员函数 startYourEngines,表示如果当前线程如果不是 UI 线程,那么就需要向 UI 线程发出一个通知,让 UI 线程执行启动 Chromium 渲染引擎的 Browser 端的操作。在 Android 4.3 及以后,WebView 也允许在 App 的非 UI 线程中创建。这时候WebView 允行在 App 的非 UI 线程中启动 Chromium 渲染引擎的 Browser 端。因此,WebViewChromium 类的成员函数 init 就会传递一个参数 false 给WebViewChromiumFactoryProvider 类的成员函数 startYourEngines。一般情况下,WebView 都是在 App 的 UI 线程中创建的。为了简单起见,我们只考虑这种情况。WebViewChromium 类的成员函数 init 调用WebViewChromiumFactoryProvider 类的成员函数 startYourEngines 启动了 Chromium 渲染引擎的 Browser 端之后,接下来还会向 App 的 UI 线程的消息队列发送一个 Runnable。当该Runnable 被执行的时候,它就会调用 WebViewChromium 类的成员函数 initForReal 创建图1 所示的 AwContents 对象。有了这个 AwContents 对象之后,后面就可以通过它来加载指定的 URL 了。接下来,我们首先分析 WebViewChromiumFactoryProvider 类的成员函数startYourEngines 启动 Chromium 渲染引擎的 Browser 端的过程,然后再分析WebViewChromium 类的成员函数 initForReal 为 WebView 创建 AwContents 对象的过程。WebViewChromiumFactoryProvider 类的成员函数 startYourEngines 的实现如下所示:java view plain copypublic class WebViewChromiumFactoryProvider implements WebViewFactoryProvider . void startYourEngines(boolean onMainThread) synchronized (mLock) ensureChromiumStartedLocked(onMainThread); . 这个函数定义在文件frameworks/webview/chromium/java/com/android/webview/chromium/WebViewChromiumFactoryProvider.java 中。WebViewChromiumFactoryProvider 类的成员函数 startYourEngines 调用另外一个成员函数 ensureChromiumStartedLocked 检查 Chromium 渲染引擎的 Browser 端是否已经启动。如果还没有启动,那么就会进行启动,如下所示:java view plain copypublic class WebViewChromiumFactoryProvider implements WebViewFactoryProvider . private void ensureChromiumStartedLocked(boolean onMainThread) . if (mStarted) / Early-out for the common case. return; Looper looper = !onMainThread ? Looper.myLooper() : Looper.getMainLooper(); . ThreadUtils.setUiThread(looper); if (ThreadUtils.runningOnUiThread() startChromiumLocked(); return; / We must post to the UI thread to cover the case that the user has invoked Chromium / startup by using the (thread-safe) CookieManager rather than creating a WebView. ThreadUtils.postOnUiThread(new Runnable() Override public void run() synchronized (mLock) startChromiumLocked(); ); while (!mStarted) try / Important: wait() releases |mLock| the UI thread can take it :-) mLock.wait(); catch (InterruptedException e) / Keep trying. eventually the UI thread will process the task we sent it. . 这个函数定义在文件frameworks/webview/chromium/java/com/android/webview/chromium/WebViewChromiumFactoryProvider.java 中。如果 Chromium 渲染引擎的 Browser 端已经启动,那么WebViewChromiumFactoryProvider 类的成员变量 mStarted 的值就会等于 true。在这种情况下,WebViewChromiumFactoryProvider 类的成员函数 ensureChromiumStartedLocked 什么也不用做就可以返回。另一方面,如果 Chromium 渲染引擎的 Browser 端还没有启动,那么WebViewChromiumFactoryProvider 类的成员函数 ensureChromiumStartedLocked 首先会根据参数 onMainThread 确定 Chromium 渲染引擎的 Browser 端要在哪个线程中运行。当参数 onMainThread 的值等于 true 的时候,就表示 Chromium 渲染引擎的 Browser端要在 App 的 UI 线程中运行。这时候如果当前线程不是 App 的 UI 线程,那么WebViewChromiumFactoryProvider 类的成员函数 ensureChromiumStartedLocked 就会向 App的 UI 线程的消息队列发送一个 Runnable。当该 Runnable 被执行的时候,才会启动Chromium 渲染引擎的 Browser 端。在这种情况下,当前线程也会等待 App 的 UI 线程启动完成 Chromium 渲染引擎的 Browser 端。当参数 onMainThread 的值等于 true 的时候,如果当前线程刚好也是 App 的 UI 线程,那么 WebViewChromiumFactoryProvider 类的成员函数 ensureChromiumStartedLocked就可以马上启动 Chromium 渲染引擎的 Browser 端。当参数 onMainThread 的值等于 false 的时候,不管当前线程是否 App 的 UI 线程,都表示 Chromium 渲染引擎的 Browser 端要在它里面运行。因此,这时候WebViewChromiumFactoryProvider 类的成员函数 ensureChromiumStartedLocked 都会马上启动 Chromium 渲染引擎的 Browser 端。无论是上述的哪一种情况,用来运行 Chromium 渲染引擎的 Browser 端的线程都会通过调用 ThreadUtils 类的静态成员函数 setUiThread 记录起来。以后 WebView 都需要在该线程中访问 Chromium 渲染引擎。WebViewChromiumFactoryProvider 类的成员函数 ensureChromiumStartedLocked 是通过调用另外一个成员函数 startChromiumLocked 启动 Chromium 渲染引擎的 Browser 端的,如下所示:java view plain copypublic class WebViewChromiumFactoryProvider implements WebViewFactoryProvider . private void startChromiumLocked() . AwBrowserProcess.start(ActivityThread.currentApplication(); . . 这个函数定义在文件frameworks/webview/chromium/java/com/android/webview/chromium/WebViewChromiumFactoryProvider.java 中。WebViewChromiumFactoryProvider 类的成员函数 startChromiumLocked 通过调用AwBrowserProcess 类的静态成员函数 start 启动 Chromium 渲染引擎的 Browser 端的,如下所示:java view plain copypublic abstract class AwBrowserProcess . public static void start(final Context context) / We must post to the UI thread to cover the case that the user / has invoked Chromium startup by using the (thread-safe) / CookieManager rather than creating a WebView. ThreadUtils.runOnUiThreadBlocking(new Runnable() Override public void run() try BrowserStartupController.get(context).startBrowserProcessesSync( BrowserStartupController.MAX_RENDERERS_SINGLE_PROCESS); . catch (ProcessInitException e) . ); . 这个函数定义在文件external/chromium_org/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java 中。前面提到,用来运行 Chromium 渲染引擎的 Browser 端的线程会通过 ThreadUtils 类的静态成员函数 setUiThread 记录起来。AwBrowserProcess 类的静态成员函数 start 为了确保 Chromium 渲染引擎的 Browser 端在该线程中启动,会通过调用 ThreadUtils 类的静态成员函数 runOnUiThreadBlocking 检查当前线程是否就是该线程。如果是的话,那么就会直接启动。否则的话,会向该线程的消息队列发送一个 Runnable。当该 Runnable 被执行的时候,再启动 Chromium 渲染引擎的 Browser 端。AwBrowserProcess 类的静态成员函数 start 是通过调用当前 App 进程中的一个BrowserStartupController 单例对象的成员函数 startBrowserProcessesSync 来启动 Chromium渲染引擎的 Browser 端的。这个 BrowserStartupController 单例对象可以通过调用BrowserStartupController 类的静态成员函数 get 获得。AwBrowserProcess 类的静态成员函数 start 在启动 Chromium 渲染引擎的 Browser端的时候,会指定一个 BrowserStartupController.MAX_RENDERERS_SINGLE_PROCESS参数。这个参数的值等于 0,表示要启动一个单进程架构的 Chromium 渲染引擎。接下来,我们就继续分析 Chromium 渲染引擎的 Browser 端的启动过程,也就是BrowserStartupController 类的成员函数 startBrowserProcessesSync 的实现,如下所示:java view plain copypublic class BrowserStartupController . public void startBrowserProcessesSync(int maxRenderers) throws ProcessInitException / If already started skip to checking the result if (!mStartupDone) if (!mHasStartedInitializingBrowserProcess) prepareToStartBrowserProcess(maxRenderers); . if (contentStart() 0) / Failed. The callbacks may not have run, so run them. enqueueCallbackExecution(STARTUP_FAILURE, NOT_ALREADY_STARTED); . . 这个函数定义在文件external/chromium_org/content/public/android/java/src/org/chromium/content/browser/BrowserStartupController.java 中。当 BrowserStartupController 类的成员变量 mStartupDone 的值等于 true 的时候,就表示 Chromium 渲染引擎的 Browser 端已经启动了。这时候 BrowserStartupController 类的成员函数 startBrowserProcessesSync 就什么也不做就直接返回。另一方面,如果 Chromium 渲染引擎的 Browser 端还没有启动。这时候BrowserStartupController 类的成员函数 startBrowserProcessesSync 就会调用另外一个成员函数 contentStart 进行启动。在启动 Chromium 渲染引擎的 Browser 端之前,BrowserStartupController 类的成员函数 startBrowserProcessesSync 也会检查成员变量 mHasStartedInitializingBrowserProcess 的值。当这个值等于 false 的时候,就会先调用成员函数 prepareToStartBrowserProcess 设置Chromium 渲染引擎的启动参数。其中,最重要的就是将 Chromium 渲染引擎设置为单进程架构。接下来,我们先分析将 Chromium 渲染引擎设置为单进程架构的过程,也就是BrowserStartupController 类的成员函数 prepareToStartBrowserProcess 的实现,然后再分析启动 Chromium 渲染引擎的 Browser 端的过程,也就是 BrowserStartupController 类的成员函数 contentStart 的实现。BrowserStartupController 类的成员函数 prepareToStartBrowserProcess 的实现如下所示:java view plain copypublic class BrowserStartupController . void prepareToStartBrowserProcess(int maxRendererProcesses) throws ProcessInitException . nativeSetCommandLineFlags(maxRendererProcesses, nativeIsPluginEnabled() ? getPlugins() : null); . . 这个函数定义在文件external/chromium_org/content/public/android/java/src/org/chromium/content/browser/BrowserStartupController.java 中。BrowserStartupController 类的成员函数 prepareToStartBrowserProcess 调用另外一个成员函数 nativeSetCommandLineFlags 将 Chromium 渲染引擎设置为单进程架构。BrowserStartupController 类的成员函数 nativeSetCommandLineFlags 是一个 JNI 方法,它由 C+层的函数Java_com_android_org_chromium_content_browser_BrowserStartupController_nativeSetCommandLineFlags 实现,如下所示:cpp view plain copy_attribute_(visibility(“default“) void Java_com_android_org_chromium_content_browser_BrowserStartupController_nativeSetCommandLineFlags(JNIEnv* env, jclass jcaller, jint maxRenderProcess

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论