OSDN Git Service

Post WebView Zygote connection code to a background thread.
authorGustav Sennton <gsennton@google.com>
Wed, 22 Mar 2017 19:30:33 +0000 (19:30 +0000)
committerGustav Sennton <gsennton@google.com>
Fri, 24 Mar 2017 12:36:12 +0000 (12:36 +0000)
Currently, the act of waiting for the WebView Zygote to start running,
and then connecting to it is run in a blocking way from
WebViewZygote.onWebViewProviderChanged(). This causes us to block large
parts of WebViewUpdateService for a long time whenever we change WebView
provider.
This CL moves the blocking code onto a background thread to unblock
WebViewUpdateService.

Bug: 35025131
Test: Ensure changing WebView provider from the WebView Implementation
Developer Setting is quick/responsive.
Test: Turn off WebView multi-process and ensure the WebView Zygote
Service is NOT started.
Test: Turn on WebView multi-process and ensure the WebView Zygote
Service is started.

Change-Id: I0b378a471491d40cbf027568ca317d6c080da4b2

core/java/android/webkit/WebViewZygote.java

index f9d7332..f78d622 100644 (file)
@@ -22,6 +22,7 @@ import android.os.Build;
 import android.os.SystemService;
 import android.os.ZygoteProcess;
 import android.text.TextUtils;
+import android.util.AndroidRuntimeException;
 import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
@@ -53,6 +54,13 @@ public class WebViewZygote {
     private static ZygoteProcess sZygote;
 
     /**
+     * Variable that allows us to determine whether the WebView zygote Service has already been
+     * started.
+     */
+    @GuardedBy("sLock")
+    private static boolean sStartedService = false;
+
+    /**
      * Information about the selected WebView package. This is set from #onWebViewProviderChanged().
      */
     @GuardedBy("sLock")
@@ -67,7 +75,9 @@ public class WebViewZygote {
 
     public static ZygoteProcess getProcess() {
         synchronized (sLock) {
-            connectToZygoteIfNeededLocked();
+            if (sZygote != null) return sZygote;
+
+            waitForServiceStartAndConnect();
             return sZygote;
         }
     }
@@ -95,17 +105,20 @@ public class WebViewZygote {
             final String serviceName = getServiceNameLocked();
             if (serviceName == null) return;
 
-            if (enabled && sZygote == null) {
-                SystemService.start(serviceName);
+            if (enabled) {
+                if (!sStartedService) {
+                    SystemService.start(serviceName);
+                    sStartedService = true;
+                }
             } else {
                 SystemService.stop(serviceName);
+                sStartedService = false;
                 sZygote = null;
             }
         }
     }
 
     public static void onWebViewProviderChanged(PackageInfo packageInfo) {
-        String serviceName;
         synchronized (sLock) {
             sPackage = packageInfo;
 
@@ -114,7 +127,7 @@ public class WebViewZygote {
                 return;
             }
 
-            serviceName = getServiceNameLocked();
+            final String serviceName = getServiceNameLocked();
             sZygote = null;
 
             // The service may enter the RUNNING state before it opens the socket,
@@ -124,14 +137,28 @@ public class WebViewZygote {
             } else {
                 SystemService.restart(serviceName);
             }
+            sStartedService = true;
+        }
+    }
 
-            try {
-                SystemService.waitForState(serviceName, SystemService.State.RUNNING, 5000);
-            } catch (TimeoutException e) {
-                Log.e(LOGTAG, "Timed out waiting for " + serviceName);
-                return;
-            }
+    private static void waitForServiceStartAndConnect() {
+        if (!sStartedService) {
+            throw new AndroidRuntimeException("Tried waiting for the WebView Zygote Service to " +
+                    "start running without first starting the service.");
+        }
+
+        String serviceName;
+        synchronized (sLock) {
+            serviceName = getServiceNameLocked();
+        }
+        try {
+            SystemService.waitForState(serviceName, SystemService.State.RUNNING, 5000);
+        } catch (TimeoutException e) {
+            Log.e(LOGTAG, "Timed out waiting for " + serviceName);
+            return;
+        }
 
+        synchronized (sLock) {
             connectToZygoteIfNeededLocked();
         }
     }
@@ -151,8 +178,9 @@ public class WebViewZygote {
 
     @GuardedBy("sLock")
     private static void connectToZygoteIfNeededLocked() {
-        if (sZygote != null)
+        if (sZygote != null) {
             return;
+        }
 
         if (sPackage == null) {
             Log.e(LOGTAG, "Cannot connect to zygote, no package specified");