• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 java.io.File;
20 
21 /**
22  * Provides access to the Dalvik "zygote" feature, which allows a VM instance to
23  * be partially initialized and then fork()'d from the partially initialized
24  * state.
25  *
26  * @hide
27  */
28 public class Zygote {
29     /*
30      * Bit values for "debugFlags" argument.  The definitions are duplicated
31      * in the native code.
32      */
33     /** enable debugging over JDWP */
34     public static final int DEBUG_ENABLE_DEBUGGER   = 1;
35     /** enable JNI checks */
36     public static final int DEBUG_ENABLE_CHECKJNI   = 1 << 1;
37     /** enable Java programming language "assert" statements */
38     public static final int DEBUG_ENABLE_ASSERT     = 1 << 2;
39     /** disable the JIT compiler */
40     public static final int DEBUG_ENABLE_SAFEMODE   = 1 << 3;
41     /** Enable logging of third-party JNI activity. */
42     public static final int DEBUG_ENABLE_JNI_LOGGING = 1 << 4;
43 
44     /**
45      * When set by the system server, all subsequent apps will be launched in
46      * VM safe mode.
47      */
48     public static boolean systemInSafeMode = false;
49 
Zygote()50     private Zygote() {}
51 
preFork()52     private static void preFork() {
53         Daemons.stop();
54         waitUntilAllThreadsStopped();
55     }
56 
57     /**
58      * We must not fork until we're single-threaded again. Wait until /proc shows we're
59      * down to just one thread.
60      */
waitUntilAllThreadsStopped()61     private static void waitUntilAllThreadsStopped() {
62         File tasks = new File("/proc/self/task");
63         while (tasks.list().length > 1) {
64             try {
65                 // Experimentally, booting and playing about with a stingray, I never saw us
66                 // go round this loop more than once with a 10ms sleep.
67                 Thread.sleep(10);
68             } catch (InterruptedException ignored) {
69             }
70         }
71     }
72 
postFork()73     private static void postFork() {
74         Daemons.start();
75     }
76 
77     /**
78      * Forks a new Zygote instance, but does not leave the zygote mode.
79      * The current VM must have been started with the -Xzygote flag. The
80      * new child is expected to eventually call forkAndSpecialize()
81      *
82      * @return 0 if this is the child, pid of the child
83      * if this is the parent, or -1 on error
84      */
fork()85     public static int fork() {
86         preFork();
87         int pid = nativeFork();
88         postFork();
89         return pid;
90     }
91 
nativeFork()92     native public static int nativeFork();
93 
94     /**
95      * Forks a new VM instance.  The current VM must have been started
96      * with the -Xzygote flag. <b>NOTE: new instance keeps all
97      * root capabilities. The new process is expected to call capset()</b>.
98      *
99      * @param uid the UNIX uid that the new process should setuid() to after
100      * fork()ing and and before spawning any threads.
101      * @param gid the UNIX gid that the new process should setgid() to after
102      * fork()ing and and before spawning any threads.
103      * @param gids null-ok; a list of UNIX gids that the new process should
104      * setgroups() to after fork and before spawning any threads.
105      * @param debugFlags bit flags that enable debugging features.
106      * @param rlimits null-ok an array of rlimit tuples, with the second
107      * dimension having a length of 3 and representing
108      * (resource, rlim_cur, rlim_max). These are set via the posix
109      * setrlimit(2) call.
110      *
111      * @return 0 if this is the child, pid of the child
112      * if this is the parent, or -1 on error.
113      */
forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits)114     public static int forkAndSpecialize(int uid, int gid, int[] gids,
115             int debugFlags, int[][] rlimits) {
116         preFork();
117         int pid = nativeForkAndSpecialize(uid, gid, gids, debugFlags, rlimits);
118         postFork();
119         return pid;
120     }
121 
nativeForkAndSpecialize(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits)122     native public static int nativeForkAndSpecialize(int uid, int gid,
123             int[] gids, int debugFlags, int[][] rlimits);
124 
125     /**
126      * Forks a new VM instance.
127      * @deprecated use {@link Zygote#forkAndSpecialize(int, int, int[], int, int[][])}
128      */
129     @Deprecated
forkAndSpecialize(int uid, int gid, int[] gids, boolean enableDebugger, int[][] rlimits)130     public static int forkAndSpecialize(int uid, int gid, int[] gids,
131             boolean enableDebugger, int[][] rlimits) {
132         int debugFlags = enableDebugger ? DEBUG_ENABLE_DEBUGGER : 0;
133         return forkAndSpecialize(uid, gid, gids, debugFlags, rlimits);
134     }
135 
136     /**
137      * Special method to start the system server process. In addition to the
138      * common actions performed in forkAndSpecialize, the pid of the child
139      * process is recorded such that the death of the child process will cause
140      * zygote to exit.
141      *
142      * @param uid the UNIX uid that the new process should setuid() to after
143      * fork()ing and and before spawning any threads.
144      * @param gid the UNIX gid that the new process should setgid() to after
145      * fork()ing and and before spawning any threads.
146      * @param gids null-ok; a list of UNIX gids that the new process should
147      * setgroups() to after fork and before spawning any threads.
148      * @param debugFlags bit flags that enable debugging features.
149      * @param rlimits null-ok an array of rlimit tuples, with the second
150      * dimension having a length of 3 and representing
151      * (resource, rlim_cur, rlim_max). These are set via the posix
152      * setrlimit(2) call.
153      * @param permittedCapabilities argument for setcap()
154      * @param effectiveCapabilities argument for setcap()
155      *
156      * @return 0 if this is the child, pid of the child
157      * if this is the parent, or -1 on error.
158      */
forkSystemServer(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities)159     public static int forkSystemServer(int uid, int gid, int[] gids,
160             int debugFlags, int[][] rlimits,
161             long permittedCapabilities, long effectiveCapabilities) {
162         preFork();
163         int pid = nativeForkSystemServer(uid, gid, gids, debugFlags, rlimits,
164                                          permittedCapabilities,
165                                          effectiveCapabilities);
166         postFork();
167         return pid;
168     }
169 
170     /**
171      * Special method to start the system server process.
172      * @deprecated use {@link Zygote#forkSystemServer(int, int, int[], int, int[][])}
173      */
174     @Deprecated
forkSystemServer(int uid, int gid, int[] gids, boolean enableDebugger, int[][] rlimits)175     public static int forkSystemServer(int uid, int gid, int[] gids,
176             boolean enableDebugger, int[][] rlimits) {
177         int debugFlags = enableDebugger ? DEBUG_ENABLE_DEBUGGER : 0;
178         return forkAndSpecialize(uid, gid, gids, debugFlags, rlimits);
179     }
180 
nativeForkSystemServer(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities)181     native public static int nativeForkSystemServer(int uid, int gid,
182             int[] gids, int debugFlags, int[][] rlimits,
183             long permittedCapabilities, long effectiveCapabilities);
184 
185     /**
186      * Executes "/system/bin/sh -c &lt;command&gt;" using the exec() system call.
187      * This method never returns.
188      *
189      * @param command The shell command to execute.
190      */
execShell(String command)191     public static void execShell(String command) {
192         nativeExecShell(command);
193     }
194 
195     /**
196      * Appends quotes shell arguments to the specified string builder.
197      * The arguments are quoted using single-quotes, escaped if necessary,
198      * prefixed with a space, and appended to the command.
199      *
200      * @param command A string builder for the shell command being constructed.
201      * @param args An array of argument strings to be quoted and appended to the command.
202      * @see #execShell(String)
203      */
appendQuotedShellArgs(StringBuilder command, String[] args)204     public static void appendQuotedShellArgs(StringBuilder command, String[] args) {
205         for (String arg : args) {
206             command.append(" '").append(arg.replace("'", "'\\''")).append("'");
207         }
208     }
209 
nativeExecShell(String command)210     native private static void nativeExecShell(String command);
211 }
212