blob: a3e41e47b267866dfbaa9c132dc76992bbba8f8c [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;
Andreas Gampe1ef8aef2016-04-11 08:39:52 -070046import dalvik.system.ZygoteHooks;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047
Brian Carlstrom46703b02011-04-06 15:41:29 -070048import libcore.io.IoUtils;
49
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import java.io.BufferedReader;
51import java.io.FileDescriptor;
Ying Wangd0c45352014-11-13 15:22:47 -080052import java.io.FileInputStream;
53import java.io.FileNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054import java.io.IOException;
55import java.io.InputStream;
56import java.io.InputStreamReader;
57import java.lang.reflect.InvocationTargetException;
58import java.lang.reflect.Method;
Sergio Giro6cb7b1c2016-05-13 16:34:46 +010059import java.security.Security;
60import java.security.Provider;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061import java.util.ArrayList;
62
63/**
64 * Startup class for the zygote process.
65 *
66 * Pre-initializes some classes, and then waits for commands on a UNIX domain
Elliott Hughese1dfcb72011-07-08 11:08:07 -070067 * socket. Based on these commands, forks off child processes that inherit
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068 * the initial state of the VM.
69 *
70 * Please see {@link ZygoteConnection.Arguments} for documentation on the
71 * client protocol.
72 *
73 * @hide
74 */
75public class ZygoteInit {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076 private static final String TAG = "Zygote";
77
Romain Guyc5e36382013-05-09 11:08:17 -070078 private static final String PROPERTY_DISABLE_OPENGL_PRELOADING = "ro.zygote.disable_gl_preload";
Luis Hector Chavez5dd239a2015-10-06 14:01:45 -070079 private static final String PROPERTY_RUNNING_IN_CONTAINER = "ro.boot.container";
Romain Guyc5e36382013-05-09 11:08:17 -070080
Narayan Kamathc41638c2014-04-07 13:56:15 +010081 private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082
83 private static final int LOG_BOOT_PROGRESS_PRELOAD_START = 3020;
84 private static final int LOG_BOOT_PROGRESS_PRELOAD_END = 3030;
85
86 /** when preloading, GC after allocating this many bytes */
87 private static final int PRELOAD_GC_THRESHOLD = 50000;
88
Narayan Kamathc41638c2014-04-07 13:56:15 +010089 private static final String ABI_LIST_ARG = "--abi-list=";
90
91 private static final String SOCKET_NAME_ARG = "--socket-name=";
Barry Hayes0b3533a2010-01-20 12:46:47 -080092
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093 private static LocalServerSocket sServerSocket;
94
95 /**
96 * Used to pre-load resources. We hold a global reference on it so it
97 * never gets destroyed.
98 */
99 private static Resources mResources;
Bob Leee5408332009-09-04 18:31:17 -0700100
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101 /**
Ying Wangd0c45352014-11-13 15:22:47 -0800102 * The path of a file that contains classes to preload.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103 */
Ying Wangd0c45352014-11-13 15:22:47 -0800104 private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105
106 /** Controls whether we should preload resources during zygote init. */
Steve Paik3c27a232015-06-10 18:25:44 -0700107 public static final boolean PRELOAD_RESOURCES = true;
Andy McFadden599c9182009-04-08 00:35:56 -0700108
109 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110 * Registers a server socket for zygote command connections
111 *
112 * @throws RuntimeException when open fails
113 */
Narayan Kamathc41638c2014-04-07 13:56:15 +0100114 private static void registerZygoteSocket(String socketName) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115 if (sServerSocket == null) {
116 int fileDesc;
Narayan Kamathc41638c2014-04-07 13:56:15 +0100117 final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118 try {
Narayan Kamathc41638c2014-04-07 13:56:15 +0100119 String env = System.getenv(fullSocketName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120 fileDesc = Integer.parseInt(env);
121 } catch (RuntimeException ex) {
Narayan Kamathc41638c2014-04-07 13:56:15 +0100122 throw new RuntimeException(fullSocketName + " unset or invalid", ex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123 }
124
125 try {
Elliott Hughes3fe59512014-12-12 14:07:34 -0800126 FileDescriptor fd = new FileDescriptor();
127 fd.setInt$(fileDesc);
128 sServerSocket = new LocalServerSocket(fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129 } catch (IOException ex) {
130 throw new RuntimeException(
131 "Error binding to local socket '" + fileDesc + "'", ex);
132 }
133 }
134 }
135
136 /**
137 * Waits for and accepts a single command connection. Throws
138 * RuntimeException on failure.
139 */
Narayan Kamathc41638c2014-04-07 13:56:15 +0100140 private static ZygoteConnection acceptCommandPeer(String abiList) {
Bob Leee5408332009-09-04 18:31:17 -0700141 try {
Narayan Kamathc41638c2014-04-07 13:56:15 +0100142 return new ZygoteConnection(sServerSocket.accept(), abiList);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800143 } catch (IOException ex) {
144 throw new RuntimeException(
145 "IOException during accept()", ex);
146 }
147 }
148
149 /**
150 * Close and clean up zygote sockets. Called on shutdown and on the
151 * child's exit path.
152 */
153 static void closeServerSocket() {
154 try {
155 if (sServerSocket != null) {
Dave Platt02f042d2013-12-12 15:45:49 -0800156 FileDescriptor fd = sServerSocket.getFileDescriptor();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157 sServerSocket.close();
Dave Platt02f042d2013-12-12 15:45:49 -0800158 if (fd != null) {
Bill Yi9a76e9b2014-04-29 18:52:48 -0700159 Os.close(fd);
Dave Platt02f042d2013-12-12 15:45:49 -0800160 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161 }
162 } catch (IOException ex) {
163 Log.e(TAG, "Zygote: error closing sockets", ex);
Bill Yi9a76e9b2014-04-29 18:52:48 -0700164 } catch (ErrnoException ex) {
Dave Platt02f042d2013-12-12 15:45:49 -0800165 Log.e(TAG, "Zygote: error closing descriptor", ex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800166 }
167
168 sServerSocket = null;
169 }
170
Dave Platt89d4c892014-02-05 17:06:42 -0800171 /**
172 * Return the server socket's underlying file descriptor, so that
173 * ZygoteConnection can pass it to the native code for proper
174 * closure after a child process is forked off.
175 */
176
177 static FileDescriptor getServerSocketFileDescriptor() {
178 return sServerSocket.getFileDescriptor();
179 }
180
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800181 private static final int UNPRIVILEGED_UID = 9999;
182 private static final int UNPRIVILEGED_GID = 9999;
183
184 private static final int ROOT_UID = 0;
185 private static final int ROOT_GID = 0;
186
Jeff Brown0c2313d2011-06-10 22:46:40 -0700187 static void preload() {
Bill Yi9a76e9b2014-04-29 18:52:48 -0700188 Log.d(TAG, "begin preload");
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900189 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadClasses");
190 preloadClasses();
191 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
192 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadResources");
193 preloadResources();
194 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
195 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadOpenGL");
Romain Guy74c69122013-05-08 17:54:20 -0700196 preloadOpenGL();
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900197 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
Brian Carlstrom6c9af962014-09-11 15:36:00 -0700198 preloadSharedLibraries();
Raph Levienc3dd1c12015-04-06 10:37:57 -0700199 preloadTextResources();
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100200 // Ask the WebViewFactory to do any initialization that must run in the zygote process,
201 // for memory sharing purposes.
202 WebViewFactory.prepareWebViewInZygote();
Sergio Giro6cb7b1c2016-05-13 16:34:46 +0100203 warmUpJcaProviders();
Bill Yi9a76e9b2014-04-29 18:52:48 -0700204 Log.d(TAG, "end preload");
Romain Guy74c69122013-05-08 17:54:20 -0700205 }
206
Brian Carlstrom6c9af962014-09-11 15:36:00 -0700207 private static void preloadSharedLibraries() {
208 Log.i(TAG, "Preloading shared libraries...");
209 System.loadLibrary("android");
210 System.loadLibrary("compiler_rt");
211 System.loadLibrary("jnigraphics");
212 }
213
Romain Guy74c69122013-05-08 17:54:20 -0700214 private static void preloadOpenGL() {
Romain Guyc5e36382013-05-09 11:08:17 -0700215 if (!SystemProperties.getBoolean(PROPERTY_DISABLE_OPENGL_PRELOADING, false)) {
216 EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
217 }
Jeff Brown0c2313d2011-06-10 22:46:40 -0700218 }
219
Raph Levienc3dd1c12015-04-06 10:37:57 -0700220 private static void preloadTextResources() {
221 Hyphenator.init();
Andreas Gampeddc13972016-02-26 16:54:59 -0800222 TextView.preloadFontCache();
Raph Levienc3dd1c12015-04-06 10:37:57 -0700223 }
224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 /**
Sergio Giro6cb7b1c2016-05-13 16:34:46 +0100226 * Warm up the providers that are already registered.
227 *
228 * By doing it here we avoid that each app does it when requesting a service from the
229 * provider for the first time.
230 */
231 private static void warmUpJcaProviders() {
232 long startTime = SystemClock.uptimeMillis();
233 Trace.traceBegin(
234 Trace.TRACE_TAG_DALVIK, "Starting warm up of JCA providers");
235 for (Provider p : Security.getProviders()) {
236 p.warmUpServiceProvision();
237 }
238 Log.i(TAG, "Warmed up JCA providers in "
239 + (SystemClock.uptimeMillis()-startTime) + "ms.");
240 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
241 }
242
243 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800244 * Performs Zygote process initialization. Loads and initializes
245 * commonly used classes.
246 *
247 * Most classes only cause a few hundred bytes to be allocated, but
248 * a few will allocate a dozen Kbytes (in one case, 500+K).
249 */
250 private static void preloadClasses() {
251 final VMRuntime runtime = VMRuntime.getRuntime();
Bob Leee5408332009-09-04 18:31:17 -0700252
Ying Wangd0c45352014-11-13 15:22:47 -0800253 InputStream is;
254 try {
255 is = new FileInputStream(PRELOADED_CLASSES);
256 } catch (FileNotFoundException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800257 Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");
Ying Wangd0c45352014-11-13 15:22:47 -0800258 return;
259 }
Bob Leee5408332009-09-04 18:31:17 -0700260
Ying Wangd0c45352014-11-13 15:22:47 -0800261 Log.i(TAG, "Preloading classes...");
262 long startTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263
Ying Wangd0c45352014-11-13 15:22:47 -0800264 // Drop root perms while running static initializers.
Narayan Kamath23e68782015-01-16 17:22:41 +0000265 final int reuid = Os.getuid();
266 final int regid = Os.getgid();
267
268 // We need to drop root perms only if we're already root. In the case of "wrapped"
269 // processes (see WrapperInit), this function is called from an unprivileged uid
270 // and gid.
271 boolean droppedPriviliges = false;
272 if (reuid == ROOT_UID && regid == ROOT_GID) {
273 try {
274 Os.setregid(ROOT_GID, UNPRIVILEGED_GID);
275 Os.setreuid(ROOT_UID, UNPRIVILEGED_UID);
276 } catch (ErrnoException ex) {
277 throw new RuntimeException("Failed to drop root", ex);
278 }
279
280 droppedPriviliges = true;
Elliott Hughes26b56e62014-12-17 12:28:29 -0800281 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282
Ying Wangd0c45352014-11-13 15:22:47 -0800283 // Alter the target heap utilization. With explicit GCs this
284 // is not likely to have any effect.
285 float defaultUtilization = runtime.getTargetHeapUtilization();
286 runtime.setTargetHeapUtilization(0.8f);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287
Ying Wangd0c45352014-11-13 15:22:47 -0800288 try {
289 BufferedReader br
290 = new BufferedReader(new InputStreamReader(is), 256);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291
Ying Wangd0c45352014-11-13 15:22:47 -0800292 int count = 0;
293 String line;
294 while ((line = br.readLine()) != null) {
295 // Skip comments and blank lines.
296 line = line.trim();
297 if (line.startsWith("#") || line.equals("")) {
298 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299 }
300
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900301 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadClass " + line);
Ying Wangd0c45352014-11-13 15:22:47 -0800302 try {
303 if (false) {
304 Log.v(TAG, "Preloading " + line + "...");
305 }
Andreas Gampedd8e5fb2015-04-21 09:01:51 -0700306 // Load and explicitly initialize the given class. Use
307 // Class.forName(String, boolean, ClassLoader) to avoid repeated stack lookups
308 // (to derive the caller's class-loader). Use true to force initialization, and
309 // null for the boot classpath class-loader (could as well cache the
310 // class-loader of this class in a variable).
Andreas Gampec917f742015-04-20 19:16:37 -0700311 Class.forName(line, true, null);
Ying Wangd0c45352014-11-13 15:22:47 -0800312 count++;
313 } catch (ClassNotFoundException e) {
314 Log.w(TAG, "Class not found for preloading: " + line);
315 } catch (UnsatisfiedLinkError e) {
316 Log.w(TAG, "Problem preloading " + line + ": " + e);
317 } catch (Throwable t) {
318 Log.e(TAG, "Error preloading " + line + ".", t);
319 if (t instanceof Error) {
320 throw (Error) t;
321 }
322 if (t instanceof RuntimeException) {
323 throw (RuntimeException) t;
324 }
325 throw new RuntimeException(t);
326 }
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900327 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328 }
Ying Wangd0c45352014-11-13 15:22:47 -0800329
330 Log.i(TAG, "...preloaded " + count + " classes in "
331 + (SystemClock.uptimeMillis()-startTime) + "ms.");
332 } catch (IOException e) {
333 Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
334 } finally {
335 IoUtils.closeQuietly(is);
336 // Restore default.
337 runtime.setTargetHeapUtilization(defaultUtilization);
338
339 // Fill in dex caches with classes, fields, and methods brought in by preloading.
Yasuhiro Matsuda1ab43d52015-06-30 17:07:32 +0900340 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadDexCaches");
Ying Wangd0c45352014-11-13 15:22:47 -0800341 runtime.preloadDexCaches();
Yasuhiro Matsuda1ab43d52015-06-30 17:07:32 +0900342 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
Ying Wangd0c45352014-11-13 15:22:47 -0800343
Narayan Kamath23e68782015-01-16 17:22:41 +0000344 // Bring back root. We'll need it later if we're in the zygote.
345 if (droppedPriviliges) {
346 try {
347 Os.setreuid(ROOT_UID, ROOT_UID);
348 Os.setregid(ROOT_GID, ROOT_GID);
349 } catch (ErrnoException ex) {
350 throw new RuntimeException("Failed to restore root", ex);
351 }
Elliott Hughes26b56e62014-12-17 12:28:29 -0800352 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800353 }
354 }
355
356 /**
357 * Load in commonly used resources, so they can be shared across
358 * processes.
359 *
360 * These tend to be a few Kbytes, but are frequently in the 20-40K
361 * range, and occasionally even larger.
362 */
363 private static void preloadResources() {
364 final VMRuntime runtime = VMRuntime.getRuntime();
Bob Leee5408332009-09-04 18:31:17 -0700365
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800366 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800367 mResources = Resources.getSystem();
368 mResources.startPreloading();
369 if (PRELOAD_RESOURCES) {
370 Log.i(TAG, "Preloading resources...");
371
372 long startTime = SystemClock.uptimeMillis();
373 TypedArray ar = mResources.obtainTypedArray(
374 com.android.internal.R.array.preloaded_drawables);
Filip Gruszczynski811dc3b2015-11-23 12:34:22 -0800375 int N = preloadDrawables(ar);
Jeff Brown14577c42012-03-08 16:40:14 -0800376 ar.recycle();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377 Log.i(TAG, "...preloaded " + N + " resources in "
378 + (SystemClock.uptimeMillis()-startTime) + "ms.");
379
380 startTime = SystemClock.uptimeMillis();
381 ar = mResources.obtainTypedArray(
382 com.android.internal.R.array.preloaded_color_state_lists);
Filip Gruszczynski811dc3b2015-11-23 12:34:22 -0800383 N = preloadColorStateLists(ar);
Jeff Brown14577c42012-03-08 16:40:14 -0800384 ar.recycle();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385 Log.i(TAG, "...preloaded " + N + " resources in "
386 + (SystemClock.uptimeMillis()-startTime) + "ms.");
Filip Gruszczynski811dc3b2015-11-23 12:34:22 -0800387
388 if (mResources.getBoolean(
389 com.android.internal.R.bool.config_freeformWindowManagement)) {
390 startTime = SystemClock.uptimeMillis();
391 ar = mResources.obtainTypedArray(
392 com.android.internal.R.array.preloaded_freeform_multi_window_drawables);
393 N = preloadDrawables(ar);
394 ar.recycle();
395 Log.i(TAG, "...preloaded " + N + " resource in "
396 + (SystemClock.uptimeMillis() - startTime) + "ms.");
397 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800398 }
399 mResources.finishPreloading();
400 } catch (RuntimeException e) {
401 Log.w(TAG, "Failure preloading resources", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800402 }
403 }
404
Filip Gruszczynski811dc3b2015-11-23 12:34:22 -0800405 private static int preloadColorStateLists(TypedArray ar) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800406 int N = ar.length();
407 for (int i=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800408 int id = ar.getResourceId(i, 0);
Joe Onorato43a17652011-04-06 19:22:23 -0700409 if (false) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800410 Log.v(TAG, "Preloading resource #" + Integer.toHexString(id));
411 }
412 if (id != 0) {
Alan Viverette77bb6f12015-02-11 17:24:33 -0800413 if (mResources.getColorStateList(id, null) == null) {
Dianne Hackborndde331c2012-08-03 14:01:57 -0700414 throw new IllegalArgumentException(
415 "Unable to find preloaded color resource #0x"
416 + Integer.toHexString(id)
417 + " (" + ar.getString(i) + ")");
418 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800419 }
420 }
421 return N;
422 }
423
424
Filip Gruszczynski811dc3b2015-11-23 12:34:22 -0800425 private static int preloadDrawables(TypedArray ar) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800426 int N = ar.length();
427 for (int i=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800428 int id = ar.getResourceId(i, 0);
Joe Onorato43a17652011-04-06 19:22:23 -0700429 if (false) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800430 Log.v(TAG, "Preloading resource #" + Integer.toHexString(id));
431 }
432 if (id != 0) {
Alan Viverette84e001a2014-09-22 00:04:22 -0700433 if (mResources.getDrawable(id, null) == null) {
Dianne Hackborndde331c2012-08-03 14:01:57 -0700434 throw new IllegalArgumentException(
435 "Unable to find preloaded drawable resource #0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 + Integer.toHexString(id)
Dianne Hackborndde331c2012-08-03 14:01:57 -0700437 + " (" + ar.getString(i) + ")");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438 }
439 }
440 }
441 return N;
442 }
443
444 /**
445 * Runs several special GCs to try to clean up a few generations of
446 * softly- and final-reachable objects, along with any other garbage.
447 * This is only useful just before a fork().
448 */
Mathieu Chartier9a88f102014-08-20 10:24:11 -0700449 /*package*/ static void gcAndFinalize() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800450 final VMRuntime runtime = VMRuntime.getRuntime();
451
452 /* runFinalizationSync() lets finalizers be called in Zygote,
453 * which doesn't have a HeapWorker thread.
454 */
Brian Carlstrom08065b92011-04-01 15:49:41 -0700455 System.gc();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800456 runtime.runFinalizationSync();
Brian Carlstrom08065b92011-04-01 15:49:41 -0700457 System.gc();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458 }
459
460 /**
461 * Finish remaining work for the newly forked system server process.
462 */
463 private static void handleSystemServerProcess(
464 ZygoteConnection.Arguments parsedArgs)
465 throws ZygoteInit.MethodAndArgsCaller {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800466
467 closeServerSocket();
468
Mike Lockwood90960e82010-08-06 09:15:25 -0400469 // set umask to 0077 so new files and directories will default to owner-only permissions.
Elliott Hughes860c5912014-04-28 19:19:13 -0700470 Os.umask(S_IRWXG | S_IRWXO);
Mike Lockwood90960e82010-08-06 09:15:25 -0400471
Jeff Brownebed7d62011-05-16 17:08:42 -0700472 if (parsedArgs.niceName != null) {
473 Process.setArgV0(parsedArgs.niceName);
474 }
475
Narayan Kamath29564cd2014-08-07 10:57:40 +0100476 final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
477 if (systemServerClasspath != null) {
478 performSystemServerDexOpt(systemServerClasspath);
479 }
480
Jeff Brownebed7d62011-05-16 17:08:42 -0700481 if (parsedArgs.invokeWith != null) {
Narayan Kamath29564cd2014-08-07 10:57:40 +0100482 String[] args = parsedArgs.remainingArgs;
483 // If we have a non-null system server class path, we'll have to duplicate the
484 // existing arguments and append the classpath to it. ART will handle the classpath
485 // correctly when we exec a new process.
486 if (systemServerClasspath != null) {
487 String[] amendedArgs = new String[args.length + 2];
488 amendedArgs[0] = "-cp";
489 amendedArgs[1] = systemServerClasspath;
490 System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);
491 }
492
Jeff Brownebed7d62011-05-16 17:08:42 -0700493 WrapperInit.execApplication(parsedArgs.invokeWith,
Elliott Hughese1dfcb72011-07-08 11:08:07 -0700494 parsedArgs.niceName, parsedArgs.targetSdkVersion,
Narayan Kamath37ad4b02015-01-19 16:05:24 +0000495 VMRuntime.getCurrentInstructionSet(), null, args);
Jeff Brownebed7d62011-05-16 17:08:42 -0700496 } else {
Narayan Kamath29564cd2014-08-07 10:57:40 +0100497 ClassLoader cl = null;
498 if (systemServerClasspath != null) {
Dimitry Ivanov89dad332016-04-20 16:02:00 -0700499 cl = createSystemServerClassLoader(systemServerClasspath,
500 parsedArgs.targetSdkVersion);
501
Narayan Kamath29564cd2014-08-07 10:57:40 +0100502 Thread.currentThread().setContextClassLoader(cl);
503 }
504
Jeff Brownebed7d62011-05-16 17:08:42 -0700505 /*
506 * Pass the remaining arguments to SystemServer.
507 */
Narayan Kamath29564cd2014-08-07 10:57:40 +0100508 RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
Jeff Brownebed7d62011-05-16 17:08:42 -0700509 }
510
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800511 /* should never reach here */
512 }
513
514 /**
Dimitry Ivanov89dad332016-04-20 16:02:00 -0700515 * Creates a PathClassLoader for the system server. It also creates
516 * a shared namespace associated with the classloader to let it access
517 * platform-private native libraries.
518 */
519 private static PathClassLoader createSystemServerClassLoader(String systemServerClasspath,
520 int targetSdkVersion) {
521 String librarySearchPath = System.getProperty("java.library.path");
522
523 return PathClassLoaderFactory.createClassLoader(systemServerClasspath,
524 librarySearchPath,
525 null /* libraryPermittedPath */,
526 ClassLoader.getSystemClassLoader(),
527 targetSdkVersion,
528 true /* isNamespaceShared */);
529 }
530
531 /**
Narayan Kamath29564cd2014-08-07 10:57:40 +0100532 * Performs dex-opt on the elements of {@code classPath}, if needed. We
533 * choose the instruction set of the current runtime.
534 */
535 private static void performSystemServerDexOpt(String classPath) {
536 final String[] classPathElements = classPath.split(":");
537 final InstallerConnection installer = new InstallerConnection();
Makoto Onukic8a2cfe2015-06-23 16:33:48 -0700538 installer.waitForConnection();
Narayan Kamath29564cd2014-08-07 10:57:40 +0100539 final String instructionSet = VMRuntime.getRuntime().vmInstructionSet();
540
541 try {
Jeff Haoc7b94822016-03-16 15:56:07 -0700542 String sharedLibraries = "";
Narayan Kamath29564cd2014-08-07 10:57:40 +0100543 for (String classPathElement : classPathElements) {
Calin Juravle693f9972016-02-25 15:26:20 +0000544 // System server is fully AOTed and never profiled
545 // for profile guided compilation.
Andreas Gampebdd30d82016-03-20 11:32:11 -0700546 // TODO: Make this configurable between INTERPRET_ONLY, SPEED, SPACE and EVERYTHING?
Richard Uhler7b08b352015-03-25 16:25:57 -0700547 final int dexoptNeeded = DexFile.getDexOptNeeded(
Andreas Gampebdd30d82016-03-20 11:32:11 -0700548 classPathElement, instructionSet, "speed",
549 false /* newProfile */);
Richard Uhler7b08b352015-03-25 16:25:57 -0700550 if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
Todd Kennedyfa54ab72015-09-25 07:46:12 -0700551 installer.dexopt(classPathElement, Process.SYSTEM_UID, instructionSet,
Jeff Haoc7b94822016-03-16 15:56:07 -0700552 dexoptNeeded, 0 /*dexFlags*/, "speed", null /*volumeUuid*/,
553 sharedLibraries);
Narayan Kamath29564cd2014-08-07 10:57:40 +0100554 }
Jeff Haoc7b94822016-03-16 15:56:07 -0700555 if (!sharedLibraries.isEmpty()) {
556 sharedLibraries += ":";
557 }
558 sharedLibraries += classPathElement;
Narayan Kamath29564cd2014-08-07 10:57:40 +0100559 }
Jeff Sharkeyfdeeeea2016-01-11 17:34:24 -0700560 } catch (IOException | InstallerException e) {
561 throw new RuntimeException("Error starting system_server", e);
Narayan Kamath29564cd2014-08-07 10:57:40 +0100562 } finally {
563 installer.disconnect();
564 }
565 }
566
567 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800568 * Prepare the arguments and fork for the system server process.
569 */
Narayan Kamath64cd9072014-05-13 13:35:14 +0100570 private static boolean startSystemServer(String abiList, String socketName)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800571 throws MethodAndArgsCaller, RuntimeException {
Alex Klyubin48a06e72013-04-19 10:01:42 -0700572 long capabilities = posixCapabilitiesAsBits(
Philip Cuadra7bd0fdd2016-04-28 15:26:49 -0700573 OsConstants.CAP_IPC_LOCK,
Alex Klyubin48a06e72013-04-19 10:01:42 -0700574 OsConstants.CAP_KILL,
575 OsConstants.CAP_NET_ADMIN,
576 OsConstants.CAP_NET_BIND_SERVICE,
577 OsConstants.CAP_NET_BROADCAST,
578 OsConstants.CAP_NET_RAW,
Alex Klyubin48a06e72013-04-19 10:01:42 -0700579 OsConstants.CAP_SYS_MODULE,
580 OsConstants.CAP_SYS_NICE,
581 OsConstants.CAP_SYS_RESOURCE,
582 OsConstants.CAP_SYS_TIME,
583 OsConstants.CAP_SYS_TTY_CONFIG
584 );
Luis Hector Chavez5dd239a2015-10-06 14:01:45 -0700585 /* Containers run without this capability, so avoid setting it in that case */
586 if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {
587 capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND);
588 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800589 /* Hardcoded command line to start the system server */
590 String args[] = {
591 "--setuid=1000",
592 "--setgid=1000",
Pavlin Radoslavov70166252015-11-23 17:13:25 -0800593 "--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 -0700594 "--capabilities=" + capabilities + "," + capabilities,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800595 "--nice-name=system_server",
Narayan Kamathb6b044a2015-02-13 17:31:25 +0000596 "--runtime-args",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800597 "com.android.server.SystemServer",
598 };
599 ZygoteConnection.Arguments parsedArgs = null;
600
601 int pid;
602
603 try {
604 parsedArgs = new ZygoteConnection.Arguments(args);
Jeff Brownebed7d62011-05-16 17:08:42 -0700605 ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
606 ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800607
608 /* Request to fork the system server process */
609 pid = Zygote.forkSystemServer(
610 parsedArgs.uid, parsedArgs.gid,
Elliott Hughese1dfcb72011-07-08 11:08:07 -0700611 parsedArgs.gids,
612 parsedArgs.debugFlags,
613 null,
Andy McFadden1b4c7962010-10-27 11:26:05 -0700614 parsedArgs.permittedCapabilities,
615 parsedArgs.effectiveCapabilities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800616 } catch (IllegalArgumentException ex) {
617 throw new RuntimeException(ex);
Bob Leee5408332009-09-04 18:31:17 -0700618 }
619
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800620 /* For child process */
621 if (pid == 0) {
Narayan Kamath64cd9072014-05-13 13:35:14 +0100622 if (hasSecondZygote(abiList)) {
623 waitForSecondaryZygote(socketName);
624 }
625
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800626 handleSystemServerProcess(parsedArgs);
627 }
628
629 return true;
630 }
631
Alex Klyubin48a06e72013-04-19 10:01:42 -0700632 /**
633 * Gets the bit array representation of the provided list of POSIX capabilities.
634 */
635 private static long posixCapabilitiesAsBits(int... capabilities) {
636 long result = 0;
637 for (int capability : capabilities) {
638 if ((capability < 0) || (capability > OsConstants.CAP_LAST_CAP)) {
639 throw new IllegalArgumentException(String.valueOf(capability));
640 }
641 result |= (1L << capability);
642 }
643 return result;
644 }
645
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800646 public static void main(String argv[]) {
Andreas Gampe1ef8aef2016-04-11 08:39:52 -0700647 // Mark zygote start. This ensures that thread creation will throw
648 // an error.
649 ZygoteHooks.startZygoteNoThreadCreation();
650
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800651 try {
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900652 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygoteInit");
653 RuntimeInit.enableDdms();
654 // Start profiling the zygote initialization.
655 SamplingProfilerIntegration.start();
656
Narayan Kamathc41638c2014-04-07 13:56:15 +0100657 boolean startSystemServer = false;
658 String socketName = "zygote";
659 String abiList = null;
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900660 for (int i = 1; i < argv.length; i++) {
661 if ("start-system-server".equals(argv[i])) {
662 startSystemServer = true;
663 } else if (argv[i].startsWith(ABI_LIST_ARG)) {
664 abiList = argv[i].substring(ABI_LIST_ARG.length());
665 } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
666 socketName = argv[i].substring(SOCKET_NAME_ARG.length());
667 } else {
668 throw new RuntimeException("Unknown command line argument: " + argv[i]);
Narayan Kamathc41638c2014-04-07 13:56:15 +0100669 }
670 }
671
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900672 if (abiList == null) {
673 throw new RuntimeException("No ABI list supplied.");
674 }
675
676 registerZygoteSocket(socketName);
677 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygotePreload");
678 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
679 SystemClock.uptimeMillis());
680 preload();
681 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
682 SystemClock.uptimeMillis());
683 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
684
685 // Finish profiling the zygote initialization.
686 SamplingProfilerIntegration.writeZygoteSnapshot();
687
688 // Do an initial gc to clean up after startup
689 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PostZygoteInitGC");
690 gcAndFinalize();
691 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
692
693 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
694
Jamie Gennis6ad04522013-04-15 18:53:24 -0700695 // Disable tracing so that forked processes do not inherit stale tracing tags from
696 // Zygote.
697 Trace.setTracingEnabled(false);
698
doheon1.lee885b7422016-01-20 13:07:27 +0900699 // Zygote process unmounts root storage spaces.
700 Zygote.nativeUnmountStorageOnInit();
701
Andreas Gampe1ef8aef2016-04-11 08:39:52 -0700702 ZygoteHooks.stopZygoteNoThreadCreation();
703
Narayan Kamathc41638c2014-04-07 13:56:15 +0100704 if (startSystemServer) {
Narayan Kamath64cd9072014-05-13 13:35:14 +0100705 startSystemServer(abiList, socketName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800706 }
707
708 Log.i(TAG, "Accepting command socket connections");
Narayan Kamathc41638c2014-04-07 13:56:15 +0100709 runSelectLoop(abiList);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800710
711 closeServerSocket();
712 } catch (MethodAndArgsCaller caller) {
713 caller.run();
714 } catch (RuntimeException ex) {
715 Log.e(TAG, "Zygote died with exception", ex);
716 closeServerSocket();
717 throw ex;
718 }
719 }
720
721 /**
Narayan Kamath64cd9072014-05-13 13:35:14 +0100722 * Return {@code true} if this device configuration has another zygote.
723 *
724 * We determine this by comparing the device ABI list with this zygotes
725 * list. If this zygote supports all ABIs this device supports, there won't
726 * be another zygote.
727 */
728 private static boolean hasSecondZygote(String abiList) {
729 return !SystemProperties.get("ro.product.cpu.abilist").equals(abiList);
730 }
731
732 private static void waitForSecondaryZygote(String socketName) {
733 String otherZygoteName = Process.ZYGOTE_SOCKET.equals(socketName) ?
734 Process.SECONDARY_ZYGOTE_SOCKET : Process.ZYGOTE_SOCKET;
735 while (true) {
736 try {
737 final Process.ZygoteState zs = Process.ZygoteState.connect(otherZygoteName);
738 zs.close();
739 break;
740 } catch (IOException ioe) {
741 Log.w(TAG, "Got error connecting to zygote, retrying. msg= " + ioe.getMessage());
742 }
743
744 try {
745 Thread.sleep(1000);
746 } catch (InterruptedException ie) {
747 }
748 }
749 }
750
751 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800752 * Runs the zygote process's select loop. Accepts new connections as
753 * they happen, and reads commands from connections one spawn-request's
754 * worth at a time.
755 *
756 * @throws MethodAndArgsCaller in a child process when a main() should
757 * be executed.
758 */
Narayan Kamathc41638c2014-04-07 13:56:15 +0100759 private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
Nick Kralevichcae3d9f2013-01-30 09:51:40 -0800760 ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
761 ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800762
763 fds.add(sServerSocket.getFileDescriptor());
764 peers.add(null);
765
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800766 while (true) {
Elliott Hughes894724b2014-12-15 12:39:51 -0800767 StructPollfd[] pollFds = new StructPollfd[fds.size()];
768 for (int i = 0; i < pollFds.length; ++i) {
769 pollFds[i] = new StructPollfd();
770 pollFds[i].fd = fds.get(i);
771 pollFds[i].events = (short) POLLIN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800772 }
Elliott Hughes894724b2014-12-15 12:39:51 -0800773 try {
774 Os.poll(pollFds, -1);
775 } catch (ErrnoException ex) {
776 throw new RuntimeException("poll failed", ex);
777 }
778 for (int i = pollFds.length - 1; i >= 0; --i) {
779 if ((pollFds[i].revents & POLLIN) == 0) {
780 continue;
781 }
782 if (i == 0) {
783 ZygoteConnection newPeer = acceptCommandPeer(abiList);
784 peers.add(newPeer);
785 fds.add(newPeer.getFileDesciptor());
786 } else {
787 boolean done = peers.get(i).runOnce();
788 if (done) {
789 peers.remove(i);
790 fds.remove(i);
791 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800792 }
793 }
794 }
795 }
796
797 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800798 * Class not instantiable.
799 */
800 private ZygoteInit() {
801 }
802
803 /**
804 * Helper exception class which holds a method and arguments and
805 * can call them. This is used as part of a trampoline to get rid of
806 * the initial process setup stack frames.
807 */
808 public static class MethodAndArgsCaller extends Exception
809 implements Runnable {
810 /** method to call */
811 private final Method mMethod;
812
813 /** argument array */
814 private final String[] mArgs;
815
816 public MethodAndArgsCaller(Method method, String[] args) {
817 mMethod = method;
818 mArgs = args;
819 }
820
821 public void run() {
822 try {
823 mMethod.invoke(null, new Object[] { mArgs });
824 } catch (IllegalAccessException ex) {
825 throw new RuntimeException(ex);
826 } catch (InvocationTargetException ex) {
827 Throwable cause = ex.getCause();
828 if (cause instanceof RuntimeException) {
829 throw (RuntimeException) cause;
830 } else if (cause instanceof Error) {
831 throw (Error) cause;
832 }
833 throw new RuntimeException(ex);
834 }
835 }
836 }
837}