/** * Tries to open socket to Zygote process if not already open. If already open, does nothing. May * block and retry. */ private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx { if (primaryZygoteState == null || primaryZygoteState.isClosed()) { primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET, getNumTries(primaryZygoteState)); } if (primaryZygoteState.matches(abi)) { return primaryZygoteState; } // TODO: Get rid of this. This is a temporary workaround until all the // compilation related pieces for the dual zygote stack are ready. // b/3647418. if (System.getenv("ANDROID_SOCKET_" + SECONDARY_ZYGOTE_SOCKET) == null) { Log.e(LOG_TAG, "Forcing app to primary zygote, secondary unavailable (ABI= " + abi + ")"); // Should be : // throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi); return primaryZygoteState; } // The primary zygote didn't match. Try the secondary. if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) { secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET, getNumTries(secondaryZygoteState)); } if (secondaryZygoteState.matches(abi)) { return secondaryZygoteState; } throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi); }
/** * Sends an argument list to the zygote process, which starts a new child and returns the child's * pid. Please note: the present implementation replaces newlines in the argument list with * spaces. * * @throws ZygoteStartFailedEx if process start failed for any reason */ private static ProcessStartResult zygoteSendArgsAndGetResult( ZygoteState zygoteState, ArrayList<String> args) throws ZygoteStartFailedEx { try { /** * See com.android.internal.os.ZygoteInit.readArgumentList() Presently the wire format to the * zygote process is: a) a count of arguments (argc, in essence) b) a number of * newline-separated argument strings equal to count * * <p>After the zygote process reads these it will write the pid of the child or -1 on * failure, followed by boolean to indicate whether a wrapper process was used. */ final BufferedWriter writer = zygoteState.writer; final DataInputStream inputStream = zygoteState.inputStream; writer.write(Integer.toString(args.size())); writer.newLine(); int sz = args.size(); for (int i = 0; i < sz; i++) { String arg = args.get(i); if (arg.indexOf('\n') >= 0) { throw new ZygoteStartFailedEx("embedded newlines not allowed"); } writer.write(arg); writer.newLine(); } writer.flush(); // Should there be a timeout on this? ProcessStartResult result = new ProcessStartResult(); result.pid = inputStream.readInt(); if (result.pid < 0) { throw new ZygoteStartFailedEx("fork() failed"); } result.usingWrapper = inputStream.readBoolean(); return result; } catch (IOException ex) { zygoteState.close(); throw new ZygoteStartFailedEx(ex); } }
/** * Tries to open socket to Zygote process if not already open. If already open, does nothing. May * block and retry. */ private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx { if (primaryZygoteState == null || primaryZygoteState.isClosed()) { primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET, getNumTries(primaryZygoteState)); } if (primaryZygoteState.matches(abi)) { return primaryZygoteState; } // The primary zygote didn't match. Try the secondary. if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) { secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET, getNumTries(secondaryZygoteState)); } if (secondaryZygoteState.matches(abi)) { return secondaryZygoteState; } throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi); }