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