blob: 4cb9c5b027f6988e211557d7b57c8837522aed72 [file] [log] [blame]
Robert Sesek8f8d1872016-03-18 16:52:57 -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.os;
18
Sudheer Shankad81b1d72018-09-05 16:37:30 -070019import android.annotation.NonNull;
20import android.annotation.Nullable;
Martijn Coenen7e6fa672018-11-05 11:45:26 +010021import android.content.pm.ApplicationInfo;
Robert Sesek8f8d1872016-03-18 16:52:57 -040022import android.net.LocalSocket;
23import android.net.LocalSocketAddress;
24import android.util.Log;
Gustav Senntonf0c52b52017-04-27 17:00:50 +010025import android.util.Slog;
Nicolas Geoffray81edac42017-09-07 14:13:29 +010026
Robert Sesekded20982016-08-15 13:59:13 -040027import com.android.internal.annotations.GuardedBy;
Robert Sesek8f8d1872016-03-18 16:52:57 -040028import com.android.internal.os.Zygote;
Robert Sesekded20982016-08-15 13:59:13 -040029import com.android.internal.util.Preconditions;
Nicolas Geoffray81edac42017-09-07 14:13:29 +010030
Robert Sesek8f8d1872016-03-18 16:52:57 -040031import java.io.BufferedWriter;
32import java.io.DataInputStream;
33import java.io.IOException;
34import java.io.OutputStreamWriter;
35import java.nio.charset.StandardCharsets;
36import java.util.ArrayList;
37import java.util.Arrays;
Martijn Coenen7e6fa672018-11-05 11:45:26 +010038import java.util.Base64;
Mathew Inwood8faeab82018-03-16 14:26:08 +000039import java.util.Collections;
Robert Sesek8f8d1872016-03-18 16:52:57 -040040import java.util.List;
Robert Sesekd0a190df2018-02-12 18:46:01 -050041import java.util.UUID;
Robert Sesek8f8d1872016-03-18 16:52:57 -040042
43/*package*/ class ZygoteStartFailedEx extends Exception {
44 ZygoteStartFailedEx(String s) {
45 super(s);
46 }
47
48 ZygoteStartFailedEx(Throwable cause) {
49 super(cause);
50 }
51
52 ZygoteStartFailedEx(String s, Throwable cause) {
53 super(s, cause);
54 }
55}
56
57/**
58 * Maintains communication state with the zygote processes. This class is responsible
59 * for the sockets opened to the zygotes and for starting processes on behalf of the
60 * {@link android.os.Process} class.
61 *
62 * {@hide}
63 */
64public class ZygoteProcess {
Chris Wailesefce9292019-01-11 13:19:20 -080065
66 /**
67 * @hide for internal use only.
68 */
69 public static final String ZYGOTE_SOCKET_NAME = "zygote";
70
71 /**
72 * @hide for internal use only.
73 */
74 public static final String ZYGOTE_SECONDARY_SOCKET_NAME = "zygote_secondary";
75
76 /**
77 * @hide for internal use only
78 */
Robert Sesek8f8d1872016-03-18 16:52:57 -040079 private static final String LOG_TAG = "ZygoteProcess";
80
81 /**
82 * The name of the socket used to communicate with the primary zygote.
83 */
Chris Wailesefce9292019-01-11 13:19:20 -080084 private final LocalSocketAddress mZygoteSocketAddress;
Robert Sesek8f8d1872016-03-18 16:52:57 -040085
86 /**
87 * The name of the secondary (alternate ABI) zygote socket.
88 */
Chris Wailesefce9292019-01-11 13:19:20 -080089 private final LocalSocketAddress mZygoteSecondarySocketAddress;
Robert Sesek8f8d1872016-03-18 16:52:57 -040090
Chris Wailesefce9292019-01-11 13:19:20 -080091 public ZygoteProcess() {
92 mZygoteSocketAddress =
93 new LocalSocketAddress(ZYGOTE_SOCKET_NAME, LocalSocketAddress.Namespace.RESERVED);
94 mZygoteSecondarySocketAddress =
95 new LocalSocketAddress(ZYGOTE_SECONDARY_SOCKET_NAME,
96 LocalSocketAddress.Namespace.RESERVED);
Robert Sesek5ac8abf2018-01-26 14:26:53 -050097 }
98
Chris Wailesefce9292019-01-11 13:19:20 -080099 public ZygoteProcess(LocalSocketAddress primarySocketAddress,
100 LocalSocketAddress secondarySocketAddress) {
101 mZygoteSocketAddress = primarySocketAddress;
102 mZygoteSecondarySocketAddress = secondarySocketAddress;
Robert Sesek8f8d1872016-03-18 16:52:57 -0400103 }
104
Robert Sesek5ac8abf2018-01-26 14:26:53 -0500105 public LocalSocketAddress getPrimarySocketAddress() {
Chris Wailesefce9292019-01-11 13:19:20 -0800106 return mZygoteSocketAddress;
Robert Sesek5ac8abf2018-01-26 14:26:53 -0500107 }
108
Robert Sesek8f8d1872016-03-18 16:52:57 -0400109 /**
110 * State for communicating with the zygote process.
111 */
112 public static class ZygoteState {
Chris Wailesefce9292019-01-11 13:19:20 -0800113 final LocalSocketAddress mZygoteSocketAddress;
Robert Sesek8f8d1872016-03-18 16:52:57 -0400114
Chris Wailesefce9292019-01-11 13:19:20 -0800115 private final LocalSocket mZygoteSessionSocket;
Robert Sesek8f8d1872016-03-18 16:52:57 -0400116
Chris Wailesefce9292019-01-11 13:19:20 -0800117 final DataInputStream mZygoteInputStream;
118 final BufferedWriter mZygoteOutputWriter;
119
120 private final List<String> mABIList;
121
122 private boolean mClosed;
123
124 private ZygoteState(LocalSocketAddress zygoteSocketAddress,
125 LocalSocket zygoteSessionSocket,
126 DataInputStream zygoteInputStream,
127 BufferedWriter zygoteOutputWriter,
128 List<String> abiList) {
129 this.mZygoteSocketAddress = zygoteSocketAddress;
130 this.mZygoteSessionSocket = zygoteSessionSocket;
131 this.mZygoteInputStream = zygoteInputStream;
132 this.mZygoteOutputWriter = zygoteOutputWriter;
133 this.mABIList = abiList;
Robert Sesek8f8d1872016-03-18 16:52:57 -0400134 }
135
Chris Wailesefce9292019-01-11 13:19:20 -0800136 /**
137 * Create a new ZygoteState object by connecting to the given Zygote socket.
138 *
139 * @param zygoteSocketAddress Zygote socket to connect to
140 * @return A new ZygoteState object containing a session socket for the given Zygote socket
141 * address
142 * @throws IOException
143 */
144 public static ZygoteState connect(LocalSocketAddress zygoteSocketAddress)
145 throws IOException {
146
Robert Sesek8f8d1872016-03-18 16:52:57 -0400147 DataInputStream zygoteInputStream = null;
Chris Wailesefce9292019-01-11 13:19:20 -0800148 BufferedWriter zygoteOutputWriter = null;
149 final LocalSocket zygoteSessionSocket = new LocalSocket();
Robert Sesek8f8d1872016-03-18 16:52:57 -0400150
151 try {
Chris Wailesefce9292019-01-11 13:19:20 -0800152 zygoteSessionSocket.connect(zygoteSocketAddress);
153 zygoteInputStream = new DataInputStream(zygoteSessionSocket.getInputStream());
154 zygoteOutputWriter =
155 new BufferedWriter(
156 new OutputStreamWriter(zygoteSessionSocket.getOutputStream()),
157 256);
Robert Sesek8f8d1872016-03-18 16:52:57 -0400158 } catch (IOException ex) {
159 try {
Chris Wailesefce9292019-01-11 13:19:20 -0800160 zygoteSessionSocket.close();
161 } catch (IOException ignore) { }
Robert Sesek8f8d1872016-03-18 16:52:57 -0400162
163 throw ex;
164 }
165
Chris Wailesefce9292019-01-11 13:19:20 -0800166 return new ZygoteState(zygoteSocketAddress,
167 zygoteSessionSocket, zygoteInputStream, zygoteOutputWriter,
168 getAbiList(zygoteOutputWriter, zygoteInputStream));
Robert Sesek8f8d1872016-03-18 16:52:57 -0400169 }
170
171 boolean matches(String abi) {
Chris Wailesefce9292019-01-11 13:19:20 -0800172 return mABIList.contains(abi);
Robert Sesek8f8d1872016-03-18 16:52:57 -0400173 }
174
175 public void close() {
176 try {
Chris Wailesefce9292019-01-11 13:19:20 -0800177 mZygoteSessionSocket.close();
Robert Sesek8f8d1872016-03-18 16:52:57 -0400178 } catch (IOException ex) {
179 Log.e(LOG_TAG,"I/O exception on routine close", ex);
180 }
181
182 mClosed = true;
183 }
184
185 boolean isClosed() {
186 return mClosed;
187 }
188 }
189
190 /**
Robert Sesekded20982016-08-15 13:59:13 -0400191 * Lock object to protect access to the two ZygoteStates below. This lock must be
192 * acquired while communicating over the ZygoteState's socket, to prevent
193 * interleaved access.
194 */
195 private final Object mLock = new Object();
196
197 /**
Mathew Inwood8faeab82018-03-16 14:26:08 +0000198 * List of exemptions to the API blacklist. These are prefix matches on the runtime format
199 * symbol signature. Any matching symbol is treated by the runtime as being on the light grey
200 * list.
201 */
202 private List<String> mApiBlacklistExemptions = Collections.emptyList();
203
204 /**
Mathew Inwood04194fe2018-04-04 14:48:03 +0100205 * Proportion of hidden API accesses that should be logged to the event log; 0 - 0x10000.
206 */
207 private int mHiddenApiAccessLogSampleRate;
208
209 /**
Robert Sesek8f8d1872016-03-18 16:52:57 -0400210 * The state of the connection to the primary zygote.
211 */
212 private ZygoteState primaryZygoteState;
213
214 /**
215 * The state of the connection to the secondary zygote.
216 */
217 private ZygoteState secondaryZygoteState;
218
219 /**
220 * Start a new process.
221 *
222 * <p>If processes are enabled, a new process is created and the
223 * static main() function of a <var>processClass</var> is executed there.
224 * The process will continue running after this function returns.
225 *
226 * <p>If processes are not enabled, a new thread in the caller's
Mathew Inwood8faeab82018-03-16 14:26:08 +0000227 * process is created and main() of <var>processclass</var> called there.
Robert Sesek8f8d1872016-03-18 16:52:57 -0400228 *
229 * <p>The niceName parameter, if not an empty string, is a custom name to
230 * give to the process instead of using processClass. This allows you to
231 * make easily identifyable processes even if you are using the same base
232 * <var>processClass</var> to start them.
233 *
Tamas Berghammerb8f7c352016-11-11 16:08:26 +0000234 * When invokeWith is not null, the process will be started as a fresh app
Tamas Berghammer0ca16fa2016-11-11 16:08:26 +0000235 * and not a zygote fork. Note that this is only allowed for uid 0 or when
Nicolas Geoffray81edac42017-09-07 14:13:29 +0100236 * runtimeFlags contains DEBUG_ENABLE_DEBUGGER.
Tamas Berghammerb8f7c352016-11-11 16:08:26 +0000237 *
Robert Sesek8f8d1872016-03-18 16:52:57 -0400238 * @param processClass The class to use as the process's main entry
239 * point.
240 * @param niceName A more readable name to use for the process.
241 * @param uid The user-id under which the process will run.
242 * @param gid The group-id under which the process will run.
243 * @param gids Additional group-ids associated with the process.
Nicolas Geoffray81edac42017-09-07 14:13:29 +0100244 * @param runtimeFlags Additional flags.
Robert Sesek8f8d1872016-03-18 16:52:57 -0400245 * @param targetSdkVersion The target SDK version for the app.
246 * @param seInfo null-ok SELinux information for the new process.
247 * @param abi non-null the ABI this app should be started with.
248 * @param instructionSet null-ok the instruction set to use.
249 * @param appDataDir null-ok the data directory of the app.
Tamas Berghammerb8f7c352016-11-11 16:08:26 +0000250 * @param invokeWith null-ok the command to invoke with.
Sudheer Shankad81b1d72018-09-05 16:37:30 -0700251 * @param packageName null-ok the name of the package this process belongs to.
Sudheer Shanka3f0645b2018-09-18 13:07:59 -0700252 * @param packagesForUid null-ok all the packages with the same uid as this process.
253 * @param visibleVols null-ok storage volumes that can be accessed by this process.
Robert Sesek8f8d1872016-03-18 16:52:57 -0400254 * @param zygoteArgs Additional arguments to supply to the zygote process.
255 *
256 * @return An object that describes the result of the attempt to start the process.
257 * @throws RuntimeException on fatal start failure
258 */
Sudheer Shankad81b1d72018-09-05 16:37:30 -0700259 public final Process.ProcessStartResult start(@NonNull final String processClass,
Robert Sesek8f8d1872016-03-18 16:52:57 -0400260 final String niceName,
Sudheer Shankad81b1d72018-09-05 16:37:30 -0700261 int uid, int gid, @Nullable int[] gids,
Nicolas Geoffray81edac42017-09-07 14:13:29 +0100262 int runtimeFlags, int mountExternal,
Robert Sesek8f8d1872016-03-18 16:52:57 -0400263 int targetSdkVersion,
Sudheer Shankad81b1d72018-09-05 16:37:30 -0700264 @Nullable String seInfo,
265 @NonNull String abi,
266 @Nullable String instructionSet,
267 @Nullable String appDataDir,
268 @Nullable String invokeWith,
269 @Nullable String packageName,
Sudheer Shanka3f0645b2018-09-18 13:07:59 -0700270 @Nullable String[] packagesForUid,
271 @Nullable String[] visibleVols,
Sudheer Shankad81b1d72018-09-05 16:37:30 -0700272 @Nullable String[] zygoteArgs) {
Robert Sesek8f8d1872016-03-18 16:52:57 -0400273 try {
274 return startViaZygote(processClass, niceName, uid, gid, gids,
Nicolas Geoffray81edac42017-09-07 14:13:29 +0100275 runtimeFlags, mountExternal, targetSdkVersion, seInfo,
Chris Wailesefce9292019-01-11 13:19:20 -0800276 abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/false,
Sudheer Shanka3f0645b2018-09-18 13:07:59 -0700277 packageName, packagesForUid, visibleVols, zygoteArgs);
Robert Sesek8f8d1872016-03-18 16:52:57 -0400278 } catch (ZygoteStartFailedEx ex) {
279 Log.e(LOG_TAG,
280 "Starting VM process through Zygote failed");
281 throw new RuntimeException(
282 "Starting VM process through Zygote failed", ex);
283 }
284 }
285
286 /** retry interval for opening a zygote socket */
287 static final int ZYGOTE_RETRY_MILLIS = 500;
288
289 /**
290 * Queries the zygote for the list of ABIS it supports.
291 *
292 * @throws ZygoteStartFailedEx if the query failed.
293 */
Robert Sesekded20982016-08-15 13:59:13 -0400294 @GuardedBy("mLock")
Chris Wailesefce9292019-01-11 13:19:20 -0800295 private static List<String> getAbiList(BufferedWriter writer, DataInputStream inputStream)
Robert Sesek8f8d1872016-03-18 16:52:57 -0400296 throws IOException {
297 // Each query starts with the argument count (1 in this case)
298 writer.write("1");
299 // ... followed by a new-line.
300 writer.newLine();
301 // ... followed by our only argument.
302 writer.write("--query-abi-list");
303 writer.newLine();
304 writer.flush();
305
306 // The response is a length prefixed stream of ASCII bytes.
307 int numBytes = inputStream.readInt();
308 byte[] bytes = new byte[numBytes];
309 inputStream.readFully(bytes);
310
Chris Wailesefce9292019-01-11 13:19:20 -0800311 String rawList = new String(bytes, StandardCharsets.US_ASCII);
312
313 return Arrays.asList(rawList.split(","));
Robert Sesek8f8d1872016-03-18 16:52:57 -0400314 }
315
316 /**
317 * Sends an argument list to the zygote process, which starts a new child
318 * and returns the child's pid. Please note: the present implementation
319 * replaces newlines in the argument list with spaces.
320 *
321 * @throws ZygoteStartFailedEx if process start failed for any reason
322 */
Robert Sesekded20982016-08-15 13:59:13 -0400323 @GuardedBy("mLock")
Robert Sesek8f8d1872016-03-18 16:52:57 -0400324 private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
325 ZygoteState zygoteState, ArrayList<String> args)
326 throws ZygoteStartFailedEx {
327 try {
Robert Sesek0b58f192016-10-10 18:34:42 -0400328 // Throw early if any of the arguments are malformed. This means we can
329 // avoid writing a partial response to the zygote.
330 int sz = args.size();
331 for (int i = 0; i < sz; i++) {
332 if (args.get(i).indexOf('\n') >= 0) {
333 throw new ZygoteStartFailedEx("embedded newlines not allowed");
334 }
335 }
336
Robert Sesek8f8d1872016-03-18 16:52:57 -0400337 /**
338 * See com.android.internal.os.SystemZygoteInit.readArgumentList()
339 * Presently the wire format to the zygote process is:
340 * a) a count of arguments (argc, in essence)
341 * b) a number of newline-separated argument strings equal to count
342 *
343 * After the zygote process reads these it will write the pid of
344 * the child or -1 on failure, followed by boolean to
345 * indicate whether a wrapper process was used.
346 */
Chris Wailesefce9292019-01-11 13:19:20 -0800347 final BufferedWriter writer = zygoteState.mZygoteOutputWriter;
348 final DataInputStream inputStream = zygoteState.mZygoteInputStream;
Robert Sesek8f8d1872016-03-18 16:52:57 -0400349
350 writer.write(Integer.toString(args.size()));
351 writer.newLine();
352
Robert Sesek8f8d1872016-03-18 16:52:57 -0400353 for (int i = 0; i < sz; i++) {
354 String arg = args.get(i);
Robert Sesek8f8d1872016-03-18 16:52:57 -0400355 writer.write(arg);
356 writer.newLine();
357 }
358
359 writer.flush();
360
361 // Should there be a timeout on this?
362 Process.ProcessStartResult result = new Process.ProcessStartResult();
Robert Sesek0b58f192016-10-10 18:34:42 -0400363
364 // Always read the entire result from the input stream to avoid leaving
365 // bytes in the stream for future process starts to accidentally stumble
366 // upon.
Robert Sesek8f8d1872016-03-18 16:52:57 -0400367 result.pid = inputStream.readInt();
Robert Sesek0b58f192016-10-10 18:34:42 -0400368 result.usingWrapper = inputStream.readBoolean();
369
Robert Sesek8f8d1872016-03-18 16:52:57 -0400370 if (result.pid < 0) {
371 throw new ZygoteStartFailedEx("fork() failed");
372 }
Robert Sesek8f8d1872016-03-18 16:52:57 -0400373 return result;
374 } catch (IOException ex) {
375 zygoteState.close();
376 throw new ZygoteStartFailedEx(ex);
377 }
378 }
379
380 /**
381 * Starts a new process via the zygote mechanism.
382 *
383 * @param processClass Class name whose static main() to run
384 * @param niceName 'nice' process name to appear in ps
385 * @param uid a POSIX uid that the new process should setuid() to
386 * @param gid a POSIX gid that the new process shuold setgid() to
387 * @param gids null-ok; a list of supplementary group IDs that the
388 * new process should setgroup() to.
Nicolas Geoffray81edac42017-09-07 14:13:29 +0100389 * @param runtimeFlags Additional flags for the runtime.
Robert Sesek8f8d1872016-03-18 16:52:57 -0400390 * @param targetSdkVersion The target SDK version for the app.
391 * @param seInfo null-ok SELinux information for the new process.
392 * @param abi the ABI the process should use.
393 * @param instructionSet null-ok the instruction set to use.
394 * @param appDataDir null-ok the data directory of the app.
Robert Sesekd0a190df2018-02-12 18:46:01 -0500395 * @param startChildZygote Start a sub-zygote. This creates a new zygote process
396 * that has its state cloned from this zygote process.
Sudheer Shankad81b1d72018-09-05 16:37:30 -0700397 * @param packageName null-ok the name of the package this process belongs to.
Sudheer Shanka3f0645b2018-09-18 13:07:59 -0700398 * @param packagesForUid null-ok all the packages with the same uid as this process.
399 * @param visibleVols null-ok storage volumes that can be accessed by this process.
Robert Sesek8f8d1872016-03-18 16:52:57 -0400400 * @param extraArgs Additional arguments to supply to the zygote process.
401 * @return An object that describes the result of the attempt to start the process.
402 * @throws ZygoteStartFailedEx if process start failed for any reason
403 */
Sudheer Shankad81b1d72018-09-05 16:37:30 -0700404 private Process.ProcessStartResult startViaZygote(@NonNull final String processClass,
405 @Nullable final String niceName,
Robert Sesek8f8d1872016-03-18 16:52:57 -0400406 final int uid, final int gid,
Sudheer Shankad81b1d72018-09-05 16:37:30 -0700407 @Nullable final int[] gids,
Nicolas Geoffray81edac42017-09-07 14:13:29 +0100408 int runtimeFlags, int mountExternal,
Robert Sesek8f8d1872016-03-18 16:52:57 -0400409 int targetSdkVersion,
Sudheer Shankad81b1d72018-09-05 16:37:30 -0700410 @Nullable String seInfo,
411 @NonNull String abi,
412 @Nullable String instructionSet,
413 @Nullable String appDataDir,
414 @Nullable String invokeWith,
Robert Sesekd0a190df2018-02-12 18:46:01 -0500415 boolean startChildZygote,
Sudheer Shankad81b1d72018-09-05 16:37:30 -0700416 @Nullable String packageName,
Sudheer Shanka3f0645b2018-09-18 13:07:59 -0700417 @Nullable String[] packagesForUid,
418 @Nullable String[] visibleVols,
Sudheer Shankad81b1d72018-09-05 16:37:30 -0700419 @Nullable String[] extraArgs)
Robert Sesek8f8d1872016-03-18 16:52:57 -0400420 throws ZygoteStartFailedEx {
Robert Sesekded20982016-08-15 13:59:13 -0400421 ArrayList<String> argsForZygote = new ArrayList<String>();
Robert Sesek8f8d1872016-03-18 16:52:57 -0400422
Robert Sesekded20982016-08-15 13:59:13 -0400423 // --runtime-args, --setuid=, --setgid=,
424 // and --setgroups= must go first
425 argsForZygote.add("--runtime-args");
426 argsForZygote.add("--setuid=" + uid);
427 argsForZygote.add("--setgid=" + gid);
Nicolas Geoffray81edac42017-09-07 14:13:29 +0100428 argsForZygote.add("--runtime-flags=" + runtimeFlags);
Robert Sesekded20982016-08-15 13:59:13 -0400429 if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) {
430 argsForZygote.add("--mount-external-default");
431 } else if (mountExternal == Zygote.MOUNT_EXTERNAL_READ) {
432 argsForZygote.add("--mount-external-read");
433 } else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) {
434 argsForZygote.add("--mount-external-write");
Sudheer Shanka98cb3f02018-08-17 16:10:29 -0700435 } else if (mountExternal == Zygote.MOUNT_EXTERNAL_FULL) {
436 argsForZygote.add("--mount-external-full");
Sudheer Shanka3a0df3b2018-12-12 12:43:43 -0800437 } else if (mountExternal == Zygote.MOUNT_EXTERNAL_INSTALLER) {
438 argsForZygote.add("--mount-external-installer");
Sudheer Shanka0b6da532019-01-09 12:06:51 -0800439 } else if (mountExternal == Zygote.MOUNT_EXTERNAL_LEGACY) {
440 argsForZygote.add("--mount-external-legacy");
Robert Sesekded20982016-08-15 13:59:13 -0400441 }
Sudheer Shanka98cb3f02018-08-17 16:10:29 -0700442
Robert Sesekded20982016-08-15 13:59:13 -0400443 argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
Robert Sesek8f8d1872016-03-18 16:52:57 -0400444
Robert Sesekded20982016-08-15 13:59:13 -0400445 // --setgroups is a comma-separated list
446 if (gids != null && gids.length > 0) {
447 StringBuilder sb = new StringBuilder();
448 sb.append("--setgroups=");
Robert Sesek8f8d1872016-03-18 16:52:57 -0400449
Robert Sesekded20982016-08-15 13:59:13 -0400450 int sz = gids.length;
451 for (int i = 0; i < sz; i++) {
452 if (i != 0) {
453 sb.append(',');
Robert Sesek8f8d1872016-03-18 16:52:57 -0400454 }
Robert Sesekded20982016-08-15 13:59:13 -0400455 sb.append(gids[i]);
Robert Sesek8f8d1872016-03-18 16:52:57 -0400456 }
457
Robert Sesekded20982016-08-15 13:59:13 -0400458 argsForZygote.add(sb.toString());
459 }
460
461 if (niceName != null) {
462 argsForZygote.add("--nice-name=" + niceName);
463 }
464
465 if (seInfo != null) {
466 argsForZygote.add("--seinfo=" + seInfo);
467 }
468
469 if (instructionSet != null) {
470 argsForZygote.add("--instruction-set=" + instructionSet);
471 }
472
473 if (appDataDir != null) {
474 argsForZygote.add("--app-data-dir=" + appDataDir);
475 }
476
Tamas Berghammerb8f7c352016-11-11 16:08:26 +0000477 if (invokeWith != null) {
478 argsForZygote.add("--invoke-with");
479 argsForZygote.add(invokeWith);
480 }
481
Robert Sesekd0a190df2018-02-12 18:46:01 -0500482 if (startChildZygote) {
483 argsForZygote.add("--start-child-zygote");
484 }
485
Sudheer Shanka154fe3f2018-07-30 14:44:26 -0700486 if (packageName != null) {
487 argsForZygote.add("--package-name=" + packageName);
488 }
489
Sudheer Shanka3f0645b2018-09-18 13:07:59 -0700490 if (packagesForUid != null && packagesForUid.length > 0) {
491 final StringBuilder sb = new StringBuilder();
492 sb.append("--packages-for-uid=");
493
494 for (int i = 0; i < packagesForUid.length; ++i) {
495 if (i != 0) {
496 sb.append(',');
497 }
498 sb.append(packagesForUid[i]);
499 }
500 argsForZygote.add(sb.toString());
501 }
502
503 if (visibleVols != null && visibleVols.length > 0) {
504 final StringBuilder sb = new StringBuilder();
505 sb.append("--visible-vols=");
506
507 for (int i = 0; i < visibleVols.length; ++i) {
508 if (i != 0) {
509 sb.append(',');
510 }
511 sb.append(visibleVols[i]);
512 }
513 argsForZygote.add(sb.toString());
514 }
515
Robert Sesekded20982016-08-15 13:59:13 -0400516 argsForZygote.add(processClass);
517
518 if (extraArgs != null) {
519 for (String arg : extraArgs) {
520 argsForZygote.add(arg);
Robert Sesek8f8d1872016-03-18 16:52:57 -0400521 }
Robert Sesekded20982016-08-15 13:59:13 -0400522 }
Robert Sesek8f8d1872016-03-18 16:52:57 -0400523
Robert Sesekded20982016-08-15 13:59:13 -0400524 synchronized(mLock) {
Robert Sesek8f8d1872016-03-18 16:52:57 -0400525 return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
526 }
527 }
528
529 /**
Robert Sesekd0a190df2018-02-12 18:46:01 -0500530 * Closes the connections to the zygote, if they exist.
531 */
532 public void close() {
533 if (primaryZygoteState != null) {
534 primaryZygoteState.close();
535 }
536 if (secondaryZygoteState != null) {
537 secondaryZygoteState.close();
538 }
539 }
540
541 /**
Robert Sesek8f8d1872016-03-18 16:52:57 -0400542 * Tries to establish a connection to the zygote that handles a given {@code abi}. Might block
543 * and retry if the zygote is unresponsive. This method is a no-op if a connection is
544 * already open.
545 */
546 public void establishZygoteConnectionForAbi(String abi) {
547 try {
Robert Sesekded20982016-08-15 13:59:13 -0400548 synchronized(mLock) {
549 openZygoteSocketIfNeeded(abi);
550 }
Robert Sesek8f8d1872016-03-18 16:52:57 -0400551 } catch (ZygoteStartFailedEx ex) {
552 throw new RuntimeException("Unable to connect to zygote for abi: " + abi, ex);
553 }
554 }
555
556 /**
Andreas Gampe8444dca2018-05-01 13:31:28 -0700557 * Attempt to retrieve the PID of the zygote serving the given abi.
558 */
559 public int getZygotePid(String abi) {
560 try {
561 synchronized (mLock) {
562 ZygoteState state = openZygoteSocketIfNeeded(abi);
563
564 // Each query starts with the argument count (1 in this case)
Chris Wailesefce9292019-01-11 13:19:20 -0800565 state.mZygoteOutputWriter.write("1");
Andreas Gampe8444dca2018-05-01 13:31:28 -0700566 // ... followed by a new-line.
Chris Wailesefce9292019-01-11 13:19:20 -0800567 state.mZygoteOutputWriter.newLine();
Andreas Gampe8444dca2018-05-01 13:31:28 -0700568 // ... followed by our only argument.
Chris Wailesefce9292019-01-11 13:19:20 -0800569 state.mZygoteOutputWriter.write("--get-pid");
570 state.mZygoteOutputWriter.newLine();
571 state.mZygoteOutputWriter.flush();
Andreas Gampe8444dca2018-05-01 13:31:28 -0700572
573 // The response is a length prefixed stream of ASCII bytes.
Chris Wailesefce9292019-01-11 13:19:20 -0800574 int numBytes = state.mZygoteInputStream.readInt();
Andreas Gampe8444dca2018-05-01 13:31:28 -0700575 byte[] bytes = new byte[numBytes];
Chris Wailesefce9292019-01-11 13:19:20 -0800576 state.mZygoteInputStream.readFully(bytes);
Andreas Gampe8444dca2018-05-01 13:31:28 -0700577
578 return Integer.parseInt(new String(bytes, StandardCharsets.US_ASCII));
579 }
580 } catch (Exception ex) {
581 throw new RuntimeException("Failure retrieving pid", ex);
582 }
583 }
584
585 /**
Mathew Inwood8faeab82018-03-16 14:26:08 +0000586 * Push hidden API blacklisting exemptions into the zygote process(es).
587 *
588 * <p>The list of exemptions will take affect for all new processes forked from the zygote after
589 * this call.
590 *
Mathew Inwood33d51382018-04-05 13:56:39 +0100591 * @param exemptions List of hidden API exemption prefixes. Any matching members are treated as
592 * whitelisted/public APIs (i.e. allowed, no logging of usage).
Mathew Inwood8faeab82018-03-16 14:26:08 +0000593 */
Mathew Inwood9f6bb5b2018-04-09 17:29:12 +0100594 public boolean setApiBlacklistExemptions(List<String> exemptions) {
Mathew Inwood8faeab82018-03-16 14:26:08 +0000595 synchronized (mLock) {
596 mApiBlacklistExemptions = exemptions;
Mathew Inwood9f6bb5b2018-04-09 17:29:12 +0100597 boolean ok = maybeSetApiBlacklistExemptions(primaryZygoteState, true);
598 if (ok) {
599 ok = maybeSetApiBlacklistExemptions(secondaryZygoteState, true);
600 }
601 return ok;
Mathew Inwood8faeab82018-03-16 14:26:08 +0000602 }
603 }
604
Mathew Inwood04194fe2018-04-04 14:48:03 +0100605 /**
606 * Set the precentage of detected hidden API accesses that are logged to the event log.
607 *
608 * <p>This rate will take affect for all new processes forked from the zygote after this call.
609 *
610 * @param rate An integer between 0 and 0x10000 inclusive. 0 means no event logging.
611 */
612 public void setHiddenApiAccessLogSampleRate(int rate) {
613 synchronized (mLock) {
614 mHiddenApiAccessLogSampleRate = rate;
615 maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState);
616 maybeSetHiddenApiAccessLogSampleRate(secondaryZygoteState);
617 }
618 }
619
Mathew Inwood8faeab82018-03-16 14:26:08 +0000620 @GuardedBy("mLock")
Mathew Inwood9f6bb5b2018-04-09 17:29:12 +0100621 private boolean maybeSetApiBlacklistExemptions(ZygoteState state, boolean sendIfEmpty) {
Mathew Inwood8faeab82018-03-16 14:26:08 +0000622 if (state == null || state.isClosed()) {
Mathew Inwood9f6bb5b2018-04-09 17:29:12 +0100623 Slog.e(LOG_TAG, "Can't set API blacklist exemptions: no zygote connection");
624 return false;
Mathew Inwood8faeab82018-03-16 14:26:08 +0000625 }
626 if (!sendIfEmpty && mApiBlacklistExemptions.isEmpty()) {
Mathew Inwood9f6bb5b2018-04-09 17:29:12 +0100627 return true;
Mathew Inwood8faeab82018-03-16 14:26:08 +0000628 }
629 try {
Chris Wailesefce9292019-01-11 13:19:20 -0800630 state.mZygoteOutputWriter.write(Integer.toString(mApiBlacklistExemptions.size() + 1));
631 state.mZygoteOutputWriter.newLine();
632 state.mZygoteOutputWriter.write("--set-api-blacklist-exemptions");
633 state.mZygoteOutputWriter.newLine();
Mathew Inwood8faeab82018-03-16 14:26:08 +0000634 for (int i = 0; i < mApiBlacklistExemptions.size(); ++i) {
Chris Wailesefce9292019-01-11 13:19:20 -0800635 state.mZygoteOutputWriter.write(mApiBlacklistExemptions.get(i));
636 state.mZygoteOutputWriter.newLine();
Mathew Inwood8faeab82018-03-16 14:26:08 +0000637 }
Chris Wailesefce9292019-01-11 13:19:20 -0800638 state.mZygoteOutputWriter.flush();
639 int status = state.mZygoteInputStream.readInt();
Mathew Inwood8faeab82018-03-16 14:26:08 +0000640 if (status != 0) {
641 Slog.e(LOG_TAG, "Failed to set API blacklist exemptions; status " + status);
642 }
Mathew Inwood9f6bb5b2018-04-09 17:29:12 +0100643 return true;
Mathew Inwood8faeab82018-03-16 14:26:08 +0000644 } catch (IOException ioe) {
645 Slog.e(LOG_TAG, "Failed to set API blacklist exemptions", ioe);
Mathew Inwood9f6bb5b2018-04-09 17:29:12 +0100646 mApiBlacklistExemptions = Collections.emptyList();
647 return false;
Mathew Inwood8faeab82018-03-16 14:26:08 +0000648 }
649 }
650
Mathew Inwood04194fe2018-04-04 14:48:03 +0100651 private void maybeSetHiddenApiAccessLogSampleRate(ZygoteState state) {
652 if (state == null || state.isClosed()) {
653 return;
654 }
655 if (mHiddenApiAccessLogSampleRate == -1) {
656 return;
657 }
658 try {
Chris Wailesefce9292019-01-11 13:19:20 -0800659 state.mZygoteOutputWriter.write(Integer.toString(1));
660 state.mZygoteOutputWriter.newLine();
661 state.mZygoteOutputWriter.write("--hidden-api-log-sampling-rate="
Mathew Inwood04194fe2018-04-04 14:48:03 +0100662 + Integer.toString(mHiddenApiAccessLogSampleRate));
Chris Wailesefce9292019-01-11 13:19:20 -0800663 state.mZygoteOutputWriter.newLine();
664 state.mZygoteOutputWriter.flush();
665 int status = state.mZygoteInputStream.readInt();
Mathew Inwood04194fe2018-04-04 14:48:03 +0100666 if (status != 0) {
667 Slog.e(LOG_TAG, "Failed to set hidden API log sampling rate; status " + status);
668 }
669 } catch (IOException ioe) {
670 Slog.e(LOG_TAG, "Failed to set hidden API log sampling rate", ioe);
671 }
672 }
673
Mathew Inwood8faeab82018-03-16 14:26:08 +0000674 /**
Chris Wailesefce9292019-01-11 13:19:20 -0800675 * Tries to open a session socket to a Zygote process with a compatible ABI if one is not
676 * already open. If a compatible session socket is already open that session socket is returned.
677 * This function may block and may have to try connecting to multiple Zygotes to find the
678 * appropriate one. Requires that mLock be held.
Robert Sesek8f8d1872016-03-18 16:52:57 -0400679 */
Robert Sesekded20982016-08-15 13:59:13 -0400680 @GuardedBy("mLock")
Chris Wailesefce9292019-01-11 13:19:20 -0800681 private ZygoteState openZygoteSocketIfNeeded(String abi)
682 throws ZygoteStartFailedEx {
683
Robert Sesekded20982016-08-15 13:59:13 -0400684 Preconditions.checkState(Thread.holdsLock(mLock), "ZygoteProcess lock not held");
685
Robert Sesek8f8d1872016-03-18 16:52:57 -0400686 if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
687 try {
Chris Wailesefce9292019-01-11 13:19:20 -0800688 primaryZygoteState =
689 ZygoteState.connect(mZygoteSocketAddress);
Robert Sesek8f8d1872016-03-18 16:52:57 -0400690 } catch (IOException ioe) {
691 throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
692 }
Chris Wailesefce9292019-01-11 13:19:20 -0800693
Mathew Inwood8faeab82018-03-16 14:26:08 +0000694 maybeSetApiBlacklistExemptions(primaryZygoteState, false);
Mathew Inwood04194fe2018-04-04 14:48:03 +0100695 maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState);
Robert Sesek8f8d1872016-03-18 16:52:57 -0400696 }
Chris Wailesefce9292019-01-11 13:19:20 -0800697
Robert Sesek8f8d1872016-03-18 16:52:57 -0400698 if (primaryZygoteState.matches(abi)) {
699 return primaryZygoteState;
700 }
701
702 // The primary zygote didn't match. Try the secondary.
703 if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
704 try {
Chris Wailesefce9292019-01-11 13:19:20 -0800705 secondaryZygoteState =
706 ZygoteState.connect(mZygoteSecondarySocketAddress);
Robert Sesek8f8d1872016-03-18 16:52:57 -0400707 } catch (IOException ioe) {
708 throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);
709 }
Chris Wailesefce9292019-01-11 13:19:20 -0800710
Mathew Inwood8faeab82018-03-16 14:26:08 +0000711 maybeSetApiBlacklistExemptions(secondaryZygoteState, false);
Mathew Inwood04194fe2018-04-04 14:48:03 +0100712 maybeSetHiddenApiAccessLogSampleRate(secondaryZygoteState);
Robert Sesek8f8d1872016-03-18 16:52:57 -0400713 }
714
715 if (secondaryZygoteState.matches(abi)) {
716 return secondaryZygoteState;
717 }
718
719 throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
720 }
Robert Sesekded20982016-08-15 13:59:13 -0400721
722 /**
Martijn Coenen7e6fa672018-11-05 11:45:26 +0100723 * Instructs the zygote to pre-load the application code for the given Application.
724 * Only the app zygote supports this function.
725 * TODO preloadPackageForAbi() can probably be removed and the callers an use this instead.
726 */
727 public boolean preloadApp(ApplicationInfo appInfo, String abi) throws ZygoteStartFailedEx,
728 IOException {
729 synchronized (mLock) {
730 ZygoteState state = openZygoteSocketIfNeeded(abi);
Chris Wailesefce9292019-01-11 13:19:20 -0800731 state.mZygoteOutputWriter.write("2");
732 state.mZygoteOutputWriter.newLine();
Martijn Coenen7e6fa672018-11-05 11:45:26 +0100733
Chris Wailesefce9292019-01-11 13:19:20 -0800734 state.mZygoteOutputWriter.write("--preload-app");
735 state.mZygoteOutputWriter.newLine();
Martijn Coenen7e6fa672018-11-05 11:45:26 +0100736
737 // Zygote args needs to be strings, so in order to pass ApplicationInfo,
738 // write it to a Parcel, and base64 the raw Parcel bytes to the other side.
739 Parcel parcel = Parcel.obtain();
740 appInfo.writeToParcel(parcel, 0 /* flags */);
741 String encodedParcelData = Base64.getEncoder().encodeToString(parcel.marshall());
742 parcel.recycle();
Chris Wailesefce9292019-01-11 13:19:20 -0800743 state.mZygoteOutputWriter.write(encodedParcelData);
744 state.mZygoteOutputWriter.newLine();
Martijn Coenen7e6fa672018-11-05 11:45:26 +0100745
Chris Wailesefce9292019-01-11 13:19:20 -0800746 state.mZygoteOutputWriter.flush();
Martijn Coenen7e6fa672018-11-05 11:45:26 +0100747
Chris Wailesefce9292019-01-11 13:19:20 -0800748 return (state.mZygoteInputStream.readInt() == 0);
Martijn Coenen7e6fa672018-11-05 11:45:26 +0100749 }
750 }
751
752 /**
Robert Sesekded20982016-08-15 13:59:13 -0400753 * Instructs the zygote to pre-load the classes and native libraries at the given paths
754 * for the specified abi. Not all zygotes support this function.
755 */
Torne (Richard Coles)f4f647e2018-02-21 16:12:36 -0500756 public boolean preloadPackageForAbi(String packagePath, String libsPath, String libFileName,
757 String cacheKey, String abi) throws ZygoteStartFailedEx,
758 IOException {
Robert Sesekded20982016-08-15 13:59:13 -0400759 synchronized(mLock) {
760 ZygoteState state = openZygoteSocketIfNeeded(abi);
Chris Wailesefce9292019-01-11 13:19:20 -0800761 state.mZygoteOutputWriter.write("5");
762 state.mZygoteOutputWriter.newLine();
Robert Sesekded20982016-08-15 13:59:13 -0400763
Chris Wailesefce9292019-01-11 13:19:20 -0800764 state.mZygoteOutputWriter.write("--preload-package");
765 state.mZygoteOutputWriter.newLine();
Robert Sesekded20982016-08-15 13:59:13 -0400766
Chris Wailesefce9292019-01-11 13:19:20 -0800767 state.mZygoteOutputWriter.write(packagePath);
768 state.mZygoteOutputWriter.newLine();
Robert Sesekded20982016-08-15 13:59:13 -0400769
Chris Wailesefce9292019-01-11 13:19:20 -0800770 state.mZygoteOutputWriter.write(libsPath);
771 state.mZygoteOutputWriter.newLine();
Robert Sesekded20982016-08-15 13:59:13 -0400772
Chris Wailesefce9292019-01-11 13:19:20 -0800773 state.mZygoteOutputWriter.write(libFileName);
774 state.mZygoteOutputWriter.newLine();
Torne (Richard Coles)f4f647e2018-02-21 16:12:36 -0500775
Chris Wailesefce9292019-01-11 13:19:20 -0800776 state.mZygoteOutputWriter.write(cacheKey);
777 state.mZygoteOutputWriter.newLine();
Torne (Richard Coles)04526702017-01-13 14:19:39 +0000778
Chris Wailesefce9292019-01-11 13:19:20 -0800779 state.mZygoteOutputWriter.flush();
Narayan Kamathbae484a2017-07-03 14:12:26 +0100780
Chris Wailesefce9292019-01-11 13:19:20 -0800781 return (state.mZygoteInputStream.readInt() == 0);
Robert Sesekded20982016-08-15 13:59:13 -0400782 }
783 }
Narayan Kamath669afcc2017-02-06 20:24:08 +0000784
785 /**
786 * Instructs the zygote to preload the default set of classes and resources. Returns
787 * {@code true} if a preload was performed as a result of this call, and {@code false}
788 * otherwise. The latter usually means that the zygote eagerly preloaded at startup
789 * or due to a previous call to {@code preloadDefault}. Note that this call is synchronous.
790 */
791 public boolean preloadDefault(String abi) throws ZygoteStartFailedEx, IOException {
792 synchronized (mLock) {
793 ZygoteState state = openZygoteSocketIfNeeded(abi);
794 // Each query starts with the argument count (1 in this case)
Chris Wailesefce9292019-01-11 13:19:20 -0800795 state.mZygoteOutputWriter.write("1");
796 state.mZygoteOutputWriter.newLine();
797 state.mZygoteOutputWriter.write("--preload-default");
798 state.mZygoteOutputWriter.newLine();
799 state.mZygoteOutputWriter.flush();
Narayan Kamath669afcc2017-02-06 20:24:08 +0000800
Chris Wailesefce9292019-01-11 13:19:20 -0800801 return (state.mZygoteInputStream.readInt() == 0);
Narayan Kamath669afcc2017-02-06 20:24:08 +0000802 }
803 }
Gustav Senntonf0c52b52017-04-27 17:00:50 +0100804
805 /**
806 * Try connecting to the Zygote over and over again until we hit a time-out.
807 * @param socketName The name of the socket to connect to.
808 */
Chris Wailesefce9292019-01-11 13:19:20 -0800809 public static void waitForConnectionToZygote(String zygoteSocketName) {
810 final LocalSocketAddress zygoteSocketAddress =
811 new LocalSocketAddress(zygoteSocketName, LocalSocketAddress.Namespace.RESERVED);
812 waitForConnectionToZygote(zygoteSocketAddress);
Robert Sesek5ac8abf2018-01-26 14:26:53 -0500813 }
814
815 /**
816 * Try connecting to the Zygote over and over again until we hit a time-out.
817 * @param address The name of the socket to connect to.
818 */
Chris Wailesefce9292019-01-11 13:19:20 -0800819 public static void waitForConnectionToZygote(LocalSocketAddress zygoteSocketAddress) {
Gustav Senntonf0c52b52017-04-27 17:00:50 +0100820 for (int n = 20; n >= 0; n--) {
821 try {
Chris Wailesefce9292019-01-11 13:19:20 -0800822 final ZygoteState zs =
823 ZygoteState.connect(zygoteSocketAddress);
Gustav Senntonf0c52b52017-04-27 17:00:50 +0100824 zs.close();
825 return;
826 } catch (IOException ioe) {
827 Log.w(LOG_TAG,
828 "Got error connecting to zygote, retrying. msg= " + ioe.getMessage());
829 }
830
831 try {
832 Thread.sleep(1000);
833 } catch (InterruptedException ie) {
834 }
835 }
Chris Wailesefce9292019-01-11 13:19:20 -0800836 Slog.wtf(LOG_TAG, "Failed to connect to Zygote through socket "
837 + zygoteSocketAddress.getName());
Gustav Senntonf0c52b52017-04-27 17:00:50 +0100838 }
Robert Sesekd0a190df2018-02-12 18:46:01 -0500839
840 /**
841 * Starts a new zygote process as a child of this zygote. This is used to create
842 * secondary zygotes that inherit data from the zygote that this object
843 * communicates with. This returns a new ZygoteProcess representing a connection
844 * to the newly created zygote. Throws an exception if the zygote cannot be started.
Martijn Coenen7e6fa672018-11-05 11:45:26 +0100845 *
846 * @param processClass The class to use as the child zygote's main entry
847 * point.
848 * @param niceName A more readable name to use for the process.
849 * @param uid The user-id under which the child zygote will run.
850 * @param gid The group-id under which the child zygote will run.
851 * @param gids Additional group-ids associated with the child zygote process.
852 * @param runtimeFlags Additional flags.
853 * @param seInfo null-ok SELinux information for the child zygote process.
854 * @param abi non-null the ABI of the child zygote
855 * @param acceptedAbiList ABIs this child zygote will accept connections for; this
856 * may be different from <code>abi</code> in case the children
857 * spawned from this Zygote only communicate using ABI-safe methods.
858 * @param instructionSet null-ok the instruction set to use.
Martijn Coenen86f08a52019-01-03 16:23:01 +0100859 * @param uidRangeStart The first UID in the range the child zygote may setuid()/setgid() to
860 * @param uidRangeEnd The last UID in the range the child zygote may setuid()/setgid() to
Robert Sesekd0a190df2018-02-12 18:46:01 -0500861 */
862 public ChildZygoteProcess startChildZygote(final String processClass,
863 final String niceName,
864 int uid, int gid, int[] gids,
865 int runtimeFlags,
866 String seInfo,
867 String abi,
Martijn Coenen7e6fa672018-11-05 11:45:26 +0100868 String acceptedAbiList,
Martijn Coenen86f08a52019-01-03 16:23:01 +0100869 String instructionSet,
870 int uidRangeStart,
871 int uidRangeEnd) {
Robert Sesekd0a190df2018-02-12 18:46:01 -0500872 // Create an unguessable address in the global abstract namespace.
873 final LocalSocketAddress serverAddress = new LocalSocketAddress(
874 processClass + "/" + UUID.randomUUID().toString());
875
Martijn Coenen7e6fa672018-11-05 11:45:26 +0100876 final String[] extraArgs = {Zygote.CHILD_ZYGOTE_SOCKET_NAME_ARG + serverAddress.getName(),
Martijn Coenen86f08a52019-01-03 16:23:01 +0100877 Zygote.CHILD_ZYGOTE_ABI_LIST_ARG + acceptedAbiList,
878 Zygote.CHILD_ZYGOTE_UID_RANGE_START + uidRangeStart,
879 Zygote.CHILD_ZYGOTE_UID_RANGE_END + uidRangeEnd};
Robert Sesekd0a190df2018-02-12 18:46:01 -0500880
881 Process.ProcessStartResult result;
882 try {
883 result = startViaZygote(processClass, niceName, uid, gid,
884 gids, runtimeFlags, 0 /* mountExternal */, 0 /* targetSdkVersion */, seInfo,
885 abi, instructionSet, null /* appDataDir */, null /* invokeWith */,
Sudheer Shanka3f0645b2018-09-18 13:07:59 -0700886 true /* startChildZygote */, null /* packageName */,
887 null /* packagesForUid */, null /* visibleVolumes */, extraArgs);
Robert Sesekd0a190df2018-02-12 18:46:01 -0500888 } catch (ZygoteStartFailedEx ex) {
889 throw new RuntimeException("Starting child-zygote through Zygote failed", ex);
890 }
891
892 return new ChildZygoteProcess(serverAddress, result.pid);
893 }
Robert Sesek8f8d1872016-03-18 16:52:57 -0400894}