blob: a7fb200ed86f36fca69e61c24a2e193067a35392 [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 Fuller41c9dc32016-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;
Bill Yi9a76e9b2014-04-29 18:52:48 -070034import android.system.ErrnoException;
Elliott Hughes860c5912014-04-28 19:19:13 -070035import android.system.Os;
36import android.system.OsConstants;
Elliott Hughes894724b2014-12-15 12:39:51 -080037import android.system.StructPollfd;
Raph Levienc3dd1c12015-04-06 10:37:57 -070038import android.text.Hyphenator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.util.EventLog;
40import android.util.Log;
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +010041import android.webkit.WebViewFactory;
Andreas Gampeddc13972016-02-26 16:54:59 -080042import android.widget.TextView;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043
Jeff Sharkeyfdeeeea2016-01-11 17:34:24 -070044import com.android.internal.os.InstallerConnection.InstallerException;
45
Narayan Kamath29564cd2014-08-07 10:57:40 +010046import dalvik.system.DexFile;
47import dalvik.system.PathClassLoader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048import dalvik.system.VMRuntime;
Andreas Gampe1ef8aef2016-04-11 08:39:52 -070049import dalvik.system.ZygoteHooks;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050
Brian Carlstrom46703b02011-04-06 15:41:29 -070051import libcore.io.IoUtils;
52
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053import java.io.BufferedReader;
54import java.io.FileDescriptor;
Ying Wangd0c45352014-11-13 15:22:47 -080055import java.io.FileInputStream;
56import java.io.FileNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057import java.io.IOException;
58import java.io.InputStream;
59import java.io.InputStreamReader;
60import java.lang.reflect.InvocationTargetException;
61import java.lang.reflect.Method;
Sergio Giro6cb7b1c2016-05-13 16:34:46 +010062import java.security.Security;
63import java.security.Provider;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064import java.util.ArrayList;
65
66/**
67 * Startup class for the zygote process.
68 *
69 * Pre-initializes some classes, and then waits for commands on a UNIX domain
Elliott Hughese1dfcb72011-07-08 11:08:07 -070070 * socket. Based on these commands, forks off child processes that inherit
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071 * the initial state of the VM.
72 *
73 * Please see {@link ZygoteConnection.Arguments} for documentation on the
74 * client protocol.
75 *
76 * @hide
77 */
78public class ZygoteInit {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079 private static final String TAG = "Zygote";
80
Romain Guyc5e36382013-05-09 11:08:17 -070081 private static final String PROPERTY_DISABLE_OPENGL_PRELOADING = "ro.zygote.disable_gl_preload";
Luis Hector Chavez5dd239a2015-10-06 14:01:45 -070082 private static final String PROPERTY_RUNNING_IN_CONTAINER = "ro.boot.container";
Romain Guyc5e36382013-05-09 11:08:17 -070083
Narayan Kamathc41638c2014-04-07 13:56:15 +010084 private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085
86 private static final int LOG_BOOT_PROGRESS_PRELOAD_START = 3020;
87 private static final int LOG_BOOT_PROGRESS_PRELOAD_END = 3030;
88
89 /** when preloading, GC after allocating this many bytes */
90 private static final int PRELOAD_GC_THRESHOLD = 50000;
91
Narayan Kamathc41638c2014-04-07 13:56:15 +010092 private static final String ABI_LIST_ARG = "--abi-list=";
93
94 private static final String SOCKET_NAME_ARG = "--socket-name=";
Barry Hayes0b3533a2010-01-20 12:46:47 -080095
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096 private static LocalServerSocket sServerSocket;
97
98 /**
99 * Used to pre-load resources. We hold a global reference on it so it
100 * never gets destroyed.
101 */
102 private static Resources mResources;
Bob Leee5408332009-09-04 18:31:17 -0700103
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104 /**
Ying Wangd0c45352014-11-13 15:22:47 -0800105 * The path of a file that contains classes to preload.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106 */
Ying Wangd0c45352014-11-13 15:22:47 -0800107 private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108
109 /** Controls whether we should preload resources during zygote init. */
Steve Paik3c27a232015-06-10 18:25:44 -0700110 public static final boolean PRELOAD_RESOURCES = true;
Andy McFadden599c9182009-04-08 00:35:56 -0700111
112 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113 * Registers a server socket for zygote command connections
114 *
115 * @throws RuntimeException when open fails
116 */
Narayan Kamathc41638c2014-04-07 13:56:15 +0100117 private static void registerZygoteSocket(String socketName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118 if (sServerSocket == null) {
119 int fileDesc;
Narayan Kamathc41638c2014-04-07 13:56:15 +0100120 final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121 try {
Narayan Kamathc41638c2014-04-07 13:56:15 +0100122 String env = System.getenv(fullSocketName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123 fileDesc = Integer.parseInt(env);
124 } catch (RuntimeException ex) {
Narayan Kamathc41638c2014-04-07 13:56:15 +0100125 throw new RuntimeException(fullSocketName + " unset or invalid", ex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126 }
127
128 try {
Elliott Hughes3fe59512014-12-12 14:07:34 -0800129 FileDescriptor fd = new FileDescriptor();
130 fd.setInt$(fileDesc);
131 sServerSocket = new LocalServerSocket(fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132 } catch (IOException ex) {
133 throw new RuntimeException(
134 "Error binding to local socket '" + fileDesc + "'", ex);
135 }
136 }
137 }
138
139 /**
140 * Waits for and accepts a single command connection. Throws
141 * RuntimeException on failure.
142 */
Narayan Kamathc41638c2014-04-07 13:56:15 +0100143 private static ZygoteConnection acceptCommandPeer(String abiList) {
Bob Leee5408332009-09-04 18:31:17 -0700144 try {
Narayan Kamathc41638c2014-04-07 13:56:15 +0100145 return new ZygoteConnection(sServerSocket.accept(), abiList);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 } catch (IOException ex) {
147 throw new RuntimeException(
148 "IOException during accept()", ex);
149 }
150 }
151
152 /**
153 * Close and clean up zygote sockets. Called on shutdown and on the
154 * child's exit path.
155 */
156 static void closeServerSocket() {
157 try {
158 if (sServerSocket != null) {
Dave Platt02f042d2013-12-12 15:45:49 -0800159 FileDescriptor fd = sServerSocket.getFileDescriptor();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800160 sServerSocket.close();
Dave Platt02f042d2013-12-12 15:45:49 -0800161 if (fd != null) {
Bill Yi9a76e9b2014-04-29 18:52:48 -0700162 Os.close(fd);
Dave Platt02f042d2013-12-12 15:45:49 -0800163 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800164 }
165 } catch (IOException ex) {
166 Log.e(TAG, "Zygote: error closing sockets", ex);
Bill Yi9a76e9b2014-04-29 18:52:48 -0700167 } catch (ErrnoException ex) {
Dave Platt02f042d2013-12-12 15:45:49 -0800168 Log.e(TAG, "Zygote: error closing descriptor", ex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169 }
170
171 sServerSocket = null;
172 }
173
Dave Platt89d4c892014-02-05 17:06:42 -0800174 /**
175 * Return the server socket's underlying file descriptor, so that
176 * ZygoteConnection can pass it to the native code for proper
177 * closure after a child process is forked off.
178 */
179
180 static FileDescriptor getServerSocketFileDescriptor() {
181 return sServerSocket.getFileDescriptor();
182 }
183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184 private static final int UNPRIVILEGED_UID = 9999;
185 private static final int UNPRIVILEGED_GID = 9999;
186
187 private static final int ROOT_UID = 0;
188 private static final int ROOT_GID = 0;
189
Jeff Brown0c2313d2011-06-10 22:46:40 -0700190 static void preload() {
Bill Yi9a76e9b2014-04-29 18:52:48 -0700191 Log.d(TAG, "begin preload");
Neil Fuller41c9dc32016-05-09 16:55:36 +0100192 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "BeginIcuCachePinning");
193 beginIcuCachePinning();
194 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900195 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadClasses");
196 preloadClasses();
197 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
198 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadResources");
199 preloadResources();
200 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
201 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadOpenGL");
Romain Guy74c69122013-05-08 17:54:20 -0700202 preloadOpenGL();
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900203 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
Brian Carlstrom6c9af962014-09-11 15:36:00 -0700204 preloadSharedLibraries();
Raph Levienc3dd1c12015-04-06 10:37:57 -0700205 preloadTextResources();
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100206 // Ask the WebViewFactory to do any initialization that must run in the zygote process,
207 // for memory sharing purposes.
208 WebViewFactory.prepareWebViewInZygote();
Neil Fuller41c9dc32016-05-09 16:55:36 +0100209 endIcuCachePinning();
Sergio Giro6cb7b1c2016-05-13 16:34:46 +0100210 warmUpJcaProviders();
Bill Yi9a76e9b2014-04-29 18:52:48 -0700211 Log.d(TAG, "end preload");
Romain Guy74c69122013-05-08 17:54:20 -0700212 }
213
Neil Fuller41c9dc32016-05-09 16:55:36 +0100214 private static void beginIcuCachePinning() {
215 // Pin ICU data in memory from this point that would normally be held by soft references.
216 // Without this, any references created immediately below or during class preloading
217 // would be collected when the Zygote GC runs in gcAndFinalize().
218 Log.i(TAG, "Installing ICU cache reference pinning...");
219
220 CacheValue.setStrength(CacheValue.Strength.STRONG);
221
222 Log.i(TAG, "Preloading ICU data...");
223 // Explicitly exercise code to cache data apps are likely to need.
224 ULocale[] localesToPin = { ULocale.ROOT, ULocale.US, ULocale.getDefault() };
225 for (ULocale uLocale : localesToPin) {
226 new DecimalFormatSymbols(uLocale);
227 }
228 }
229
230 private static void endIcuCachePinning() {
231 // All cache references created by ICU from this point will be soft.
232 CacheValue.setStrength(CacheValue.Strength.SOFT);
233
234 Log.i(TAG, "Uninstalled ICU cache reference pinning...");
235 }
236
Brian Carlstrom6c9af962014-09-11 15:36:00 -0700237 private static void preloadSharedLibraries() {
238 Log.i(TAG, "Preloading shared libraries...");
239 System.loadLibrary("android");
240 System.loadLibrary("compiler_rt");
241 System.loadLibrary("jnigraphics");
242 }
243
Romain Guy74c69122013-05-08 17:54:20 -0700244 private static void preloadOpenGL() {
Romain Guyc5e36382013-05-09 11:08:17 -0700245 if (!SystemProperties.getBoolean(PROPERTY_DISABLE_OPENGL_PRELOADING, false)) {
246 EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
247 }
Jeff Brown0c2313d2011-06-10 22:46:40 -0700248 }
249
Raph Levienc3dd1c12015-04-06 10:37:57 -0700250 private static void preloadTextResources() {
251 Hyphenator.init();
Andreas Gampeddc13972016-02-26 16:54:59 -0800252 TextView.preloadFontCache();
Raph Levienc3dd1c12015-04-06 10:37:57 -0700253 }
254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 /**
Sergio Giro6cb7b1c2016-05-13 16:34:46 +0100256 * Warm up the providers that are already registered.
257 *
258 * By doing it here we avoid that each app does it when requesting a service from the
259 * provider for the first time.
260 */
261 private static void warmUpJcaProviders() {
262 long startTime = SystemClock.uptimeMillis();
263 Trace.traceBegin(
264 Trace.TRACE_TAG_DALVIK, "Starting warm up of JCA providers");
265 for (Provider p : Security.getProviders()) {
266 p.warmUpServiceProvision();
267 }
268 Log.i(TAG, "Warmed up JCA providers in "
269 + (SystemClock.uptimeMillis()-startTime) + "ms.");
270 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
271 }
272
273 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800274 * Performs Zygote process initialization. Loads and initializes
275 * commonly used classes.
276 *
277 * Most classes only cause a few hundred bytes to be allocated, but
278 * a few will allocate a dozen Kbytes (in one case, 500+K).
279 */
280 private static void preloadClasses() {
281 final VMRuntime runtime = VMRuntime.getRuntime();
Bob Leee5408332009-09-04 18:31:17 -0700282
Ying Wangd0c45352014-11-13 15:22:47 -0800283 InputStream is;
284 try {
285 is = new FileInputStream(PRELOADED_CLASSES);
286 } catch (FileNotFoundException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287 Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");
Ying Wangd0c45352014-11-13 15:22:47 -0800288 return;
289 }
Bob Leee5408332009-09-04 18:31:17 -0700290
Ying Wangd0c45352014-11-13 15:22:47 -0800291 Log.i(TAG, "Preloading classes...");
292 long startTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800293
Ying Wangd0c45352014-11-13 15:22:47 -0800294 // Drop root perms while running static initializers.
Narayan Kamath23e68782015-01-16 17:22:41 +0000295 final int reuid = Os.getuid();
296 final int regid = Os.getgid();
297
298 // We need to drop root perms only if we're already root. In the case of "wrapped"
299 // processes (see WrapperInit), this function is called from an unprivileged uid
300 // and gid.
301 boolean droppedPriviliges = false;
302 if (reuid == ROOT_UID && regid == ROOT_GID) {
303 try {
304 Os.setregid(ROOT_GID, UNPRIVILEGED_GID);
305 Os.setreuid(ROOT_UID, UNPRIVILEGED_UID);
306 } catch (ErrnoException ex) {
307 throw new RuntimeException("Failed to drop root", ex);
308 }
309
310 droppedPriviliges = true;
Elliott Hughes26b56e62014-12-17 12:28:29 -0800311 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800312
Ying Wangd0c45352014-11-13 15:22:47 -0800313 // Alter the target heap utilization. With explicit GCs this
314 // is not likely to have any effect.
315 float defaultUtilization = runtime.getTargetHeapUtilization();
316 runtime.setTargetHeapUtilization(0.8f);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800317
Ying Wangd0c45352014-11-13 15:22:47 -0800318 try {
319 BufferedReader br
320 = new BufferedReader(new InputStreamReader(is), 256);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800321
Ying Wangd0c45352014-11-13 15:22:47 -0800322 int count = 0;
323 String line;
324 while ((line = br.readLine()) != null) {
325 // Skip comments and blank lines.
326 line = line.trim();
327 if (line.startsWith("#") || line.equals("")) {
328 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800329 }
330
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900331 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadClass " + line);
Ying Wangd0c45352014-11-13 15:22:47 -0800332 try {
333 if (false) {
334 Log.v(TAG, "Preloading " + line + "...");
335 }
Andreas Gampedd8e5fb2015-04-21 09:01:51 -0700336 // Load and explicitly initialize the given class. Use
337 // Class.forName(String, boolean, ClassLoader) to avoid repeated stack lookups
338 // (to derive the caller's class-loader). Use true to force initialization, and
339 // null for the boot classpath class-loader (could as well cache the
340 // class-loader of this class in a variable).
Andreas Gampec917f742015-04-20 19:16:37 -0700341 Class.forName(line, true, null);
Ying Wangd0c45352014-11-13 15:22:47 -0800342 count++;
343 } catch (ClassNotFoundException e) {
344 Log.w(TAG, "Class not found for preloading: " + line);
345 } catch (UnsatisfiedLinkError e) {
346 Log.w(TAG, "Problem preloading " + line + ": " + e);
347 } catch (Throwable t) {
348 Log.e(TAG, "Error preloading " + line + ".", t);
349 if (t instanceof Error) {
350 throw (Error) t;
351 }
352 if (t instanceof RuntimeException) {
353 throw (RuntimeException) t;
354 }
355 throw new RuntimeException(t);
356 }
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900357 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358 }
Ying Wangd0c45352014-11-13 15:22:47 -0800359
360 Log.i(TAG, "...preloaded " + count + " classes in "
361 + (SystemClock.uptimeMillis()-startTime) + "ms.");
362 } catch (IOException e) {
363 Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
364 } finally {
365 IoUtils.closeQuietly(is);
366 // Restore default.
367 runtime.setTargetHeapUtilization(defaultUtilization);
368
369 // Fill in dex caches with classes, fields, and methods brought in by preloading.
Yasuhiro Matsuda1ab43d52015-06-30 17:07:32 +0900370 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadDexCaches");
Ying Wangd0c45352014-11-13 15:22:47 -0800371 runtime.preloadDexCaches();
Yasuhiro Matsuda1ab43d52015-06-30 17:07:32 +0900372 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
Ying Wangd0c45352014-11-13 15:22:47 -0800373
Narayan Kamath23e68782015-01-16 17:22:41 +0000374 // Bring back root. We'll need it later if we're in the zygote.
375 if (droppedPriviliges) {
376 try {
377 Os.setreuid(ROOT_UID, ROOT_UID);
378 Os.setregid(ROOT_GID, ROOT_GID);
379 } catch (ErrnoException ex) {
380 throw new RuntimeException("Failed to restore root", ex);
381 }
Elliott Hughes26b56e62014-12-17 12:28:29 -0800382 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800383 }
384 }
385
386 /**
387 * Load in commonly used resources, so they can be shared across
388 * processes.
389 *
390 * These tend to be a few Kbytes, but are frequently in the 20-40K
391 * range, and occasionally even larger.
392 */
393 private static void preloadResources() {
394 final VMRuntime runtime = VMRuntime.getRuntime();
Bob Leee5408332009-09-04 18:31:17 -0700395
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800396 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800397 mResources = Resources.getSystem();
398 mResources.startPreloading();
399 if (PRELOAD_RESOURCES) {
400 Log.i(TAG, "Preloading resources...");
401
402 long startTime = SystemClock.uptimeMillis();
403 TypedArray ar = mResources.obtainTypedArray(
404 com.android.internal.R.array.preloaded_drawables);
Filip Gruszczynski811dc3b2015-11-23 12:34:22 -0800405 int N = preloadDrawables(ar);
Jeff Brown14577c42012-03-08 16:40:14 -0800406 ar.recycle();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800407 Log.i(TAG, "...preloaded " + N + " resources in "
408 + (SystemClock.uptimeMillis()-startTime) + "ms.");
409
410 startTime = SystemClock.uptimeMillis();
411 ar = mResources.obtainTypedArray(
412 com.android.internal.R.array.preloaded_color_state_lists);
Filip Gruszczynski811dc3b2015-11-23 12:34:22 -0800413 N = preloadColorStateLists(ar);
Jeff Brown14577c42012-03-08 16:40:14 -0800414 ar.recycle();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800415 Log.i(TAG, "...preloaded " + N + " resources in "
416 + (SystemClock.uptimeMillis()-startTime) + "ms.");
Filip Gruszczynski811dc3b2015-11-23 12:34:22 -0800417
418 if (mResources.getBoolean(
419 com.android.internal.R.bool.config_freeformWindowManagement)) {
420 startTime = SystemClock.uptimeMillis();
421 ar = mResources.obtainTypedArray(
422 com.android.internal.R.array.preloaded_freeform_multi_window_drawables);
423 N = preloadDrawables(ar);
424 ar.recycle();
425 Log.i(TAG, "...preloaded " + N + " resource in "
426 + (SystemClock.uptimeMillis() - startTime) + "ms.");
427 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800428 }
429 mResources.finishPreloading();
430 } catch (RuntimeException e) {
431 Log.w(TAG, "Failure preloading resources", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432 }
433 }
434
Filip Gruszczynski811dc3b2015-11-23 12:34:22 -0800435 private static int preloadColorStateLists(TypedArray ar) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 int N = ar.length();
437 for (int i=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438 int id = ar.getResourceId(i, 0);
Joe Onorato43a17652011-04-06 19:22:23 -0700439 if (false) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440 Log.v(TAG, "Preloading resource #" + Integer.toHexString(id));
441 }
442 if (id != 0) {
Alan Viverette77bb6f12015-02-11 17:24:33 -0800443 if (mResources.getColorStateList(id, null) == null) {
Dianne Hackborndde331c2012-08-03 14:01:57 -0700444 throw new IllegalArgumentException(
445 "Unable to find preloaded color resource #0x"
446 + Integer.toHexString(id)
447 + " (" + ar.getString(i) + ")");
448 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449 }
450 }
451 return N;
452 }
453
454
Filip Gruszczynski811dc3b2015-11-23 12:34:22 -0800455 private static int preloadDrawables(TypedArray ar) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800456 int N = ar.length();
457 for (int i=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458 int id = ar.getResourceId(i, 0);
Joe Onorato43a17652011-04-06 19:22:23 -0700459 if (false) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800460 Log.v(TAG, "Preloading resource #" + Integer.toHexString(id));
461 }
462 if (id != 0) {
Alan Viverette84e001a2014-09-22 00:04:22 -0700463 if (mResources.getDrawable(id, null) == null) {
Dianne Hackborndde331c2012-08-03 14:01:57 -0700464 throw new IllegalArgumentException(
465 "Unable to find preloaded drawable resource #0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800466 + Integer.toHexString(id)
Dianne Hackborndde331c2012-08-03 14:01:57 -0700467 + " (" + ar.getString(i) + ")");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800468 }
469 }
470 }
471 return N;
472 }
473
474 /**
475 * Runs several special GCs to try to clean up a few generations of
476 * softly- and final-reachable objects, along with any other garbage.
477 * This is only useful just before a fork().
478 */
Mathieu Chartier9a88f102014-08-20 10:24:11 -0700479 /*package*/ static void gcAndFinalize() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800480 final VMRuntime runtime = VMRuntime.getRuntime();
481
482 /* runFinalizationSync() lets finalizers be called in Zygote,
483 * which doesn't have a HeapWorker thread.
484 */
Brian Carlstrom08065b92011-04-01 15:49:41 -0700485 System.gc();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800486 runtime.runFinalizationSync();
Brian Carlstrom08065b92011-04-01 15:49:41 -0700487 System.gc();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800488 }
489
490 /**
491 * Finish remaining work for the newly forked system server process.
492 */
493 private static void handleSystemServerProcess(
494 ZygoteConnection.Arguments parsedArgs)
495 throws ZygoteInit.MethodAndArgsCaller {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800496
497 closeServerSocket();
498
Mike Lockwood90960e82010-08-06 09:15:25 -0400499 // set umask to 0077 so new files and directories will default to owner-only permissions.
Elliott Hughes860c5912014-04-28 19:19:13 -0700500 Os.umask(S_IRWXG | S_IRWXO);
Mike Lockwood90960e82010-08-06 09:15:25 -0400501
Jeff Brownebed7d62011-05-16 17:08:42 -0700502 if (parsedArgs.niceName != null) {
503 Process.setArgV0(parsedArgs.niceName);
504 }
505
Narayan Kamath29564cd2014-08-07 10:57:40 +0100506 final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
507 if (systemServerClasspath != null) {
508 performSystemServerDexOpt(systemServerClasspath);
509 }
510
Jeff Brownebed7d62011-05-16 17:08:42 -0700511 if (parsedArgs.invokeWith != null) {
Narayan Kamath29564cd2014-08-07 10:57:40 +0100512 String[] args = parsedArgs.remainingArgs;
513 // If we have a non-null system server class path, we'll have to duplicate the
514 // existing arguments and append the classpath to it. ART will handle the classpath
515 // correctly when we exec a new process.
516 if (systemServerClasspath != null) {
517 String[] amendedArgs = new String[args.length + 2];
518 amendedArgs[0] = "-cp";
519 amendedArgs[1] = systemServerClasspath;
520 System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);
521 }
522
Jeff Brownebed7d62011-05-16 17:08:42 -0700523 WrapperInit.execApplication(parsedArgs.invokeWith,
Elliott Hughese1dfcb72011-07-08 11:08:07 -0700524 parsedArgs.niceName, parsedArgs.targetSdkVersion,
Narayan Kamath37ad4b02015-01-19 16:05:24 +0000525 VMRuntime.getCurrentInstructionSet(), null, args);
Jeff Brownebed7d62011-05-16 17:08:42 -0700526 } else {
Narayan Kamath29564cd2014-08-07 10:57:40 +0100527 ClassLoader cl = null;
528 if (systemServerClasspath != null) {
Dimitry Ivanov89dad332016-04-20 16:02:00 -0700529 cl = createSystemServerClassLoader(systemServerClasspath,
530 parsedArgs.targetSdkVersion);
531
Narayan Kamath29564cd2014-08-07 10:57:40 +0100532 Thread.currentThread().setContextClassLoader(cl);
533 }
534
Jeff Brownebed7d62011-05-16 17:08:42 -0700535 /*
536 * Pass the remaining arguments to SystemServer.
537 */
Narayan Kamath29564cd2014-08-07 10:57:40 +0100538 RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
Jeff Brownebed7d62011-05-16 17:08:42 -0700539 }
540
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800541 /* should never reach here */
542 }
543
544 /**
Dimitry Ivanov89dad332016-04-20 16:02:00 -0700545 * Creates a PathClassLoader for the system server. It also creates
546 * a shared namespace associated with the classloader to let it access
547 * platform-private native libraries.
548 */
549 private static PathClassLoader createSystemServerClassLoader(String systemServerClasspath,
550 int targetSdkVersion) {
551 String librarySearchPath = System.getProperty("java.library.path");
552
553 return PathClassLoaderFactory.createClassLoader(systemServerClasspath,
554 librarySearchPath,
555 null /* libraryPermittedPath */,
556 ClassLoader.getSystemClassLoader(),
557 targetSdkVersion,
558 true /* isNamespaceShared */);
559 }
560
561 /**
Narayan Kamath29564cd2014-08-07 10:57:40 +0100562 * Performs dex-opt on the elements of {@code classPath}, if needed. We
563 * choose the instruction set of the current runtime.
564 */
565 private static void performSystemServerDexOpt(String classPath) {
566 final String[] classPathElements = classPath.split(":");
567 final InstallerConnection installer = new InstallerConnection();
Makoto Onukic8a2cfe2015-06-23 16:33:48 -0700568 installer.waitForConnection();
Narayan Kamath29564cd2014-08-07 10:57:40 +0100569 final String instructionSet = VMRuntime.getRuntime().vmInstructionSet();
570
571 try {
Jeff Haoc7b94822016-03-16 15:56:07 -0700572 String sharedLibraries = "";
Narayan Kamath29564cd2014-08-07 10:57:40 +0100573 for (String classPathElement : classPathElements) {
Calin Juravle693f9972016-02-25 15:26:20 +0000574 // System server is fully AOTed and never profiled
575 // for profile guided compilation.
Andreas Gampebdd30d82016-03-20 11:32:11 -0700576 // TODO: Make this configurable between INTERPRET_ONLY, SPEED, SPACE and EVERYTHING?
Richard Uhler7b08b352015-03-25 16:25:57 -0700577 final int dexoptNeeded = DexFile.getDexOptNeeded(
Andreas Gampebdd30d82016-03-20 11:32:11 -0700578 classPathElement, instructionSet, "speed",
579 false /* newProfile */);
Richard Uhler7b08b352015-03-25 16:25:57 -0700580 if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
Todd Kennedyfa54ab72015-09-25 07:46:12 -0700581 installer.dexopt(classPathElement, Process.SYSTEM_UID, instructionSet,
Jeff Haoc7b94822016-03-16 15:56:07 -0700582 dexoptNeeded, 0 /*dexFlags*/, "speed", null /*volumeUuid*/,
583 sharedLibraries);
Narayan Kamath29564cd2014-08-07 10:57:40 +0100584 }
Jeff Haoc7b94822016-03-16 15:56:07 -0700585 if (!sharedLibraries.isEmpty()) {
586 sharedLibraries += ":";
587 }
588 sharedLibraries += classPathElement;
Narayan Kamath29564cd2014-08-07 10:57:40 +0100589 }
Jeff Sharkeyfdeeeea2016-01-11 17:34:24 -0700590 } catch (IOException | InstallerException e) {
591 throw new RuntimeException("Error starting system_server", e);
Narayan Kamath29564cd2014-08-07 10:57:40 +0100592 } finally {
593 installer.disconnect();
594 }
595 }
596
597 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800598 * Prepare the arguments and fork for the system server process.
599 */
Narayan Kamath64cd9072014-05-13 13:35:14 +0100600 private static boolean startSystemServer(String abiList, String socketName)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800601 throws MethodAndArgsCaller, RuntimeException {
Alex Klyubin48a06e72013-04-19 10:01:42 -0700602 long capabilities = posixCapabilitiesAsBits(
Philip Cuadra7bd0fdd2016-04-28 15:26:49 -0700603 OsConstants.CAP_IPC_LOCK,
Alex Klyubin48a06e72013-04-19 10:01:42 -0700604 OsConstants.CAP_KILL,
605 OsConstants.CAP_NET_ADMIN,
606 OsConstants.CAP_NET_BIND_SERVICE,
607 OsConstants.CAP_NET_BROADCAST,
608 OsConstants.CAP_NET_RAW,
Alex Klyubin48a06e72013-04-19 10:01:42 -0700609 OsConstants.CAP_SYS_MODULE,
610 OsConstants.CAP_SYS_NICE,
611 OsConstants.CAP_SYS_RESOURCE,
612 OsConstants.CAP_SYS_TIME,
613 OsConstants.CAP_SYS_TTY_CONFIG
614 );
Luis Hector Chavez5dd239a2015-10-06 14:01:45 -0700615 /* Containers run without this capability, so avoid setting it in that case */
616 if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {
617 capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND);
618 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800619 /* Hardcoded command line to start the system server */
620 String args[] = {
621 "--setuid=1000",
622 "--setgid=1000",
Pavlin Radoslavov70166252015-11-23 17:13:25 -0800623 "--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 -0700624 "--capabilities=" + capabilities + "," + capabilities,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800625 "--nice-name=system_server",
Narayan Kamathb6b044a2015-02-13 17:31:25 +0000626 "--runtime-args",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800627 "com.android.server.SystemServer",
628 };
629 ZygoteConnection.Arguments parsedArgs = null;
630
631 int pid;
632
633 try {
634 parsedArgs = new ZygoteConnection.Arguments(args);
Jeff Brownebed7d62011-05-16 17:08:42 -0700635 ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
636 ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800637
638 /* Request to fork the system server process */
639 pid = Zygote.forkSystemServer(
640 parsedArgs.uid, parsedArgs.gid,
Elliott Hughese1dfcb72011-07-08 11:08:07 -0700641 parsedArgs.gids,
642 parsedArgs.debugFlags,
643 null,
Andy McFadden1b4c7962010-10-27 11:26:05 -0700644 parsedArgs.permittedCapabilities,
645 parsedArgs.effectiveCapabilities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800646 } catch (IllegalArgumentException ex) {
647 throw new RuntimeException(ex);
Bob Leee5408332009-09-04 18:31:17 -0700648 }
649
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800650 /* For child process */
651 if (pid == 0) {
Narayan Kamath64cd9072014-05-13 13:35:14 +0100652 if (hasSecondZygote(abiList)) {
653 waitForSecondaryZygote(socketName);
654 }
655
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800656 handleSystemServerProcess(parsedArgs);
657 }
658
659 return true;
660 }
661
Alex Klyubin48a06e72013-04-19 10:01:42 -0700662 /**
663 * Gets the bit array representation of the provided list of POSIX capabilities.
664 */
665 private static long posixCapabilitiesAsBits(int... capabilities) {
666 long result = 0;
667 for (int capability : capabilities) {
668 if ((capability < 0) || (capability > OsConstants.CAP_LAST_CAP)) {
669 throw new IllegalArgumentException(String.valueOf(capability));
670 }
671 result |= (1L << capability);
672 }
673 return result;
674 }
675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800676 public static void main(String argv[]) {
Andreas Gampe1ef8aef2016-04-11 08:39:52 -0700677 // Mark zygote start. This ensures that thread creation will throw
678 // an error.
679 ZygoteHooks.startZygoteNoThreadCreation();
680
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800681 try {
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900682 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygoteInit");
683 RuntimeInit.enableDdms();
684 // Start profiling the zygote initialization.
685 SamplingProfilerIntegration.start();
686
Narayan Kamathc41638c2014-04-07 13:56:15 +0100687 boolean startSystemServer = false;
688 String socketName = "zygote";
689 String abiList = null;
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900690 for (int i = 1; i < argv.length; i++) {
691 if ("start-system-server".equals(argv[i])) {
692 startSystemServer = true;
693 } else if (argv[i].startsWith(ABI_LIST_ARG)) {
694 abiList = argv[i].substring(ABI_LIST_ARG.length());
695 } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
696 socketName = argv[i].substring(SOCKET_NAME_ARG.length());
697 } else {
698 throw new RuntimeException("Unknown command line argument: " + argv[i]);
Narayan Kamathc41638c2014-04-07 13:56:15 +0100699 }
700 }
701
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900702 if (abiList == null) {
703 throw new RuntimeException("No ABI list supplied.");
704 }
705
706 registerZygoteSocket(socketName);
707 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygotePreload");
708 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
709 SystemClock.uptimeMillis());
710 preload();
711 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
712 SystemClock.uptimeMillis());
713 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
714
715 // Finish profiling the zygote initialization.
716 SamplingProfilerIntegration.writeZygoteSnapshot();
717
718 // Do an initial gc to clean up after startup
719 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PostZygoteInitGC");
720 gcAndFinalize();
721 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
722
723 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
724
Jamie Gennis6ad04522013-04-15 18:53:24 -0700725 // Disable tracing so that forked processes do not inherit stale tracing tags from
726 // Zygote.
727 Trace.setTracingEnabled(false);
728
doheon1.lee885b7422016-01-20 13:07:27 +0900729 // Zygote process unmounts root storage spaces.
730 Zygote.nativeUnmountStorageOnInit();
731
Andreas Gampe1ef8aef2016-04-11 08:39:52 -0700732 ZygoteHooks.stopZygoteNoThreadCreation();
733
Narayan Kamathc41638c2014-04-07 13:56:15 +0100734 if (startSystemServer) {
Narayan Kamath64cd9072014-05-13 13:35:14 +0100735 startSystemServer(abiList, socketName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800736 }
737
738 Log.i(TAG, "Accepting command socket connections");
Narayan Kamathc41638c2014-04-07 13:56:15 +0100739 runSelectLoop(abiList);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800740
741 closeServerSocket();
742 } catch (MethodAndArgsCaller caller) {
743 caller.run();
744 } catch (RuntimeException ex) {
745 Log.e(TAG, "Zygote died with exception", ex);
746 closeServerSocket();
747 throw ex;
748 }
749 }
750
751 /**
Narayan Kamath64cd9072014-05-13 13:35:14 +0100752 * Return {@code true} if this device configuration has another zygote.
753 *
754 * We determine this by comparing the device ABI list with this zygotes
755 * list. If this zygote supports all ABIs this device supports, there won't
756 * be another zygote.
757 */
758 private static boolean hasSecondZygote(String abiList) {
759 return !SystemProperties.get("ro.product.cpu.abilist").equals(abiList);
760 }
761
762 private static void waitForSecondaryZygote(String socketName) {
763 String otherZygoteName = Process.ZYGOTE_SOCKET.equals(socketName) ?
764 Process.SECONDARY_ZYGOTE_SOCKET : Process.ZYGOTE_SOCKET;
765 while (true) {
766 try {
767 final Process.ZygoteState zs = Process.ZygoteState.connect(otherZygoteName);
768 zs.close();
769 break;
770 } catch (IOException ioe) {
771 Log.w(TAG, "Got error connecting to zygote, retrying. msg= " + ioe.getMessage());
772 }
773
774 try {
775 Thread.sleep(1000);
776 } catch (InterruptedException ie) {
777 }
778 }
779 }
780
781 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782 * Runs the zygote process's select loop. Accepts new connections as
783 * they happen, and reads commands from connections one spawn-request's
784 * worth at a time.
785 *
786 * @throws MethodAndArgsCaller in a child process when a main() should
787 * be executed.
788 */
Narayan Kamathc41638c2014-04-07 13:56:15 +0100789 private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
Nick Kralevichcae3d9f2013-01-30 09:51:40 -0800790 ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
791 ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800792
793 fds.add(sServerSocket.getFileDescriptor());
794 peers.add(null);
795
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800796 while (true) {
Elliott Hughes894724b2014-12-15 12:39:51 -0800797 StructPollfd[] pollFds = new StructPollfd[fds.size()];
798 for (int i = 0; i < pollFds.length; ++i) {
799 pollFds[i] = new StructPollfd();
800 pollFds[i].fd = fds.get(i);
801 pollFds[i].events = (short) POLLIN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800802 }
Elliott Hughes894724b2014-12-15 12:39:51 -0800803 try {
804 Os.poll(pollFds, -1);
805 } catch (ErrnoException ex) {
806 throw new RuntimeException("poll failed", ex);
807 }
808 for (int i = pollFds.length - 1; i >= 0; --i) {
809 if ((pollFds[i].revents & POLLIN) == 0) {
810 continue;
811 }
812 if (i == 0) {
813 ZygoteConnection newPeer = acceptCommandPeer(abiList);
814 peers.add(newPeer);
815 fds.add(newPeer.getFileDesciptor());
816 } else {
817 boolean done = peers.get(i).runOnce();
818 if (done) {
819 peers.remove(i);
820 fds.remove(i);
821 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800822 }
823 }
824 }
825 }
826
827 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800828 * Class not instantiable.
829 */
830 private ZygoteInit() {
831 }
832
833 /**
834 * Helper exception class which holds a method and arguments and
835 * can call them. This is used as part of a trampoline to get rid of
836 * the initial process setup stack frames.
837 */
838 public static class MethodAndArgsCaller extends Exception
839 implements Runnable {
840 /** method to call */
841 private final Method mMethod;
842
843 /** argument array */
844 private final String[] mArgs;
845
846 public MethodAndArgsCaller(Method method, String[] args) {
847 mMethod = method;
848 mArgs = args;
849 }
850
851 public void run() {
852 try {
853 mMethod.invoke(null, new Object[] { mArgs });
854 } catch (IllegalAccessException ex) {
855 throw new RuntimeException(ex);
856 } catch (InvocationTargetException ex) {
857 Throwable cause = ex.getCause();
858 if (cause instanceof RuntimeException) {
859 throw (RuntimeException) cause;
860 } else if (cause instanceof Error) {
861 throw (Error) cause;
862 }
863 throw new RuntimeException(ex);
864 }
865 }
866 }
867}