Merge "Frameworks/base: Early init native bridge"

This commit is contained in:
Andreas Gampe
2014-09-24 21:59:50 +00:00
committed by Gerrit Code Review
5 changed files with 61 additions and 17 deletions

View File

@ -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) {

View File

@ -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

View File

@ -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) {
@ -379,6 +380,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
@ -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;
}

View File

@ -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 }

View File

@ -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) {