diff options
author | 2014-09-10 06:55:07 -0400 | |
---|---|---|
committer | 2014-09-22 16:04:37 -0700 | |
commit | 2eacd06bfb82b33dfcbccafbcfc0bf1218484bb5 (patch) | |
tree | 33cdf1eeda739b4534120c22fa0b74e8dfbbbd10 | |
parent | 799812cd6f7f9aa4a87d81dafd273d51ac5ba992 (diff) |
Frameworks/base: Early init native bridge
Add the app directory to the arguments for starting a process.
Add a check for NeedsNativeBridge and a call to PreInitializeBridge
in the native fork code.
Change-Id: I0b93da93251c6b4638de786bf98cf99df07c3fc2
-rw-r--r-- | core/java/android/os/Process.java | 10 | ||||
-rw-r--r-- | core/java/com/android/internal/os/Zygote.java | 7 | ||||
-rw-r--r-- | core/java/com/android/internal/os/ZygoteConnection.java | 11 | ||||
-rw-r--r-- | core/jni/com_android_internal_os_Zygote.cpp | 47 | ||||
-rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 3 |
5 files changed, 61 insertions, 17 deletions
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 7bedfc118bd6..0bcc20b6a972 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -457,6 +457,7 @@ public class Process { * @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 appDataDir null-ok the data directory of the app. * @param zygoteArgs Additional arguments to supply to the zygote process. * * @return An object that describes the result of the attempt to start the process. @@ -472,11 +473,12 @@ public class Process { String seInfo, String abi, String instructionSet, + String appDataDir, String[] zygoteArgs) { try { return startViaZygote(processClass, niceName, uid, gid, gids, debugFlags, mountExternal, targetSdkVersion, seInfo, - abi, instructionSet, zygoteArgs); + abi, instructionSet, appDataDir, zygoteArgs); } catch (ZygoteStartFailedEx ex) { Log.e(LOG_TAG, "Starting VM process through Zygote failed"); @@ -580,6 +582,7 @@ public class Process { * @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 appDataDir null-ok the data directory of the app. * @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 @@ -593,6 +596,7 @@ public class Process { String seInfo, String abi, String instructionSet, + String appDataDir, String[] extraArgs) throws ZygoteStartFailedEx { synchronized(Process.class) { @@ -656,6 +660,10 @@ public class Process { argsForZygote.add("--instruction-set=" + instructionSet); } + if (appDataDir != null) { + argsForZygote.add("--app-data-dir=" + appDataDir); + } + 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 f23326c4919a..fced092b9e42 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -76,24 +76,25 @@ public final class Zygote { * (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. + * @param appDataDir null-ok the data directory of the app. * * @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, - String instructionSet) { + String instructionSet, String appDataDir) { VM_HOOKS.preFork(); int pid = nativeForkAndSpecialize( uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose, - instructionSet); + instructionSet, appDataDir); 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, - String instructionSet); + String instructionSet, String appDataDir); /** * Special method to start the system server process. In addition to the diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java index 6c1901bf14e2..0b32b3760f1b 100644 --- a/core/java/com/android/internal/os/ZygoteConnection.java +++ b/core/java/com/android/internal/os/ZygoteConnection.java @@ -222,7 +222,8 @@ class ZygoteConnection { pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo, - parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet); + parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet, + parsedArgs.appDataDir); } catch (IOException ex) { logAndPrintError(newStderr, "Exception creating pipe", ex); } catch (ErrnoException ex) { @@ -380,6 +381,12 @@ class ZygoteConnection { String instructionSet; /** + * The app data directory. May be null, e.g., for the system server. Note that this might + * not be reliable in the case of process-sharing apps. + */ + String appDataDir; + + /** * Constructs instance and parses args * @param args zygote command-line args * @throws IllegalArgumentException @@ -536,6 +543,8 @@ class ZygoteConnection { abiListQuery = true; } else if (arg.startsWith("--instruction-set=")) { instructionSet = arg.substring(arg.indexOf('=') + 1); + } else if (arg.startsWith("--app-data-dir=")) { + appDataDir = 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 bfbeca10478a..ee10393fe591 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -48,6 +48,8 @@ #include "ScopedPrimitiveArray.h" #include "ScopedUtfChars.h" +#include "nativebridge/native_bridge.h" + namespace { using android::String8; @@ -246,20 +248,24 @@ static void SetSchedulerPolicy(JNIEnv* env) { // Create a private mount namespace and bind mount appropriate emulated // storage for the given user. -static bool MountEmulatedStorage(uid_t uid, jint mount_mode) { - if (mount_mode == MOUNT_EXTERNAL_NONE) { +static bool MountEmulatedStorage(uid_t uid, jint mount_mode, bool force_mount_namespace) { + if (mount_mode == MOUNT_EXTERNAL_NONE && !force_mount_namespace) { return true; } - // See storage config details at http://source.android.com/tech/storage/ - userid_t user_id = multiuser_get_user_id(uid); - // Create a second private mount namespace for our process if (unshare(CLONE_NEWNS) == -1) { ALOGW("Failed to unshare(): %d", errno); return false; } + if (mount_mode == MOUNT_EXTERNAL_NONE) { + return true; + } + + // See storage config details at http://source.android.com/tech/storage/ + userid_t user_id = multiuser_get_user_id(uid); + // Create bind mounts to expose external storage if (mount_mode == MOUNT_EXTERNAL_MULTIUSER || mount_mode == MOUNT_EXTERNAL_MULTIUSER_ALL) { // These paths must already be created by init.rc @@ -403,7 +409,7 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra jint mount_external, jstring java_se_info, jstring java_se_name, bool is_system_server, jintArray fdsToClose, - jstring instructionSet) { + jstring instructionSet, jstring dataDir) { SetSigChldHandler(); pid_t pid = fork(); @@ -422,7 +428,13 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra DropCapabilitiesBoundingSet(env); - if (!MountEmulatedStorage(uid, mount_external)) { + bool need_native_bridge = false; + if (instructionSet != NULL) { + ScopedUtfChars isa_string(env, instructionSet); + need_native_bridge = android::NeedsNativeBridge(isa_string.c_str()); + } + + if (!MountEmulatedStorage(uid, mount_external, need_native_bridge)) { ALOGW("Failed to mount emulated storage: %d", errno); if (errno == ENOTCONN || errno == EROFS) { // When device is actively encrypting, we get ENOTCONN here @@ -440,6 +452,17 @@ static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArra SetRLimits(env, javaRlimits); + if (!is_system_server && need_native_bridge) { + // Set the environment for the apps running with native bridge. + ScopedUtfChars isa_string(env, instructionSet); // Known non-null because of need_native_... + if (dataDir == NULL) { + android::PreInitializeNativeBridge(NULL, isa_string.c_str()); + } else { + ScopedUtfChars data_dir(env, dataDir); + android::PreInitializeNativeBridge(data_dir.c_str(), isa_string.c_str()); + } + } + int rc = setresgid(gid, gid, gid); if (rc == -1) { ALOGE("setresgid(%d) failed", gid); @@ -525,9 +548,10 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( 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, jstring instructionSet) { + jintArray fdsToClose, jstring instructionSet, jstring appDataDir) { return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags, - rlimits, 0, 0, mount_external, se_info, se_name, false, fdsToClose, instructionSet); + rlimits, 0, 0, mount_external, se_info, se_name, false, fdsToClose, + instructionSet, appDataDir); } static jint com_android_internal_os_Zygote_nativeForkSystemServer( @@ -537,7 +561,8 @@ static jint com_android_internal_os_Zygote_nativeForkSystemServer( pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags, rlimits, permittedCapabilities, effectiveCapabilities, - MOUNT_EXTERNAL_NONE, NULL, NULL, true, NULL, NULL); + MOUNT_EXTERNAL_NONE, NULL, NULL, true, NULL, + 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); @@ -556,7 +581,7 @@ static jint com_android_internal_os_Zygote_nativeForkSystemServer( static JNINativeMethod gMethods[] = { { "nativeForkAndSpecialize", - "(II[II[[IILjava/lang/String;Ljava/lang/String;[ILjava/lang/String;)I", + "(II[II[[IILjava/lang/String;Ljava/lang/String;[ILjava/lang/String;Ljava/lang/String;)I", (void *) com_android_internal_os_Zygote_nativeForkAndSpecialize }, { "nativeForkSystemServer", "(II[II[[IJJ)I", (void *) com_android_internal_os_Zygote_nativeForkSystemServer } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index a77e24126014..9f8158a23da8 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -2796,7 +2796,8 @@ public final class ActivityManagerService extends ActivityManagerNative // 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, instructionSet, null); + app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet, + app.info.dataDir, null); BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics(); synchronized (bs) { |