WebViewZygote.java revision f05f99b9106ab6dffcf71735f0f7c269ad23282e
1ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek/* 2ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek * Copyright (C) 2016 The Android Open Source Project 3ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek * 4ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek * Licensed under the Apache License, Version 2.0 (the "License"); 5ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek * you may not use this file except in compliance with the License. 6ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek * You may obtain a copy of the License at 7ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek * 8ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek * http://www.apache.org/licenses/LICENSE-2.0 9ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek * 10ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek * Unless required by applicable law or agreed to in writing, software 11ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek * distributed under the License is distributed on an "AS IS" BASIS, 12ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek * See the License for the specific language governing permissions and 14ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek * limitations under the License. 15ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek */ 16ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek 17ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesekpackage android.webkit; 18ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek 193b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles)import android.app.LoadedApk; 20ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesekimport android.content.pm.PackageInfo; 21ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesekimport android.os.Build; 22ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesekimport android.os.SystemService; 23ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesekimport android.os.ZygoteProcess; 243b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles)import android.text.TextUtils; 25f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Senntonimport android.util.AndroidRuntimeException; 26ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesekimport android.util.Log; 27ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek 2889cc5205b3b54b85c584583760d07af7049e6e28Robert Sesekimport com.android.internal.annotations.GuardedBy; 2989cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek 303b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles)import java.io.File; 31ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesekimport java.io.IOException; 323b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles)import java.util.ArrayList; 33ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesekimport java.util.Arrays; 343b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles)import java.util.List; 35ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesekimport java.util.concurrent.TimeoutException; 36ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek 37ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek/** @hide */ 38ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesekpublic class WebViewZygote { 39ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek private static final String LOGTAG = "WebViewZygote"; 40ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek 41ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek private static final String WEBVIEW_ZYGOTE_SERVICE_32 = "webview_zygote32"; 42ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek private static final String WEBVIEW_ZYGOTE_SERVICE_64 = "webview_zygote64"; 43ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek 4489cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek /** 4589cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek * Lock object that protects all other static members. 4689cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek */ 4789cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek private static final Object sLock = new Object(); 4889cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek 4989cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek /** 5089cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek * Instance that maintains the socket connection to the zygote. This is null if the zygote 5189cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek * is not running or is not connected. 5289cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek */ 5389cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek @GuardedBy("sLock") 54ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek private static ZygoteProcess sZygote; 55ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek 5689cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek /** 57f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton * Variable that allows us to determine whether the WebView zygote Service has already been 58f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton * started. 59f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton */ 60f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton @GuardedBy("sLock") 61f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton private static boolean sStartedService = false; 62f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton 63f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton /** 6489cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek * Information about the selected WebView package. This is set from #onWebViewProviderChanged(). 6589cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek */ 6689cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek @GuardedBy("sLock") 67ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek private static PackageInfo sPackage; 68ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek 6989cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek /** 7089cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek * Flag for whether multi-process WebView is enabled. If this is false, the zygote 7189cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek * will not be started. 7289cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek */ 7389cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek @GuardedBy("sLock") 74ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek private static boolean sMultiprocessEnabled = false; 75ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek 76ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek public static ZygoteProcess getProcess() { 7789cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek synchronized (sLock) { 78f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton if (sZygote != null) return sZygote; 79f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton 80f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton waitForServiceStartAndConnect(); 8189cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek return sZygote; 8289cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek } 83ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek } 84ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek 85ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek public static String getPackageName() { 8689cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek synchronized (sLock) { 8789cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek return sPackage.packageName; 8889cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek } 89ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek } 90ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek 91c5f86647b19d5cac4d9874ef84954fcf7a6d5fa9Robert Sesek public static boolean isMultiprocessEnabled() { 9289cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek synchronized (sLock) { 9389cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek return sMultiprocessEnabled && sPackage != null; 9489cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek } 95c5f86647b19d5cac4d9874ef84954fcf7a6d5fa9Robert Sesek } 96c5f86647b19d5cac4d9874ef84954fcf7a6d5fa9Robert Sesek 97ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek public static void setMultiprocessEnabled(boolean enabled) { 9889cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek synchronized (sLock) { 9989cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek sMultiprocessEnabled = enabled; 10089cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek 10189cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek // When toggling between multi-process being on/off, start or stop the 10289cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek // service. If it is enabled and the zygote is not yet started, bring up the service. 10389cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek // Otherwise, bring down the service. The name may be null if the package 10489cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek // information has not yet been resolved. 10589cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek final String serviceName = getServiceNameLocked(); 10689cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek if (serviceName == null) return; 10789cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek 108f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton if (enabled) { 109f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton if (!sStartedService) { 110f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton SystemService.start(serviceName); 111f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton sStartedService = true; 112f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton } 11389cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek } else { 11489cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek SystemService.stop(serviceName); 115f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton sStartedService = false; 11689cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek sZygote = null; 11789cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek } 118ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek } 119ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek } 120ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek 121ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek public static void onWebViewProviderChanged(PackageInfo packageInfo) { 12289cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek synchronized (sLock) { 12389cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek sPackage = packageInfo; 124ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek 12589cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek // If multi-process is not enabled, then do not start the zygote service. 12689cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek if (!sMultiprocessEnabled) { 12789cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek return; 12889cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek } 129ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek 130f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton final String serviceName = getServiceNameLocked(); 13189cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek sZygote = null; 132ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek 13389cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek // The service may enter the RUNNING state before it opens the socket, 13489cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek // so connectToZygoteIfNeededLocked() may still fail. 13589cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek if (SystemService.isStopped(serviceName)) { 13689cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek SystemService.start(serviceName); 13789cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek } else { 13889cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek SystemService.restart(serviceName); 13989cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek } 140f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton sStartedService = true; 141f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton } 142f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton } 14389cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek 144f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton private static void waitForServiceStartAndConnect() { 145f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton if (!sStartedService) { 146f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton throw new AndroidRuntimeException("Tried waiting for the WebView Zygote Service to " + 147f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton "start running without first starting the service."); 148f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton } 149f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton 150f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton String serviceName; 151f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton synchronized (sLock) { 152f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton serviceName = getServiceNameLocked(); 153f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton } 154f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton try { 155f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton SystemService.waitForState(serviceName, SystemService.State.RUNNING, 5000); 156f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton } catch (TimeoutException e) { 157f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton Log.e(LOGTAG, "Timed out waiting for " + serviceName); 158f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton return; 159f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton } 16089cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek 161f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton synchronized (sLock) { 16289cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek connectToZygoteIfNeededLocked(); 163ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek } 164ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek } 165ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek 16689cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek @GuardedBy("sLock") 16789cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek private static String getServiceNameLocked() { 168ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek if (sPackage == null) 169ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek return null; 170ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek 171ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek if (Arrays.asList(Build.SUPPORTED_64_BIT_ABIS).contains( 172ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek sPackage.applicationInfo.primaryCpuAbi)) { 173ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek return WEBVIEW_ZYGOTE_SERVICE_64; 174ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek } 175ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek 176ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek return WEBVIEW_ZYGOTE_SERVICE_32; 177ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek } 178ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek 17989cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek @GuardedBy("sLock") 18089cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek private static void connectToZygoteIfNeededLocked() { 181f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton if (sZygote != null) { 182ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek return; 183f05f99b9106ab6dffcf71735f0f7c269ad23282eGustav Sennton } 184ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek 185ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek if (sPackage == null) { 186ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek Log.e(LOGTAG, "Cannot connect to zygote, no package specified"); 187ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek return; 188ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek } 189ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek 19089cc5205b3b54b85c584583760d07af7049e6e28Robert Sesek final String serviceName = getServiceNameLocked(); 191ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek if (!SystemService.isRunning(serviceName)) { 192ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek Log.e(LOGTAG, serviceName + " is not running"); 193ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek return; 194ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek } 195ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek 196ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek try { 197ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek sZygote = new ZygoteProcess("webview_zygote", null); 198ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek 1993b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles) // All the work below is usually done by LoadedApk, but the zygote can't talk to 2003b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles) // PackageManager or construct a LoadedApk since it's single-threaded pre-fork, so 2013b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles) // doesn't have an ActivityThread and can't use Binder. 2023b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles) // Instead, figure out the paths here, in the system server where we have access to 2033b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles) // the package manager. Reuse the logic from LoadedApk to determine the correct 2043b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles) // paths and pass them to the zygote as strings. 2053b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles) final List<String> zipPaths = new ArrayList<>(10); 2063b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles) final List<String> libPaths = new ArrayList<>(10); 207638d81009918eae44eec3261e235b78eae44331dDimitry Ivanov LoadedApk.makePaths(null, false, sPackage.applicationInfo, zipPaths, libPaths); 2083b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles) final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths); 2093b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles) final String zip = (zipPaths.size() == 1) ? zipPaths.get(0) : 2103b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles) TextUtils.join(File.pathSeparator, zipPaths); 2113b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles) 2123b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles) Log.d(LOGTAG, "Preloading package " + zip + " " + librarySearchPath); 2133b6ca99b1069e8f303727a00c1da7acabe017fd8Torne (Richard Coles) sZygote.preloadPackageForAbi(zip, librarySearchPath, Build.SUPPORTED_ABIS[0]); 214ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek } catch (Exception e) { 215ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek Log.e(LOGTAG, "Error connecting to " + serviceName, e); 216ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek sZygote = null; 217ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek } 218ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek } 219ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek} 220