WrapperInit.java revision 973b4663b0b5ee62006522bf4742af076096e548
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
17package com.android.internal.os;
18
19import android.os.Process;
20import android.util.Slog;
21
22import java.io.DataOutputStream;
23import java.io.FileDescriptor;
24import java.io.FileOutputStream;
25import java.io.IOException;
26
27import libcore.io.IoUtils;
28
29/**
30 * Startup class for the wrapper process.
31 * @hide
32 */
33public class WrapperInit {
34    private final static String TAG = "AndroidRuntime";
35
36    /**
37     * Class not instantiable.
38     */
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     */
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     */
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     */
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