diff options
| author | Robert Sesek <rsesek@google.com> | 2018-02-17 03:51:28 +0000 |
|---|---|---|
| committer | android-build-merger <android-build-merger@google.com> | 2018-02-17 03:51:28 +0000 |
| commit | 4523bf284a19fd0db329d2c68b3e8a142582beb4 (patch) | |
| tree | 8a2ce4c7d7a00677b712bec496d2e33a17993980 /core/java/android | |
| parent | f63b3dcb89992e728224ed169d91a6d268d891ce (diff) | |
| parent | 5b9410c74b7a887b0877bda87e231db8dd96e022 (diff) | |
Merge "Add Zygote.startChildZygote() to fork a new process that itself is a zygote." am: 554cfd1f1d
am: 5b9410c74b
Change-Id: I5e9d5c960b9f78cfa7ca7ab88e9d2075f97daca8
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/os/ChildZygoteProcess.java | 44 | ||||
| -rw-r--r-- | core/java/android/os/ZygoteProcess.java | 55 |
2 files changed, 98 insertions, 1 deletions
diff --git a/core/java/android/os/ChildZygoteProcess.java b/core/java/android/os/ChildZygoteProcess.java new file mode 100644 index 000000000000..337a3e279a1a --- /dev/null +++ b/core/java/android/os/ChildZygoteProcess.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2018 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.os; + +import android.net.LocalSocketAddress; + +/** + * Represents a connection to a child-zygote process. A child-zygote is spawend from another + * zygote process using {@link startChildZygote()}. + * + * {@hide} + */ +public class ChildZygoteProcess extends ZygoteProcess { + /** + * The PID of the child zygote process. + */ + private final int mPid; + + ChildZygoteProcess(LocalSocketAddress socketAddress, int pid) { + super(socketAddress, null); + mPid = pid; + } + + /** + * Returns the PID of the child-zygote process. + */ + public int getPid() { + return mPid; + } +} diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java index 4a976403e7a8..57418c8b9879 100644 --- a/core/java/android/os/ZygoteProcess.java +++ b/core/java/android/os/ZygoteProcess.java @@ -33,6 +33,7 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.UUID; /*package*/ class ZygoteStartFailedEx extends Exception { ZygoteStartFailedEx(String s) { @@ -217,7 +218,8 @@ public class ZygoteProcess { try { return startViaZygote(processClass, niceName, uid, gid, gids, runtimeFlags, mountExternal, targetSdkVersion, seInfo, - abi, instructionSet, appDataDir, invokeWith, zygoteArgs); + abi, instructionSet, appDataDir, invokeWith, false /* startChildZygote */, + zygoteArgs); } catch (ZygoteStartFailedEx ex) { Log.e(LOG_TAG, "Starting VM process through Zygote failed"); @@ -333,6 +335,8 @@ public class ZygoteProcess { * @param abi the ABI the process should use. * @param instructionSet null-ok the instruction set to use. * @param appDataDir null-ok the data directory of the app. + * @param startChildZygote Start a sub-zygote. This creates a new zygote process + * that has its state cloned from this zygote process. * @param extraArgs Additional arguments to supply to the zygote process. * @return An object that describes the result of the attempt to start the process. * @throws ZygoteStartFailedEx if process start failed for any reason @@ -348,6 +352,7 @@ public class ZygoteProcess { String instructionSet, String appDataDir, String invokeWith, + boolean startChildZygote, String[] extraArgs) throws ZygoteStartFailedEx { ArrayList<String> argsForZygote = new ArrayList<String>(); @@ -404,6 +409,10 @@ public class ZygoteProcess { argsForZygote.add(invokeWith); } + if (startChildZygote) { + argsForZygote.add("--start-child-zygote"); + } + argsForZygote.add(processClass); if (extraArgs != null) { @@ -418,6 +427,18 @@ public class ZygoteProcess { } /** + * Closes the connections to the zygote, if they exist. + */ + public void close() { + if (primaryZygoteState != null) { + primaryZygoteState.close(); + } + if (secondaryZygoteState != null) { + secondaryZygoteState.close(); + } + } + + /** * Tries to establish a connection to the zygote that handles a given {@code abi}. Might block * and retry if the zygote is unresponsive. This method is a no-op if a connection is * already open. @@ -549,4 +570,36 @@ public class ZygoteProcess { } Slog.wtf(LOG_TAG, "Failed to connect to Zygote through socket " + address.getName()); } + + /** + * Starts a new zygote process as a child of this zygote. This is used to create + * secondary zygotes that inherit data from the zygote that this object + * communicates with. This returns a new ZygoteProcess representing a connection + * to the newly created zygote. Throws an exception if the zygote cannot be started. + */ + public ChildZygoteProcess startChildZygote(final String processClass, + final String niceName, + int uid, int gid, int[] gids, + int runtimeFlags, + String seInfo, + String abi, + String instructionSet) { + // Create an unguessable address in the global abstract namespace. + final LocalSocketAddress serverAddress = new LocalSocketAddress( + processClass + "/" + UUID.randomUUID().toString()); + + final String[] extraArgs = {Zygote.CHILD_ZYGOTE_SOCKET_NAME_ARG + serverAddress.getName()}; + + Process.ProcessStartResult result; + try { + result = startViaZygote(processClass, niceName, uid, gid, + gids, runtimeFlags, 0 /* mountExternal */, 0 /* targetSdkVersion */, seInfo, + abi, instructionSet, null /* appDataDir */, null /* invokeWith */, + true /* startChildZygote */, extraArgs); + } catch (ZygoteStartFailedEx ex) { + throw new RuntimeException("Starting child-zygote through Zygote failed", ex); + } + + return new ChildZygoteProcess(serverAddress, result.pid); + } } |
