1ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown/*
2ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * Copyright (C) 2011 The Android Open Source Project
3ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown *
4ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
5ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * you may not use this file except in compliance with the License.
6ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * You may obtain a copy of the License at
7ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown *
8ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
9ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown *
10ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * Unless required by applicable law or agreed to in writing, software
11ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
12ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * See the License for the specific language governing permissions and
14ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * limitations under the License.
15ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown */
16ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown
17ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brownpackage com.android.internal.os;
18ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown
19ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brownimport android.os.Process;
20ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brownimport android.util.Slog;
21ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown
22ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brownimport java.io.DataOutputStream;
23ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brownimport java.io.FileDescriptor;
24ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brownimport java.io.FileOutputStream;
25ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brownimport java.io.IOException;
26ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown
27ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brownimport libcore.io.IoUtils;
28ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown
29ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown/**
30ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * Startup class for the wrapper process.
31ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown * @hide
32ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown */
33ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brownpublic class WrapperInit {
34ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown    private final static String TAG = "AndroidRuntime";
35ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown
36ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown    /**
37ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     * Class not instantiable.
38ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     */
39ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown    private WrapperInit() {
40ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown    }
41ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown
42ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown    /**
43ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     * The main function called when starting a runtime application through a
44ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     * wrapper process instead of by forking Zygote.
45ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     *
46ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     * The first argument specifies the file descriptor for a pipe that should receive
47e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes     * the pid of this process, or 0 if none.
48e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes     *
49e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes     * The second argument is the target SDK version for the app.
50e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes     *
51e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes     * The remaining arguments are passed to the runtime.
52ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     *
53ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     * @param args The command-line arguments.
54ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     */
55ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown    public static void main(String[] args) {
56ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        try {
57e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes            // Parse our mandatory arguments.
58e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes            int fdNum = Integer.parseInt(args[0], 10);
59e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes            int targetSdkVersion = Integer.parseInt(args[1], 10);
60e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes
610c2313dc4f4bfaf6aa0506df4c54f25591a9e4c7Jeff Brown            // Tell the Zygote what our actual PID is (since it only knows about the
620c2313dc4f4bfaf6aa0506df4c54f25591a9e4c7Jeff Brown            // wrapper that it directly forked).
63ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown            if (fdNum != 0) {
64ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown                try {
65ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown                    FileDescriptor fd = ZygoteInit.createFileDescriptor(fdNum);
66ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown                    DataOutputStream os = new DataOutputStream(new FileOutputStream(fd));
67ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown                    os.writeInt(Process.myPid());
68ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown                    os.close();
69ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown                    IoUtils.closeQuietly(fd);
70ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown                } catch (IOException ex) {
71ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown                    Slog.d(TAG, "Could not write pid of wrapped process to Zygote pipe.", ex);
72ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown                }
73ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown            }
74ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown
750c2313dc4f4bfaf6aa0506df4c54f25591a9e4c7Jeff Brown            // Mimic Zygote preloading.
760c2313dc4f4bfaf6aa0506df4c54f25591a9e4c7Jeff Brown            ZygoteInit.preload();
770c2313dc4f4bfaf6aa0506df4c54f25591a9e4c7Jeff Brown
780c2313dc4f4bfaf6aa0506df4c54f25591a9e4c7Jeff Brown            // Launch the application.
79e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes            String[] runtimeArgs = new String[args.length - 2];
80e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes            System.arraycopy(args, 2, runtimeArgs, 0, runtimeArgs.length);
81e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes            RuntimeInit.wrapperInit(targetSdkVersion, runtimeArgs);
82ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        } catch (ZygoteInit.MethodAndArgsCaller caller) {
83ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown            caller.run();
84ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        }
85ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown    }
86ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown
87ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown    /**
88ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     * Executes a runtime application with a wrapper command.
89ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     * This method never returns.
90ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     *
91ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     * @param invokeWith The wrapper command.
92ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     * @param niceName The nice name for the application, or null if none.
93e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes     * @param targetSdkVersion The target SDK version for the app.
94ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     * @param pipeFd The pipe to which the application's pid should be written, or null if none.
95973b4663b0b5ee62006522bf4742af076096e548Narayan Kamath     * @param args Arguments for {@link RuntimeInit#main}.
96ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     */
97ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown    public static void execApplication(String invokeWith, String niceName,
98e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes            int targetSdkVersion, FileDescriptor pipeFd, String[] args) {
99ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        StringBuilder command = new StringBuilder(invokeWith);
100ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        command.append(" /system/bin/app_process /system/bin --application");
101ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        if (niceName != null) {
102ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown            command.append(" '--nice-name=").append(niceName).append("'");
103ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        }
104ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        command.append(" com.android.internal.os.WrapperInit ");
105ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        command.append(pipeFd != null ? pipeFd.getInt$() : 0);
106e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes        command.append(' ');
107e1dfcb7ab01fb991079ec1f70f75281a0ca9073eElliott Hughes        command.append(targetSdkVersion);
108ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        Zygote.appendQuotedShellArgs(command, args);
109ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        Zygote.execShell(command.toString());
110ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown    }
111ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown
112ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown    /**
113ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     * Executes a standalone application with a wrapper command.
114ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     * This method never returns.
115ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     *
116ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     * @param invokeWith The wrapper command.
117ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     * @param classPath The class path.
118ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     * @param className The class name to invoke.
119ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     * @param args Arguments for the main() method of the specified class.
120ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown     */
121ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown    public static void execStandalone(String invokeWith, String classPath, String className,
122ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown            String[] args) {
123ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        StringBuilder command = new StringBuilder(invokeWith);
124ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        command.append(" /system/bin/dalvikvm -classpath '").append(classPath);
125ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        command.append("' ").append(className);
126ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        Zygote.appendQuotedShellArgs(command, args);
127ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown        Zygote.execShell(command.toString());
128ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown    }
129ebed7d6e35f7f960e6e6add2b8ab7c7a31a511c3Jeff Brown}
130