Loading core/java/android/os/Process.java +9 −1 Original line number Diff line number Diff line Loading @@ -469,6 +469,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. Loading @@ -484,11 +485,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"); Loading Loading @@ -592,6 +594,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 Loading @@ -605,6 +608,7 @@ public class Process { String seInfo, String abi, String instructionSet, String appDataDir, String[] extraArgs) throws ZygoteStartFailedEx { synchronized(Process.class) { Loading Loading @@ -668,6 +672,10 @@ public class Process { argsForZygote.add("--instruction-set=" + instructionSet); } if (appDataDir != null) { argsForZygote.add("--app-data-dir=" + appDataDir); } argsForZygote.add(processClass); if (extraArgs != null) { Loading core/java/com/android/internal/os/Zygote.java +4 −3 Original line number Diff line number Diff line Loading @@ -79,19 +79,20 @@ 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) { long startTime = SystemClock.elapsedRealtime(); VM_HOOKS.preFork(); checkTime(startTime, "Zygote.preFork"); int pid = nativeForkAndSpecialize( uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose, instructionSet); instructionSet, appDataDir); checkTime(startTime, "Zygote.nativeForkAndSpecialize"); VM_HOOKS.postForkCommon(); checkTime(startTime, "Zygote.postForkCommon"); Loading @@ -100,7 +101,7 @@ public final class Zygote { 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); /** * Temporary hack: check time since start time and log if over a fixed threshold. Loading core/java/com/android/internal/os/ZygoteConnection.java +14 −5 Original line number Diff line number Diff line Loading @@ -245,7 +245,8 @@ class ZygoteConnection { checkTime(startTime, "zygoteConnection.runOnce: preForkAndSpecialize"); 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); checkTime(startTime, "zygoteConnection.runOnce: postForkAndSpecialize"); } catch (IOException ex) { logAndPrintError(newStderr, "Exception creating pipe", ex); Loading Loading @@ -403,6 +404,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 Loading Loading @@ -560,6 +567,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; } Loading core/jni/com_android_internal_os_Zygote.cpp +35 −11 Original line number Diff line number Diff line Loading @@ -51,6 +51,8 @@ #include "ScopedPrimitiveArray.h" #include "ScopedUtfChars.h" #include "nativebridge/native_bridge.h" namespace { using android::String8; Loading Loading @@ -249,20 +251,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 Loading Loading @@ -422,7 +428,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) { uint64_t start = MsTime(); SetSigChldHandler(); ckTime(start, "ForkAndSpecializeCommon:SetSigChldHandler"); Loading @@ -446,7 +452,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 Loading Loading @@ -475,6 +487,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); Loading Loading @@ -563,7 +586,7 @@ 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) { // Grant CAP_WAKE_ALARM to the Bluetooth process. jlong capabilities = 0; if (uid == AID_BLUETOOTH) { Loading @@ -572,7 +595,7 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags, rlimits, capabilities, capabilities, mount_external, se_info, se_name, false, fdsToClose, instructionSet); se_name, false, fdsToClose, instructionSet, appDataDir); } static jint com_android_internal_os_Zygote_nativeForkSystemServer( Loading @@ -582,7 +605,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); Loading @@ -601,7 +625,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 } Loading services/core/java/com/android/server/am/ActivityManagerService.java +77 −77 Original line number Diff line number Diff line Loading @@ -3176,7 +3176,7 @@ public final class ActivityManagerService extends ActivityManagerNative Process.ProcessStartResult startResult = Process.start(entryPoint, app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet, entryPointArgs); app.info.dataDir, entryPointArgs); checkTime(startTime, "startProcess: returned from zygote!"); if (app.isolated) { Loading Loading
core/java/android/os/Process.java +9 −1 Original line number Diff line number Diff line Loading @@ -469,6 +469,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. Loading @@ -484,11 +485,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"); Loading Loading @@ -592,6 +594,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 Loading @@ -605,6 +608,7 @@ public class Process { String seInfo, String abi, String instructionSet, String appDataDir, String[] extraArgs) throws ZygoteStartFailedEx { synchronized(Process.class) { Loading Loading @@ -668,6 +672,10 @@ public class Process { argsForZygote.add("--instruction-set=" + instructionSet); } if (appDataDir != null) { argsForZygote.add("--app-data-dir=" + appDataDir); } argsForZygote.add(processClass); if (extraArgs != null) { Loading
core/java/com/android/internal/os/Zygote.java +4 −3 Original line number Diff line number Diff line Loading @@ -79,19 +79,20 @@ 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) { long startTime = SystemClock.elapsedRealtime(); VM_HOOKS.preFork(); checkTime(startTime, "Zygote.preFork"); int pid = nativeForkAndSpecialize( uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose, instructionSet); instructionSet, appDataDir); checkTime(startTime, "Zygote.nativeForkAndSpecialize"); VM_HOOKS.postForkCommon(); checkTime(startTime, "Zygote.postForkCommon"); Loading @@ -100,7 +101,7 @@ public final class Zygote { 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); /** * Temporary hack: check time since start time and log if over a fixed threshold. Loading
core/java/com/android/internal/os/ZygoteConnection.java +14 −5 Original line number Diff line number Diff line Loading @@ -245,7 +245,8 @@ class ZygoteConnection { checkTime(startTime, "zygoteConnection.runOnce: preForkAndSpecialize"); 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); checkTime(startTime, "zygoteConnection.runOnce: postForkAndSpecialize"); } catch (IOException ex) { logAndPrintError(newStderr, "Exception creating pipe", ex); Loading Loading @@ -403,6 +404,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 Loading Loading @@ -560,6 +567,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; } Loading
core/jni/com_android_internal_os_Zygote.cpp +35 −11 Original line number Diff line number Diff line Loading @@ -51,6 +51,8 @@ #include "ScopedPrimitiveArray.h" #include "ScopedUtfChars.h" #include "nativebridge/native_bridge.h" namespace { using android::String8; Loading Loading @@ -249,20 +251,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 Loading Loading @@ -422,7 +428,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) { uint64_t start = MsTime(); SetSigChldHandler(); ckTime(start, "ForkAndSpecializeCommon:SetSigChldHandler"); Loading @@ -446,7 +452,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 Loading Loading @@ -475,6 +487,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); Loading Loading @@ -563,7 +586,7 @@ 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) { // Grant CAP_WAKE_ALARM to the Bluetooth process. jlong capabilities = 0; if (uid == AID_BLUETOOTH) { Loading @@ -572,7 +595,7 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags, rlimits, capabilities, capabilities, mount_external, se_info, se_name, false, fdsToClose, instructionSet); se_name, false, fdsToClose, instructionSet, appDataDir); } static jint com_android_internal_os_Zygote_nativeForkSystemServer( Loading @@ -582,7 +605,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); Loading @@ -601,7 +625,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 } Loading
services/core/java/com/android/server/am/ActivityManagerService.java +77 −77 Original line number Diff line number Diff line Loading @@ -3176,7 +3176,7 @@ public final class ActivityManagerService extends ActivityManagerNative Process.ProcessStartResult startResult = Process.start(entryPoint, app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet, entryPointArgs); app.info.dataDir, entryPointArgs); checkTime(startTime, "startProcess: returned from zygote!"); if (app.isolated) { Loading