Merge "Create the WebViewZygote and implement WebViewZygoteInit."
This commit is contained in:
49
cmds/webview_zygote/Android.mk
Normal file
49
cmds/webview_zygote/Android.mk
Normal file
@ -0,0 +1,49 @@
|
||||
#
|
||||
# Copyright (C) 2016 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := webview_zygote
|
||||
|
||||
LOCAL_SRC_FILES := webview_zygote.cpp
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libandroid_runtime \
|
||||
libbinder \
|
||||
liblog \
|
||||
libcutils \
|
||||
libutils
|
||||
|
||||
LOCAL_LDFLAGS_32 := -Wl,--version-script,art/sigchainlib/version-script32.txt -Wl,--export-dynamic
|
||||
LOCAL_LDFLAGS_64 := -Wl,--version-script,art/sigchainlib/version-script64.txt -Wl,--export-dynamic
|
||||
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES := libsigchain
|
||||
|
||||
LOCAL_INIT_RC := webview_zygote32.rc
|
||||
|
||||
# Always include the 32-bit version of webview_zygote. If the target is 64-bit,
|
||||
# also include the 64-bit webview_zygote.
|
||||
ifeq ($(TARGET_SUPPORTS_64_BIT_APPS),true)
|
||||
LOCAL_INIT_RC += webview_zygote64.rc
|
||||
endif
|
||||
|
||||
LOCAL_MULTILIB := both
|
||||
|
||||
LOCAL_MODULE_STEM_32 := webview_zygote32
|
||||
LOCAL_MODULE_STEM_64 := webview_zygote64
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
76
cmds/webview_zygote/webview_zygote.cpp
Normal file
76
cmds/webview_zygote/webview_zygote.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
#define LOG_TAG "WebViewZygote"
|
||||
|
||||
#include <sys/prctl.h>
|
||||
|
||||
#include <android_runtime/AndroidRuntime.h>
|
||||
#include <binder/IPCThreadState.h>
|
||||
#include <binder/ProcessState.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/String8.h>
|
||||
#include <utils/Vector.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
class WebViewRuntime : public AndroidRuntime {
|
||||
public:
|
||||
WebViewRuntime(char* argBlockStart, size_t argBlockSize)
|
||||
: AndroidRuntime(argBlockStart, argBlockSize) {}
|
||||
|
||||
~WebViewRuntime() override {}
|
||||
|
||||
void onStarted() override {
|
||||
// Nothing to do since this is a zygote server.
|
||||
}
|
||||
|
||||
void onVmCreated(JNIEnv*) override {
|
||||
// Nothing to do when the VM is created in the zygote.
|
||||
}
|
||||
|
||||
void onZygoteInit() override {
|
||||
// Called after a new process is forked.
|
||||
sp<ProcessState> proc = ProcessState::self();
|
||||
proc->startThreadPool();
|
||||
}
|
||||
|
||||
void onExit(int code) override {
|
||||
IPCThreadState::self()->stopProcess();
|
||||
AndroidRuntime::onExit(code);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
int main(int argc, char* const argv[]) {
|
||||
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
|
||||
LOG_ALWAYS_FATAL("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno));
|
||||
return 12;
|
||||
}
|
||||
|
||||
size_t argBlockSize = 0;
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
argBlockSize += strlen(argv[i]) + 1;
|
||||
}
|
||||
|
||||
android::WebViewRuntime runtime(argv[0], argBlockSize);
|
||||
runtime.addOption("-Xzygote");
|
||||
|
||||
android::Vector<android::String8> args;
|
||||
runtime.start("com.android.internal.os.WebViewZygoteInit", args, /*zygote=*/ true);
|
||||
}
|
22
cmds/webview_zygote/webview_zygote32.rc
Normal file
22
cmds/webview_zygote/webview_zygote32.rc
Normal file
@ -0,0 +1,22 @@
|
||||
#
|
||||
# Copyright (C) 2016 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
service webview_zygote32 /system/bin/webview_zygote32
|
||||
user webview_zygote
|
||||
socket webview_zygote stream 660 webview_zygote system
|
||||
|
||||
on property:init.svc.zygote=stopped
|
||||
stop webview_zygote32
|
22
cmds/webview_zygote/webview_zygote64.rc
Normal file
22
cmds/webview_zygote/webview_zygote64.rc
Normal file
@ -0,0 +1,22 @@
|
||||
#
|
||||
# Copyright (C) 2016 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
service webview_zygote64 /system/bin/webview_zygote64
|
||||
user webview_zygote
|
||||
socket webview_zygote stream 660 webview_zygote system
|
||||
|
||||
on property:init.svc.zygote=stopped
|
||||
stop webview_zygote64
|
@ -18,6 +18,7 @@ package android.os;
|
||||
|
||||
import android.system.Os;
|
||||
import android.util.Log;
|
||||
import android.webkit.WebViewZygote;
|
||||
import dalvik.system.VMRuntime;
|
||||
|
||||
/**
|
||||
@ -130,6 +131,12 @@ public class Process {
|
||||
*/
|
||||
public static final int CAMERASERVER_UID = 1047;
|
||||
|
||||
/**
|
||||
* Defines the UID/GID for the WebView zygote process.
|
||||
* @hide
|
||||
*/
|
||||
public static final int WEBVIEW_ZYGOTE_UID = 1051;
|
||||
|
||||
/**
|
||||
* Defines the start of a range of UIDs (and GIDs), going from this
|
||||
* number to {@link #LAST_APPLICATION_UID} that are reserved for assigning
|
||||
@ -417,6 +424,22 @@ public class Process {
|
||||
abi, instructionSet, appDataDir, zygoteArgs);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static final ProcessStartResult startWebView(final String processClass,
|
||||
final String niceName,
|
||||
int uid, int gid, int[] gids,
|
||||
int debugFlags, int mountExternal,
|
||||
int targetSdkVersion,
|
||||
String seInfo,
|
||||
String abi,
|
||||
String instructionSet,
|
||||
String appDataDir,
|
||||
String[] zygoteArgs) {
|
||||
return WebViewZygote.getProcess().start(processClass, niceName, uid, gid, gids,
|
||||
debugFlags, mountExternal, targetSdkVersion, seInfo,
|
||||
abi, instructionSet, appDataDir, zygoteArgs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns elapsed milliseconds of the time this process has run.
|
||||
* @return Returns the number of milliseconds this process has return.
|
||||
|
@ -19,7 +19,9 @@ package android.os;
|
||||
import android.net.LocalSocket;
|
||||
import android.net.LocalSocketAddress;
|
||||
import android.util.Log;
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.os.Zygote;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
@ -110,7 +112,8 @@ public class ZygoteProcess {
|
||||
}
|
||||
|
||||
String abiListString = getAbiList(zygoteWriter, zygoteInputStream);
|
||||
Log.i("Zygote", "Process: zygote socket opened, supported ABIS: " + abiListString);
|
||||
Log.i("Zygote", "Process: zygote socket " + socketAddress + " opened, supported ABIS: "
|
||||
+ abiListString);
|
||||
|
||||
return new ZygoteState(zygoteSocket, zygoteInputStream, zygoteWriter,
|
||||
Arrays.asList(abiListString.split(",")));
|
||||
@ -135,6 +138,13 @@ public class ZygoteProcess {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock object to protect access to the two ZygoteStates below. This lock must be
|
||||
* acquired while communicating over the ZygoteState's socket, to prevent
|
||||
* interleaved access.
|
||||
*/
|
||||
private final Object mLock = new Object();
|
||||
|
||||
/**
|
||||
* The state of the connection to the primary zygote.
|
||||
*/
|
||||
@ -207,6 +217,7 @@ public class ZygoteProcess {
|
||||
*
|
||||
* @throws ZygoteStartFailedEx if the query failed.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
private static String getAbiList(BufferedWriter writer, DataInputStream inputStream)
|
||||
throws IOException {
|
||||
// Each query starts with the argument count (1 in this case)
|
||||
@ -233,6 +244,7 @@ public class ZygoteProcess {
|
||||
*
|
||||
* @throws ZygoteStartFailedEx if process start failed for any reason
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
|
||||
ZygoteState zygoteState, ArrayList<String> args)
|
||||
throws ZygoteStartFailedEx {
|
||||
@ -311,7 +323,6 @@ public class ZygoteProcess {
|
||||
String appDataDir,
|
||||
String[] extraArgs)
|
||||
throws ZygoteStartFailedEx {
|
||||
synchronized(Process.class) {
|
||||
ArrayList<String> argsForZygote = new ArrayList<String>();
|
||||
|
||||
// --runtime-args, --setuid=, --setgid=,
|
||||
@ -395,6 +406,7 @@ public class ZygoteProcess {
|
||||
}
|
||||
}
|
||||
|
||||
synchronized(mLock) {
|
||||
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
|
||||
}
|
||||
}
|
||||
@ -406,7 +418,9 @@ public class ZygoteProcess {
|
||||
*/
|
||||
public void establishZygoteConnectionForAbi(String abi) {
|
||||
try {
|
||||
synchronized(mLock) {
|
||||
openZygoteSocketIfNeeded(abi);
|
||||
}
|
||||
} catch (ZygoteStartFailedEx ex) {
|
||||
throw new RuntimeException("Unable to connect to zygote for abi: " + abi, ex);
|
||||
}
|
||||
@ -414,9 +428,12 @@ public class ZygoteProcess {
|
||||
|
||||
/**
|
||||
* Tries to open socket to Zygote process if not already open. If
|
||||
* already open, does nothing. May block and retry.
|
||||
* already open, does nothing. May block and retry. Requires that mLock be held.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
|
||||
Preconditions.checkState(Thread.holdsLock(mLock), "ZygoteProcess lock not held");
|
||||
|
||||
if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
|
||||
try {
|
||||
primaryZygoteState = ZygoteState.connect(mSocket);
|
||||
@ -444,4 +461,28 @@ public class ZygoteProcess {
|
||||
|
||||
throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs the zygote to pre-load the classes and native libraries at the given paths
|
||||
* for the specified abi. Not all zygotes support this function.
|
||||
*/
|
||||
public void preloadPackageForAbi(String packagePath, String libsPath, String abi)
|
||||
throws ZygoteStartFailedEx, IOException {
|
||||
synchronized(mLock) {
|
||||
ZygoteState state = openZygoteSocketIfNeeded(abi);
|
||||
state.writer.write("3");
|
||||
state.writer.newLine();
|
||||
|
||||
state.writer.write("--preload-package");
|
||||
state.writer.newLine();
|
||||
|
||||
state.writer.write(packagePath);
|
||||
state.writer.newLine();
|
||||
|
||||
state.writer.write(libsPath);
|
||||
state.writer.newLine();
|
||||
|
||||
state.writer.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -472,6 +472,9 @@ public final class WebViewFactory {
|
||||
// Log and discard errors at this stage as we must not crash the system server.
|
||||
Log.e(LOGTAG, "error preparing webview native library", t);
|
||||
}
|
||||
|
||||
WebViewZygote.onWebViewProviderChanged(packageInfo);
|
||||
|
||||
return prepareWebViewInSystemServer(nativeLibs);
|
||||
}
|
||||
|
||||
|
135
core/java/android/webkit/WebViewZygote.java
Normal file
135
core/java/android/webkit/WebViewZygote.java
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.webkit;
|
||||
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.os.Build;
|
||||
import android.os.SystemService;
|
||||
import android.os.ZygoteProcess;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
/** @hide */
|
||||
public class WebViewZygote {
|
||||
private static final String LOGTAG = "WebViewZygote";
|
||||
|
||||
private static final String WEBVIEW_ZYGOTE_SERVICE_32 = "webview_zygote32";
|
||||
private static final String WEBVIEW_ZYGOTE_SERVICE_64 = "webview_zygote64";
|
||||
|
||||
private static ZygoteProcess sZygote;
|
||||
|
||||
private static PackageInfo sPackage;
|
||||
|
||||
private static boolean sMultiprocessEnabled = false;
|
||||
|
||||
public static ZygoteProcess getProcess() {
|
||||
connectToZygoteIfNeeded();
|
||||
return sZygote;
|
||||
}
|
||||
|
||||
public static String getPackageName() {
|
||||
return sPackage.packageName;
|
||||
}
|
||||
|
||||
public static void setMultiprocessEnabled(boolean enabled) {
|
||||
sMultiprocessEnabled = enabled;
|
||||
|
||||
// When toggling between multi-process being on/off, start or stop the
|
||||
// service. If it is enabled and the zygote is not yet started, bring up the service.
|
||||
// Otherwise, bring down the service. The name may be null if the package
|
||||
// information has not yet been resolved.
|
||||
final String serviceName = getServiceName();
|
||||
if (serviceName == null) return;
|
||||
|
||||
if (enabled && sZygote == null) {
|
||||
SystemService.start(serviceName);
|
||||
} else {
|
||||
SystemService.stop(serviceName);
|
||||
sZygote = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void onWebViewProviderChanged(PackageInfo packageInfo) {
|
||||
sPackage = packageInfo;
|
||||
|
||||
// If multi-process is not enabled, then do not start the zygote service.
|
||||
if (!sMultiprocessEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String serviceName = getServiceName();
|
||||
|
||||
if (SystemService.isStopped(serviceName)) {
|
||||
SystemService.start(serviceName);
|
||||
} else if (sZygote != null) {
|
||||
SystemService.restart(serviceName);
|
||||
}
|
||||
|
||||
try {
|
||||
SystemService.waitForState(serviceName, SystemService.State.RUNNING, 5000);
|
||||
} catch (TimeoutException e) {
|
||||
Log.e(LOGTAG, "Timed out waiting for " + serviceName);
|
||||
return;
|
||||
}
|
||||
|
||||
connectToZygoteIfNeeded();
|
||||
}
|
||||
|
||||
private static String getServiceName() {
|
||||
if (sPackage == null)
|
||||
return null;
|
||||
|
||||
if (Arrays.asList(Build.SUPPORTED_64_BIT_ABIS).contains(
|
||||
sPackage.applicationInfo.primaryCpuAbi)) {
|
||||
return WEBVIEW_ZYGOTE_SERVICE_64;
|
||||
}
|
||||
|
||||
return WEBVIEW_ZYGOTE_SERVICE_32;
|
||||
}
|
||||
|
||||
private static void connectToZygoteIfNeeded() {
|
||||
if (sZygote != null)
|
||||
return;
|
||||
|
||||
if (sPackage == null) {
|
||||
Log.e(LOGTAG, "Cannot connect to zygote, no package specified");
|
||||
return;
|
||||
}
|
||||
|
||||
final String serviceName = getServiceName();
|
||||
if (!SystemService.isRunning(serviceName)) {
|
||||
Log.e(LOGTAG, serviceName + " is not running");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
sZygote = new ZygoteProcess("webview_zygote", null);
|
||||
|
||||
String packagePath = sPackage.applicationInfo.sourceDir;
|
||||
String libsPath = sPackage.applicationInfo.nativeLibraryDir;
|
||||
|
||||
Log.d(LOGTAG, "Preloading package " + packagePath + " " + libsPath);
|
||||
sZygote.preloadPackageForAbi(packagePath, libsPath, Build.SUPPORTED_ABIS[0]);
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "Error connecting to " + serviceName, e);
|
||||
sZygote = null;
|
||||
}
|
||||
}
|
||||
}
|
@ -16,6 +16,15 @@
|
||||
|
||||
package com.android.internal.os;
|
||||
|
||||
import android.net.LocalSocket;
|
||||
import android.os.Build;
|
||||
import android.system.ErrnoException;
|
||||
import android.system.Os;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Startup class for the WebView zygote process.
|
||||
*
|
||||
@ -26,7 +35,48 @@ package com.android.internal.os;
|
||||
class WebViewZygoteInit {
|
||||
public static final String TAG = "WebViewZygoteInit";
|
||||
|
||||
private static ZygoteServer sServer;
|
||||
|
||||
private static class WebViewZygoteServer extends ZygoteServer {
|
||||
@Override
|
||||
protected ZygoteConnection createNewConnection(LocalSocket socket, String abiList)
|
||||
throws IOException {
|
||||
return new WebViewZygoteConnection(socket, abiList);
|
||||
}
|
||||
}
|
||||
|
||||
private static class WebViewZygoteConnection extends ZygoteConnection {
|
||||
WebViewZygoteConnection(LocalSocket socket, String abiList) throws IOException {
|
||||
super(socket, abiList);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean handlePreloadPackage(String packagePath, String libsPath) {
|
||||
// TODO: Use preload information to setup the ClassLoader.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String argv[]) {
|
||||
throw new RuntimeException("Not implemented yet");
|
||||
sServer = new WebViewZygoteServer();
|
||||
|
||||
// Zygote goes into its own process group.
|
||||
try {
|
||||
Os.setpgid(0, 0);
|
||||
} catch (ErrnoException ex) {
|
||||
throw new RuntimeException("Failed to setpgid(0,0)", ex);
|
||||
}
|
||||
|
||||
try {
|
||||
sServer.registerServerSocket("webview_zygote");
|
||||
sServer.runSelectLoop(TextUtils.join(",", Build.SUPPORTED_ABIS));
|
||||
sServer.closeServerSocket();
|
||||
} catch (Zygote.MethodAndArgsCaller caller) {
|
||||
caller.run();
|
||||
} catch (RuntimeException e) {
|
||||
Log.e(TAG, "Fatal exception:", e);
|
||||
}
|
||||
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ import java.io.InputStreamReader;
|
||||
import java.io.PrintStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import libcore.io.IoUtils;
|
||||
|
||||
/**
|
||||
@ -169,6 +170,11 @@ class ZygoteConnection {
|
||||
return handleAbiListQuery();
|
||||
}
|
||||
|
||||
if (parsedArgs.preloadPackage != null) {
|
||||
return handlePreloadPackage(parsedArgs.preloadPackage,
|
||||
parsedArgs.preloadPackageLibs);
|
||||
}
|
||||
|
||||
if (parsedArgs.permittedCapabilities != 0 || parsedArgs.effectiveCapabilities != 0) {
|
||||
throw new ZygoteSecurityException("Client may not specify capabilities: " +
|
||||
"permitted=0x" + Long.toHexString(parsedArgs.permittedCapabilities) +
|
||||
@ -270,6 +276,10 @@ class ZygoteConnection {
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean handlePreloadPackage(String packagePath, String libsPath) {
|
||||
throw new RuntimeException("Zyogte does not support package preloading");
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes socket associated with this connection.
|
||||
*/
|
||||
@ -374,6 +384,12 @@ class ZygoteConnection {
|
||||
*/
|
||||
String appDataDir;
|
||||
|
||||
/**
|
||||
* Whether to preload a package, with the package path in the remainingArgs.
|
||||
*/
|
||||
String preloadPackage;
|
||||
String preloadPackageLibs;
|
||||
|
||||
/**
|
||||
* Constructs instance and parses args
|
||||
* @param args zygote command-line args
|
||||
@ -532,6 +548,9 @@ class ZygoteConnection {
|
||||
instructionSet = arg.substring(arg.indexOf('=') + 1);
|
||||
} else if (arg.startsWith("--app-data-dir=")) {
|
||||
appDataDir = arg.substring(arg.indexOf('=') + 1);
|
||||
} else if (arg.equals("--preload-package")) {
|
||||
preloadPackage = args[++curArg];
|
||||
preloadPackageLibs = args[++curArg];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
@ -541,6 +560,11 @@ class ZygoteConnection {
|
||||
if (args.length - curArg > 0) {
|
||||
throw new IllegalArgumentException("Unexpected arguments after --query-abi-list.");
|
||||
}
|
||||
} else if (preloadPackage != null) {
|
||||
if (args.length - curArg > 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"Unexpected arguments after --preload-package.");
|
||||
}
|
||||
} else {
|
||||
if (!seenRuntimeArgs) {
|
||||
throw new IllegalArgumentException("Unexpected argument : " + args[curArg]);
|
||||
|
@ -19,6 +19,7 @@ package com.android.internal.os;
|
||||
import static android.system.OsConstants.POLLIN;
|
||||
|
||||
import android.net.LocalServerSocket;
|
||||
import android.net.LocalSocket;
|
||||
import android.system.Os;
|
||||
import android.system.ErrnoException;
|
||||
import android.system.StructPollfd;
|
||||
@ -80,13 +81,18 @@ class ZygoteServer {
|
||||
*/
|
||||
private ZygoteConnection acceptCommandPeer(String abiList) {
|
||||
try {
|
||||
return new ZygoteConnection(mServerSocket.accept(), abiList);
|
||||
return createNewConnection(mServerSocket.accept(), abiList);
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException(
|
||||
"IOException during accept()", ex);
|
||||
}
|
||||
}
|
||||
|
||||
protected ZygoteConnection createNewConnection(LocalSocket socket, String abiList)
|
||||
throws IOException {
|
||||
return new ZygoteConnection(socket, abiList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close and clean up zygote sockets. Called on shutdown and on the
|
||||
* child's exit path.
|
||||
|
@ -36,6 +36,7 @@ import android.util.AndroidRuntimeException;
|
||||
import android.util.Log;
|
||||
import android.webkit.WebViewFactory;
|
||||
import android.webkit.WebViewProviderInfo;
|
||||
import android.webkit.WebViewZygote;
|
||||
|
||||
import com.android.internal.util.XmlUtils;
|
||||
|
||||
@ -268,6 +269,11 @@ public class SystemImpl implements SystemInterface {
|
||||
return pm.getPackageInfo(configInfo.packageName, PACKAGE_FLAGS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMultiprocessEnabled(boolean enabled) {
|
||||
WebViewZygote.setMultiprocessEnabled(enabled);
|
||||
}
|
||||
|
||||
// flags declaring we want extra info from the package manager for webview providers
|
||||
private final static int PACKAGE_FLAGS = PackageManager.GET_META_DATA
|
||||
| PackageManager.GET_SIGNATURES | PackageManager.MATCH_DEBUG_TRIAGED_MISSING
|
||||
|
@ -48,4 +48,6 @@ public interface SystemInterface {
|
||||
public boolean systemIsDebuggable();
|
||||
public PackageInfo getPackageInfoForProvider(WebViewProviderInfo configInfo)
|
||||
throws NameNotFoundException;
|
||||
|
||||
public void setMultiprocessEnabled(boolean enabled);
|
||||
}
|
||||
|
@ -20,7 +20,12 @@ import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.Signature;
|
||||
import android.content.ContentResolver;
|
||||
import android.database.ContentObserver;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.util.Base64;
|
||||
import android.util.Slog;
|
||||
import android.webkit.WebViewFactory;
|
||||
@ -42,6 +47,7 @@ public class WebViewUpdateServiceImpl {
|
||||
|
||||
private SystemInterface mSystemInterface;
|
||||
private WebViewUpdater mWebViewUpdater;
|
||||
private SettingsObserver mSettingsObserver;
|
||||
private Context mContext;
|
||||
|
||||
public WebViewUpdateServiceImpl(Context context, SystemInterface systemInterface) {
|
||||
@ -61,6 +67,10 @@ public class WebViewUpdateServiceImpl {
|
||||
void prepareWebViewInSystemServer() {
|
||||
updateFallbackStateOnBoot();
|
||||
mWebViewUpdater.prepareWebViewInSystemServer();
|
||||
|
||||
// Register for changes in the multiprocess developer option. This has to be done
|
||||
// here, since the update service gets created before the ContentResolver service.
|
||||
mSettingsObserver = new SettingsObserver();
|
||||
}
|
||||
|
||||
private boolean existsValidNonFallbackProvider(WebViewProviderInfo[] providers) {
|
||||
@ -667,4 +677,41 @@ public class WebViewUpdateServiceImpl {
|
||||
& ApplicationInfo.PRIVATE_FLAG_HIDDEN) == 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Watches for changes in the WEBVIEW_MULTIPROCESS setting and lets
|
||||
* the WebViewZygote know, so it can start or stop the zygote process
|
||||
* appropriately.
|
||||
*/
|
||||
private class SettingsObserver extends ContentObserver {
|
||||
private final ContentResolver mResolver;
|
||||
|
||||
SettingsObserver() {
|
||||
super(new Handler());
|
||||
|
||||
mResolver = mContext.getContentResolver();
|
||||
mResolver.registerContentObserver(
|
||||
Settings.Global.getUriFor(Settings.Global.WEBVIEW_MULTIPROCESS),
|
||||
false, this);
|
||||
|
||||
// Push the current value of the setting immediately.
|
||||
notifyZygote();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange, Uri uri) {
|
||||
notifyZygote();
|
||||
}
|
||||
|
||||
private void notifyZygote() {
|
||||
boolean enableMultiprocess = false;
|
||||
|
||||
try {
|
||||
enableMultiprocess = Settings.Global.getInt(mResolver,
|
||||
Settings.Global.WEBVIEW_MULTIPROCESS) == 1;
|
||||
} catch (Settings.SettingNotFoundException ex) {
|
||||
}
|
||||
|
||||
mSystemInterface.setMultiprocessEnabled(enableMultiprocess);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -113,4 +113,7 @@ public class TestSystemImpl implements SystemInterface {
|
||||
public int getFactoryPackageVersion(String packageName) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMultiprocessEnabled(boolean enabled) {}
|
||||
}
|
||||
|
Reference in New Issue
Block a user