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