Frameworks/base: Add native bridge post-fork initialization

Change-Id: I5a20de1cb68dd1802937b369b14c50c9c1031c67
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 5b9b5b0..7bedfc1 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -456,6 +456,7 @@
      * @param targetSdkVersion The target SDK version for the app.
      * @param seInfo null-ok SELinux information for the new process.
      * @param abi non-null the ABI this app should be started with.
+     * @param instructionSet null-ok the instruction set to use.
      * @param zygoteArgs Additional arguments to supply to the zygote process.
      * 
      * @return An object that describes the result of the attempt to start the process.
@@ -470,11 +471,12 @@
                                   int targetSdkVersion,
                                   String seInfo,
                                   String abi,
+                                  String instructionSet,
                                   String[] zygoteArgs) {
         try {
             return startViaZygote(processClass, niceName, uid, gid, gids,
                     debugFlags, mountExternal, targetSdkVersion, seInfo,
-                    abi, zygoteArgs);
+                    abi, instructionSet, zygoteArgs);
         } catch (ZygoteStartFailedEx ex) {
             Log.e(LOG_TAG,
                     "Starting VM process through Zygote failed");
@@ -577,6 +579,7 @@
      * @param targetSdkVersion The target SDK version for the app.
      * @param seInfo null-ok SELinux information for the new process.
      * @param abi the ABI the process should use.
+     * @param instructionSet null-ok the instruction set to use.
      * @param extraArgs Additional arguments to supply to the zygote process.
      * @return An object that describes the result of the attempt to start the process.
      * @throws ZygoteStartFailedEx if process start failed for any reason
@@ -589,6 +592,7 @@
                                   int targetSdkVersion,
                                   String seInfo,
                                   String abi,
+                                  String instructionSet,
                                   String[] extraArgs)
                                   throws ZygoteStartFailedEx {
         synchronized(Process.class) {
@@ -648,6 +652,10 @@
                 argsForZygote.add("--seinfo=" + seInfo);
             }
 
+            if (instructionSet != null) {
+                argsForZygote.add("--instruction-set=" + instructionSet);
+            }
+
             argsForZygote.add(processClass);
 
             if (extraArgs != null) {
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 54c532a..f23326c 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -75,21 +75,25 @@
      * file descriptor numbers that are to be closed by the child
      * (and replaced by /dev/null) after forking.  An integer value
      * of -1 in any entry in the array means "ignore this one".
+     * @param instructionSet null-ok the instruction set to use.
      *
      * @return 0 if this is the child, pid of the child
      * if this is the parent, or -1 on error.
      */
     public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
-          int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose) {
+          int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
+          String instructionSet) {
         VM_HOOKS.preFork();
         int pid = nativeForkAndSpecialize(
-                  uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose);
+                  uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
+                  instructionSet);
         VM_HOOKS.postForkCommon();
         return pid;
     }
 
     native private static int nativeForkAndSpecialize(int uid, int gid, int[] gids,int debugFlags,
-          int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose);
+          int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
+          String instructionSet);
 
     /**
      * Special method to start the system server process. In addition to the
@@ -126,8 +130,8 @@
     native private static int nativeForkSystemServer(int uid, int gid, int[] gids, int debugFlags,
             int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
 
-    private static void callPostForkChildHooks(int debugFlags) {
-        VM_HOOKS.postForkChild(debugFlags);
+    private static void callPostForkChildHooks(int debugFlags, String instructionSet) {
+        VM_HOOKS.postForkChild(debugFlags, instructionSet);
     }
 
 
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 0c48368..6c1901b 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -222,7 +222,7 @@
 
             pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                     parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
-                    parsedArgs.niceName, fdsToClose);
+                    parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet);
         } catch (IOException ex) {
             logAndPrintError(newStderr, "Exception creating pipe", ex);
         } catch (ErrnoException ex) {
@@ -311,6 +311,7 @@
      *      [--] <args for RuntimeInit >
      *   <li> If <code>--runtime-init</code> is absent:
      *      [--] &lt;classname&gt; [args...]
+     *   <li> --instruction-set=<i>instruction-set-string</i> which instruction set to use/emulate.
      * </ul>
      */
     static class Arguments {
@@ -374,6 +375,11 @@
         boolean abiListQuery;
 
         /**
+         * The instruction set to use, or null when not important.
+         */
+        String instructionSet;
+
+        /**
          * Constructs instance and parses args
          * @param args zygote command-line args
          * @throws IllegalArgumentException
@@ -528,6 +534,8 @@
                     mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL;
                 } else if (arg.equals("--query-abi-list")) {
                     abiListQuery = true;
+                } else if (arg.startsWith("--instruction-set=")) {
+                    instructionSet = arg.substring(arg.indexOf('=') + 1);
                 } else {
                     break;
                 }
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 0cdddba..bfbeca1 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -402,7 +402,8 @@
                                      jlong permittedCapabilities, jlong effectiveCapabilities,
                                      jint mount_external,
                                      jstring java_se_info, jstring java_se_name,
-                                     bool is_system_server, jintArray fdsToClose) {
+                                     bool is_system_server, jintArray fdsToClose,
+                                     jstring instructionSet) {
   SetSigChldHandler();
 
   pid_t pid = fork();
@@ -505,7 +506,8 @@
 
     UnsetSigChldHandler();
 
-    env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags);
+    env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags,
+                              is_system_server ? NULL : instructionSet);
     if (env->ExceptionCheck()) {
       ALOGE("Error calling post fork hooks.");
       RuntimeAbort(env);
@@ -523,9 +525,9 @@
         JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
         jint debug_flags, jobjectArray rlimits,
         jint mount_external, jstring se_info, jstring se_name,
-        jintArray fdsToClose) {
+        jintArray fdsToClose, jstring instructionSet) {
     return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags,
-            rlimits, 0, 0, mount_external, se_info, se_name, false, fdsToClose);
+            rlimits, 0, 0, mount_external, se_info, se_name, false, fdsToClose, instructionSet);
 }
 
 static jint com_android_internal_os_Zygote_nativeForkSystemServer(
@@ -535,7 +537,7 @@
   pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
                                       debug_flags, rlimits,
                                       permittedCapabilities, effectiveCapabilities,
-                                      MOUNT_EXTERNAL_NONE, NULL, NULL, true, NULL);
+                                      MOUNT_EXTERNAL_NONE, NULL, NULL, true, NULL, NULL);
   if (pid > 0) {
       // The zygote process checks whether the child process has died or not.
       ALOGI("System server process %d has been created", pid);
@@ -553,7 +555,8 @@
 }
 
 static JNINativeMethod gMethods[] = {
-    { "nativeForkAndSpecialize", "(II[II[[IILjava/lang/String;Ljava/lang/String;[I)I",
+    { "nativeForkAndSpecialize",
+      "(II[II[[IILjava/lang/String;Ljava/lang/String;[ILjava/lang/String;)I",
       (void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
     { "nativeForkSystemServer", "(II[II[[IJJ)I",
       (void *) com_android_internal_os_Zygote_nativeForkSystemServer }
@@ -564,7 +567,8 @@
   if (gZygoteClass == NULL) {
     RuntimeAbort(env);
   }
-  gCallPostForkChildHooks = env->GetStaticMethodID(gZygoteClass, "callPostForkChildHooks", "(I)V");
+  gCallPostForkChildHooks = env->GetStaticMethodID(gZygoteClass, "callPostForkChildHooks",
+                                                   "(ILjava/lang/String;)V");
 
   return AndroidRuntime::registerNativeMethods(env, "com/android/internal/os/Zygote",
       gMethods, NELEM(gMethods));
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index dea41e4..a77e241 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -170,6 +170,7 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.WindowManager;
+import dalvik.system.VMRuntime;
 
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
@@ -2786,11 +2787,16 @@
                 requiredAbi = Build.SUPPORTED_ABIS[0];
             }
 
+            String instructionSet = null;
+            if (app.info.cpuAbi != null) {
+                instructionSet = VMRuntime.getInstructionSet(app.info.cpuAbi);
+            }
+
             // Start the process.  It will either succeed and return a result containing
             // the PID of the new process, or else throw a RuntimeException.
             Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
                     app.processName, uid, uid, gids, debugFlags, mountExternal,
-                    app.info.targetSdkVersion, app.info.seinfo, requiredAbi, null);
+                    app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet, null);
 
             BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
             synchronized (bs) {