diff options
| -rw-r--r-- | cmds/webview_zygote/Android.mk | 51 | ||||
| -rw-r--r-- | cmds/webview_zygote/webview_zygote.cpp | 76 | ||||
| -rw-r--r-- | cmds/webview_zygote/webview_zygote32.rc | 22 | ||||
| -rw-r--r-- | cmds/webview_zygote/webview_zygote64.rc | 22 | ||||
| -rw-r--r-- | core/java/android/webkit/WebViewZygote.java | 115 | ||||
| -rw-r--r-- | core/java/com/android/internal/os/WebViewZygoteInit.java | 29 |
6 files changed, 56 insertions, 259 deletions
diff --git a/cmds/webview_zygote/Android.mk b/cmds/webview_zygote/Android.mk deleted file mode 100644 index 955e58ed933b..000000000000 --- a/cmds/webview_zygote/Android.mk +++ /dev/null @@ -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) diff --git a/cmds/webview_zygote/webview_zygote.cpp b/cmds/webview_zygote/webview_zygote.cpp deleted file mode 100644 index 88fee645b3ee..000000000000 --- a/cmds/webview_zygote/webview_zygote.cpp +++ /dev/null @@ -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); -} diff --git a/cmds/webview_zygote/webview_zygote32.rc b/cmds/webview_zygote/webview_zygote32.rc deleted file mode 100644 index b7decc8eba3b..000000000000 --- a/cmds/webview_zygote/webview_zygote32.rc +++ /dev/null @@ -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 diff --git a/cmds/webview_zygote/webview_zygote64.rc b/cmds/webview_zygote/webview_zygote64.rc deleted file mode 100644 index 2935b28cff55..000000000000 --- a/cmds/webview_zygote/webview_zygote64.rc +++ /dev/null @@ -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 diff --git a/core/java/android/webkit/WebViewZygote.java b/core/java/android/webkit/WebViewZygote.java index 5f5109a34863..d2923c4b8d12 100644 --- a/core/java/android/webkit/WebViewZygote.java +++ b/core/java/android/webkit/WebViewZygote.java @@ -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(); } } } diff --git a/core/java/com/android/internal/os/WebViewZygoteInit.java b/core/java/com/android/internal/os/WebViewZygoteInit.java index b38c851e5101..32b580c2d277 100644 --- a/core/java/com/android/internal/os/WebViewZygoteInit.java +++ b/core/java/com/android/internal/os/WebViewZygoteInit.java @@ -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"); + + 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"); + } - // Zygote goes into its own process group. try { - Os.setpgid(0, 0); + Os.prctl(OsConstants.PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); } catch (ErrnoException ex) { - throw new RuntimeException("Failed to setpgid(0,0)", 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)); |