am d4b64409: Merge "Make zygotes aware of their supported ABIs."

* commit 'd4b644092e8d2719d01ad297b080bd50b1fdf60d':
  Make zygotes aware of their supported ABIs.
This commit is contained in:
Narayan Kamath
2014-04-09 13:59:00 +00:00
committed by Android Git Automerger
3 changed files with 84 additions and 66 deletions

View File

@@ -10,8 +10,9 @@
#include <binder/IPCThreadState.h> #include <binder/IPCThreadState.h>
#include <binder/ProcessState.h> #include <binder/ProcessState.h>
#include <utils/Log.h> #include <utils/Log.h>
#include <cutils/process_name.h>
#include <cutils/memory.h> #include <cutils/memory.h>
#include <cutils/process_name.h>
#include <cutils/properties.h>
#include <cutils/trace.h> #include <cutils/trace.h>
#include <android_runtime/AndroidRuntime.h> #include <android_runtime/AndroidRuntime.h>
@@ -135,6 +136,12 @@ static size_t computeArgBlockSize(int argc, char* const argv[]) {
return (end - start); return (end - start);
} }
#if defined(__LP64__)
static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist64";
#else
static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist32";
#endif
int main(int argc, char* const argv[]) int main(int argc, char* const argv[])
{ {
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
@@ -205,6 +212,17 @@ int main(int argc, char* const argv[])
args.add(String8("start-system-server")); args.add(String8("start-system-server"));
} }
char prop[PROP_VALUE_MAX];
if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
LOG_ALWAYS_FATAL("app_process: Unable to deterimine ABI list from property %s.",
ABI_LIST_PROPERTY);
return 11;
}
String8 abiFlag("--abi-list=");
abiFlag.append(prop);
args.add(abiFlag);
// In zygote mode, pass all remaining arguments to the zygote // In zygote mode, pass all remaining arguments to the zygote
// main() method. // main() method.
for (; i < argc; ++i) { for (; i < argc; ++i) {

View File

@@ -22,9 +22,7 @@ import android.os.Process;
import android.os.SELinux; import android.os.SELinux;
import android.os.SystemProperties; import android.os.SystemProperties;
import android.util.Log; import android.util.Log;
import dalvik.system.PathClassLoader; import dalvik.system.PathClassLoader;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
@@ -34,8 +32,8 @@ import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.PrintStream; import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import libcore.io.ErrnoException; import libcore.io.ErrnoException;
import libcore.io.IoUtils; import libcore.io.IoUtils;
import libcore.io.Libcore; import libcore.io.Libcore;
@@ -59,7 +57,7 @@ class ZygoteConnection {
private static final int CONNECTION_TIMEOUT_MILLIS = 1000; private static final int CONNECTION_TIMEOUT_MILLIS = 1000;
/** max number of arguments that a connection can specify */ /** max number of arguments that a connection can specify */
private static final int MAX_ZYGOTE_ARGC=1024; private static final int MAX_ZYGOTE_ARGC = 1024;
/** /**
* The command socket. * The command socket.
@@ -73,15 +71,18 @@ class ZygoteConnection {
private final BufferedReader mSocketReader; private final BufferedReader mSocketReader;
private final Credentials peer; private final Credentials peer;
private final String peerSecurityContext; private final String peerSecurityContext;
private final String abiList;
/** /**
* Constructs instance from connected socket. * Constructs instance from connected socket.
* *
* @param socket non-null; connected socket * @param socket non-null; connected socket
* @param abiList non-null; a list of ABIs this zygote supports.
* @throws IOException * @throws IOException
*/ */
ZygoteConnection(LocalSocket socket) throws IOException { ZygoteConnection(LocalSocket socket, String abiList) throws IOException {
mSocket = socket; mSocket = socket;
this.abiList = abiList;
mSocketOutStream mSocketOutStream
= new DataOutputStream(socket.getOutputStream()); = new DataOutputStream(socket.getOutputStream());
@@ -110,43 +111,6 @@ class ZygoteConnection {
return mSocket.getFileDescriptor(); return mSocket.getFileDescriptor();
} }
/**
* Reads start commands from an open command socket.
* Start commands are presently a pair of newline-delimited lines
* indicating a) class to invoke main() on b) nice name to set argv[0] to.
* Continues to read commands and forkAndSpecialize children until
* the socket is closed. This method is used in ZYGOTE_FORK_MODE
*
* @throws ZygoteInit.MethodAndArgsCaller trampoline to invoke main()
* method in child process
*/
void run() throws ZygoteInit.MethodAndArgsCaller {
int loopCount = ZygoteInit.GC_LOOP_COUNT;
while (true) {
/*
* Call gc() before we block in readArgumentList().
* It's work that has to be done anyway, and it's better
* to avoid making every child do it. It will also
* madvise() any free memory as a side-effect.
*
* Don't call it every time, because walking the entire
* heap is a lot of overhead to free a few hundred bytes.
*/
if (loopCount <= 0) {
ZygoteInit.gc();
loopCount = ZygoteInit.GC_LOOP_COUNT;
} else {
loopCount--;
}
if (runOnce()) {
break;
}
}
}
/** /**
* Reads one start command from the command socket. If successful, * Reads one start command from the command socket. If successful,
* a child is forked and a {@link ZygoteInit.MethodAndArgsCaller} * a child is forked and a {@link ZygoteInit.MethodAndArgsCaller}
@@ -196,6 +160,11 @@ class ZygoteConnection {
try { try {
parsedArgs = new Arguments(args); parsedArgs = new Arguments(args);
if (parsedArgs.abiListQuery) {
return handleAbiListQuery();
}
if (parsedArgs.permittedCapabilities != 0 || parsedArgs.effectiveCapabilities != 0) { if (parsedArgs.permittedCapabilities != 0 || parsedArgs.effectiveCapabilities != 0) {
throw new ZygoteSecurityException("Client may not specify capabilities: " + throw new ZygoteSecurityException("Client may not specify capabilities: " +
"permitted=0x" + Long.toHexString(parsedArgs.permittedCapabilities) + "permitted=0x" + Long.toHexString(parsedArgs.permittedCapabilities) +
@@ -287,6 +256,18 @@ class ZygoteConnection {
} }
} }
private boolean handleAbiListQuery() {
try {
final byte[] abiListBytes = abiList.getBytes(StandardCharsets.US_ASCII);
mSocketOutStream.writeInt(abiListBytes.length);
mSocketOutStream.write(abiListBytes);
return false;
} catch (IOException ioe) {
Log.e(TAG, "Error writing to command socket", ioe);
return true;
}
}
/** /**
* Closes socket associated with this connection. * Closes socket associated with this connection.
*/ */
@@ -387,6 +368,11 @@ class ZygoteConnection {
*/ */
String remainingArgs[]; String remainingArgs[];
/**
* Whether the current arguments constitute an ABI list query.
*/
boolean abiListQuery;
/** /**
* Constructs instance and parses args * Constructs instance and parses args
* @param args zygote command-line args * @param args zygote command-line args
@@ -540,6 +526,8 @@ class ZygoteConnection {
mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER; mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER;
} else if (arg.equals("--mount-external-multiuser-all")) { } else if (arg.equals("--mount-external-multiuser-all")) {
mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL; mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL;
} else if (arg.equals("--query-abi-list")) {
abiListQuery = true;
} else { } else {
break; break;
} }
@@ -975,7 +963,7 @@ class ZygoteConnection {
mSocketOutStream.writeInt(pid); mSocketOutStream.writeInt(pid);
mSocketOutStream.writeBoolean(usingWrapper); mSocketOutStream.writeBoolean(usingWrapper);
} catch (IOException ex) { } catch (IOException ex) {
Log.e(TAG, "Error reading from command socket", ex); Log.e(TAG, "Error writing to command socket", ex);
return true; return true;
} }

View File

@@ -64,7 +64,7 @@ public class ZygoteInit {
private static final String PROPERTY_DISABLE_OPENGL_PRELOADING = "ro.zygote.disable_gl_preload"; private static final String PROPERTY_DISABLE_OPENGL_PRELOADING = "ro.zygote.disable_gl_preload";
private static final String ANDROID_SOCKET_ENV = "ANDROID_SOCKET_zygote"; private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";
private static final int LOG_BOOT_PROGRESS_PRELOAD_START = 3020; private static final int LOG_BOOT_PROGRESS_PRELOAD_START = 3020;
private static final int LOG_BOOT_PROGRESS_PRELOAD_END = 3030; private static final int LOG_BOOT_PROGRESS_PRELOAD_END = 3030;
@@ -72,8 +72,9 @@ public class ZygoteInit {
/** when preloading, GC after allocating this many bytes */ /** when preloading, GC after allocating this many bytes */
private static final int PRELOAD_GC_THRESHOLD = 50000; private static final int PRELOAD_GC_THRESHOLD = 50000;
public static final String USAGE_STRING = private static final String ABI_LIST_ARG = "--abi-list=";
" <\"start-system-server\"|\"\" for startSystemServer>";
private static final String SOCKET_NAME_ARG = "--socket-name=";
private static LocalServerSocket sServerSocket; private static LocalServerSocket sServerSocket;
@@ -150,15 +151,15 @@ public class ZygoteInit {
* *
* @throws RuntimeException when open fails * @throws RuntimeException when open fails
*/ */
private static void registerZygoteSocket() { private static void registerZygoteSocket(String socketName) {
if (sServerSocket == null) { if (sServerSocket == null) {
int fileDesc; int fileDesc;
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
try { try {
String env = System.getenv(ANDROID_SOCKET_ENV); String env = System.getenv(fullSocketName);
fileDesc = Integer.parseInt(env); fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) { } catch (RuntimeException ex) {
throw new RuntimeException( throw new RuntimeException(fullSocketName + " unset or invalid", ex);
ANDROID_SOCKET_ENV + " unset or invalid", ex);
} }
try { try {
@@ -175,9 +176,9 @@ public class ZygoteInit {
* Waits for and accepts a single command connection. Throws * Waits for and accepts a single command connection. Throws
* RuntimeException on failure. * RuntimeException on failure.
*/ */
private static ZygoteConnection acceptCommandPeer() { private static ZygoteConnection acceptCommandPeer(String abiList) {
try { try {
return new ZygoteConnection(sServerSocket.accept()); return new ZygoteConnection(sServerSocket.accept(), abiList);
} catch (IOException ex) { } catch (IOException ex) {
throw new RuntimeException( throw new RuntimeException(
"IOException during accept()", ex); "IOException during accept()", ex);
@@ -567,7 +568,26 @@ public class ZygoteInit {
// Start profiling the zygote initialization. // Start profiling the zygote initialization.
SamplingProfilerIntegration.start(); SamplingProfilerIntegration.start();
registerZygoteSocket(); boolean startSystemServer = false;
String socketName = "zygote";
String abiList = null;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
socketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
if (abiList == null) {
throw new RuntimeException("No ABI list supplied.");
}
registerZygoteSocket(socketName);
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis()); SystemClock.uptimeMillis());
preload(); preload();
@@ -584,20 +604,12 @@ public class ZygoteInit {
// Zygote. // Zygote.
Trace.setTracingEnabled(false); Trace.setTracingEnabled(false);
// If requested, start system server directly from Zygote if (startSystemServer) {
if (argv.length != 2) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
if (argv[1].equals("start-system-server")) {
startSystemServer(); startSystemServer();
} else if (!argv[1].equals("")) {
throw new RuntimeException(argv[0] + USAGE_STRING);
} }
Log.i(TAG, "Accepting command socket connections"); Log.i(TAG, "Accepting command socket connections");
runSelectLoop(abiList);
runSelectLoop();
closeServerSocket(); closeServerSocket();
} catch (MethodAndArgsCaller caller) { } catch (MethodAndArgsCaller caller) {
@@ -617,7 +629,7 @@ public class ZygoteInit {
* @throws MethodAndArgsCaller in a child process when a main() should * @throws MethodAndArgsCaller in a child process when a main() should
* be executed. * be executed.
*/ */
private static void runSelectLoop() throws MethodAndArgsCaller { private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>(); ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>(); ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
FileDescriptor[] fdArray = new FileDescriptor[4]; FileDescriptor[] fdArray = new FileDescriptor[4];
@@ -656,7 +668,7 @@ public class ZygoteInit {
if (index < 0) { if (index < 0) {
throw new RuntimeException("Error in select()"); throw new RuntimeException("Error in select()");
} else if (index == 0) { } else if (index == 0) {
ZygoteConnection newPeer = acceptCommandPeer(); ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer); peers.add(newPeer);
fds.add(newPeer.getFileDesciptor()); fds.add(newPeer.getFileDesciptor());
} else { } else {