blob: ef5231cb6ff377dddb0b231bb40b1ff54daeef11 [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 Hughesa9569ff2014-04-28 20:53:52 -070019import static android.system.OsConstants.S_IRWXG;
20import static android.system.OsConstants.S_IRWXO;
Kenny Root4c74f8c2012-08-17 08:45:55 -070021
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import android.content.res.Resources;
23import android.content.res.TypedArray;
Neil Fuller4f41f612016-05-09 16:55:36 +010024import android.icu.impl.CacheValue;
25import android.icu.text.DecimalFormatSymbols;
26import android.icu.util.ULocale;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.net.LocalServerSocket;
Romain Guy74c69122013-05-08 17:54:20 -070028import android.opengl.EGL14;
Jeff Sharkey740f5232016-12-09 14:31:26 -070029import android.os.IInstalld;
Jeff Brownebed7d62011-05-16 17:08:42 -070030import android.os.Process;
Jeff Sharkey740f5232016-12-09 14:31:26 -070031import android.os.RemoteException;
32import android.os.ServiceManager;
33import android.os.ServiceSpecificException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034import android.os.SystemClock;
Romain Guyc5e36382013-05-09 11:08:17 -070035import android.os.SystemProperties;
Jamie Gennis6ad04522013-04-15 18:53:24 -070036import android.os.Trace;
Robert Sesek8f8d1872016-03-18 16:52:57 -040037import android.os.ZygoteProcess;
Jeff Sharkeyc98c7bc2016-12-07 14:57:34 -070038import android.os.storage.StorageManager;
Sergio Giro69de3202016-05-17 16:52:33 +010039import android.security.keystore.AndroidKeyStoreProvider;
Bill Yi9a76e9b2014-04-29 18:52:48 -070040import android.system.ErrnoException;
Elliott Hughes860c5912014-04-28 19:19:13 -070041import android.system.Os;
42import android.system.OsConstants;
Raph Levienc3dd1c12015-04-06 10:37:57 -070043import android.text.Hyphenator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044import android.util.EventLog;
45import android.util.Log;
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +010046import android.webkit.WebViewFactory;
Andreas Gampeddc13972016-02-26 16:54:59 -080047import android.widget.TextView;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048
Jeff Sharkeyfdeeeea2016-01-11 17:34:24 -070049
Narayan Kamath29564cd2014-08-07 10:57:40 +010050import dalvik.system.DexFile;
51import dalvik.system.PathClassLoader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import dalvik.system.VMRuntime;
Andreas Gampe1ef8aef2016-04-11 08:39:52 -070053import dalvik.system.ZygoteHooks;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054
Brian Carlstrom46703b02011-04-06 15:41:29 -070055import libcore.io.IoUtils;
56
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057import java.io.BufferedReader;
Ying Wangd0c45352014-11-13 15:22:47 -080058import java.io.FileInputStream;
59import java.io.FileNotFoundException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060import java.io.IOException;
61import java.io.InputStream;
62import java.io.InputStreamReader;
Sergio Giro6cb7b1c2016-05-13 16:34:46 +010063import java.security.Security;
64import java.security.Provider;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065
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
Jesse Halle8ce1272017-01-17 12:34:14 -080081 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084 private static final int LOG_BOOT_PROGRESS_PRELOAD_START = 3020;
85 private static final int LOG_BOOT_PROGRESS_PRELOAD_END = 3030;
86
87 /** when preloading, GC after allocating this many bytes */
88 private static final int PRELOAD_GC_THRESHOLD = 50000;
89
Narayan Kamathc41638c2014-04-07 13:56:15 +010090 private static final String ABI_LIST_ARG = "--abi-list=";
91
92 private static final String SOCKET_NAME_ARG = "--socket-name=";
Barry Hayes0b3533a2010-01-20 12:46:47 -080093
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094 /**
Tobias Sargeantdd4bb312016-01-19 16:34:54 +000095 * Used to pre-load resources.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096 */
97 private static Resources mResources;
Bob Leee5408332009-09-04 18:31:17 -070098
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099 /**
Ying Wangd0c45352014-11-13 15:22:47 -0800100 * The path of a file that contains classes to preload.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101 */
Ying Wangd0c45352014-11-13 15:22:47 -0800102 private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103
104 /** Controls whether we should preload resources during zygote init. */
Steve Paik3c27a232015-06-10 18:25:44 -0700105 public static final boolean PRELOAD_RESOURCES = true;
Andy McFadden599c9182009-04-08 00:35:56 -0700106
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107 private static final int UNPRIVILEGED_UID = 9999;
108 private static final int UNPRIVILEGED_GID = 9999;
109
110 private static final int ROOT_UID = 0;
111 private static final int ROOT_GID = 0;
112
Jeff Brown0c2313d2011-06-10 22:46:40 -0700113 static void preload() {
Bill Yi9a76e9b2014-04-29 18:52:48 -0700114 Log.d(TAG, "begin preload");
Neil Fuller4f41f612016-05-09 16:55:36 +0100115 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "BeginIcuCachePinning");
116 beginIcuCachePinning();
117 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900118 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadClasses");
119 preloadClasses();
120 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
121 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadResources");
122 preloadResources();
123 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
Jesse Halle8ce1272017-01-17 12:34:14 -0800124 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadOpenGL");
125 preloadOpenGL();
126 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
Brian Carlstrom6c9af962014-09-11 15:36:00 -0700127 preloadSharedLibraries();
Raph Levienc3dd1c12015-04-06 10:37:57 -0700128 preloadTextResources();
Torne (Richard Coles)08cfaf62014-05-08 16:07:05 +0100129 // Ask the WebViewFactory to do any initialization that must run in the zygote process,
130 // for memory sharing purposes.
131 WebViewFactory.prepareWebViewInZygote();
Neil Fuller4f41f612016-05-09 16:55:36 +0100132 endIcuCachePinning();
Sergio Giro6cb7b1c2016-05-13 16:34:46 +0100133 warmUpJcaProviders();
Bill Yi9a76e9b2014-04-29 18:52:48 -0700134 Log.d(TAG, "end preload");
Romain Guy74c69122013-05-08 17:54:20 -0700135 }
136
Neil Fuller4f41f612016-05-09 16:55:36 +0100137 private static void beginIcuCachePinning() {
138 // Pin ICU data in memory from this point that would normally be held by soft references.
139 // Without this, any references created immediately below or during class preloading
140 // would be collected when the Zygote GC runs in gcAndFinalize().
141 Log.i(TAG, "Installing ICU cache reference pinning...");
142
143 CacheValue.setStrength(CacheValue.Strength.STRONG);
144
145 Log.i(TAG, "Preloading ICU data...");
146 // Explicitly exercise code to cache data apps are likely to need.
147 ULocale[] localesToPin = { ULocale.ROOT, ULocale.US, ULocale.getDefault() };
148 for (ULocale uLocale : localesToPin) {
149 new DecimalFormatSymbols(uLocale);
150 }
151 }
152
153 private static void endIcuCachePinning() {
154 // All cache references created by ICU from this point will be soft.
155 CacheValue.setStrength(CacheValue.Strength.SOFT);
156
157 Log.i(TAG, "Uninstalled ICU cache reference pinning...");
158 }
159
Brian Carlstrom6c9af962014-09-11 15:36:00 -0700160 private static void preloadSharedLibraries() {
161 Log.i(TAG, "Preloading shared libraries...");
162 System.loadLibrary("android");
163 System.loadLibrary("compiler_rt");
164 System.loadLibrary("jnigraphics");
165 }
166
Jesse Halle8ce1272017-01-17 12:34:14 -0800167 private static void preloadOpenGL() {
168 if (!SystemProperties.getBoolean(PROPERTY_DISABLE_OPENGL_PRELOADING, false)) {
169 EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
170 }
171 }
172
Raph Levienc3dd1c12015-04-06 10:37:57 -0700173 private static void preloadTextResources() {
174 Hyphenator.init();
Andreas Gampeddc13972016-02-26 16:54:59 -0800175 TextView.preloadFontCache();
Raph Levienc3dd1c12015-04-06 10:37:57 -0700176 }
177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800178 /**
Sergio Giro69de3202016-05-17 16:52:33 +0100179 * Register AndroidKeyStoreProvider and warm up the providers that are already registered.
Sergio Giro6cb7b1c2016-05-13 16:34:46 +0100180 *
181 * By doing it here we avoid that each app does it when requesting a service from the
182 * provider for the first time.
183 */
184 private static void warmUpJcaProviders() {
185 long startTime = SystemClock.uptimeMillis();
186 Trace.traceBegin(
Sergio Giro69de3202016-05-17 16:52:33 +0100187 Trace.TRACE_TAG_DALVIK, "Starting installation of AndroidKeyStoreProvider");
188 // AndroidKeyStoreProvider.install() manipulates the list of JCA providers to insert
189 // preferred providers. Note this is not done via security.properties as the JCA providers
190 // are not on the classpath in the case of, for example, raw dalvikvm runtimes.
191 AndroidKeyStoreProvider.install();
192 Log.i(TAG, "Installed AndroidKeyStoreProvider in "
193 + (SystemClock.uptimeMillis() - startTime) + "ms.");
194 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
195
196 startTime = SystemClock.uptimeMillis();
197 Trace.traceBegin(
Sergio Giro6cb7b1c2016-05-13 16:34:46 +0100198 Trace.TRACE_TAG_DALVIK, "Starting warm up of JCA providers");
199 for (Provider p : Security.getProviders()) {
200 p.warmUpServiceProvision();
201 }
202 Log.i(TAG, "Warmed up JCA providers in "
Sergio Giro69de3202016-05-17 16:52:33 +0100203 + (SystemClock.uptimeMillis() - startTime) + "ms.");
Sergio Giro6cb7b1c2016-05-13 16:34:46 +0100204 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
205 }
206
207 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208 * Performs Zygote process initialization. Loads and initializes
209 * commonly used classes.
210 *
211 * Most classes only cause a few hundred bytes to be allocated, but
212 * a few will allocate a dozen Kbytes (in one case, 500+K).
213 */
214 private static void preloadClasses() {
215 final VMRuntime runtime = VMRuntime.getRuntime();
Bob Leee5408332009-09-04 18:31:17 -0700216
Ying Wangd0c45352014-11-13 15:22:47 -0800217 InputStream is;
218 try {
219 is = new FileInputStream(PRELOADED_CLASSES);
220 } catch (FileNotFoundException e) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221 Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");
Ying Wangd0c45352014-11-13 15:22:47 -0800222 return;
223 }
Bob Leee5408332009-09-04 18:31:17 -0700224
Ying Wangd0c45352014-11-13 15:22:47 -0800225 Log.i(TAG, "Preloading classes...");
226 long startTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227
Ying Wangd0c45352014-11-13 15:22:47 -0800228 // Drop root perms while running static initializers.
Narayan Kamath23e68782015-01-16 17:22:41 +0000229 final int reuid = Os.getuid();
230 final int regid = Os.getgid();
231
232 // We need to drop root perms only if we're already root. In the case of "wrapped"
233 // processes (see WrapperInit), this function is called from an unprivileged uid
234 // and gid.
235 boolean droppedPriviliges = false;
236 if (reuid == ROOT_UID && regid == ROOT_GID) {
237 try {
238 Os.setregid(ROOT_GID, UNPRIVILEGED_GID);
239 Os.setreuid(ROOT_UID, UNPRIVILEGED_UID);
240 } catch (ErrnoException ex) {
241 throw new RuntimeException("Failed to drop root", ex);
242 }
243
244 droppedPriviliges = true;
Elliott Hughes26b56e62014-12-17 12:28:29 -0800245 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246
Ying Wangd0c45352014-11-13 15:22:47 -0800247 // Alter the target heap utilization. With explicit GCs this
248 // is not likely to have any effect.
249 float defaultUtilization = runtime.getTargetHeapUtilization();
250 runtime.setTargetHeapUtilization(0.8f);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800251
Ying Wangd0c45352014-11-13 15:22:47 -0800252 try {
253 BufferedReader br
254 = new BufferedReader(new InputStreamReader(is), 256);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255
Ying Wangd0c45352014-11-13 15:22:47 -0800256 int count = 0;
257 String line;
258 while ((line = br.readLine()) != null) {
259 // Skip comments and blank lines.
260 line = line.trim();
261 if (line.startsWith("#") || line.equals("")) {
262 continue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263 }
264
Andreas Gampec4253622016-10-28 18:19:30 -0700265 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, line);
Ying Wangd0c45352014-11-13 15:22:47 -0800266 try {
267 if (false) {
268 Log.v(TAG, "Preloading " + line + "...");
269 }
Andreas Gampedd8e5fb2015-04-21 09:01:51 -0700270 // Load and explicitly initialize the given class. Use
271 // Class.forName(String, boolean, ClassLoader) to avoid repeated stack lookups
272 // (to derive the caller's class-loader). Use true to force initialization, and
273 // null for the boot classpath class-loader (could as well cache the
274 // class-loader of this class in a variable).
Andreas Gampec917f742015-04-20 19:16:37 -0700275 Class.forName(line, true, null);
Ying Wangd0c45352014-11-13 15:22:47 -0800276 count++;
277 } catch (ClassNotFoundException e) {
278 Log.w(TAG, "Class not found for preloading: " + line);
279 } catch (UnsatisfiedLinkError e) {
280 Log.w(TAG, "Problem preloading " + line + ": " + e);
281 } catch (Throwable t) {
282 Log.e(TAG, "Error preloading " + line + ".", t);
283 if (t instanceof Error) {
284 throw (Error) t;
285 }
286 if (t instanceof RuntimeException) {
287 throw (RuntimeException) t;
288 }
289 throw new RuntimeException(t);
290 }
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900291 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292 }
Ying Wangd0c45352014-11-13 15:22:47 -0800293
294 Log.i(TAG, "...preloaded " + count + " classes in "
295 + (SystemClock.uptimeMillis()-startTime) + "ms.");
296 } catch (IOException e) {
297 Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
298 } finally {
299 IoUtils.closeQuietly(is);
300 // Restore default.
301 runtime.setTargetHeapUtilization(defaultUtilization);
302
303 // Fill in dex caches with classes, fields, and methods brought in by preloading.
Yasuhiro Matsuda1ab43d52015-06-30 17:07:32 +0900304 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadDexCaches");
Ying Wangd0c45352014-11-13 15:22:47 -0800305 runtime.preloadDexCaches();
Yasuhiro Matsuda1ab43d52015-06-30 17:07:32 +0900306 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
Ying Wangd0c45352014-11-13 15:22:47 -0800307
Narayan Kamath23e68782015-01-16 17:22:41 +0000308 // Bring back root. We'll need it later if we're in the zygote.
309 if (droppedPriviliges) {
310 try {
311 Os.setreuid(ROOT_UID, ROOT_UID);
312 Os.setregid(ROOT_GID, ROOT_GID);
313 } catch (ErrnoException ex) {
314 throw new RuntimeException("Failed to restore root", ex);
315 }
Elliott Hughes26b56e62014-12-17 12:28:29 -0800316 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800317 }
318 }
319
320 /**
321 * Load in commonly used resources, so they can be shared across
322 * processes.
323 *
324 * These tend to be a few Kbytes, but are frequently in the 20-40K
325 * range, and occasionally even larger.
326 */
327 private static void preloadResources() {
328 final VMRuntime runtime = VMRuntime.getRuntime();
Bob Leee5408332009-09-04 18:31:17 -0700329
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330 try {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800331 mResources = Resources.getSystem();
332 mResources.startPreloading();
333 if (PRELOAD_RESOURCES) {
334 Log.i(TAG, "Preloading resources...");
335
336 long startTime = SystemClock.uptimeMillis();
337 TypedArray ar = mResources.obtainTypedArray(
338 com.android.internal.R.array.preloaded_drawables);
Filip Gruszczynski811dc3b2015-11-23 12:34:22 -0800339 int N = preloadDrawables(ar);
Jeff Brown14577c42012-03-08 16:40:14 -0800340 ar.recycle();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341 Log.i(TAG, "...preloaded " + N + " resources in "
342 + (SystemClock.uptimeMillis()-startTime) + "ms.");
343
344 startTime = SystemClock.uptimeMillis();
345 ar = mResources.obtainTypedArray(
346 com.android.internal.R.array.preloaded_color_state_lists);
Filip Gruszczynski811dc3b2015-11-23 12:34:22 -0800347 N = preloadColorStateLists(ar);
Jeff Brown14577c42012-03-08 16:40:14 -0800348 ar.recycle();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800349 Log.i(TAG, "...preloaded " + N + " resources in "
350 + (SystemClock.uptimeMillis()-startTime) + "ms.");
Filip Gruszczynski811dc3b2015-11-23 12:34:22 -0800351
352 if (mResources.getBoolean(
353 com.android.internal.R.bool.config_freeformWindowManagement)) {
354 startTime = SystemClock.uptimeMillis();
355 ar = mResources.obtainTypedArray(
356 com.android.internal.R.array.preloaded_freeform_multi_window_drawables);
357 N = preloadDrawables(ar);
358 ar.recycle();
359 Log.i(TAG, "...preloaded " + N + " resource in "
360 + (SystemClock.uptimeMillis() - startTime) + "ms.");
361 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800362 }
363 mResources.finishPreloading();
364 } catch (RuntimeException e) {
365 Log.w(TAG, "Failure preloading resources", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800366 }
367 }
368
Filip Gruszczynski811dc3b2015-11-23 12:34:22 -0800369 private static int preloadColorStateLists(TypedArray ar) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370 int N = ar.length();
371 for (int i=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800372 int id = ar.getResourceId(i, 0);
Joe Onorato43a17652011-04-06 19:22:23 -0700373 if (false) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800374 Log.v(TAG, "Preloading resource #" + Integer.toHexString(id));
375 }
376 if (id != 0) {
Alan Viverette77bb6f12015-02-11 17:24:33 -0800377 if (mResources.getColorStateList(id, null) == null) {
Dianne Hackborndde331c2012-08-03 14:01:57 -0700378 throw new IllegalArgumentException(
379 "Unable to find preloaded color resource #0x"
380 + Integer.toHexString(id)
381 + " (" + ar.getString(i) + ")");
382 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800383 }
384 }
385 return N;
386 }
387
388
Filip Gruszczynski811dc3b2015-11-23 12:34:22 -0800389 private static int preloadDrawables(TypedArray ar) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800390 int N = ar.length();
391 for (int i=0; i<N; i++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392 int id = ar.getResourceId(i, 0);
Joe Onorato43a17652011-04-06 19:22:23 -0700393 if (false) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800394 Log.v(TAG, "Preloading resource #" + Integer.toHexString(id));
395 }
396 if (id != 0) {
Alan Viverette84e001a2014-09-22 00:04:22 -0700397 if (mResources.getDrawable(id, null) == null) {
Dianne Hackborndde331c2012-08-03 14:01:57 -0700398 throw new IllegalArgumentException(
399 "Unable to find preloaded drawable resource #0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800400 + Integer.toHexString(id)
Dianne Hackborndde331c2012-08-03 14:01:57 -0700401 + " (" + ar.getString(i) + ")");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800402 }
403 }
404 }
405 return N;
406 }
407
408 /**
409 * Runs several special GCs to try to clean up a few generations of
410 * softly- and final-reachable objects, along with any other garbage.
411 * This is only useful just before a fork().
412 */
Mathieu Chartier9a88f102014-08-20 10:24:11 -0700413 /*package*/ static void gcAndFinalize() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414 final VMRuntime runtime = VMRuntime.getRuntime();
415
416 /* runFinalizationSync() lets finalizers be called in Zygote,
417 * which doesn't have a HeapWorker thread.
418 */
Brian Carlstrom08065b92011-04-01 15:49:41 -0700419 System.gc();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800420 runtime.runFinalizationSync();
Brian Carlstrom08065b92011-04-01 15:49:41 -0700421 System.gc();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800422 }
423
424 /**
425 * Finish remaining work for the newly forked system server process.
426 */
427 private static void handleSystemServerProcess(
428 ZygoteConnection.Arguments parsedArgs)
Tobias Sargeantdd4bb312016-01-19 16:34:54 +0000429 throws Zygote.MethodAndArgsCaller {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800430
Mike Lockwood90960e82010-08-06 09:15:25 -0400431 // set umask to 0077 so new files and directories will default to owner-only permissions.
Elliott Hughes860c5912014-04-28 19:19:13 -0700432 Os.umask(S_IRWXG | S_IRWXO);
Mike Lockwood90960e82010-08-06 09:15:25 -0400433
Jeff Brownebed7d62011-05-16 17:08:42 -0700434 if (parsedArgs.niceName != null) {
435 Process.setArgV0(parsedArgs.niceName);
436 }
437
Narayan Kamath29564cd2014-08-07 10:57:40 +0100438 final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
439 if (systemServerClasspath != null) {
440 performSystemServerDexOpt(systemServerClasspath);
441 }
442
Jeff Brownebed7d62011-05-16 17:08:42 -0700443 if (parsedArgs.invokeWith != null) {
Narayan Kamath29564cd2014-08-07 10:57:40 +0100444 String[] args = parsedArgs.remainingArgs;
445 // If we have a non-null system server class path, we'll have to duplicate the
446 // existing arguments and append the classpath to it. ART will handle the classpath
447 // correctly when we exec a new process.
448 if (systemServerClasspath != null) {
449 String[] amendedArgs = new String[args.length + 2];
450 amendedArgs[0] = "-cp";
451 amendedArgs[1] = systemServerClasspath;
452 System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);
453 }
454
Jeff Brownebed7d62011-05-16 17:08:42 -0700455 WrapperInit.execApplication(parsedArgs.invokeWith,
Elliott Hughese1dfcb72011-07-08 11:08:07 -0700456 parsedArgs.niceName, parsedArgs.targetSdkVersion,
Narayan Kamath37ad4b02015-01-19 16:05:24 +0000457 VMRuntime.getCurrentInstructionSet(), null, args);
Jeff Brownebed7d62011-05-16 17:08:42 -0700458 } else {
Narayan Kamath29564cd2014-08-07 10:57:40 +0100459 ClassLoader cl = null;
460 if (systemServerClasspath != null) {
Dimitry Ivanov89dad332016-04-20 16:02:00 -0700461 cl = createSystemServerClassLoader(systemServerClasspath,
462 parsedArgs.targetSdkVersion);
463
Narayan Kamath29564cd2014-08-07 10:57:40 +0100464 Thread.currentThread().setContextClassLoader(cl);
465 }
466
Jeff Brownebed7d62011-05-16 17:08:42 -0700467 /*
468 * Pass the remaining arguments to SystemServer.
469 */
Narayan Kamath29564cd2014-08-07 10:57:40 +0100470 RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
Jeff Brownebed7d62011-05-16 17:08:42 -0700471 }
472
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800473 /* should never reach here */
474 }
475
476 /**
Dimitry Ivanov89dad332016-04-20 16:02:00 -0700477 * Creates a PathClassLoader for the system server. It also creates
478 * a shared namespace associated with the classloader to let it access
479 * platform-private native libraries.
480 */
481 private static PathClassLoader createSystemServerClassLoader(String systemServerClasspath,
482 int targetSdkVersion) {
Dimitry Ivanov9e9061f2016-09-20 10:50:40 -0700483 String libraryPath = System.getProperty("java.library.path");
Dimitry Ivanov89dad332016-04-20 16:02:00 -0700484
485 return PathClassLoaderFactory.createClassLoader(systemServerClasspath,
Dimitry Ivanov9e9061f2016-09-20 10:50:40 -0700486 libraryPath,
487 libraryPath,
Dimitry Ivanov89dad332016-04-20 16:02:00 -0700488 ClassLoader.getSystemClassLoader(),
489 targetSdkVersion,
490 true /* isNamespaceShared */);
491 }
492
493 /**
Narayan Kamath29564cd2014-08-07 10:57:40 +0100494 * Performs dex-opt on the elements of {@code classPath}, if needed. We
495 * choose the instruction set of the current runtime.
496 */
497 private static void performSystemServerDexOpt(String classPath) {
498 final String[] classPathElements = classPath.split(":");
Jeff Sharkey740f5232016-12-09 14:31:26 -0700499 final IInstalld installd = IInstalld.Stub
500 .asInterface(ServiceManager.getService("installd"));
Narayan Kamath29564cd2014-08-07 10:57:40 +0100501 final String instructionSet = VMRuntime.getRuntime().vmInstructionSet();
502
Jeff Sharkey740f5232016-12-09 14:31:26 -0700503 String sharedLibraries = "";
504 for (String classPathElement : classPathElements) {
505 // System server is fully AOTed and never profiled
506 // for profile guided compilation.
507 // TODO: Make this configurable between INTERPRET_ONLY, SPEED, SPACE and EVERYTHING?
Andreas Gampee7bc1522016-08-09 20:44:04 -0700508
Jeff Sharkey740f5232016-12-09 14:31:26 -0700509 int dexoptNeeded;
510 try {
511 dexoptNeeded = DexFile.getDexOptNeeded(
512 classPathElement, instructionSet, "speed",
513 false /* newProfile */);
514 } catch (FileNotFoundException ignored) {
515 // Do not add to the classpath.
516 Log.w(TAG, "Missing classpath element for system server: " + classPathElement);
517 continue;
518 } catch (IOException e) {
519 // Not fully clear what to do here as we don't know the cause of the
520 // IO exception. Add to the classpath to be conservative, but don't
521 // attempt to compile it.
522 Log.w(TAG, "Error checking classpath element for system server: "
523 + classPathElement, e);
524 dexoptNeeded = DexFile.NO_DEXOPT_NEEDED;
Narayan Kamath29564cd2014-08-07 10:57:40 +0100525 }
Jeff Sharkey740f5232016-12-09 14:31:26 -0700526
527 if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
528 final String packageName = "*";
529 final String outputPath = null;
530 final int dexFlags = 0;
531 final String compilerFilter = "speed";
532 final String uuid = StorageManager.UUID_PRIVATE_INTERNAL;
533 try {
534 installd.dexopt(classPathElement, Process.SYSTEM_UID, packageName,
535 instructionSet, dexoptNeeded, outputPath, dexFlags, compilerFilter,
536 uuid, sharedLibraries);
537 } catch (RemoteException | ServiceSpecificException e) {
538 // Ignore (but log), we need this on the classpath for fallback mode.
539 Log.w(TAG, "Failed compiling classpath element for system server: "
540 + classPathElement, e);
541 }
542 }
543
544 if (!sharedLibraries.isEmpty()) {
545 sharedLibraries += ":";
546 }
547 sharedLibraries += classPathElement;
Narayan Kamath29564cd2014-08-07 10:57:40 +0100548 }
549 }
550
551 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800552 * Prepare the arguments and fork for the system server process.
553 */
Tobias Sargeantdd4bb312016-01-19 16:34:54 +0000554 private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
555 throws Zygote.MethodAndArgsCaller, RuntimeException {
Alex Klyubin48a06e72013-04-19 10:01:42 -0700556 long capabilities = posixCapabilitiesAsBits(
Philip Cuadra7bd0fdd2016-04-28 15:26:49 -0700557 OsConstants.CAP_IPC_LOCK,
Alex Klyubin48a06e72013-04-19 10:01:42 -0700558 OsConstants.CAP_KILL,
559 OsConstants.CAP_NET_ADMIN,
560 OsConstants.CAP_NET_BIND_SERVICE,
561 OsConstants.CAP_NET_BROADCAST,
562 OsConstants.CAP_NET_RAW,
Alex Klyubin48a06e72013-04-19 10:01:42 -0700563 OsConstants.CAP_SYS_MODULE,
564 OsConstants.CAP_SYS_NICE,
565 OsConstants.CAP_SYS_RESOURCE,
566 OsConstants.CAP_SYS_TIME,
John Stultz5733f382016-07-28 12:35:31 -0700567 OsConstants.CAP_SYS_TTY_CONFIG,
568 OsConstants.CAP_WAKE_ALARM
Alex Klyubin48a06e72013-04-19 10:01:42 -0700569 );
Luis Hector Chavez5dd239a2015-10-06 14:01:45 -0700570 /* Containers run without this capability, so avoid setting it in that case */
571 if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {
572 capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND);
573 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800574 /* Hardcoded command line to start the system server */
575 String args[] = {
576 "--setuid=1000",
577 "--setgid=1000",
Pavlin Radoslavov70166252015-11-23 17:13:25 -0800578 "--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 -0700579 "--capabilities=" + capabilities + "," + capabilities,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800580 "--nice-name=system_server",
Narayan Kamathb6b044a2015-02-13 17:31:25 +0000581 "--runtime-args",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800582 "com.android.server.SystemServer",
583 };
584 ZygoteConnection.Arguments parsedArgs = null;
585
586 int pid;
587
588 try {
589 parsedArgs = new ZygoteConnection.Arguments(args);
Jeff Brownebed7d62011-05-16 17:08:42 -0700590 ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
591 ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800592
593 /* Request to fork the system server process */
594 pid = Zygote.forkSystemServer(
595 parsedArgs.uid, parsedArgs.gid,
Elliott Hughese1dfcb72011-07-08 11:08:07 -0700596 parsedArgs.gids,
597 parsedArgs.debugFlags,
598 null,
Andy McFadden1b4c7962010-10-27 11:26:05 -0700599 parsedArgs.permittedCapabilities,
600 parsedArgs.effectiveCapabilities);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800601 } catch (IllegalArgumentException ex) {
602 throw new RuntimeException(ex);
Bob Leee5408332009-09-04 18:31:17 -0700603 }
604
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800605 /* For child process */
606 if (pid == 0) {
Narayan Kamath64cd9072014-05-13 13:35:14 +0100607 if (hasSecondZygote(abiList)) {
608 waitForSecondaryZygote(socketName);
609 }
610
Tobias Sargeantdd4bb312016-01-19 16:34:54 +0000611 zygoteServer.closeServerSocket();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800612 handleSystemServerProcess(parsedArgs);
613 }
614
615 return true;
616 }
617
Alex Klyubin48a06e72013-04-19 10:01:42 -0700618 /**
619 * Gets the bit array representation of the provided list of POSIX capabilities.
620 */
621 private static long posixCapabilitiesAsBits(int... capabilities) {
622 long result = 0;
623 for (int capability : capabilities) {
624 if ((capability < 0) || (capability > OsConstants.CAP_LAST_CAP)) {
625 throw new IllegalArgumentException(String.valueOf(capability));
626 }
627 result |= (1L << capability);
628 }
629 return result;
630 }
631
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800632 public static void main(String argv[]) {
Tobias Sargeantdd4bb312016-01-19 16:34:54 +0000633 ZygoteServer zygoteServer = new ZygoteServer();
634
Andreas Gampe1ef8aef2016-04-11 08:39:52 -0700635 // Mark zygote start. This ensures that thread creation will throw
636 // an error.
637 ZygoteHooks.startZygoteNoThreadCreation();
638
Robert Seseke4f8d692016-09-13 19:13:01 -0400639 // Zygote goes into its own process group.
640 try {
641 Os.setpgid(0, 0);
642 } catch (ErrnoException ex) {
643 throw new RuntimeException("Failed to setpgid(0,0)", ex);
644 }
645
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800646 try {
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900647 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygoteInit");
648 RuntimeInit.enableDdms();
649 // Start profiling the zygote initialization.
650 SamplingProfilerIntegration.start();
651
Narayan Kamathc41638c2014-04-07 13:56:15 +0100652 boolean startSystemServer = false;
653 String socketName = "zygote";
654 String abiList = null;
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900655 for (int i = 1; i < argv.length; i++) {
656 if ("start-system-server".equals(argv[i])) {
657 startSystemServer = true;
658 } else if (argv[i].startsWith(ABI_LIST_ARG)) {
659 abiList = argv[i].substring(ABI_LIST_ARG.length());
660 } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
661 socketName = argv[i].substring(SOCKET_NAME_ARG.length());
662 } else {
663 throw new RuntimeException("Unknown command line argument: " + argv[i]);
Narayan Kamathc41638c2014-04-07 13:56:15 +0100664 }
665 }
666
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900667 if (abiList == null) {
668 throw new RuntimeException("No ABI list supplied.");
669 }
670
Tobias Sargeantdd4bb312016-01-19 16:34:54 +0000671 zygoteServer.registerServerSocket(socketName);
Yasuhiro Matsuda25878b22015-09-03 16:18:21 +0900672 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygotePreload");
673 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
674 SystemClock.uptimeMillis());
675 preload();
676 EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
677 SystemClock.uptimeMillis());
678 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
679
680 // Finish profiling the zygote initialization.
681 SamplingProfilerIntegration.writeZygoteSnapshot();
682
683 // Do an initial gc to clean up after startup
684 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PostZygoteInitGC");
685 gcAndFinalize();
686 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
687
Jamie Gennis6ad04522013-04-15 18:53:24 -0700688 // Disable tracing so that forked processes do not inherit stale tracing tags from
689 // Zygote.
690 Trace.setTracingEnabled(false);
691
doheon1.lee885b7422016-01-20 13:07:27 +0900692 // Zygote process unmounts root storage spaces.
693 Zygote.nativeUnmountStorageOnInit();
694
Andreas Gampe1ef8aef2016-04-11 08:39:52 -0700695 ZygoteHooks.stopZygoteNoThreadCreation();
696
Narayan Kamathc41638c2014-04-07 13:56:15 +0100697 if (startSystemServer) {
Tobias Sargeantdd4bb312016-01-19 16:34:54 +0000698 startSystemServer(abiList, socketName, zygoteServer);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800699 }
700
701 Log.i(TAG, "Accepting command socket connections");
Tobias Sargeantdd4bb312016-01-19 16:34:54 +0000702 zygoteServer.runSelectLoop(abiList);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800703
Tobias Sargeantdd4bb312016-01-19 16:34:54 +0000704 zygoteServer.closeServerSocket();
705 } catch (Zygote.MethodAndArgsCaller caller) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800706 caller.run();
Christopher Ferrisea8b5de2016-06-17 15:29:58 -0700707 } catch (Throwable ex) {
Tobias Sargeantdd4bb312016-01-19 16:34:54 +0000708 Log.e(TAG, "System zygote died with exception", ex);
709 zygoteServer.closeServerSocket();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800710 throw ex;
711 }
712 }
713
714 /**
Narayan Kamath64cd9072014-05-13 13:35:14 +0100715 * Return {@code true} if this device configuration has another zygote.
716 *
717 * We determine this by comparing the device ABI list with this zygotes
718 * list. If this zygote supports all ABIs this device supports, there won't
719 * be another zygote.
720 */
721 private static boolean hasSecondZygote(String abiList) {
722 return !SystemProperties.get("ro.product.cpu.abilist").equals(abiList);
723 }
724
725 private static void waitForSecondaryZygote(String socketName) {
726 String otherZygoteName = Process.ZYGOTE_SOCKET.equals(socketName) ?
727 Process.SECONDARY_ZYGOTE_SOCKET : Process.ZYGOTE_SOCKET;
728 while (true) {
729 try {
Robert Sesek8f8d1872016-03-18 16:52:57 -0400730 final ZygoteProcess.ZygoteState zs =
731 ZygoteProcess.ZygoteState.connect(otherZygoteName);
Narayan Kamath64cd9072014-05-13 13:35:14 +0100732 zs.close();
733 break;
734 } catch (IOException ioe) {
735 Log.w(TAG, "Got error connecting to zygote, retrying. msg= " + ioe.getMessage());
736 }
737
738 try {
739 Thread.sleep(1000);
740 } catch (InterruptedException ie) {
741 }
742 }
743 }
744
745 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800746 * Class not instantiable.
747 */
748 private ZygoteInit() {
749 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800750}