
1114c3c1d4cd
ac1943345e
1abb805041
2e07ab8c24
0044836677
c561811fad
7a848373ef
89646bdeb1
2a70bbac4a
d414dcaa35
b4cd877e3a
98634286bb
114c2635390c
11add34a4bc6
11a2b51906de
10527787f3c8
ffde474ad7
aa87e487c4
c906fe9722
c69c3eecd4
b2303adccc
5bb05db6f7
536b497688
24802a832b
ce6dcc2368
3d3d5c4d38
2eda592b79
1029f28b53c0
1013a992c716
9750efbf6bc
ed563b6f26
aad3c7d750
da3180f9a8
68773a29b7
283b3fa09c
f133136b65
01a01ce5f6
17c309c098
8806ec3ef1
Signed-off-by: Tad <tad@spotco.us>
173 lines
7.0 KiB
Diff
173 lines
7.0 KiB
Diff
From 527787f3c82d385c98c2e954bbbf092937100085 Mon Sep 17 00:00:00 2001
|
|
From: Daniel Micay <danielmicay@gmail.com>
|
|
Date: Sat, 14 Mar 2015 18:10:20 -0400
|
|
Subject: [PATCH] add exec-based spawning support
|
|
|
|
---
|
|
.../com/android/internal/os/ExecInit.java | 115 ++++++++++++++++++
|
|
.../com/android/internal/os/WrapperInit.java | 2 +-
|
|
.../android/internal/os/ZygoteConnection.java | 8 ++
|
|
3 files changed, 124 insertions(+), 1 deletion(-)
|
|
create mode 100644 core/java/com/android/internal/os/ExecInit.java
|
|
|
|
diff --git a/core/java/com/android/internal/os/ExecInit.java b/core/java/com/android/internal/os/ExecInit.java
|
|
new file mode 100644
|
|
index 000000000000..10edd64e0f95
|
|
--- /dev/null
|
|
+++ b/core/java/com/android/internal/os/ExecInit.java
|
|
@@ -0,0 +1,115 @@
|
|
+package com.android.internal.os;
|
|
+
|
|
+import android.os.Trace;
|
|
+import android.system.ErrnoException;
|
|
+import android.system.Os;
|
|
+import android.util.Slog;
|
|
+import android.util.TimingsTraceLog;
|
|
+import dalvik.system.VMRuntime;
|
|
+
|
|
+/**
|
|
+ * Startup class for the process.
|
|
+ * @hide
|
|
+ */
|
|
+public class ExecInit {
|
|
+ /**
|
|
+ * Class not instantiable.
|
|
+ */
|
|
+ private ExecInit() {
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * The main function called when starting a runtime application.
|
|
+ *
|
|
+ * The first argument is the target SDK version for the app.
|
|
+ *
|
|
+ * The remaining arguments are passed to the runtime.
|
|
+ *
|
|
+ * @param args The command-line arguments.
|
|
+ */
|
|
+ public static void main(String[] args) {
|
|
+ // Parse our mandatory argument.
|
|
+ int targetSdkVersion = Integer.parseInt(args[0], 10);
|
|
+
|
|
+ // Mimic system Zygote preloading.
|
|
+ ZygoteInit.preload(new TimingsTraceLog("ExecInitTiming",
|
|
+ Trace.TRACE_TAG_DALVIK));
|
|
+
|
|
+ // Launch the application.
|
|
+ String[] runtimeArgs = new String[args.length - 1];
|
|
+ System.arraycopy(args, 1, runtimeArgs, 0, runtimeArgs.length);
|
|
+ Runnable r = execInit(targetSdkVersion, runtimeArgs);
|
|
+
|
|
+ r.run();
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Executes a runtime application with exec-based spawning.
|
|
+ * This method never returns.
|
|
+ *
|
|
+ * @param niceName The nice name for the application, or null if none.
|
|
+ * @param targetSdkVersion The target SDK version for the app.
|
|
+ * @param args Arguments for {@link RuntimeInit#main}.
|
|
+ */
|
|
+ public static void execApplication(String niceName, int targetSdkVersion,
|
|
+ String instructionSet, String[] args) {
|
|
+ int niceArgs = niceName == null ? 0 : 1;
|
|
+ int baseArgs = 5 + niceArgs;
|
|
+ String[] argv = new String[baseArgs + args.length];
|
|
+ if (VMRuntime.is64BitInstructionSet(instructionSet)) {
|
|
+ argv[0] = "/system/bin/app_process64";
|
|
+ } else {
|
|
+ argv[0] = "/system/bin/app_process32";
|
|
+ }
|
|
+ argv[1] = "/system/bin";
|
|
+ argv[2] = "--application";
|
|
+ if (niceName != null) {
|
|
+ argv[3] = "--nice-name=" + niceName;
|
|
+ }
|
|
+ argv[3 + niceArgs] = "com.android.internal.os.ExecInit";
|
|
+ argv[4 + niceArgs] = Integer.toString(targetSdkVersion);
|
|
+ System.arraycopy(args, 0, argv, baseArgs, args.length);
|
|
+
|
|
+ WrapperInit.preserveCapabilities();
|
|
+ try {
|
|
+ Os.execv(argv[0], argv);
|
|
+ } catch (ErrnoException e) {
|
|
+ throw new RuntimeException(e);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * The main function called when an application is started with exec-based spawning.
|
|
+ *
|
|
+ * When the app starts, the runtime starts {@link RuntimeInit#main}
|
|
+ * which calls {@link main} which then calls this method.
|
|
+ * So we don't need to call commonInit() here.
|
|
+ *
|
|
+ * @param targetSdkVersion target SDK version
|
|
+ * @param argv arg strings
|
|
+ */
|
|
+ private static Runnable execInit(int targetSdkVersion, String[] argv) {
|
|
+ if (RuntimeInit.DEBUG) {
|
|
+ Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from exec");
|
|
+ }
|
|
+
|
|
+ // Check whether the first argument is a "-cp" in argv, and assume the next argument is the
|
|
+ // classpath. If found, create a PathClassLoader and use it for applicationInit.
|
|
+ ClassLoader classLoader = null;
|
|
+ if (argv != null && argv.length > 2 && argv[0].equals("-cp")) {
|
|
+ classLoader = ZygoteInit.createPathClassLoader(argv[1], targetSdkVersion);
|
|
+
|
|
+ // Install this classloader as the context classloader, too.
|
|
+ Thread.currentThread().setContextClassLoader(classLoader);
|
|
+
|
|
+ // Remove the classpath from the arguments.
|
|
+ String removedArgs[] = new String[argv.length - 2];
|
|
+ System.arraycopy(argv, 2, removedArgs, 0, argv.length - 2);
|
|
+ argv = removedArgs;
|
|
+ }
|
|
+
|
|
+ // Perform the same initialization that would happen after the Zygote forks.
|
|
+ Zygote.nativePreApplicationInit();
|
|
+ return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
|
|
+ }
|
|
+}
|
|
diff --git a/core/java/com/android/internal/os/WrapperInit.java b/core/java/com/android/internal/os/WrapperInit.java
|
|
index f0e779694c90..9f41a4136db9 100644
|
|
--- a/core/java/com/android/internal/os/WrapperInit.java
|
|
+++ b/core/java/com/android/internal/os/WrapperInit.java
|
|
@@ -183,7 +183,7 @@ private static Runnable wrapperInit(int targetSdkVersion, String[] argv) {
|
|
* This is acceptable here as failure will leave the wrapped app with strictly less
|
|
* capabilities, which may make it crash, but not exceed its allowances.
|
|
*/
|
|
- private static void preserveCapabilities() {
|
|
+ public static void preserveCapabilities() {
|
|
StructCapUserHeader header = new StructCapUserHeader(
|
|
OsConstants._LINUX_CAPABILITY_VERSION_3, 0);
|
|
StructCapUserData[] data;
|
|
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
|
|
index e556dd4d8243..1054d2fb9b13 100644
|
|
--- a/core/java/com/android/internal/os/ZygoteConnection.java
|
|
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
|
|
@@ -33,6 +33,7 @@
|
|
import android.net.LocalSocket;
|
|
import android.os.Parcel;
|
|
import android.os.Process;
|
|
+import android.os.SystemProperties;
|
|
import android.os.Trace;
|
|
import android.system.ErrnoException;
|
|
import android.system.Os;
|
|
@@ -596,6 +597,13 @@ private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor[] de
|
|
throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned");
|
|
} else {
|
|
if (!isZygote) {
|
|
+ if (SystemProperties.getBoolean("sys.spawn.exec", true)) {
|
|
+ ExecInit.execApplication(parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
|
|
+ VMRuntime.getCurrentInstructionSet(), parsedArgs.mRemainingArgs);
|
|
+
|
|
+ // Should not get here.
|
|
+ throw new IllegalStateException("ExecInit.execApplication unexpectedly returned");
|
|
+ }
|
|
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
|
|
parsedArgs.mRemainingArgs, null /* classLoader */);
|
|
} else {
|