Merge "Frameworks/base: Early init native bridge"
This commit is contained in:
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 }
|
||||
|
@ -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) {
|
||||
|
Reference in New Issue
Block a user