blob: 68299615b5b9f9051b9e67a96cc53e6b873c9060 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 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 com.android.internal.os;
18
Elliott Hughes894724b2014-12-15 12:39:51 -080019import static android.system.OsConstants.POLLIN;
Elliott Hughesa9569ff2014-04-28 20:53:52 -070020import static android.system.OsConstants.S_IRWXG;
21import static android.system.OsConstants.S_IRWXO;
Kenny Root4c74f8c2012-08-17 08:45:55 -070022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import android.content.res.Resources;
24import android.content.res.TypedArray;
Neil Fuller4f41f612016-05-09 16:55:36 +010025import android.icu.impl.CacheValue;
26import android.icu.text.DecimalFormatSymbols;
27import android.icu.util.ULocale;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import android.net.LocalServerSocket;
Romain Guy74c69122013-05-08 17:54:20 -070029import android.opengl.EGL14;
Jeff Brownebed7d62011-05-16 17:08:42 -070030import android.os.Process;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031import android.os.SystemClock;
Romain Guyc5e36382013-05-09 11:08:17 -070032import android.os.SystemProperties;
Jamie Gennis6ad04522013-04-15 18:53:24 -070033import android.os.Trace;
Sergio Giro69de3202016-05-17 16:52:33 +010034import android.security.keystore.AndroidKeyStoreProvider;
Bill Yi9a76e9b2014-04-29 18:52:48 -070035import android.system.ErrnoException;
Elliott Hughes860c5912014-04-28 19:19:13 -070036import android.system.Os;
37import android.system.OsConstants;
Elliott Hughes894724b2014-12-15 12:39:51 -080038import android.system.StructPollfd;
Raph Levienc3dd1c12015-04-06 10:37:57 -070039import android.text.Hyphenator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import android.util.EventLog;
41import android.util.Log;
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +010042import android.webkit.WebViewFactory;
Andreas Gampeddc13972016-02-26 16:54:59 -080043import android.widget.TextView;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044
Jeff Sharkeyfdeeeea2016-01-11 17:34:24 -070045import com.android.internal.os.InstallerConnection.InstallerException;
46
Narayan Kamath29564cd2014-08-07 10:57:40 +010047import dalvik.system.DexFile;
48import dalvik.system.PathClassLoader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049import dalvik.system.VMRuntime;
Andreas Gampe1ef8aef2016-04-11 08:39:52 -070050import dalvik.system.ZygoteHooks;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051
Brian Carlstrom46703b02011-04-06 15:41:29 -070052import libcore.io.IoUtils;
53
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054import java.io.BufferedReader;
55import java.io.FileDescriptor;
Ying Wangd0c45352014-11-13 15:22:47 -080056import java.io.FileInputStream;
57import java.io.FileNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058import java.io.IOException;
59import java.io.InputStream;
60import java.io.InputStreamReader;
61import java.lang.reflect.InvocationTargetException;
62import java.lang.reflect.Method;
Sergio Giro6cb7b1c2016-05-13 16:34:46 +010063import java.security.Security;
64import java.security.Provider;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065import java.util.ArrayList;
66
67/**
68 * Startup class for the zygote process.
69 *
70 * Pre-initializes some classes, and then waits for commands on a UNIX domain
Elliott Hughese1dfcb72011-07-08 11:08:07 -070071 * socket. Based on these commands, forks off child processes that inherit
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072 * the initial state of the VM.
73 *
74 * Please see {@link ZygoteConnection.Arguments} for documentation on the
75 * client protocol.
76 *
77 * @hide
78 */
79public class ZygoteInit {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080 private static final String TAG = "Zygote";
81
Jesse Halle8ce1272017-01-17 12:34:14 -080082 private static final String PROPERTY_DISABLE_OPENGL_PRELOADING = "ro.zygote.disable_gl_preload";
Luis Hector Chavez5dd239a2015-10-06 14:01:45 -070083 private static final String PROPERTY_RUNNING_IN_CONTAINER = "ro.boot.container";
Romain Guyc5e36382013-05-09 11:08:17 -070084
Narayan Kamathc41638c2014-04-07 13:56:15 +010085 private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086
87 private static final int LOG_BOOT_PROGRESS_PRELOAD_START = 3020;
88 private static final int LOG_BOOT_PROGRESS_PRELOAD_END = 3030;
89
90 /** when preloading, GC after allocating this many bytes */
91 private static final int PRELOAD_GC_THRESHOLD = 50000;
92
Narayan Kamathc41638c2014-04-07 13:56:15 +010093 private static final String ABI_LIST_ARG = "--abi-list=";
94
95 private static final String SOCKET_NAME_ARG = "--socket-name=";
Barry Hayes0b3533a2010-01-20 12:46:47 -080096
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097 private static LocalServerSocket sServerSocket;
98
99 /**
100 * Used to pre-load resources. We hold a global reference on it so it
101 * never gets destroyed.
102 */
103 private static Resources mResources;
Bob Leee5408332009-09-04 18:31:17 -0700104
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105 /**
Ying Wangd0c45352014-11-13 15:22:47 -0800106 * The path of a file that contains classes to preload.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107 */
Ying Wangd0c45352014-11-13 15:22:47 -0800108 private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109
110 /** Controls whether we should preload resources during zygote init. */
Steve Paik3c27a232015-06-10 18:25:44 -0700111 public static final boolean PRELOAD_RESOURCES = true;
Andy McFadden599c9182009-04-08 00:35:56 -0700112
113 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114 * Registers a server socket for zygote command connections
115 *
116 * @throws RuntimeException when open fails
117 */
Narayan Kamathc41638c2014-04-07 13:56:15 +0100118 private static void registerZygoteSocket(String socketName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119 if (sServerSocket == null) {
120 int fileDesc;
Narayan Kamathc41638c2014-04-07 13:56:15 +0100121 final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122 try {
Narayan Kamathc41638c2014-04-07 13:56:15 +0100123 String env = System.getenv(fullSocketName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124 fileDesc = Integer.parseInt(env);
125 } catch (RuntimeException ex) {
Narayan Kamathc41638c2014-04-07 13:56:15 +0100126 throw new RuntimeException(fullSocketName + " unset or invalid", ex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127 }
128
129 try {
Elliott Hughes3fe59512014-12-12 14:07:34 -0800130 FileDescriptor fd = new FileDescriptor();
131 fd.setInt$(fileDesc);
132 sServerSocket = new LocalServerSocket(fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133 } catch (IOException ex) {
134 throw new RuntimeException(
135 "Error binding to local socket '" + fileDesc + "'", ex);
136 }
137 }
138 }
139
140 /**
141 * Waits for and accepts a single command connection. Throws
142 * RuntimeException on failure.
143 */
Narayan Kamathc41638c2014-04-07 13:56:15 +0100144 private static ZygoteConnection acceptCommandPeer(String abiList) {
Bob Leee5408332009-09-04 18:31:17 -0700145 try {
Narayan Kamathc41638c2014-04-07 13:56:15 +0100146 return new ZygoteConnection(sServerSocket.accept(), abiList);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800147 } catch (IOException ex) {
148 throw new RuntimeException(
149 "IOException during accept()", ex);
150 }
151 }
152
153 /**
154 * Close and clean up zygote sockets. Called on shutdown and on the
155 * child's exit path.
156 */
157 static void closeServerSocket() {
158 try {
159 if (sServerSocket != null) {
Dave Platt02f042d2013-12-12 15:45:49 -0800160 FileDescriptor fd = sServerSocket.getFileDescriptor();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161 sServerSocket.close();
Dave Platt02f042d2013-12-12 15:45:49 -0800162 if (fd != null) {
Bill Yi9a76e9b2014-04-29 18:52:48 -0700163 Os.close(fd);
Dave Platt02f042d2013-12-12 15:45:49 -0800164 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 }
166 } catch (IOException ex) {
167 Log.e(TAG, "Zygote: error closing sockets", ex);
Bill Yi9a76e9b2014-04-29 18:52:48 -0700168 } catch (ErrnoException ex) {
Dave Platt02f042d2013-12-12 15:45:49 -0800169 Log.e(TAG, "Zygote: error closing descriptor", ex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800170 }
171
172 sServerSocket = null;
173 }
174
Dave Platt89d4c892014-02-05 17:06:42 -0800175 /**
176 * Return the server socket's underlying file descriptor, so that
177 * ZygoteConnection can pass it to the native code for proper
178 * closure after a child process is forked off.
179 */
180
181 static FileDescriptor getServerSocketFileDescriptor() {
182 return sServerSocket.getFileDescriptor();
183 }
184
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800185 private static final int UNPRIVILEGED_UID = 9999;
186 private static final int UNPRIVILEGED_GID = 9999;
187
188 private static final int ROOT_UID = 0;
189 private static final int ROOT_GID = 0;
190
Jeff Brown0c2313d2011-06-10 22:46:40 -0700191 static void preload() {
Bill Yi9a76e9b2014-04-29 18:52:48 -0700192 Log.d(TAG, "begin preload");
Neil Fuller4f41f612016-05-09 16:55:36 +0100193 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "BeginIcuCachePinning");
194 beginIcuCachePinning();
195 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900196 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadClasses");
197 preloadClasses();
198 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
199 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadResources");
200 preloadResources();
201 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
Jesse Halle8ce1272017-01-17 12:34:14 -0800202 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadOpenGL");
203 preloadOpenGL();
204 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
Brian Carlstrom6c9af962014-09-11 15:36:00 -0700205 preloadSharedLibraries();
Raph Levienc3dd1c12015-04-06 10:37:57 -0700206 preloadTextResources();
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100207 // Ask the WebViewFactory to do any initialization that must run in the zygote process,
208 // for memory sharing purposes.
209 WebViewFactory.prepareWebViewInZygote();
Neil Fuller4f41f612016-05-09 16:55:36 +0100210 endIcuCachePinning();
Sergio Giro6cb7b1c2016-05-13 16:34:46 +0100211 warmUpJcaProviders();
Bill Yi9a76e9b2014-04-29 18:52:48 -0700212 Log.d(TAG, "end preload");
Romain Guy74c69122013-05-08 17:54:20 -0700213 }
214
Neil Fuller4f41f612016-05-09 16:55:36 +0100215 private static void beginIcuCachePinning() {
216 // Pin ICU data in memory from this point that would normally be held by soft references.
217 // Without this, any references created immediately below or during class preloading
218 // would be collected when the Zygote GC runs in gcAndFinalize().
219 Log.i(TAG, "Installing ICU cache reference pinning...");
220
221 CacheValue.setStrength(CacheValue.Strength.STRONG);
222
223 Log.i(TAG, "Preloading ICU data...");
224 // Explicitly exercise code to cache data apps are likely to need.
225 ULocale[] localesToPin = { ULocale.ROOT, ULocale.US, ULocale.getDefault() };
226 for (ULocale uLocale : localesToPin) {
227 new DecimalFormatSymbols(uLocale);
228 }
229 }
230
231 private static void endIcuCachePinning() {
232 // All cache references created by ICU from this point will be soft.
233 CacheValue.setStrength(CacheValue.Strength.SOFT);
234
235 Log.i(TAG, "Uninstalled ICU cache reference pinning...");
236 }
237
Brian Carlstrom6c9af962014-09-11 15:36:00 -0700238 private static void preloadSharedLibraries() {
239 Log.i(TAG, "Preloading shared libraries...");
240 System.loadLibrary("android");
241 System.loadLibrary("compiler_rt");
242 System.loadLibrary("jnigraphics");
243 }
244
Jesse Halle8ce1272017-01-17 12:34:14 -0800245 private static void preloadOpenGL() {
246 if (!SystemProperties.getBoolean(PROPERTY_DISABLE_OPENGL_PRELOADING, false)) {
247 EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
248 }
249 }
250
Raph Levienc3dd1c12015-04-06 10:37:57 -0700251 private static void preloadTextResources() {
252 Hyphenator.init();
Andreas Gampeddc13972016-02-26 16:54:59 -0800253 TextView.preloadFontCache();
Raph Levienc3dd1c12015-04-06 10:37:57 -0700254 }
255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256 /**
Sergio Giro69de3202016-05-17 16:52:33 +0100257 * Register AndroidKeyStoreProvider and warm up the providers that are already registered.
Sergio Giro6cb7b1c2016-05-13 16:34:46 +0100258 *
259 * By doing it here we avoid that each app does it when requesting a service from the
260 * provider for the first time.
261 */
262 private static void warmUpJcaProviders() {
263 long startTime = SystemClock.uptimeMillis();
264 Trace.traceBegin(
Sergio Giro69de3202016-05-17 16:52:33 +0100265 Trace.TRACE_TAG_DALVIK, "Starting installation of AndroidKeyStoreProvider");
266 // AndroidKeyStoreProvider.install() manipulates the list of JCA providers to insert
267 // preferred providers. Note this is not done via security.properties as the JCA providers
268 // are not on the classpath in the case of, for example, raw dalvikvm runtimes.
269 AndroidKeyStoreProvider.install();
270 Log.i(TAG, "Installed AndroidKeyStoreProvider in "
271 + (SystemClock.uptimeMillis() - startTime) + "ms.");
272 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
273
274 startTime = SystemClock.uptimeMillis();
275 Trace.traceBegin(
Sergio Giro6cb7b1c2016-05-13 16:34:46 +0100276 Trace.TRACE_TAG_DALVIK, "Starting warm up of JCA providers");
277 for (Provider p : Security.getProviders()) {
278 p.warmUpServiceProvision();
279 }
280 Log.i(TAG, "Warmed up JCA providers in "
Sergio Giro69de3202016-05-17 16:52:33 +0100281 + (SystemClock.uptimeMillis() - startTime) + "ms.");
Sergio Giro6cb7b1c2016-05-13 16:34:46 +0100282 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
283 }
284
285 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286 * Performs Zygote process initialization. Loads and initializes
287 * commonly used classes.
288 *
289 * Most classes only cause a few hundred bytes to be allocated, but
290 * a few will allocate a dozen Kbytes (in one case, 500+K).
291 */
292 private static void preloadClasses() {
293 final VMRuntime runtime = VMRuntime.getRuntime();
Bob Leee5408332009-09-04 18:31:17 -0700294
Ying Wangd0c45352014-11-13 15:22:47 -0800295 InputStream is;
296 try {
297 is = new FileInputStream(PRELOADED_CLASSES);
298 } catch (FileNotFoundException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299 Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");
Ying Wangd0c45352014-11-13 15:22:47 -0800300 return;
301 }
Bob Leee5408332009-09-04 18:31:17 -0700302
Ying Wangd0c45352014-11-13 15:22:47 -0800303 Log.i(TAG, "Preloading classes...");
304 long startTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800305
Ying Wangd0c45352014-11-13 15:22:47 -0800306 // Drop root perms while running static initializers.
Narayan Kamath23e68782015-01-16 17:22:41 +0000307 final int reuid = Os.getuid();
308 final int regid = Os.getgid();
309
310 // We need to drop root perms only if we're already root. In the case of "wrapped"
311 // processes (see WrapperInit), this function is called from an unprivileged uid
312 // and gid.
313 boolean droppedPriviliges = false;
314 if (reuid == ROOT_UID && regid == ROOT_GID) {
315 try {
316 Os.setregid(ROOT_GID, UNPRIVILEGED_GID);
317 Os.setreuid(ROOT_UID, UNPRIVILEGED_UID);
318 } catch (ErrnoException ex) {
319 throw new RuntimeException("Failed to drop root", ex);
320 }
321
322 droppedPriviliges = true;
Elliott Hughes26b56e62014-12-17 12:28:29 -0800323 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800324
Ying Wangd0c45352014-11-13 15:22:47 -0800325 // Alter the target heap utilization. With explicit GCs this
326 // is not likely to have any effect.
327 float defaultUtilization = runtime.getTargetHeapUtilization();
328 runtime.setTargetHeapUtilization(0.8f);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800329
Ying Wangd0c45352014-11-13 15:22:47 -0800330 try {
331 BufferedReader br
332 = new BufferedReader(new InputStreamReader(is), 256);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800333
Ying Wangd0c45352014-11-13 15:22:47 -0800334 int count = 0;
335 String line;
336 while ((line = br.readLine()) != null) {
337 // Skip comments and blank lines.
338 line = line.trim();
339 if (line.startsWith("#") || line.equals("")) {
340 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341 }
342
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900343 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadClass " + line);
Ying Wangd0c45352014-11-13 15:22:47 -0800344 try {
345 if (false) {
346 Log.v(TAG, "Preloading " + line + "...");
347 }
Andreas Gampedd8e5fb2015-04-21 09:01:51 -0700348 // Load and explicitly initialize the given class. Use
349 // Class.forName(String, boolean, ClassLoader) to avoid repeated stack lookups
350 // (to derive the caller's class-loader). Use true to force initialization, and
351 // null for the boot classpath class-loader (could as well cache the
352 // class-loader of this class in a variable).
Andreas Gampec917f742015-04-20 19:16:37 -0700353 Class.forName(line, true, null);
Ying Wangd0c45352014-11-13 15:22:47 -0800354 count++;
355 } catch (ClassNotFoundException e) {
356 Log.w(TAG, "Class not found for preloading: " + line);
357 } catch (UnsatisfiedLinkError e) {
358 Log.w(TAG, "Problem preloading " + line + ": " + e);
359 } catch (Throwable t) {
360 Log.e(TAG, "Error preloading " + line + ".", t);
361 if (t instanceof Error) {
362 throw (Error) t;
363 }
364 if (t instanceof RuntimeException) {
365 throw (RuntimeException) t;
366 }
367 throw new RuntimeException(t);
368 }
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900369 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370 }
Ying Wangd0c45352014-11-13 15:22:47 -0800371
372 Log.i(TAG, "...preloaded " + count + " classes in "
373 + (SystemClock.uptimeMillis()-startTime) + "ms.");
374 } catch (IOException e) {
375 Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
376 } finally {
377 IoUtils.closeQuietly(is);
378 // Restore default.
379 runtime.setTargetHeapUtilization(defaultUtilization);
380
381 // Fill in dex caches with classes, fields, and methods brought in by preloading.
Yasuhiro Matsuda1ab43d52015-06-30 17:07:32 +0900382 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadDexCaches");
Ying Wangd0c45352014-11-13 15:22:47 -0800383 runtime.preloadDexCaches();
Yasuhiro Matsuda1ab43d52015-06-30 17:07:32 +0900384 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
Ying Wangd0c45352014-11-13 15:22:47 -0800385
Narayan Kamath23e68782015-01-16 17:22:41 +0000386 // Bring back root. We'll need it later if we're in the zygote.
387 if (droppedPriviliges) {
388 try {
389 Os.setreuid(ROOT_UID, ROOT_UID);
390 Os.setregid(ROOT_GID, ROOT_GID);
391 } catch (ErrnoException ex) {
392 throw new RuntimeException("Failed to restore root", ex);
393 }
Elliott Hughes26b56e62014-12-17 12:28:29 -0800394 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800395 }
396 }
397
398 /**
399 * Load in commonly used resources, so they can be shared across
400 * processes.
401 *
402 * These tend to be a few Kbytes, but are frequently in the 20-40K
403 * range, and occasionally even larger.
404 */
405 private static void preloadResources() {
406 final VMRuntime runtime = VMRuntime.getRuntime();
Bob Leee5408332009-09-04 18:31:17 -0700407
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800408 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800409 mResources = Resources.getSystem();
410 mResources.startPreloading();
411 if (PRELOAD_RESOURCES) {
412 Log.i(TAG, "Preloading resources...");
413
414 long startTime = SystemClock.uptimeMillis();
415 TypedArray ar = mResources.obtainTypedArray(
416 com.android.internal.R.array.preloaded_drawables);
Filip Gruszczynski811dc3b2015-11-23 12:34:22 -0800417 int N = preloadDrawables(ar);
Jeff Brown14577c42012-03-08 16:40:14 -0800418 ar.recycle();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800419 Log.i(TAG, "...preloaded " + N + " resources in "
420 + (SystemClock.uptimeMillis()-startTime) + "ms.");
421
422 startTime = SystemClock.uptimeMillis();
423 ar = mResources.obtainTypedArray(
424 com.android.internal.R.array.preloaded_color_state_lists);
Filip Gruszczynski811dc3b2015-11-23 12:34:22 -0800425 N = preloadColorStateLists(ar);
Jeff Brown14577c42012-03-08 16:40:14 -0800426 ar.recycle();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800427 Log.i(TAG, "...preloaded " + N + " resources in "
428 + (SystemClock.uptimeMillis()-startTime) + "ms.");
Filip Gruszczynski811dc3b2015-11-23 12:34:22 -0800429
430 if (mResources.getBoolean(
431 com.android.internal.R.bool.config_freeformWindowManagement)) {
432 startTime = SystemClock.uptimeMillis();
433 ar = mResources.obtainTypedArray(
434 com.android.internal.R.array.preloaded_freeform_multi_window_drawables);
435 N = preloadDrawables(ar);
436 ar.recycle();
437 Log.i(TAG, "...preloaded " + N + " resource in "
438 + (SystemClock.uptimeMillis() - startTime) + "ms.");
439 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440 }
441 mResources.finishPreloading();
442 } catch (RuntimeException e) {
443 Log.w(TAG, "Failure preloading resources", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800444 }
445 }
446
Filip Gruszczynski811dc3b2015-11-23 12:34:22 -0800447 private static int preloadColorStateLists(TypedArray ar) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800448 int N = ar.length();
449 for (int i=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800450 int id = ar.getResourceId(i, 0);
Joe Onorato43a17652011-04-06 19:22:23 -0700451 if (false) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800452 Log.v(TAG, "Preloading resource #" + Integer.toHexString(id));
453 }
454 if (id != 0) {
Alan Viverette77bb6f12015-02-11 17:24:33 -0800455 if (mResources.getColorStateList(id, null) == null) {
Dianne Hackborndde331c2012-08-03 14:01:57 -0700456 throw new IllegalArgumentException(
457 "Unable to find preloaded color resource #0x"
458 + Integer.toHexString(id)
459 + " (" + ar.getString(i) + ")");
460 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800461 }
462 }
463 return N;
464 }
465
466
Filip Gruszczynski811dc3b2015-11-23 12:34:22 -0800467 private static int preloadDrawables(TypedArray ar) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800468 int N = ar.length();
469 for (int i=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800470 int id = ar.getResourceId(i, 0);
Joe Onorato43a17652011-04-06 19:22:23 -0700471 if (false) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800472 Log.v(TAG, "Preloading resource #" + Integer.toHexString(id));
473 }
474 if (id != 0) {
Alan Viverette84e001a2014-09-22 00:04:22 -0700475 if (mResources.getDrawable(id, null) == null) {
Dianne Hackborndde331c2012-08-03 14:01:57 -0700476 throw new IllegalArgumentException(
477 "Unable to find preloaded drawable resource #0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800478 + Integer.toHexString(id)
Dianne Hackborndde331c2012-08-03 14:01:57 -0700479 + " (" + ar.getString(i) + ")");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800480 }
481 }
482 }
483 return N;
484 }
485
486 /**
487 * Runs several special GCs to try to clean up a few generations of
488 * softly- and final-reachable objects, along with any other garbage.
489 * This is only useful just before a fork().
490 */
Mathieu Chartier9a88f102014-08-20 10:24:11 -0700491 /*package*/ static void gcAndFinalize() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800492 final VMRuntime runtime = VMRuntime.getRuntime();
493
494 /* runFinalizationSync() lets finalizers be called in Zygote,
495 * which doesn't have a HeapWorker thread.
496 */
Brian Carlstrom08065b92011-04-01 15:49:41 -0700497 System.gc();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800498 runtime.runFinalizationSync();
Brian Carlstrom08065b92011-04-01 15:49:41 -0700499 System.gc();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800500 }
501
502 /**
503 * Finish remaining work for the newly forked system server process.
504 */
505 private static void handleSystemServerProcess(
506 ZygoteConnection.Arguments parsedArgs)
507 throws ZygoteInit.MethodAndArgsCaller {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800508
509 closeServerSocket();
510
Mike Lockwood90960e82010-08-06 09:15:25 -0400511 // set umask to 0077 so new files and directories will default to owner-only permissions.
Elliott Hughes860c5912014-04-28 19:19:13 -0700512 Os.umask(S_IRWXG | S_IRWXO);
Mike Lockwood90960e82010-08-06 09:15:25 -0400513
Jeff Brownebed7d62011-05-16 17:08:42 -0700514 if (parsedArgs.niceName != null) {
515 Process.setArgV0(parsedArgs.niceName);
516 }
517
Narayan Kamath29564cd2014-08-07 10:57:40 +0100518 final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
519 if (systemServerClasspath != null) {
520 performSystemServerDexOpt(systemServerClasspath);
521 }
522
Jeff Brownebed7d62011-05-16 17:08:42 -0700523 if (parsedArgs.invokeWith != null) {
Narayan Kamath29564cd2014-08-07 10:57:40 +0100524 String[] args = parsedArgs.remainingArgs;
525 // If we have a non-null system server class path, we'll have to duplicate the
526 // existing arguments and append the classpath to it. ART will handle the classpath
527 // correctly when we exec a new process.
528 if (systemServerClasspath != null) {
529 String[] amendedArgs = new String[args.length + 2];
530 amendedArgs[0] = "-cp";
531 amendedArgs[1] = systemServerClasspath;
532 System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);
533 }
534
Jeff Brownebed7d62011-05-16 17:08:42 -0700535 WrapperInit.execApplication(parsedArgs.invokeWith,
Elliott Hughese1dfcb72011-07-08 11:08:07 -0700536 parsedArgs.niceName, parsedArgs.targetSdkVersion,
Narayan Kamath37ad4b02015-01-19 16:05:24 +0000537 VMRuntime.getCurrentInstructionSet(), null, args);
Jeff Brownebed7d62011-05-16 17:08:42 -0700538 } else {
Narayan Kamath29564cd2014-08-07 10:57:40 +0100539 ClassLoader cl = null;
540 if (systemServerClasspath != null) {
Dimitry Ivanov89dad332016-04-20 16:02:00 -0700541 cl = createSystemServerClassLoader(systemServerClasspath,
542 parsedArgs.targetSdkVersion);
543
Narayan Kamath29564cd2014-08-07 10:57:40 +0100544 Thread.currentThread().setContextClassLoader(cl);
545 }
546
Jeff Brownebed7d62011-05-16 17:08:42 -0700547 /*
548 * Pass the remaining arguments to SystemServer.
549 */
Narayan Kamath29564cd2014-08-07 10:57:40 +0100550 RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
Jeff Brownebed7d62011-05-16 17:08:42 -0700551 }
552
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800553 /* should never reach here */
554 }
555
556 /**
Dimitry Ivanov89dad332016-04-20 16:02:00 -0700557 * Creates a PathClassLoader for the system server. It also creates
558 * a shared namespace associated with the classloader to let it access
559 * platform-private native libraries.
560 */
561 private static PathClassLoader createSystemServerClassLoader(String systemServerClasspath,
562 int targetSdkVersion) {
563 String librarySearchPath = System.getProperty("java.library.path");
564
565 return PathClassLoaderFactory.createClassLoader(systemServerClasspath,
566 librarySearchPath,
567 null /* libraryPermittedPath */,
568 ClassLoader.getSystemClassLoader(),
569 targetSdkVersion,
570 true /* isNamespaceShared */);
571 }
572
573 /**
Narayan Kamath29564cd2014-08-07 10:57:40 +0100574 * Performs dex-opt on the elements of {@code classPath}, if needed. We
575 * choose the instruction set of the current runtime.
576 */
577 private static void performSystemServerDexOpt(String classPath) {
578 final String[] classPathElements = classPath.split(":");
579 final InstallerConnection installer = new InstallerConnection();
Makoto Onukic8a2cfe2015-06-23 16:33:48 -0700580 installer.waitForConnection();
Narayan Kamath29564cd2014-08-07 10:57:40 +0100581 final String instructionSet = VMRuntime.getRuntime().vmInstructionSet();
582
583 try {
Jeff Haoc7b94822016-03-16 15:56:07 -0700584 String sharedLibraries = "";
Narayan Kamath29564cd2014-08-07 10:57:40 +0100585 for (String classPathElement : classPathElements) {
Calin Juravle693f9972016-02-25 15:26:20 +0000586 // System server is fully AOTed and never profiled
587 // for profile guided compilation.
Andreas Gampebdd30d82016-03-20 11:32:11 -0700588 // TODO: Make this configurable between INTERPRET_ONLY, SPEED, SPACE and EVERYTHING?
Andreas Gampee7bc1522016-08-09 20:44:04 -0700589
590 int dexoptNeeded;
591 try {
592 dexoptNeeded = DexFile.getDexOptNeeded(
Andreas Gampebdd30d82016-03-20 11:32:11 -0700593 classPathElement, instructionSet, "speed",
594 false /* newProfile */);
Andreas Gampee7bc1522016-08-09 20:44:04 -0700595 } catch (FileNotFoundException ignored) {
596 // Do not add to the classpath.
597 Log.w(TAG, "Missing classpath element for system server: " + classPathElement);
598 continue;
599 } catch (IOException e) {
600 // Not fully clear what to do here as we don't know the cause of the
601 // IO exception. Add to the classpath to be conservative, but don't
602 // attempt to compile it.
603 Log.w(TAG, "Error checking classpath element for system server: "
604 + classPathElement, e);
605 dexoptNeeded = DexFile.NO_DEXOPT_NEEDED;
Narayan Kamath29564cd2014-08-07 10:57:40 +0100606 }
Andreas Gampee7bc1522016-08-09 20:44:04 -0700607
608 if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
609 try {
610 installer.dexopt(classPathElement, Process.SYSTEM_UID, instructionSet,
611 dexoptNeeded, 0 /*dexFlags*/, "speed", null /*volumeUuid*/,
612 sharedLibraries);
613 } catch (InstallerException e) {
614 // Ignore (but log), we need this on the classpath for fallback mode.
615 Log.w(TAG, "Failed compiling classpath element for system server: "
616 + classPathElement, e);
617 }
618 }
619
Jeff Haoc7b94822016-03-16 15:56:07 -0700620 if (!sharedLibraries.isEmpty()) {
621 sharedLibraries += ":";
622 }
623 sharedLibraries += classPathElement;
Narayan Kamath29564cd2014-08-07 10:57:40 +0100624 }
Narayan Kamath29564cd2014-08-07 10:57:40 +0100625 } finally {
626 installer.disconnect();
627 }
628 }
629
630 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800631 * Prepare the arguments and fork for the system server process.
632 */
Narayan Kamath64cd9072014-05-13 13:35:14 +0100633 private static boolean startSystemServer(String abiList, String socketName)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800634 throws MethodAndArgsCaller, RuntimeException {
Alex Klyubin48a06e72013-04-19 10:01:42 -0700635 long capabilities = posixCapabilitiesAsBits(
Philip Cuadra7bd0fdd2016-04-28 15:26:49 -0700636 OsConstants.CAP_IPC_LOCK,
Alex Klyubin48a06e72013-04-19 10:01:42 -0700637 OsConstants.CAP_KILL,
638 OsConstants.CAP_NET_ADMIN,
639 OsConstants.CAP_NET_BIND_SERVICE,
640 OsConstants.CAP_NET_BROADCAST,
641 OsConstants.CAP_NET_RAW,
Alex Klyubin48a06e72013-04-19 10:01:42 -0700642 OsConstants.CAP_SYS_MODULE,
643 OsConstants.CAP_SYS_NICE,
644 OsConstants.CAP_SYS_RESOURCE,
645 OsConstants.CAP_SYS_TIME,
646 OsConstants.CAP_SYS_TTY_CONFIG
647 );
Luis Hector Chavez5dd239a2015-10-06 14:01:45 -0700648 /* Containers run without this capability, so avoid setting it in that case */
649 if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {
650 capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND);
651 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800652 /* Hardcoded command line to start the system server */
653 String args[] = {
654 "--setuid=1000",
655 "--setgid=1000",
Pavlin Radoslavov70166252015-11-23 17:13:25 -0800656 "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007,3009,3010",
Alex Klyubin48a06e72013-04-19 10:01:42 -0700657 "--capabilities=" + capabilities + "," + capabilities,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800658 "--nice-name=system_server",
Narayan Kamathb6b044a2015-02-13 17:31:25 +0000659 "--runtime-args",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800660 "com.android.server.SystemServer",
661 };
662 ZygoteConnection.Arguments parsedArgs = null;
663
664 int pid;
665
666 try {
667 parsedArgs = new ZygoteConnection.Arguments(args);
Jeff Brownebed7d62011-05-16 17:08:42 -0700668 ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
669 ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800670
671 /* Request to fork the system server process */
672 pid = Zygote.forkSystemServer(
673 parsedArgs.uid, parsedArgs.gid,
Elliott Hughese1dfcb72011-07-08 11:08:07 -0700674 parsedArgs.gids,
675 parsedArgs.debugFlags,
676 null,
Andy McFadden1b4c7962010-10-27 11:26:05 -0700677 parsedArgs.permittedCapabilities,
678 parsedArgs.effectiveCapabilities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800679 } catch (IllegalArgumentException ex) {
680 throw new RuntimeException(ex);
Bob Leee5408332009-09-04 18:31:17 -0700681 }
682
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800683 /* For child process */
684 if (pid == 0) {
Narayan Kamath64cd9072014-05-13 13:35:14 +0100685 if (hasSecondZygote(abiList)) {
686 waitForSecondaryZygote(socketName);
687 }
688
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800689 handleSystemServerProcess(parsedArgs);
690 }
691
692 return true;
693 }
694
Alex Klyubin48a06e72013-04-19 10:01:42 -0700695 /**
696 * Gets the bit array representation of the provided list of POSIX capabilities.
697 */
698 private static long posixCapabilitiesAsBits(int... capabilities) {
699 long result = 0;
700 for (int capability : capabilities) {
701 if ((capability < 0) || (capability > OsConstants.CAP_LAST_CAP)) {
702 throw new IllegalArgumentException(String.valueOf(capability));
703 }
704 result |= (1L << capability);
705 }
706 return result;
707 }
708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800709 public static void main(String argv[]) {
Andreas Gampe1ef8aef2016-04-11 08:39:52 -0700710 // Mark zygote start. This ensures that thread creation will throw
711 // an error.
712 ZygoteHooks.startZygoteNoThreadCreation();
713
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800714 try {
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900715 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygoteInit");
716 RuntimeInit.enableDdms();
717 // Start profiling the zygote initialization.
718 SamplingProfilerIntegration.start();
719
Narayan Kamathc41638c2014-04-07 13:56:15 +0100720 boolean startSystemServer = false;
721 String socketName = "zygote";
722 String abiList = null;
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900723 for (int i = 1; i < argv.length; i++) {
724 if ("start-system-server".equals(argv[i])) {
725 startSystemServer = true;
726 } else if (argv[i].startsWith(ABI_LIST_ARG)) {
727 abiList = argv[i].substring(ABI_LIST_ARG.length());
728 } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
729 socketName = argv[i].substring(SOCKET_NAME_ARG.length());
730 } else {
731 throw new RuntimeException("Unknown command line argument: " + argv[i]);
Narayan Kamathc41638c2014-04-07 13:56:15 +0100732 }
733 }
734
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900735 if (abiList == null) {
736 throw new RuntimeException("No ABI list supplied.");
737 }
738
739 registerZygoteSocket(socketName);
740 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygotePreload");
741 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
742 SystemClock.uptimeMillis());
743 preload();
744 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
745 SystemClock.uptimeMillis());
746 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
747
748 // Finish profiling the zygote initialization.
749 SamplingProfilerIntegration.writeZygoteSnapshot();
750
751 // Do an initial gc to clean up after startup
752 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PostZygoteInitGC");
753 gcAndFinalize();
754 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
755
756 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
757
Jamie Gennis6ad04522013-04-15 18:53:24 -0700758 // Disable tracing so that forked processes do not inherit stale tracing tags from
759 // Zygote.
760 Trace.setTracingEnabled(false);
761
doheon1.lee885b7422016-01-20 13:07:27 +0900762 // Zygote process unmounts root storage spaces.
763 Zygote.nativeUnmountStorageOnInit();
764
Andreas Gampe1ef8aef2016-04-11 08:39:52 -0700765 ZygoteHooks.stopZygoteNoThreadCreation();
766
Narayan Kamathc41638c2014-04-07 13:56:15 +0100767 if (startSystemServer) {
Narayan Kamath64cd9072014-05-13 13:35:14 +0100768 startSystemServer(abiList, socketName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800769 }
770
771 Log.i(TAG, "Accepting command socket connections");
Narayan Kamathc41638c2014-04-07 13:56:15 +0100772 runSelectLoop(abiList);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800773
774 closeServerSocket();
775 } catch (MethodAndArgsCaller caller) {
776 caller.run();
Christopher Ferrisea8b5de2016-06-17 15:29:58 -0700777 } catch (Throwable ex) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800778 Log.e(TAG, "Zygote died with exception", ex);
779 closeServerSocket();
780 throw ex;
781 }
782 }
783
784 /**
Narayan Kamath64cd9072014-05-13 13:35:14 +0100785 * Return {@code true} if this device configuration has another zygote.
786 *
787 * We determine this by comparing the device ABI list with this zygotes
788 * list. If this zygote supports all ABIs this device supports, there won't
789 * be another zygote.
790 */
791 private static boolean hasSecondZygote(String abiList) {
792 return !SystemProperties.get("ro.product.cpu.abilist").equals(abiList);
793 }
794
795 private static void waitForSecondaryZygote(String socketName) {
796 String otherZygoteName = Process.ZYGOTE_SOCKET.equals(socketName) ?
797 Process.SECONDARY_ZYGOTE_SOCKET : Process.ZYGOTE_SOCKET;
798 while (true) {
799 try {
800 final Process.ZygoteState zs = Process.ZygoteState.connect(otherZygoteName);
801 zs.close();
802 break;
803 } catch (IOException ioe) {
804 Log.w(TAG, "Got error connecting to zygote, retrying. msg= " + ioe.getMessage());
805 }
806
807 try {
808 Thread.sleep(1000);
809 } catch (InterruptedException ie) {
810 }
811 }
812 }
813
814 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800815 * Runs the zygote process's select loop. Accepts new connections as
816 * they happen, and reads commands from connections one spawn-request's
817 * worth at a time.
818 *
819 * @throws MethodAndArgsCaller in a child process when a main() should
820 * be executed.
821 */
Narayan Kamathc41638c2014-04-07 13:56:15 +0100822 private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
Nick Kralevichcae3d9f2013-01-30 09:51:40 -0800823 ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
824 ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800825
826 fds.add(sServerSocket.getFileDescriptor());
827 peers.add(null);
828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829 while (true) {
Elliott Hughes894724b2014-12-15 12:39:51 -0800830 StructPollfd[] pollFds = new StructPollfd[fds.size()];
831 for (int i = 0; i < pollFds.length; ++i) {
832 pollFds[i] = new StructPollfd();
833 pollFds[i].fd = fds.get(i);
834 pollFds[i].events = (short) POLLIN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800835 }
Elliott Hughes894724b2014-12-15 12:39:51 -0800836 try {
837 Os.poll(pollFds, -1);
838 } catch (ErrnoException ex) {
839 throw new RuntimeException("poll failed", ex);
840 }
841 for (int i = pollFds.length - 1; i >= 0; --i) {
842 if ((pollFds[i].revents & POLLIN) == 0) {
843 continue;
844 }
845 if (i == 0) {
846 ZygoteConnection newPeer = acceptCommandPeer(abiList);
847 peers.add(newPeer);
848 fds.add(newPeer.getFileDesciptor());
849 } else {
850 boolean done = peers.get(i).runOnce();
851 if (done) {
852 peers.remove(i);
853 fds.remove(i);
854 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800855 }
856 }
857 }
858 }
859
860 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800861 * Class not instantiable.
862 */
863 private ZygoteInit() {
864 }
865
866 /**
867 * Helper exception class which holds a method and arguments and
868 * can call them. This is used as part of a trampoline to get rid of
869 * the initial process setup stack frames.
870 */
871 public static class MethodAndArgsCaller extends Exception
872 implements Runnable {
873 /** method to call */
874 private final Method mMethod;
875
876 /** argument array */
877 private final String[] mArgs;
878
879 public MethodAndArgsCaller(Method method, String[] args) {
880 mMethod = method;
881 mArgs = args;
882 }
883
884 public void run() {
885 try {
886 mMethod.invoke(null, new Object[] { mArgs });
887 } catch (IllegalAccessException ex) {
888 throw new RuntimeException(ex);
889 } catch (InvocationTargetException ex) {
890 Throwable cause = ex.getCause();
891 if (cause instanceof RuntimeException) {
892 throw (RuntimeException) cause;
893 } else if (cause instanceof Error) {
894 throw (Error) cause;
895 }
896 throw new RuntimeException(ex);
897 }
898 }
899 }
900}