Start setup resources earlier in the startup process

From crrev.com/c/923174, we set up resources on a background thread in
an attempt to reduce the start up time.

Calling resource rewriter's onResourcesLoaded() on a background thread
seems safe, and now we're calling it even earlier to reduce startup time.

Bug: 817644
Change-Id: I684b2c1c0cfb9fa2b1e1b7a3bfe35659ba836720
Reviewed-on: https://chromium-review.googlesource.com/1069219
Reviewed-by: Bo <boliu@chromium.org>
Reviewed-by: Tao Bai <michaelbai@chromium.org>
Commit-Queue: Changwan Ryu <changwan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#560699}
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumAwInit.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumAwInit.java
index 5ec9101..c67093d 100644
--- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumAwInit.java
+++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumAwInit.java
@@ -17,7 +17,6 @@
 import android.webkit.TokenBindingService;
 import android.webkit.WebStorage;
 import android.webkit.WebViewDatabase;
-import android.webkit.WebViewFactory;
 
 import com.android.webview.chromium.WebViewDelegateFactory.WebViewDelegate;
 
@@ -70,6 +69,7 @@
     private AwServiceWorkerController mServiceWorkerController;
     private AwTracingController mAwTracingController;
     private VariationsSeedLoader mSeedLoader;
+    private Thread mSetUpResourcesThread;
 
     // Guards accees to the other members, and is notifyAll() signalled on the UI thread
     // when the chromium process has been started.
@@ -116,19 +116,8 @@
                 return;
             }
 
-            final PackageInfo webViewPackageInfo = WebViewFactory.getLoadedPackageInfo();
             final Context context = ContextUtils.getApplicationContext();
 
-            // Make sure that ResourceProvider is initialized before starting the browser process.
-            Thread startUpResourcesThread = new Thread(new Runnable() {
-                @Override
-                public void run() {
-                    // Run this in parallel as it takes some time.
-                    setUpResources(webViewPackageInfo, context);
-                }
-            });
-            startUpResourcesThread.start();
-
             // We are rewriting Java resources in the background.
             // NOTE: Any reference to Java resources will cause a crash.
 
@@ -145,12 +134,8 @@
             initPlatSupportLibrary();
             doNetworkInitializations(context);
 
-            try (ScopedSysTraceEvent e = ScopedSysTraceEvent.scoped(
-                         "WebViewChromiumAwInit.startUpResourcesThread_join")) {
-                startUpResourcesThread.join();
-            } catch (InterruptedException e) {
-                throw new RuntimeException(e);
-            }
+            waitUntilSetUpResources();
+
             // NOTE: Finished writing Java resources. From this point on, it's safe to use them.
 
             AwBrowserProcess.configureChildProcessLauncher();
@@ -197,6 +182,33 @@
         }
     }
 
+    /**
+     * Set up resources on a background thread.
+     * @param context The context.
+     */
+    public void setUpResourcesOnBackgroundThread(PackageInfo webViewPackageInfo, Context context) {
+        assert mSetUpResourcesThread == null : "This method shouldn't be called twice.";
+
+        // Make sure that ResourceProvider is initialized before starting the browser process.
+        mSetUpResourcesThread = new Thread(new Runnable() {
+            @Override
+            public void run() {
+                // Run this in parallel as it takes some time.
+                setUpResources(webViewPackageInfo, context);
+            }
+        });
+        mSetUpResourcesThread.start();
+    }
+
+    private void waitUntilSetUpResources() {
+        try (ScopedSysTraceEvent e = ScopedSysTraceEvent.scoped(
+                     "WebViewChromiumAwInit.waitUntilSetUpResources")) {
+            mSetUpResourcesThread.join();
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
     private void setUpResources(PackageInfo webViewPackageInfo, Context context) {
         try (ScopedSysTraceEvent e =
                         ScopedSysTraceEvent.scoped("WebViewChromiumAwInit.setUpResources")) {
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java
index 6fefd01..bd5dbf6 100644
--- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java
+++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumFactoryProvider.java
@@ -222,6 +222,9 @@
             // WebView needs to make sure to always use the wrapped application context.
             ContextUtils.initApplicationContext(ResourcesContextWrapperFactory.get(ctx));
 
+            mAwInit.setUpResourcesOnBackgroundThread(
+                    packageInfo, ContextUtils.getApplicationContext());
+
             try (ScopedSysTraceEvent e2 = ScopedSysTraceEvent.scoped(
                          "WebViewChromiumFactoryProvider.initCommandLine")) {
                 // This may take ~20 ms only on userdebug devices.