1 /*
2  * Copyright (C) 2011 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 com.android.internal.os;
18 
19 import android.os.Process;
20 import android.util.Slog;
21 
22 import java.io.DataOutputStream;
23 import java.io.FileDescriptor;
24 import java.io.FileOutputStream;
25 import java.io.IOException;
26 
27 import libcore.io.IoUtils;
28 
29 /**
30  * Startup class for the wrapper process.
31  * @hide
32  */
33 public class WrapperInit {
34     private final static String TAG = "AndroidRuntime";
35 
36     /**
37      * Class not instantiable.
38      */
WrapperInit()39     private WrapperInit() {
40     }
41 
42     /**
43      * The main function called when starting a runtime application through a
44      * wrapper process instead of by forking Zygote.
45      *
46      * The first argument specifies the file descriptor for a pipe that should receive
47      * the pid of this process, or 0 if none.
48      *
49      * The second argument is the target SDK version for the app.
50      *
51      * The remaining arguments are passed to the runtime.
52      *
53      * @param args The command-line arguments.
54      */
main(String[] args)55     public static void main(String[] args) {
56         try {
57             // Parse our mandatory arguments.
58             int fdNum = Integer.parseInt(args[0], 10);
59             int targetSdkVersion = Integer.parseInt(args[1], 10);
60 
61             // Tell the Zygote what our actual PID is (since it only knows about the
62             // wrapper that it directly forked).
63             if (fdNum != 0) {
64                 try {
65                     FileDescriptor fd = ZygoteInit.createFileDescriptor(fdNum);
66                     DataOutputStream os = new DataOutputStream(new FileOutputStream(fd));
67                     os.writeInt(Process.myPid());
68                     os.close();
69                     IoUtils.closeQuietly(fd);
70                 } catch (IOException ex) {
71                     Slog.d(TAG, "Could not write pid of wrapped process to Zygote pipe.", ex);
72                 }
73             }
74 
75             // Mimic Zygote preloading.
76             ZygoteInit.preload();
77 
78             // Launch the application.
79             String[] runtimeArgs = new String[args.length - 2];
80             System.arraycopy(args, 2, runtimeArgs, 0, runtimeArgs.length);
81             RuntimeInit.wrapperInit(targetSdkVersion, runtimeArgs);
82         } catch (ZygoteInit.MethodAndArgsCaller caller) {
83             caller.run();
84         }
85     }
86 
87     /**
88      * Executes a runtime application with a wrapper command.
89      * This method never returns.
90      *
91      * @param invokeWith The wrapper command.
92      * @param niceName The nice name for the application, or null if none.
93      * @param targetSdkVersion The target SDK version for the app.
94      * @param pipeFd The pipe to which the application's pid should be written, or null if none.
95      * @param args Arguments for {@link RuntimeInit#main}.
96      */
execApplication(String invokeWith, String niceName, int targetSdkVersion, FileDescriptor pipeFd, String[] args)97     public static void execApplication(String invokeWith, String niceName,
98             int targetSdkVersion, FileDescriptor pipeFd, String[] args) {
99         StringBuilder command = new StringBuilder(invokeWith);
100         command.append(" /system/bin/app_process /system/bin --application");
101         if (niceName != null) {
102             command.append(" '--nice-name=").append(niceName).append("'");
103         }
104         command.append(" com.android.internal.os.WrapperInit ");
105         command.append(pipeFd != null ? pipeFd.getInt$() : 0);
106         command.append(' ');
107         command.append(targetSdkVersion);
108         Zygote.appendQuotedShellArgs(command, args);
109         Zygote.execShell(command.toString());
110     }
111 
112     /**
113      * Executes a standalone application with a wrapper command.
114      * This method never returns.
115      *
116      * @param invokeWith The wrapper command.
117      * @param classPath The class path.
118      * @param className The class name to invoke.
119      * @param args Arguments for the main() method of the specified class.
120      */
execStandalone(String invokeWith, String classPath, String className, String[] args)121     public static void execStandalone(String invokeWith, String classPath, String className,
122             String[] args) {
123         StringBuilder command = new StringBuilder(invokeWith);
124         command.append(" /system/bin/dalvikvm -classpath '").append(classPath);
125         command.append("' ").append(className);
126         Zygote.appendQuotedShellArgs(command, args);
127         Zygote.execShell(command.toString());
128     }
129 }
130