blob: 49e11b8baf51f4b6bcdc0ead8acf3ce5919a7179 [file] [log] [blame]
Robert Sesekded20982016-08-15 13:59:13 -04001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.webkit;
18
Torne (Richard Coles)3b6ca992016-10-10 15:11:36 +010019import android.app.LoadedApk;
Torne (Richard Coles)4fd8aa52017-09-19 15:21:29 -040020import android.content.pm.ApplicationInfo;
Robert Sesekded20982016-08-15 13:59:13 -040021import android.content.pm.PackageInfo;
Torne (Richard Coles)e0624042018-03-13 17:48:52 -040022import android.os.AsyncTask;
Robert Sesekded20982016-08-15 13:59:13 -040023import android.os.Build;
Robert Sesek602d1322018-01-17 18:48:18 -050024import android.os.ChildZygoteProcess;
25import android.os.Process;
Robert Sesekded20982016-08-15 13:59:13 -040026import android.os.ZygoteProcess;
Torne (Richard Coles)3b6ca992016-10-10 15:11:36 +010027import android.text.TextUtils;
Robert Sesekded20982016-08-15 13:59:13 -040028import android.util.Log;
29
Robert Sesek89cc5202016-12-16 12:06:44 -050030import com.android.internal.annotations.GuardedBy;
31
Torne (Richard Coles)3b6ca992016-10-10 15:11:36 +010032import java.io.File;
Torne (Richard Coles)3b6ca992016-10-10 15:11:36 +010033import java.util.ArrayList;
Torne (Richard Coles)3b6ca992016-10-10 15:11:36 +010034import java.util.List;
Robert Sesekded20982016-08-15 13:59:13 -040035
36/** @hide */
37public class WebViewZygote {
38 private static final String LOGTAG = "WebViewZygote";
39
Robert Sesek89cc5202016-12-16 12:06:44 -050040 /**
41 * Lock object that protects all other static members.
42 */
43 private static final Object sLock = new Object();
44
45 /**
Nate Fischer0a6140d2017-09-05 12:37:49 -070046 * Instance that maintains the socket connection to the zygote. This is {@code null} if the
47 * zygote is not running or is not connected.
Robert Sesek89cc5202016-12-16 12:06:44 -050048 */
49 @GuardedBy("sLock")
Robert Sesek602d1322018-01-17 18:48:18 -050050 private static ChildZygoteProcess sZygote;
Gustav Senntonf05f99b2017-03-22 19:30:33 +000051
52 /**
Robert Sesek89cc5202016-12-16 12:06:44 -050053 * Information about the selected WebView package. This is set from #onWebViewProviderChanged().
54 */
55 @GuardedBy("sLock")
Robert Sesekded20982016-08-15 13:59:13 -040056 private static PackageInfo sPackage;
57
Robert Sesek89cc5202016-12-16 12:06:44 -050058 /**
Torne (Richard Coles)4fd8aa52017-09-19 15:21:29 -040059 * Original ApplicationInfo for the selected WebView package before stub fixup. This is set from
Torne (Richard Coles)04526702017-01-13 14:19:39 +000060 * #onWebViewProviderChanged().
61 */
62 @GuardedBy("sLock")
Torne (Richard Coles)4fd8aa52017-09-19 15:21:29 -040063 private static ApplicationInfo sPackageOriginalAppInfo;
Torne (Richard Coles)04526702017-01-13 14:19:39 +000064
65 /**
Nate Fischer0a6140d2017-09-05 12:37:49 -070066 * Flag for whether multi-process WebView is enabled. If this is {@code false}, the zygote
Robert Sesek89cc5202016-12-16 12:06:44 -050067 * will not be started.
68 */
69 @GuardedBy("sLock")
Robert Sesekded20982016-08-15 13:59:13 -040070 private static boolean sMultiprocessEnabled = false;
71
72 public static ZygoteProcess getProcess() {
Robert Sesek89cc5202016-12-16 12:06:44 -050073 synchronized (sLock) {
Gustav Senntonf05f99b2017-03-22 19:30:33 +000074 if (sZygote != null) return sZygote;
75
Robert Sesek602d1322018-01-17 18:48:18 -050076 connectToZygoteIfNeededLocked();
Robert Sesek89cc5202016-12-16 12:06:44 -050077 return sZygote;
78 }
Robert Sesekded20982016-08-15 13:59:13 -040079 }
80
81 public static String getPackageName() {
Robert Sesek89cc5202016-12-16 12:06:44 -050082 synchronized (sLock) {
83 return sPackage.packageName;
84 }
Robert Sesekded20982016-08-15 13:59:13 -040085 }
86
Robert Sesekc5f86642016-11-04 10:20:38 -040087 public static boolean isMultiprocessEnabled() {
Robert Sesek89cc5202016-12-16 12:06:44 -050088 synchronized (sLock) {
89 return sMultiprocessEnabled && sPackage != null;
90 }
Robert Sesekc5f86642016-11-04 10:20:38 -040091 }
92
Robert Sesekded20982016-08-15 13:59:13 -040093 public static void setMultiprocessEnabled(boolean enabled) {
Robert Sesek89cc5202016-12-16 12:06:44 -050094 synchronized (sLock) {
95 sMultiprocessEnabled = enabled;
Robert Sesekded20982016-08-15 13:59:13 -040096
Torne (Richard Coles)e0624042018-03-13 17:48:52 -040097 // When toggling between multi-process being on/off, start or stop the
98 // zygote. If it is enabled and the zygote is not yet started, launch it.
99 // Otherwise, kill it. The name may be null if the package information has
100 // not yet been resolved.
101 if (enabled) {
102 // Run on a background thread as this waits for the zygote to start and we don't
103 // want to block the caller on this. It's okay if this is delayed as anyone trying
104 // to use the zygote will call it first anyway.
105 AsyncTask.THREAD_POOL_EXECUTOR.execute(WebViewZygote::getProcess);
106 } else {
107 // No need to run this in the background, it's very brief.
Robert Sesek602d1322018-01-17 18:48:18 -0500108 stopZygoteLocked();
Robert Sesek89cc5202016-12-16 12:06:44 -0500109 }
Robert Sesekded20982016-08-15 13:59:13 -0400110 }
111 }
112
Torne (Richard Coles)4fd8aa52017-09-19 15:21:29 -0400113 public static void onWebViewProviderChanged(PackageInfo packageInfo,
114 ApplicationInfo originalAppInfo) {
Robert Sesek89cc5202016-12-16 12:06:44 -0500115 synchronized (sLock) {
116 sPackage = packageInfo;
Torne (Richard Coles)4fd8aa52017-09-19 15:21:29 -0400117 sPackageOriginalAppInfo = originalAppInfo;
Robert Sesekded20982016-08-15 13:59:13 -0400118
Robert Sesek89cc5202016-12-16 12:06:44 -0500119 // If multi-process is not enabled, then do not start the zygote service.
120 if (!sMultiprocessEnabled) {
121 return;
122 }
123
Robert Sesek602d1322018-01-17 18:48:18 -0500124 stopZygoteLocked();
Robert Sesekded20982016-08-15 13:59:13 -0400125 }
Robert Sesekded20982016-08-15 13:59:13 -0400126 }
127
Robert Sesek89cc5202016-12-16 12:06:44 -0500128 @GuardedBy("sLock")
Robert Sesek602d1322018-01-17 18:48:18 -0500129 private static void stopZygoteLocked() {
130 if (sZygote != null) {
131 // Close the connection and kill the zygote process. This will not cause
132 // child processes to be killed by itself. But if this is called in response to
133 // setMultiprocessEnabled() or onWebViewProviderChanged(), the WebViewUpdater
134 // will kill all processes that depend on the WebView package.
135 sZygote.close();
136 Process.killProcess(sZygote.getPid());
137 sZygote = null;
Robert Sesekded20982016-08-15 13:59:13 -0400138 }
Robert Sesekded20982016-08-15 13:59:13 -0400139 }
140
Robert Sesek89cc5202016-12-16 12:06:44 -0500141 @GuardedBy("sLock")
142 private static void connectToZygoteIfNeededLocked() {
Gustav Senntonf05f99b2017-03-22 19:30:33 +0000143 if (sZygote != null) {
Robert Sesekded20982016-08-15 13:59:13 -0400144 return;
Gustav Senntonf05f99b2017-03-22 19:30:33 +0000145 }
Robert Sesekded20982016-08-15 13:59:13 -0400146
147 if (sPackage == null) {
148 Log.e(LOGTAG, "Cannot connect to zygote, no package specified");
149 return;
150 }
151
Robert Sesekded20982016-08-15 13:59:13 -0400152 try {
Robert Sesek602d1322018-01-17 18:48:18 -0500153 sZygote = Process.zygoteProcess.startChildZygote(
154 "com.android.internal.os.WebViewZygoteInit",
155 "webview_zygote",
156 Process.WEBVIEW_ZYGOTE_UID,
157 Process.WEBVIEW_ZYGOTE_UID,
158 null, // gids
159 0, // runtimeFlags
160 "webview_zygote", // seInfo
161 sPackage.applicationInfo.primaryCpuAbi, // abi
162 null); // instructionSet
Robert Sesekded20982016-08-15 13:59:13 -0400163
Torne (Richard Coles)3b6ca992016-10-10 15:11:36 +0100164 // All the work below is usually done by LoadedApk, but the zygote can't talk to
165 // PackageManager or construct a LoadedApk since it's single-threaded pre-fork, so
166 // doesn't have an ActivityThread and can't use Binder.
167 // Instead, figure out the paths here, in the system server where we have access to
168 // the package manager. Reuse the logic from LoadedApk to determine the correct
169 // paths and pass them to the zygote as strings.
170 final List<String> zipPaths = new ArrayList<>(10);
171 final List<String> libPaths = new ArrayList<>(10);
Dimitry Ivanov638d8102017-02-22 15:39:42 -0800172 LoadedApk.makePaths(null, false, sPackage.applicationInfo, zipPaths, libPaths);
Torne (Richard Coles)3b6ca992016-10-10 15:11:36 +0100173 final String librarySearchPath = TextUtils.join(File.pathSeparator, libPaths);
174 final String zip = (zipPaths.size() == 1) ? zipPaths.get(0) :
175 TextUtils.join(File.pathSeparator, zipPaths);
Robert Sesekded20982016-08-15 13:59:13 -0400176
Torne (Richard Coles)f4f647e2018-02-21 16:12:36 -0500177 String libFileName = WebViewFactory.getWebViewLibrary(sPackage.applicationInfo);
178
Torne (Richard Coles)4fd8aa52017-09-19 15:21:29 -0400179 // In the case where the ApplicationInfo has been modified by the stub WebView,
180 // we need to use the original ApplicationInfo to determine what the original classpath
181 // would have been to use as a cache key.
182 LoadedApk.makePaths(null, false, sPackageOriginalAppInfo, zipPaths, null);
183 final String cacheKey = (zipPaths.size() == 1) ? zipPaths.get(0) :
184 TextUtils.join(File.pathSeparator, zipPaths);
185
Robert Sesek602d1322018-01-17 18:48:18 -0500186 ZygoteProcess.waitForConnectionToZygote(sZygote.getPrimarySocketAddress());
Gustav Sennton833813c2017-04-24 14:23:39 +0100187
Torne (Richard Coles)3b6ca992016-10-10 15:11:36 +0100188 Log.d(LOGTAG, "Preloading package " + zip + " " + librarySearchPath);
Torne (Richard Coles)f4f647e2018-02-21 16:12:36 -0500189 sZygote.preloadPackageForAbi(zip, librarySearchPath, libFileName, cacheKey,
Torne (Richard Coles)04526702017-01-13 14:19:39 +0000190 Build.SUPPORTED_ABIS[0]);
Robert Sesekded20982016-08-15 13:59:13 -0400191 } catch (Exception e) {
Robert Sesek602d1322018-01-17 18:48:18 -0500192 Log.e(LOGTAG, "Error connecting to webview zygote", e);
193 stopZygoteLocked();
Robert Sesekded20982016-08-15 13:59:13 -0400194 }
195 }
Robert Sesekded20982016-08-15 13:59:13 -0400196}