Merge "Reparent the webview_zygote to be a child of the main app_process zygote." am: 1c81aa6375

am: 486190f87b

Change-Id: I683dbbf730bfd02e43cb67bfcaa0df56d69c9796
This commit is contained in:
Robert Sesek
2018-02-21 02:33:14 +00:00
committed by android-build-merger
6 changed files with 58 additions and 261 deletions

View File

@@ -1,51 +0,0 @@
#
# 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_CFLAGS := -Wall -Werror
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)

View File

@@ -1,76 +0,0 @@
/*
* 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);
}

View File

@@ -1,22 +0,0 @@
#
# 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

View File

@@ -1,22 +0,0 @@
#
# 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

View File

@@ -20,29 +20,22 @@ import android.app.LoadedApk;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.os.Build;
import android.os.SystemService;
import android.os.ChildZygoteProcess;
import android.os.Process;
import android.os.ZygoteProcess;
import android.text.TextUtils;
import android.util.AndroidRuntimeException;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
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 final String WEBVIEW_ZYGOTE_SOCKET = "webview_zygote";
/**
* Lock object that protects all other static members.
*/
@@ -53,14 +46,7 @@ public class WebViewZygote {
* is not running or is not connected.
*/
@GuardedBy("sLock")
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;
private static ChildZygoteProcess sZygote;
/**
* Information about the selected WebView package. This is set from #onWebViewProviderChanged().
@@ -86,7 +72,7 @@ public class WebViewZygote {
synchronized (sLock) {
if (sZygote != null) return sZygote;
waitForServiceStartAndConnect();
connectToZygoteIfNeededLocked();
return sZygote;
}
}
@@ -108,21 +94,13 @@ public class WebViewZygote {
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 = getServiceNameLocked();
if (serviceName == null) return;
// zygote. If it is enabled and the zygote is not yet started, launch it.
// Otherwise, kill it. The name may be null if the package information has
// not yet been resolved.
if (enabled) {
if (!sStartedService) {
SystemService.start(serviceName);
sStartedService = true;
}
connectToZygoteIfNeededLocked();
} else {
SystemService.stop(serviceName);
sStartedService = false;
sZygote = null;
stopZygoteLocked();
}
}
}
@@ -138,53 +116,21 @@ public class WebViewZygote {
return;
}
final String serviceName = getServiceNameLocked();
sZygote = null;
// The service may enter the RUNNING state before it opens the socket,
// so connectToZygoteIfNeededLocked() may still fail.
if (SystemService.isStopped(serviceName)) {
SystemService.start(serviceName);
} else {
SystemService.restart(serviceName);
}
sStartedService = true;
}
}
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();
stopZygoteLocked();
}
}
@GuardedBy("sLock")
private static String getServiceNameLocked() {
if (sPackage == null)
return null;
if (Arrays.asList(Build.SUPPORTED_64_BIT_ABIS).contains(
sPackage.applicationInfo.primaryCpuAbi)) {
return WEBVIEW_ZYGOTE_SERVICE_64;
private static void stopZygoteLocked() {
if (sZygote != null) {
// Close the connection and kill the zygote process. This will not cause
// child processes to be killed by itself. But if this is called in response to
// setMultiprocessEnabled() or onWebViewProviderChanged(), the WebViewUpdater
// will kill all processes that depend on the WebView package.
sZygote.close();
Process.killProcess(sZygote.getPid());
sZygote = null;
}
return WEBVIEW_ZYGOTE_SERVICE_32;
}
@GuardedBy("sLock")
@@ -198,14 +144,17 @@ public class WebViewZygote {
return;
}
final String serviceName = getServiceNameLocked();
if (!SystemService.isRunning(serviceName)) {
Log.e(LOGTAG, serviceName + " is not running");
return;
}
try {
sZygote = new ZygoteProcess(WEBVIEW_ZYGOTE_SOCKET, null);
sZygote = Process.zygoteProcess.startChildZygote(
"com.android.internal.os.WebViewZygoteInit",
"webview_zygote",
Process.WEBVIEW_ZYGOTE_UID,
Process.WEBVIEW_ZYGOTE_UID,
null, // gids
0, // runtimeFlags
"webview_zygote", // seInfo
sPackage.applicationInfo.primaryCpuAbi, // abi
null); // instructionSet
// All the work below is usually done by LoadedApk, but the zygote can't talk to
// PackageManager or construct a LoadedApk since it's single-threaded pre-fork, so
@@ -227,14 +176,14 @@ public class WebViewZygote {
final String cacheKey = (zipPaths.size() == 1) ? zipPaths.get(0) :
TextUtils.join(File.pathSeparator, zipPaths);
ZygoteProcess.waitForConnectionToZygote(WEBVIEW_ZYGOTE_SOCKET);
ZygoteProcess.waitForConnectionToZygote(sZygote.getPrimarySocketAddress());
Log.d(LOGTAG, "Preloading package " + zip + " " + librarySearchPath);
sZygote.preloadPackageForAbi(zip, librarySearchPath, cacheKey,
Build.SUPPORTED_ABIS[0]);
} catch (Exception e) {
Log.e(LOGTAG, "Error connecting to " + serviceName, e);
sZygote = null;
Log.e(LOGTAG, "Error connecting to webview zygote", e);
stopZygoteLocked();
}
}
}

View File

@@ -18,9 +18,11 @@ package com.android.internal.os;
import android.app.ApplicationLoaders;
import android.net.LocalSocket;
import android.net.LocalServerSocket;
import android.os.Build;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.WebViewFactory;
@@ -118,18 +120,35 @@ class WebViewZygoteInit {
}
public static void main(String argv[]) {
sServer = new WebViewZygoteServer();
Log.i(TAG, "Starting WebViewZygoteInit");
// Zygote goes into its own process group.
try {
Os.setpgid(0, 0);
} catch (ErrnoException ex) {
throw new RuntimeException("Failed to setpgid(0,0)", ex);
String socketName = null;
for (String arg : argv) {
Log.i(TAG, arg);
if (arg.startsWith(Zygote.CHILD_ZYGOTE_SOCKET_NAME_ARG)) {
socketName = arg.substring(Zygote.CHILD_ZYGOTE_SOCKET_NAME_ARG.length());
}
}
if (socketName == null) {
throw new RuntimeException("No " + Zygote.CHILD_ZYGOTE_SOCKET_NAME_ARG + " specified");
}
try {
Os.prctl(OsConstants.PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
} catch (ErrnoException ex) {
throw new RuntimeException("Failed to set PR_SET_NO_NEW_PRIVS", ex);
}
sServer = new WebViewZygoteServer();
final Runnable caller;
try {
sServer.registerServerSocketFromEnv("webview_zygote");
sServer.registerServerSocketAtAbstractName(socketName);
// Add the abstract socket to the FD whitelist so that the native zygote code
// can properly detach it after forking.
Zygote.nativeAllowFileAcrossFork("ABSTRACT/" + socketName);
// The select loop returns early in the child process after a fork and
// loops forever in the zygote.
caller = sServer.runSelectLoop(TextUtils.join(",", Build.SUPPORTED_ABIS));