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;
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")
public static ZygoteProcess getProcess() {
synchronized (sLock) {
- connectToZygoteIfNeededLocked();
+ if (sZygote != null) return sZygote;
+
+ waitForServiceStartAndConnect();
return sZygote;
}
}
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;
return;
}
- serviceName = getServiceNameLocked();
+ final String serviceName = getServiceNameLocked();
sZygote = null;
// The service may enter the RUNNING state before it opens the socket,
} 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();
}
}
@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");