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 <command>" 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