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