blob: eb509c2632c133aea660ac7b4d672bb40adc0664 [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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import android.net.LocalServerSocket;
Romain Guy74c69122013-05-08 17:54:20 -070026import android.opengl.EGL14;
Jeff Brownebed7d62011-05-16 17:08:42 -070027import android.os.Process;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import android.os.SystemClock;
Romain Guyc5e36382013-05-09 11:08:17 -070029import android.os.SystemProperties;
Jamie Gennis6ad04522013-04-15 18:53:24 -070030import android.os.Trace;
Bill Yi9a76e9b2014-04-29 18:52:48 -070031import android.system.ErrnoException;
Elliott Hughes860c5912014-04-28 19:19:13 -070032import android.system.Os;
33import android.system.OsConstants;
Elliott Hughes894724b2014-12-15 12:39:51 -080034import android.system.StructPollfd;
Raph Levienc3dd1c12015-04-06 10:37:57 -070035import android.text.Hyphenator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.util.EventLog;
37import android.util.Log;
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +010038import android.webkit.WebViewFactory;
Andreas Gampeddc13972016-02-26 16:54:59 -080039import android.widget.TextView;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040
Jeff Sharkeyfdeeeea2016-01-11 17:34:24 -070041import com.android.internal.os.InstallerConnection.InstallerException;
42
Narayan Kamath29564cd2014-08-07 10:57:40 +010043import dalvik.system.DexFile;
44import dalvik.system.PathClassLoader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import dalvik.system.VMRuntime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046
Brian Carlstrom46703b02011-04-06 15:41:29 -070047import libcore.io.IoUtils;
48
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049import java.io.BufferedReader;
50import java.io.FileDescriptor;
Ying Wangd0c45352014-11-13 15:22:47 -080051import java.io.FileInputStream;
52import java.io.FileNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053import java.io.IOException;
54import java.io.InputStream;
55import java.io.InputStreamReader;
56import java.lang.reflect.InvocationTargetException;
57import java.lang.reflect.Method;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058import java.util.ArrayList;
59
60/**
61 * Startup class for the zygote process.
62 *
63 * Pre-initializes some classes, and then waits for commands on a UNIX domain
Elliott Hughese1dfcb72011-07-08 11:08:07 -070064 * socket. Based on these commands, forks off child processes that inherit
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065 * the initial state of the VM.
66 *
67 * Please see {@link ZygoteConnection.Arguments} for documentation on the
68 * client protocol.
69 *
70 * @hide
71 */
72public class ZygoteInit {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073 private static final String TAG = "Zygote";
74
Romain Guyc5e36382013-05-09 11:08:17 -070075 private static final String PROPERTY_DISABLE_OPENGL_PRELOADING = "ro.zygote.disable_gl_preload";
Luis Hector Chavez5dd239a2015-10-06 14:01:45 -070076 private static final String PROPERTY_RUNNING_IN_CONTAINER = "ro.boot.container";
Romain Guyc5e36382013-05-09 11:08:17 -070077
Narayan Kamathc41638c2014-04-07 13:56:15 +010078 private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079
80 private static final int LOG_BOOT_PROGRESS_PRELOAD_START = 3020;
81 private static final int LOG_BOOT_PROGRESS_PRELOAD_END = 3030;
82
83 /** when preloading, GC after allocating this many bytes */
84 private static final int PRELOAD_GC_THRESHOLD = 50000;
85
Narayan Kamathc41638c2014-04-07 13:56:15 +010086 private static final String ABI_LIST_ARG = "--abi-list=";
87
88 private static final String SOCKET_NAME_ARG = "--socket-name=";
Barry Hayes0b3533a2010-01-20 12:46:47 -080089
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090 private static LocalServerSocket sServerSocket;
91
92 /**
93 * Used to pre-load resources. We hold a global reference on it so it
94 * never gets destroyed.
95 */
96 private static Resources mResources;
Bob Leee5408332009-09-04 18:31:17 -070097
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098 /**
Ying Wangd0c45352014-11-13 15:22:47 -080099 * The path of a file that contains classes to preload.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100 */
Ying Wangd0c45352014-11-13 15:22:47 -0800101 private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102
103 /** Controls whether we should preload resources during zygote init. */
Steve Paik3c27a232015-06-10 18:25:44 -0700104 public static final boolean PRELOAD_RESOURCES = true;
Andy McFadden599c9182009-04-08 00:35:56 -0700105
106 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107 * Registers a server socket for zygote command connections
108 *
109 * @throws RuntimeException when open fails
110 */
Narayan Kamathc41638c2014-04-07 13:56:15 +0100111 private static void registerZygoteSocket(String socketName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112 if (sServerSocket == null) {
113 int fileDesc;
Narayan Kamathc41638c2014-04-07 13:56:15 +0100114 final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115 try {
Narayan Kamathc41638c2014-04-07 13:56:15 +0100116 String env = System.getenv(fullSocketName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117 fileDesc = Integer.parseInt(env);
118 } catch (RuntimeException ex) {
Narayan Kamathc41638c2014-04-07 13:56:15 +0100119 throw new RuntimeException(fullSocketName + " unset or invalid", ex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120 }
121
122 try {
Elliott Hughes3fe59512014-12-12 14:07:34 -0800123 FileDescriptor fd = new FileDescriptor();
124 fd.setInt$(fileDesc);
125 sServerSocket = new LocalServerSocket(fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126 } catch (IOException ex) {
127 throw new RuntimeException(
128 "Error binding to local socket '" + fileDesc + "'", ex);
129 }
130 }
131 }
132
133 /**
134 * Waits for and accepts a single command connection. Throws
135 * RuntimeException on failure.
136 */
Narayan Kamathc41638c2014-04-07 13:56:15 +0100137 private static ZygoteConnection acceptCommandPeer(String abiList) {
Bob Leee5408332009-09-04 18:31:17 -0700138 try {
Narayan Kamathc41638c2014-04-07 13:56:15 +0100139 return new ZygoteConnection(sServerSocket.accept(), abiList);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 } catch (IOException ex) {
141 throw new RuntimeException(
142 "IOException during accept()", ex);
143 }
144 }
145
146 /**
147 * Close and clean up zygote sockets. Called on shutdown and on the
148 * child's exit path.
149 */
150 static void closeServerSocket() {
151 try {
152 if (sServerSocket != null) {
Dave Platt02f042d2013-12-12 15:45:49 -0800153 FileDescriptor fd = sServerSocket.getFileDescriptor();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154 sServerSocket.close();
Dave Platt02f042d2013-12-12 15:45:49 -0800155 if (fd != null) {
Bill Yi9a76e9b2014-04-29 18:52:48 -0700156 Os.close(fd);
Dave Platt02f042d2013-12-12 15:45:49 -0800157 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800158 }
159 } catch (IOException ex) {
160 Log.e(TAG, "Zygote: error closing sockets", ex);
Bill Yi9a76e9b2014-04-29 18:52:48 -0700161 } catch (ErrnoException ex) {
Dave Platt02f042d2013-12-12 15:45:49 -0800162 Log.e(TAG, "Zygote: error closing descriptor", ex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163 }
164
165 sServerSocket = null;
166 }
167
Dave Platt89d4c892014-02-05 17:06:42 -0800168 /**
169 * Return the server socket's underlying file descriptor, so that
170 * ZygoteConnection can pass it to the native code for proper
171 * closure after a child process is forked off.
172 */
173
174 static FileDescriptor getServerSocketFileDescriptor() {
175 return sServerSocket.getFileDescriptor();
176 }
177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800178 private static final int UNPRIVILEGED_UID = 9999;
179 private static final int UNPRIVILEGED_GID = 9999;
180
181 private static final int ROOT_UID = 0;
182 private static final int ROOT_GID = 0;
183
Jeff Brown0c2313d2011-06-10 22:46:40 -0700184 static void preload() {
Bill Yi9a76e9b2014-04-29 18:52:48 -0700185 Log.d(TAG, "begin preload");
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900186 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadClasses");
187 preloadClasses();
188 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
189 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadResources");
190 preloadResources();
191 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
192 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadOpenGL");
Romain Guy74c69122013-05-08 17:54:20 -0700193 preloadOpenGL();
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900194 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
Brian Carlstrom6c9af962014-09-11 15:36:00 -0700195 preloadSharedLibraries();
Raph Levienc3dd1c12015-04-06 10:37:57 -0700196 preloadTextResources();
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100197 // Ask the WebViewFactory to do any initialization that must run in the zygote process,
198 // for memory sharing purposes.
199 WebViewFactory.prepareWebViewInZygote();
Bill Yi9a76e9b2014-04-29 18:52:48 -0700200 Log.d(TAG, "end preload");
Romain Guy74c69122013-05-08 17:54:20 -0700201 }
202
Brian Carlstrom6c9af962014-09-11 15:36:00 -0700203 private static void preloadSharedLibraries() {
204 Log.i(TAG, "Preloading shared libraries...");
205 System.loadLibrary("android");
206 System.loadLibrary("compiler_rt");
207 System.loadLibrary("jnigraphics");
208 }
209
Romain Guy74c69122013-05-08 17:54:20 -0700210 private static void preloadOpenGL() {
Romain Guyc5e36382013-05-09 11:08:17 -0700211 if (!SystemProperties.getBoolean(PROPERTY_DISABLE_OPENGL_PRELOADING, false)) {
212 EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
213 }
Jeff Brown0c2313d2011-06-10 22:46:40 -0700214 }
215
Raph Levienc3dd1c12015-04-06 10:37:57 -0700216 private static void preloadTextResources() {
217 Hyphenator.init();
Andreas Gampeddc13972016-02-26 16:54:59 -0800218 TextView.preloadFontCache();
Raph Levienc3dd1c12015-04-06 10:37:57 -0700219 }
220
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221 /**
222 * Performs Zygote process initialization. Loads and initializes
223 * commonly used classes.
224 *
225 * Most classes only cause a few hundred bytes to be allocated, but
226 * a few will allocate a dozen Kbytes (in one case, 500+K).
227 */
228 private static void preloadClasses() {
229 final VMRuntime runtime = VMRuntime.getRuntime();
Bob Leee5408332009-09-04 18:31:17 -0700230
Ying Wangd0c45352014-11-13 15:22:47 -0800231 InputStream is;
232 try {
233 is = new FileInputStream(PRELOADED_CLASSES);
234 } catch (FileNotFoundException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235 Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");
Ying Wangd0c45352014-11-13 15:22:47 -0800236 return;
237 }
Bob Leee5408332009-09-04 18:31:17 -0700238
Ying Wangd0c45352014-11-13 15:22:47 -0800239 Log.i(TAG, "Preloading classes...");
240 long startTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800241
Ying Wangd0c45352014-11-13 15:22:47 -0800242 // Drop root perms while running static initializers.
Narayan Kamath23e68782015-01-16 17:22:41 +0000243 final int reuid = Os.getuid();
244 final int regid = Os.getgid();
245
246 // We need to drop root perms only if we're already root. In the case of "wrapped"
247 // processes (see WrapperInit), this function is called from an unprivileged uid
248 // and gid.
249 boolean droppedPriviliges = false;
250 if (reuid == ROOT_UID && regid == ROOT_GID) {
251 try {
252 Os.setregid(ROOT_GID, UNPRIVILEGED_GID);
253 Os.setreuid(ROOT_UID, UNPRIVILEGED_UID);
254 } catch (ErrnoException ex) {
255 throw new RuntimeException("Failed to drop root", ex);
256 }
257
258 droppedPriviliges = true;
Elliott Hughes26b56e62014-12-17 12:28:29 -0800259 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260
Ying Wangd0c45352014-11-13 15:22:47 -0800261 // Alter the target heap utilization. With explicit GCs this
262 // is not likely to have any effect.
263 float defaultUtilization = runtime.getTargetHeapUtilization();
264 runtime.setTargetHeapUtilization(0.8f);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265
Ying Wangd0c45352014-11-13 15:22:47 -0800266 try {
267 BufferedReader br
268 = new BufferedReader(new InputStreamReader(is), 256);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800269
Ying Wangd0c45352014-11-13 15:22:47 -0800270 int count = 0;
271 String line;
272 while ((line = br.readLine()) != null) {
273 // Skip comments and blank lines.
274 line = line.trim();
275 if (line.startsWith("#") || line.equals("")) {
276 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 }
278
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900279 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadClass " + line);
Ying Wangd0c45352014-11-13 15:22:47 -0800280 try {
281 if (false) {
282 Log.v(TAG, "Preloading " + line + "...");
283 }
Andreas Gampedd8e5fb2015-04-21 09:01:51 -0700284 // Load and explicitly initialize the given class. Use
285 // Class.forName(String, boolean, ClassLoader) to avoid repeated stack lookups
286 // (to derive the caller's class-loader). Use true to force initialization, and
287 // null for the boot classpath class-loader (could as well cache the
288 // class-loader of this class in a variable).
Andreas Gampec917f742015-04-20 19:16:37 -0700289 Class.forName(line, true, null);
Ying Wangd0c45352014-11-13 15:22:47 -0800290 count++;
291 } catch (ClassNotFoundException e) {
292 Log.w(TAG, "Class not found for preloading: " + line);
293 } catch (UnsatisfiedLinkError e) {
294 Log.w(TAG, "Problem preloading " + line + ": " + e);
295 } catch (Throwable t) {
296 Log.e(TAG, "Error preloading " + line + ".", t);
297 if (t instanceof Error) {
298 throw (Error) t;
299 }
300 if (t instanceof RuntimeException) {
301 throw (RuntimeException) t;
302 }
303 throw new RuntimeException(t);
304 }
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900305 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306 }
Ying Wangd0c45352014-11-13 15:22:47 -0800307
308 Log.i(TAG, "...preloaded " + count + " classes in "
309 + (SystemClock.uptimeMillis()-startTime) + "ms.");
310 } catch (IOException e) {
311 Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
312 } finally {
313 IoUtils.closeQuietly(is);
314 // Restore default.
315 runtime.setTargetHeapUtilization(defaultUtilization);
316
317 // Fill in dex caches with classes, fields, and methods brought in by preloading.
Yasuhiro Matsuda1ab43d52015-06-30 17:07:32 +0900318 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadDexCaches");
Ying Wangd0c45352014-11-13 15:22:47 -0800319 runtime.preloadDexCaches();
Yasuhiro Matsuda1ab43d52015-06-30 17:07:32 +0900320 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
Ying Wangd0c45352014-11-13 15:22:47 -0800321
Narayan Kamath23e68782015-01-16 17:22:41 +0000322 // Bring back root. We'll need it later if we're in the zygote.
323 if (droppedPriviliges) {
324 try {
325 Os.setreuid(ROOT_UID, ROOT_UID);
326 Os.setregid(ROOT_GID, ROOT_GID);
327 } catch (ErrnoException ex) {
328 throw new RuntimeException("Failed to restore root", ex);
329 }
Elliott Hughes26b56e62014-12-17 12:28:29 -0800330 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800331 }
332 }
333
334 /**
335 * Load in commonly used resources, so they can be shared across
336 * processes.
337 *
338 * These tend to be a few Kbytes, but are frequently in the 20-40K
339 * range, and occasionally even larger.
340 */
341 private static void preloadResources() {
342 final VMRuntime runtime = VMRuntime.getRuntime();
Bob Leee5408332009-09-04 18:31:17 -0700343
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800344 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800345 mResources = Resources.getSystem();
346 mResources.startPreloading();
347 if (PRELOAD_RESOURCES) {
348 Log.i(TAG, "Preloading resources...");
349
350 long startTime = SystemClock.uptimeMillis();
351 TypedArray ar = mResources.obtainTypedArray(
352 com.android.internal.R.array.preloaded_drawables);
Filip Gruszczynski811dc3b2015-11-23 12:34:22 -0800353 int N = preloadDrawables(ar);
Jeff Brown14577c42012-03-08 16:40:14 -0800354 ar.recycle();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355 Log.i(TAG, "...preloaded " + N + " resources in "
356 + (SystemClock.uptimeMillis()-startTime) + "ms.");
357
358 startTime = SystemClock.uptimeMillis();
359 ar = mResources.obtainTypedArray(
360 com.android.internal.R.array.preloaded_color_state_lists);
Filip Gruszczynski811dc3b2015-11-23 12:34:22 -0800361 N = preloadColorStateLists(ar);
Jeff Brown14577c42012-03-08 16:40:14 -0800362 ar.recycle();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363 Log.i(TAG, "...preloaded " + N + " resources in "
364 + (SystemClock.uptimeMillis()-startTime) + "ms.");
Filip Gruszczynski811dc3b2015-11-23 12:34:22 -0800365
366 if (mResources.getBoolean(
367 com.android.internal.R.bool.config_freeformWindowManagement)) {
368 startTime = SystemClock.uptimeMillis();
369 ar = mResources.obtainTypedArray(
370 com.android.internal.R.array.preloaded_freeform_multi_window_drawables);
371 N = preloadDrawables(ar);
372 ar.recycle();
373 Log.i(TAG, "...preloaded " + N + " resource in "
374 + (SystemClock.uptimeMillis() - startTime) + "ms.");
375 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800376 }
377 mResources.finishPreloading();
378 } catch (RuntimeException e) {
379 Log.w(TAG, "Failure preloading resources", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800380 }
381 }
382
Filip Gruszczynski811dc3b2015-11-23 12:34:22 -0800383 private static int preloadColorStateLists(TypedArray ar) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384 int N = ar.length();
385 for (int i=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386 int id = ar.getResourceId(i, 0);
Joe Onorato43a17652011-04-06 19:22:23 -0700387 if (false) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800388 Log.v(TAG, "Preloading resource #" + Integer.toHexString(id));
389 }
390 if (id != 0) {
Alan Viverette77bb6f12015-02-11 17:24:33 -0800391 if (mResources.getColorStateList(id, null) == null) {
Dianne Hackborndde331c2012-08-03 14:01:57 -0700392 throw new IllegalArgumentException(
393 "Unable to find preloaded color resource #0x"
394 + Integer.toHexString(id)
395 + " (" + ar.getString(i) + ")");
396 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800397 }
398 }
399 return N;
400 }
401
402
Filip Gruszczynski811dc3b2015-11-23 12:34:22 -0800403 private static int preloadDrawables(TypedArray ar) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800404 int N = ar.length();
405 for (int i=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800406 int id = ar.getResourceId(i, 0);
Joe Onorato43a17652011-04-06 19:22:23 -0700407 if (false) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800408 Log.v(TAG, "Preloading resource #" + Integer.toHexString(id));
409 }
410 if (id != 0) {
Alan Viverette84e001a2014-09-22 00:04:22 -0700411 if (mResources.getDrawable(id, null) == null) {
Dianne Hackborndde331c2012-08-03 14:01:57 -0700412 throw new IllegalArgumentException(
413 "Unable to find preloaded drawable resource #0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414 + Integer.toHexString(id)
Dianne Hackborndde331c2012-08-03 14:01:57 -0700415 + " (" + ar.getString(i) + ")");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800416 }
417 }
418 }
419 return N;
420 }
421
422 /**
423 * Runs several special GCs to try to clean up a few generations of
424 * softly- and final-reachable objects, along with any other garbage.
425 * This is only useful just before a fork().
426 */
Mathieu Chartier9a88f102014-08-20 10:24:11 -0700427 /*package*/ static void gcAndFinalize() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800428 final VMRuntime runtime = VMRuntime.getRuntime();
429
430 /* runFinalizationSync() lets finalizers be called in Zygote,
431 * which doesn't have a HeapWorker thread.
432 */
Brian Carlstrom08065b92011-04-01 15:49:41 -0700433 System.gc();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434 runtime.runFinalizationSync();
Brian Carlstrom08065b92011-04-01 15:49:41 -0700435 System.gc();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 }
437
438 /**
439 * Finish remaining work for the newly forked system server process.
440 */
441 private static void handleSystemServerProcess(
442 ZygoteConnection.Arguments parsedArgs)
443 throws ZygoteInit.MethodAndArgsCaller {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800444
445 closeServerSocket();
446
Mike Lockwood90960e82010-08-06 09:15:25 -0400447 // set umask to 0077 so new files and directories will default to owner-only permissions.
Elliott Hughes860c5912014-04-28 19:19:13 -0700448 Os.umask(S_IRWXG | S_IRWXO);
Mike Lockwood90960e82010-08-06 09:15:25 -0400449
Jeff Brownebed7d62011-05-16 17:08:42 -0700450 if (parsedArgs.niceName != null) {
451 Process.setArgV0(parsedArgs.niceName);
452 }
453
Narayan Kamath29564cd2014-08-07 10:57:40 +0100454 final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
455 if (systemServerClasspath != null) {
456 performSystemServerDexOpt(systemServerClasspath);
457 }
458
Jeff Brownebed7d62011-05-16 17:08:42 -0700459 if (parsedArgs.invokeWith != null) {
Narayan Kamath29564cd2014-08-07 10:57:40 +0100460 String[] args = parsedArgs.remainingArgs;
461 // If we have a non-null system server class path, we'll have to duplicate the
462 // existing arguments and append the classpath to it. ART will handle the classpath
463 // correctly when we exec a new process.
464 if (systemServerClasspath != null) {
465 String[] amendedArgs = new String[args.length + 2];
466 amendedArgs[0] = "-cp";
467 amendedArgs[1] = systemServerClasspath;
468 System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);
469 }
470
Jeff Brownebed7d62011-05-16 17:08:42 -0700471 WrapperInit.execApplication(parsedArgs.invokeWith,
Elliott Hughese1dfcb72011-07-08 11:08:07 -0700472 parsedArgs.niceName, parsedArgs.targetSdkVersion,
Narayan Kamath37ad4b02015-01-19 16:05:24 +0000473 VMRuntime.getCurrentInstructionSet(), null, args);
Jeff Brownebed7d62011-05-16 17:08:42 -0700474 } else {
Narayan Kamath29564cd2014-08-07 10:57:40 +0100475 ClassLoader cl = null;
476 if (systemServerClasspath != null) {
477 cl = new PathClassLoader(systemServerClasspath, ClassLoader.getSystemClassLoader());
478 Thread.currentThread().setContextClassLoader(cl);
479 }
480
Jeff Brownebed7d62011-05-16 17:08:42 -0700481 /*
482 * Pass the remaining arguments to SystemServer.
483 */
Narayan Kamath29564cd2014-08-07 10:57:40 +0100484 RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
Jeff Brownebed7d62011-05-16 17:08:42 -0700485 }
486
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800487 /* should never reach here */
488 }
489
490 /**
Narayan Kamath29564cd2014-08-07 10:57:40 +0100491 * Performs dex-opt on the elements of {@code classPath}, if needed. We
492 * choose the instruction set of the current runtime.
493 */
494 private static void performSystemServerDexOpt(String classPath) {
495 final String[] classPathElements = classPath.split(":");
496 final InstallerConnection installer = new InstallerConnection();
Makoto Onukic8a2cfe2015-06-23 16:33:48 -0700497 installer.waitForConnection();
Narayan Kamath29564cd2014-08-07 10:57:40 +0100498 final String instructionSet = VMRuntime.getRuntime().vmInstructionSet();
499
500 try {
501 for (String classPathElement : classPathElements) {
Richard Uhler7b08b352015-03-25 16:25:57 -0700502 final int dexoptNeeded = DexFile.getDexOptNeeded(
503 classPathElement, "*", instructionSet, false /* defer */);
504 if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
Calin Juravledb4a79a2015-12-23 18:55:08 +0200505 // System server is fully AOTed and never profiled
506 // for profile guided compilation.
Todd Kennedyfa54ab72015-09-25 07:46:12 -0700507 installer.dexopt(classPathElement, Process.SYSTEM_UID, instructionSet,
Calin Juravledb4a79a2015-12-23 18:55:08 +0200508 dexoptNeeded, 0 /*dexFlags*/, null /*volumeUuid*/,
509 false /*useProfiles*/);
Narayan Kamath29564cd2014-08-07 10:57:40 +0100510 }
511 }
Jeff Sharkeyfdeeeea2016-01-11 17:34:24 -0700512 } catch (IOException | InstallerException e) {
513 throw new RuntimeException("Error starting system_server", e);
Narayan Kamath29564cd2014-08-07 10:57:40 +0100514 } finally {
515 installer.disconnect();
516 }
517 }
518
519 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800520 * Prepare the arguments and fork for the system server process.
521 */
Narayan Kamath64cd9072014-05-13 13:35:14 +0100522 private static boolean startSystemServer(String abiList, String socketName)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800523 throws MethodAndArgsCaller, RuntimeException {
Alex Klyubin48a06e72013-04-19 10:01:42 -0700524 long capabilities = posixCapabilitiesAsBits(
525 OsConstants.CAP_KILL,
526 OsConstants.CAP_NET_ADMIN,
527 OsConstants.CAP_NET_BIND_SERVICE,
528 OsConstants.CAP_NET_BROADCAST,
529 OsConstants.CAP_NET_RAW,
Alex Klyubin48a06e72013-04-19 10:01:42 -0700530 OsConstants.CAP_SYS_MODULE,
531 OsConstants.CAP_SYS_NICE,
532 OsConstants.CAP_SYS_RESOURCE,
533 OsConstants.CAP_SYS_TIME,
534 OsConstants.CAP_SYS_TTY_CONFIG
535 );
Luis Hector Chavez5dd239a2015-10-06 14:01:45 -0700536 /* Containers run without this capability, so avoid setting it in that case */
537 if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {
538 capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND);
539 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800540 /* Hardcoded command line to start the system server */
541 String args[] = {
542 "--setuid=1000",
543 "--setgid=1000",
Pavlin Radoslavov70166252015-11-23 17:13:25 -0800544 "--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 -0700545 "--capabilities=" + capabilities + "," + capabilities,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800546 "--nice-name=system_server",
Narayan Kamathb6b044a2015-02-13 17:31:25 +0000547 "--runtime-args",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800548 "com.android.server.SystemServer",
549 };
550 ZygoteConnection.Arguments parsedArgs = null;
551
552 int pid;
553
554 try {
555 parsedArgs = new ZygoteConnection.Arguments(args);
Jeff Brownebed7d62011-05-16 17:08:42 -0700556 ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
557 ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800558
559 /* Request to fork the system server process */
560 pid = Zygote.forkSystemServer(
561 parsedArgs.uid, parsedArgs.gid,
Elliott Hughese1dfcb72011-07-08 11:08:07 -0700562 parsedArgs.gids,
563 parsedArgs.debugFlags,
564 null,
Andy McFadden1b4c7962010-10-27 11:26:05 -0700565 parsedArgs.permittedCapabilities,
566 parsedArgs.effectiveCapabilities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800567 } catch (IllegalArgumentException ex) {
568 throw new RuntimeException(ex);
Bob Leee5408332009-09-04 18:31:17 -0700569 }
570
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800571 /* For child process */
572 if (pid == 0) {
Narayan Kamath64cd9072014-05-13 13:35:14 +0100573 if (hasSecondZygote(abiList)) {
574 waitForSecondaryZygote(socketName);
575 }
576
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800577 handleSystemServerProcess(parsedArgs);
578 }
579
580 return true;
581 }
582
Alex Klyubin48a06e72013-04-19 10:01:42 -0700583 /**
584 * Gets the bit array representation of the provided list of POSIX capabilities.
585 */
586 private static long posixCapabilitiesAsBits(int... capabilities) {
587 long result = 0;
588 for (int capability : capabilities) {
589 if ((capability < 0) || (capability > OsConstants.CAP_LAST_CAP)) {
590 throw new IllegalArgumentException(String.valueOf(capability));
591 }
592 result |= (1L << capability);
593 }
594 return result;
595 }
596
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800597 public static void main(String argv[]) {
598 try {
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900599 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygoteInit");
600 RuntimeInit.enableDdms();
601 // Start profiling the zygote initialization.
602 SamplingProfilerIntegration.start();
603
Narayan Kamathc41638c2014-04-07 13:56:15 +0100604 boolean startSystemServer = false;
605 String socketName = "zygote";
606 String abiList = null;
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900607 for (int i = 1; i < argv.length; i++) {
608 if ("start-system-server".equals(argv[i])) {
609 startSystemServer = true;
610 } else if (argv[i].startsWith(ABI_LIST_ARG)) {
611 abiList = argv[i].substring(ABI_LIST_ARG.length());
612 } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
613 socketName = argv[i].substring(SOCKET_NAME_ARG.length());
614 } else {
615 throw new RuntimeException("Unknown command line argument: " + argv[i]);
Narayan Kamathc41638c2014-04-07 13:56:15 +0100616 }
617 }
618
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900619 if (abiList == null) {
620 throw new RuntimeException("No ABI list supplied.");
621 }
622
623 registerZygoteSocket(socketName);
624 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygotePreload");
625 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
626 SystemClock.uptimeMillis());
627 preload();
628 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
629 SystemClock.uptimeMillis());
630 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
631
632 // Finish profiling the zygote initialization.
633 SamplingProfilerIntegration.writeZygoteSnapshot();
634
635 // Do an initial gc to clean up after startup
636 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PostZygoteInitGC");
637 gcAndFinalize();
638 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
639
640 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
641
Jamie Gennis6ad04522013-04-15 18:53:24 -0700642 // Disable tracing so that forked processes do not inherit stale tracing tags from
643 // Zygote.
644 Trace.setTracingEnabled(false);
645
Narayan Kamathc41638c2014-04-07 13:56:15 +0100646 if (startSystemServer) {
Narayan Kamath64cd9072014-05-13 13:35:14 +0100647 startSystemServer(abiList, socketName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800648 }
649
650 Log.i(TAG, "Accepting command socket connections");
Narayan Kamathc41638c2014-04-07 13:56:15 +0100651 runSelectLoop(abiList);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800652
653 closeServerSocket();
654 } catch (MethodAndArgsCaller caller) {
655 caller.run();
656 } catch (RuntimeException ex) {
657 Log.e(TAG, "Zygote died with exception", ex);
658 closeServerSocket();
659 throw ex;
660 }
661 }
662
663 /**
Narayan Kamath64cd9072014-05-13 13:35:14 +0100664 * Return {@code true} if this device configuration has another zygote.
665 *
666 * We determine this by comparing the device ABI list with this zygotes
667 * list. If this zygote supports all ABIs this device supports, there won't
668 * be another zygote.
669 */
670 private static boolean hasSecondZygote(String abiList) {
671 return !SystemProperties.get("ro.product.cpu.abilist").equals(abiList);
672 }
673
674 private static void waitForSecondaryZygote(String socketName) {
675 String otherZygoteName = Process.ZYGOTE_SOCKET.equals(socketName) ?
676 Process.SECONDARY_ZYGOTE_SOCKET : Process.ZYGOTE_SOCKET;
677 while (true) {
678 try {
679 final Process.ZygoteState zs = Process.ZygoteState.connect(otherZygoteName);
680 zs.close();
681 break;
682 } catch (IOException ioe) {
683 Log.w(TAG, "Got error connecting to zygote, retrying. msg= " + ioe.getMessage());
684 }
685
686 try {
687 Thread.sleep(1000);
688 } catch (InterruptedException ie) {
689 }
690 }
691 }
692
693 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800694 * Runs the zygote process's select loop. Accepts new connections as
695 * they happen, and reads commands from connections one spawn-request's
696 * worth at a time.
697 *
698 * @throws MethodAndArgsCaller in a child process when a main() should
699 * be executed.
700 */
Narayan Kamathc41638c2014-04-07 13:56:15 +0100701 private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
Nick Kralevichcae3d9f2013-01-30 09:51:40 -0800702 ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
703 ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800704
705 fds.add(sServerSocket.getFileDescriptor());
706 peers.add(null);
707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800708 while (true) {
Elliott Hughes894724b2014-12-15 12:39:51 -0800709 StructPollfd[] pollFds = new StructPollfd[fds.size()];
710 for (int i = 0; i < pollFds.length; ++i) {
711 pollFds[i] = new StructPollfd();
712 pollFds[i].fd = fds.get(i);
713 pollFds[i].events = (short) POLLIN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800714 }
Elliott Hughes894724b2014-12-15 12:39:51 -0800715 try {
716 Os.poll(pollFds, -1);
717 } catch (ErrnoException ex) {
718 throw new RuntimeException("poll failed", ex);
719 }
720 for (int i = pollFds.length - 1; i >= 0; --i) {
721 if ((pollFds[i].revents & POLLIN) == 0) {
722 continue;
723 }
724 if (i == 0) {
725 ZygoteConnection newPeer = acceptCommandPeer(abiList);
726 peers.add(newPeer);
727 fds.add(newPeer.getFileDesciptor());
728 } else {
729 boolean done = peers.get(i).runOnce();
730 if (done) {
731 peers.remove(i);
732 fds.remove(i);
733 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800734 }
735 }
736 }
737 }
738
739 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800740 * Class not instantiable.
741 */
742 private ZygoteInit() {
743 }
744
745 /**
746 * Helper exception class which holds a method and arguments and
747 * can call them. This is used as part of a trampoline to get rid of
748 * the initial process setup stack frames.
749 */
750 public static class MethodAndArgsCaller extends Exception
751 implements Runnable {
752 /** method to call */
753 private final Method mMethod;
754
755 /** argument array */
756 private final String[] mArgs;
757
758 public MethodAndArgsCaller(Method method, String[] args) {
759 mMethod = method;
760 mArgs = args;
761 }
762
763 public void run() {
764 try {
765 mMethod.invoke(null, new Object[] { mArgs });
766 } catch (IllegalAccessException ex) {
767 throw new RuntimeException(ex);
768 } catch (InvocationTargetException ex) {
769 Throwable cause = ex.getCause();
770 if (cause instanceof RuntimeException) {
771 throw (RuntimeException) cause;
772 } else if (cause instanceof Error) {
773 throw (Error) cause;
774 }
775 throw new RuntimeException(ex);
776 }
777 }
778 }
779}