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