Loading core/java/android/os/Process.java +31 −25 Original line number Diff line number Diff line Loading @@ -270,13 +270,12 @@ public class Process { * @param targetSdkVersion The target SDK version for the app. * @param zygoteArgs Additional arguments to supply to the zygote process. * * @return int If > 0 the pid of the new process; if 0 the process is * being emulated by a thread * @return An object that describes the result of the attempt to start the process. * @throws RuntimeException on fatal start failure * * {@hide} */ public static final int start(final String processClass, public static final ProcessStartResult start(final String processClass, final String niceName, int uid, int gid, int[] gids, int debugFlags, int targetSdkVersion, Loading Loading @@ -376,14 +375,11 @@ public class Process { * and returns the child's pid. Please note: the present implementation * replaces newlines in the argument list with spaces. * @param args argument list * @return PID of new child process * @return An object that describes the result of the attempt to start the process. * @throws ZygoteStartFailedEx if process start failed for any reason */ private static int zygoteSendArgsAndGetPid(ArrayList<String> args) private static ProcessStartResult zygoteSendArgsAndGetResult(ArrayList<String> args) throws ZygoteStartFailedEx { int pid; openZygoteSocketIfNeeded(); try { Loading @@ -394,7 +390,8 @@ public class Process { * b) a number of newline-separated argument strings equal to count * * After the zygote process reads these it will write the pid of * the child or -1 on failure. * the child or -1 on failure, followed by boolean to * indicate whether a wrapper process was used. */ sZygoteWriter.write(Integer.toString(args.size())); Loading @@ -414,11 +411,13 @@ public class Process { sZygoteWriter.flush(); // Should there be a timeout on this? pid = sZygoteInputStream.readInt(); if (pid < 0) { ProcessStartResult result = new ProcessStartResult(); result.pid = sZygoteInputStream.readInt(); if (result.pid < 0) { throw new ZygoteStartFailedEx("fork() failed"); } result.usingWrapper = sZygoteInputStream.readBoolean(); return result; } catch (IOException ex) { try { if (sZygoteSocket != null) { Loading @@ -433,8 +432,6 @@ public class Process { throw new ZygoteStartFailedEx(ex); } return pid; } /** Loading @@ -449,18 +446,16 @@ public class Process { * @param debugFlags Additional flags. * @param targetSdkVersion The target SDK version for the app. * @param extraArgs Additional arguments to supply to the zygote process. * @return PID * @return An object that describes the result of the attempt to start the process. * @throws ZygoteStartFailedEx if process start failed for any reason */ private static int startViaZygote(final String processClass, private static ProcessStartResult startViaZygote(final String processClass, final String niceName, final int uid, final int gid, final int[] gids, int debugFlags, int targetSdkVersion, String[] extraArgs) throws ZygoteStartFailedEx { int pid; synchronized(Process.class) { ArrayList<String> argsForZygote = new ArrayList<String>(); Loading Loading @@ -517,14 +512,8 @@ public class Process { } } pid = zygoteSendArgsAndGetPid(argsForZygote); return zygoteSendArgsAndGetResult(argsForZygote); } if (pid <= 0) { throw new ZygoteStartFailedEx("zygote start failed:" + pid); } return pid; } /** Loading Loading @@ -808,4 +797,21 @@ public class Process { * @hide */ public static final native long getPss(int pid); /** * Specifies the outcome of having started a process. * @hide */ public static final class ProcessStartResult { /** * The PID of the newly started process. * Always >= 0. (If the start failed, an exception will have been thrown instead.) */ public int pid; /** * True if the process was started with a wrapper attached. */ public boolean usingWrapper; } } core/java/com/android/internal/os/ZygoteConnection.java +3 −0 Original line number Diff line number Diff line Loading @@ -900,6 +900,7 @@ class ZygoteConnection { } } boolean usingWrapper = false; if (pipeFd != null && pid > 0) { DataInputStream is = new DataInputStream(new FileInputStream(pipeFd)); int innerPid = -1; Loading @@ -924,6 +925,7 @@ class ZygoteConnection { if (parentPid > 0) { Log.i(TAG, "Wrapped process has pid " + innerPid); pid = innerPid; usingWrapper = true; } else { Log.w(TAG, "Wrapped process reported a pid that is not a child of " + "the process that we forked: childPid=" + pid Loading @@ -934,6 +936,7 @@ class ZygoteConnection { try { mSocketOutStream.writeInt(pid); mSocketOutStream.writeBoolean(usingWrapper); } catch (IOException ex) { Log.e(TAG, "Error reading from command socket", ex); return true; Loading services/java/com/android/server/am/ActivityManagerService.java +23 −19 Original line number Diff line number Diff line Loading @@ -208,6 +208,12 @@ public final class ActivityManagerService extends ActivityManagerNative // before we decide it's never going to come up for real. static final int PROC_START_TIMEOUT = 10*1000; // How long we wait for a launched process to attach to the activity manager // before we decide it's never going to come up for real, when the process was // started with a wrapper for instrumentation (such as Valgrind) because it // could take much longer than usual. static final int PROC_START_TIMEOUT_WITH_WRAPPER = 300*1000; // How long to wait after going idle before forcing apps to GC. static final int GC_TIMEOUT = 5*1000; Loading Loading @@ -1950,9 +1956,13 @@ public final class ActivityManagerService extends ActivityManagerNative if ("1".equals(SystemProperties.get("debug.assert"))) { debugFlags |= Zygote.DEBUG_ENABLE_ASSERT; } int pid = Process.start("android.app.ActivityThread", // Start the process. It will either succeed and return a result containing // 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, app.info.targetSdkVersion, null); BatteryStatsImpl bs = app.batteryStats.getBatteryStats(); synchronized (bs) { if (bs.isOnBattery()) { Loading @@ -1960,12 +1970,12 @@ public final class ActivityManagerService extends ActivityManagerNative } } EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid, EventLog.writeEvent(EventLogTags.AM_PROC_START, startResult.pid, uid, app.processName, hostingType, hostingNameStr != null ? hostingNameStr : ""); if (app.persistent) { Watchdog.getInstance().processStarted(app.processName, pid); Watchdog.getInstance().processStarted(app.processName, startResult.pid); } StringBuilder buf = mStringBuilder; Loading @@ -1979,7 +1989,7 @@ public final class ActivityManagerService extends ActivityManagerNative buf.append(hostingNameStr); } buf.append(": pid="); buf.append(pid); buf.append(startResult.pid); buf.append(" uid="); buf.append(uid); buf.append(" gids={"); Loading @@ -1992,21 +2002,15 @@ public final class ActivityManagerService extends ActivityManagerNative } buf.append("}"); Slog.i(TAG, buf.toString()); if (pid > 0) { app.pid = pid; app.pid = startResult.pid; app.usingWrapper = startResult.usingWrapper; app.removed = false; synchronized (mPidsSelfLocked) { this.mPidsSelfLocked.put(pid, app); this.mPidsSelfLocked.put(startResult.pid, app); Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG); msg.obj = app; mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT); } } else { app.pid = 0; RuntimeException e = new RuntimeException( "Failure starting process " + app.processName + ": returned pid=" + pid); Slog.e(TAG, e.getMessage(), e); mHandler.sendMessageDelayed(msg, startResult.usingWrapper ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT); } } catch (RuntimeException e) { // XXX do better error recovery. Loading services/java/com/android/server/am/ActivityRecord.java +5 −5 Original line number Diff line number Diff line Loading @@ -658,12 +658,12 @@ final class ActivityRecord extends IApplicationToken.Stub { public long getKeyDispatchingTimeout() { synchronized(service) { ActivityRecord r = getWaitingHistoryRecordLocked(); if (r == null || r.app == null || r.app.instrumentationClass == null) { return ActivityManagerService.KEY_DISPATCHING_TIMEOUT; if (r != null && r.app != null && (r.app.instrumentationClass != null || r.app.usingWrapper)) { return ActivityManagerService.INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT; } return ActivityManagerService.INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT; return ActivityManagerService.KEY_DISPATCHING_TIMEOUT; } } Loading services/java/com/android/server/am/ProcessRecord.java +1 −0 Original line number Diff line number Diff line Loading @@ -78,6 +78,7 @@ class ProcessRecord { IInstrumentationWatcher instrumentationWatcher; // who is waiting Bundle instrumentationArguments;// as given to us ComponentName instrumentationResultClass;// copy of instrumentationClass boolean usingWrapper; // Set to true when process was launched with a wrapper attached BroadcastRecord curReceiver;// receiver currently running in the app long lastWakeTime; // How long proc held wake lock at last check long lastCpuTime; // How long proc has run CPU at last check Loading Loading
core/java/android/os/Process.java +31 −25 Original line number Diff line number Diff line Loading @@ -270,13 +270,12 @@ public class Process { * @param targetSdkVersion The target SDK version for the app. * @param zygoteArgs Additional arguments to supply to the zygote process. * * @return int If > 0 the pid of the new process; if 0 the process is * being emulated by a thread * @return An object that describes the result of the attempt to start the process. * @throws RuntimeException on fatal start failure * * {@hide} */ public static final int start(final String processClass, public static final ProcessStartResult start(final String processClass, final String niceName, int uid, int gid, int[] gids, int debugFlags, int targetSdkVersion, Loading Loading @@ -376,14 +375,11 @@ public class Process { * and returns the child's pid. Please note: the present implementation * replaces newlines in the argument list with spaces. * @param args argument list * @return PID of new child process * @return An object that describes the result of the attempt to start the process. * @throws ZygoteStartFailedEx if process start failed for any reason */ private static int zygoteSendArgsAndGetPid(ArrayList<String> args) private static ProcessStartResult zygoteSendArgsAndGetResult(ArrayList<String> args) throws ZygoteStartFailedEx { int pid; openZygoteSocketIfNeeded(); try { Loading @@ -394,7 +390,8 @@ public class Process { * b) a number of newline-separated argument strings equal to count * * After the zygote process reads these it will write the pid of * the child or -1 on failure. * the child or -1 on failure, followed by boolean to * indicate whether a wrapper process was used. */ sZygoteWriter.write(Integer.toString(args.size())); Loading @@ -414,11 +411,13 @@ public class Process { sZygoteWriter.flush(); // Should there be a timeout on this? pid = sZygoteInputStream.readInt(); if (pid < 0) { ProcessStartResult result = new ProcessStartResult(); result.pid = sZygoteInputStream.readInt(); if (result.pid < 0) { throw new ZygoteStartFailedEx("fork() failed"); } result.usingWrapper = sZygoteInputStream.readBoolean(); return result; } catch (IOException ex) { try { if (sZygoteSocket != null) { Loading @@ -433,8 +432,6 @@ public class Process { throw new ZygoteStartFailedEx(ex); } return pid; } /** Loading @@ -449,18 +446,16 @@ public class Process { * @param debugFlags Additional flags. * @param targetSdkVersion The target SDK version for the app. * @param extraArgs Additional arguments to supply to the zygote process. * @return PID * @return An object that describes the result of the attempt to start the process. * @throws ZygoteStartFailedEx if process start failed for any reason */ private static int startViaZygote(final String processClass, private static ProcessStartResult startViaZygote(final String processClass, final String niceName, final int uid, final int gid, final int[] gids, int debugFlags, int targetSdkVersion, String[] extraArgs) throws ZygoteStartFailedEx { int pid; synchronized(Process.class) { ArrayList<String> argsForZygote = new ArrayList<String>(); Loading Loading @@ -517,14 +512,8 @@ public class Process { } } pid = zygoteSendArgsAndGetPid(argsForZygote); return zygoteSendArgsAndGetResult(argsForZygote); } if (pid <= 0) { throw new ZygoteStartFailedEx("zygote start failed:" + pid); } return pid; } /** Loading Loading @@ -808,4 +797,21 @@ public class Process { * @hide */ public static final native long getPss(int pid); /** * Specifies the outcome of having started a process. * @hide */ public static final class ProcessStartResult { /** * The PID of the newly started process. * Always >= 0. (If the start failed, an exception will have been thrown instead.) */ public int pid; /** * True if the process was started with a wrapper attached. */ public boolean usingWrapper; } }
core/java/com/android/internal/os/ZygoteConnection.java +3 −0 Original line number Diff line number Diff line Loading @@ -900,6 +900,7 @@ class ZygoteConnection { } } boolean usingWrapper = false; if (pipeFd != null && pid > 0) { DataInputStream is = new DataInputStream(new FileInputStream(pipeFd)); int innerPid = -1; Loading @@ -924,6 +925,7 @@ class ZygoteConnection { if (parentPid > 0) { Log.i(TAG, "Wrapped process has pid " + innerPid); pid = innerPid; usingWrapper = true; } else { Log.w(TAG, "Wrapped process reported a pid that is not a child of " + "the process that we forked: childPid=" + pid Loading @@ -934,6 +936,7 @@ class ZygoteConnection { try { mSocketOutStream.writeInt(pid); mSocketOutStream.writeBoolean(usingWrapper); } catch (IOException ex) { Log.e(TAG, "Error reading from command socket", ex); return true; Loading
services/java/com/android/server/am/ActivityManagerService.java +23 −19 Original line number Diff line number Diff line Loading @@ -208,6 +208,12 @@ public final class ActivityManagerService extends ActivityManagerNative // before we decide it's never going to come up for real. static final int PROC_START_TIMEOUT = 10*1000; // How long we wait for a launched process to attach to the activity manager // before we decide it's never going to come up for real, when the process was // started with a wrapper for instrumentation (such as Valgrind) because it // could take much longer than usual. static final int PROC_START_TIMEOUT_WITH_WRAPPER = 300*1000; // How long to wait after going idle before forcing apps to GC. static final int GC_TIMEOUT = 5*1000; Loading Loading @@ -1950,9 +1956,13 @@ public final class ActivityManagerService extends ActivityManagerNative if ("1".equals(SystemProperties.get("debug.assert"))) { debugFlags |= Zygote.DEBUG_ENABLE_ASSERT; } int pid = Process.start("android.app.ActivityThread", // Start the process. It will either succeed and return a result containing // 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, app.info.targetSdkVersion, null); BatteryStatsImpl bs = app.batteryStats.getBatteryStats(); synchronized (bs) { if (bs.isOnBattery()) { Loading @@ -1960,12 +1970,12 @@ public final class ActivityManagerService extends ActivityManagerNative } } EventLog.writeEvent(EventLogTags.AM_PROC_START, pid, uid, EventLog.writeEvent(EventLogTags.AM_PROC_START, startResult.pid, uid, app.processName, hostingType, hostingNameStr != null ? hostingNameStr : ""); if (app.persistent) { Watchdog.getInstance().processStarted(app.processName, pid); Watchdog.getInstance().processStarted(app.processName, startResult.pid); } StringBuilder buf = mStringBuilder; Loading @@ -1979,7 +1989,7 @@ public final class ActivityManagerService extends ActivityManagerNative buf.append(hostingNameStr); } buf.append(": pid="); buf.append(pid); buf.append(startResult.pid); buf.append(" uid="); buf.append(uid); buf.append(" gids={"); Loading @@ -1992,21 +2002,15 @@ public final class ActivityManagerService extends ActivityManagerNative } buf.append("}"); Slog.i(TAG, buf.toString()); if (pid > 0) { app.pid = pid; app.pid = startResult.pid; app.usingWrapper = startResult.usingWrapper; app.removed = false; synchronized (mPidsSelfLocked) { this.mPidsSelfLocked.put(pid, app); this.mPidsSelfLocked.put(startResult.pid, app); Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG); msg.obj = app; mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT); } } else { app.pid = 0; RuntimeException e = new RuntimeException( "Failure starting process " + app.processName + ": returned pid=" + pid); Slog.e(TAG, e.getMessage(), e); mHandler.sendMessageDelayed(msg, startResult.usingWrapper ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT); } } catch (RuntimeException e) { // XXX do better error recovery. Loading
services/java/com/android/server/am/ActivityRecord.java +5 −5 Original line number Diff line number Diff line Loading @@ -658,12 +658,12 @@ final class ActivityRecord extends IApplicationToken.Stub { public long getKeyDispatchingTimeout() { synchronized(service) { ActivityRecord r = getWaitingHistoryRecordLocked(); if (r == null || r.app == null || r.app.instrumentationClass == null) { return ActivityManagerService.KEY_DISPATCHING_TIMEOUT; if (r != null && r.app != null && (r.app.instrumentationClass != null || r.app.usingWrapper)) { return ActivityManagerService.INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT; } return ActivityManagerService.INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT; return ActivityManagerService.KEY_DISPATCHING_TIMEOUT; } } Loading
services/java/com/android/server/am/ProcessRecord.java +1 −0 Original line number Diff line number Diff line Loading @@ -78,6 +78,7 @@ class ProcessRecord { IInstrumentationWatcher instrumentationWatcher; // who is waiting Bundle instrumentationArguments;// as given to us ComponentName instrumentationResultClass;// copy of instrumentationClass boolean usingWrapper; // Set to true when process was launched with a wrapper attached BroadcastRecord curReceiver;// receiver currently running in the app long lastWakeTime; // How long proc held wake lock at last check long lastCpuTime; // How long proc has run CPU at last check Loading