1 /*
2  * Copyright (C) 2006 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 
17 package dalvik.system;
18 
19 import android.icu.impl.CacheValue;
20 import android.icu.text.DateFormatSymbols;
21 import android.icu.text.DecimalFormatSymbols;
22 import android.icu.util.ULocale;
23 
24 import java.io.File;
25 import java.io.FileDescriptor;
26 
27 /**
28  * Provides hooks for the zygote to call back into the runtime to perform
29  * parent or child specific initialization..
30  *
31  * @hide
32  */
33 @libcore.api.CorePlatformApi
34 public final class ZygoteHooks {
35     private static long token;
36 
37     /** All methods are static, no need to instantiate. */
ZygoteHooks()38     private ZygoteHooks() {
39     }
40 
41     /**
42      * Called by the zygote when starting up. It marks the point when any thread
43      * start should be an error, as only internal daemon threads are allowed there.
44      */
45     @libcore.api.CorePlatformApi
startZygoteNoThreadCreation()46     public static native void startZygoteNoThreadCreation();
47 
48     /**
49      * Called when the zygote begins preloading classes and data.
50      */
51     @libcore.api.CorePlatformApi
onBeginPreload()52     public static void onBeginPreload() {
53         // Pin ICU data in memory from this point that would normally be held by soft references.
54         // Without this, any references created immediately below or during class preloading
55         // would be collected when the Zygote GC runs in gcAndFinalize().
56         CacheValue.setStrength(CacheValue.Strength.STRONG);
57 
58         // Explicitly exercise code to cache data apps/framework are likely to need.
59         ULocale[] localesToPin = { ULocale.ROOT, ULocale.US, ULocale.getDefault() };
60         for (ULocale uLocale : localesToPin) {
61             new DecimalFormatSymbols(uLocale);
62             new DateFormatSymbols(uLocale);
63         }
64 
65         // Framework's LocalLog is used during app start-up. It indirectly uses the current ICU time
66         // zone. Pre-loading the current time zone in ICU improves app startup time. b/150605074
67         // We're being explicit about the fully qualified name of the TimeZone class to avoid
68         // confusion with java.util.TimeZome.getDefault().
69         android.icu.util.TimeZone.getDefault();
70     }
71 
72     /**
73      * Called when the zygote has completed preloading classes and data.
74      */
75     @libcore.api.CorePlatformApi
onEndPreload()76     public static void onEndPreload() {
77         // All cache references created by ICU from this point will be soft.
78         CacheValue.setStrength(CacheValue.Strength.SOFT);
79 
80         // Clone standard descriptors as originals closed / rebound during zygote post fork.
81         FileDescriptor.in.cloneForFork();
82         FileDescriptor.out.cloneForFork();
83         FileDescriptor.err.cloneForFork();
84     }
85 
86     /**
87      * Runs several special GCs to try to clean up a few generations of
88      * softly- and final-reachable objects, along with any other garbage.
89      * This is only useful just before a fork().
90      */
91     @libcore.api.CorePlatformApi
gcAndFinalize()92     public static void gcAndFinalize() {
93         final VMRuntime runtime = VMRuntime.getRuntime();
94 
95         /* runFinalizationSync() lets finalizers be called in Zygote,
96          * which doesn't have a HeapWorker thread.
97          */
98         System.gc();
99         runtime.runFinalizationSync();
100         System.gc();
101     }
102 
103     /**
104      * Called by the zygote when startup is finished. It marks the point when it is
105      * conceivable that threads would be started again, e.g., restarting daemons.
106      */
107     @libcore.api.CorePlatformApi
stopZygoteNoThreadCreation()108     public static native void stopZygoteNoThreadCreation();
109 
110     /**
111      * Called by the zygote prior to every fork. Each call to {@code preFork}
112      * is followed by a matching call to {@link #postForkChild(int, boolean, boolean, String)} on
113      * the child process and {@link #postForkCommon()} on both the parent and the child
114      * process. {@code postForkCommon} is called after {@code postForkChild} in
115      * the child process.
116      */
117     @libcore.api.CorePlatformApi
preFork()118     public static void preFork() {
119         Daemons.stop();
120         token = nativePreFork();
121         waitUntilAllThreadsStopped();
122     }
123 
124     /**
125      * Called by the zygote in the system server process after forking. This method is is called
126      * before {@code postForkChild} for system server.
127      */
128     @libcore.api.CorePlatformApi
postForkSystemServer(int runtimeFlags)129     public static void postForkSystemServer(int runtimeFlags) {
130         nativePostForkSystemServer(runtimeFlags);
131     }
132 
133     /**
134      * Called by the zygote in the child process after every fork. The runtime
135      * flags from {@code runtimeFlags} are applied to the child process. The string
136      * {@code instructionSet} determines whether to use a native bridge.
137      */
138     @libcore.api.CorePlatformApi
postForkChild(int runtimeFlags, boolean isSystemServer, boolean isZygote, String instructionSet)139     public static void postForkChild(int runtimeFlags, boolean isSystemServer, boolean isZygote,
140             String instructionSet) {
141         nativePostForkChild(token, runtimeFlags, isSystemServer, isZygote, instructionSet);
142 
143         Math.setRandomSeedInternal(System.currentTimeMillis());
144     }
145 
146     /**
147      * Called by the zygote in both the parent and child processes after
148      * every fork. In the child process, this method is called after
149      * {@code postForkChild}.
150      */
151     @libcore.api.CorePlatformApi
postForkCommon()152     public static void postForkCommon() {
153         // Notify the runtime before creating new threads.
154         nativePostZygoteFork();
155         Daemons.startPostZygoteFork();
156     }
157 
158 
159     // Hook for SystemServer specific early initialization post-forking.
nativePostForkSystemServer(int runtimeFlags)160     private static native void nativePostForkSystemServer(int runtimeFlags);
161 
nativePreFork()162     private static native long nativePreFork();
nativePostZygoteFork()163     private static native void nativePostZygoteFork();
164 
165     // Hook for all child processes post forking.
nativePostForkChild(long token, int runtimeFlags, boolean isSystemServer, boolean isZygote, String instructionSet)166     private static native void nativePostForkChild(long token, int runtimeFlags,
167                                                    boolean isSystemServer, boolean isZygote,
168                                                    String instructionSet);
169 
170     /**
171      * We must not fork until we're single-threaded again. Wait until /proc shows we're
172      * down to just one thread.
173      */
waitUntilAllThreadsStopped()174     private static void waitUntilAllThreadsStopped() {
175         File tasks = new File("/proc/self/task");
176         // All Java daemons are stopped already. We're just waiting for their OS counterparts to
177         // finish as well. This shouldn't take much time so spinning is ok here.
178         while (tasks.list().length > 1) {
179           Thread.yield();
180         }
181     }
182 }
183