Loading core/java/com/android/internal/os/Zygote.java +16 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import android.system.ErrnoException; import android.system.Os; import android.util.Log; import dalvik.annotation.optimization.FastNative; import dalvik.system.ZygoteHooks; import libcore.io.IoUtils; Loading Loading @@ -969,4 +970,19 @@ public final class Zygote { command.append(" '").append(arg.replace("'", "'\\''")).append("'"); } } /** * Parse the given unsolicited zygote message as type SIGCHLD, * extract the payload information into the given output buffer. * * @param in The unsolicited zygote message to be parsed * @param length The number of bytes in the message * @param out The output buffer where the payload information will be placed * @return Number of elements being place into output buffer, or -1 if * either the message is malformed or not the type as expected here. * * @hide */ @FastNative public static native int nativeParseSigChld(byte[] in, int length, int[] out); } core/jni/com_android_internal_os_Zygote.cpp +125 −4 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ #include <sys/stat.h> #include <sys/time.h> #include <sys/types.h> #include <sys/un.h> #include <sys/utsname.h> #include <sys/wait.h> #include <unistd.h> Loading Loading @@ -163,6 +164,12 @@ static std::atomic_uint32_t gUsapPoolCount = 0; */ static int gUsapPoolEventFD = -1; /** * The socket file descriptor used to send notifications to the * system_server. */ static int gSystemServerSocketFd = -1; /** * The maximum value that the gUSAPPoolSizeMax variable may take. This value * is a mirror of ZygoteServer.USAP_POOL_SIZE_MAX_LIMIT Loading Loading @@ -314,6 +321,26 @@ enum RuntimeFlags : uint32_t { PROFILE_FROM_SHELL = 1 << 15, }; enum UnsolicitedZygoteMessageTypes : uint32_t { UNSOLICITED_ZYGOTE_MESSAGE_TYPE_RESERVED = 0, UNSOLICITED_ZYGOTE_MESSAGE_TYPE_SIGCHLD = 1, }; struct UnsolicitedZygoteMessageSigChld { struct { UnsolicitedZygoteMessageTypes type; } header; struct { pid_t pid; uid_t uid; int status; } payload; }; // Keep sync with services/core/java/com/android/server/am/ProcessList.java static constexpr struct sockaddr_un kSystemServerSockAddr = {.sun_family = AF_LOCAL, .sun_path = "/data/system/unsolzygotesocket"}; // Forward declaration so we don't have to move the signal handler. static bool RemoveUsapTableEntry(pid_t usap_pid); Loading @@ -323,8 +350,37 @@ static void RuntimeAbort(JNIEnv* env, int line, const char* msg) { env->FatalError(oss.str().c_str()); } // Create the socket which is going to be used to send unsolicited message // to system_server, the socket will be closed post forking a child process. // It's expected to be called at each zygote's initialization. static void initUnsolSocketToSystemServer() { gSystemServerSocketFd = socket(AF_LOCAL, SOCK_DGRAM | SOCK_NONBLOCK, 0); if (gSystemServerSocketFd >= 0) { ALOGV("Zygote:systemServerSocketFD = %d", gSystemServerSocketFd); } else { ALOGE("Unable to create socket file descriptor to connect to system_server"); } } static void sendSigChildStatus(const pid_t pid, const uid_t uid, const int status) { int socketFd = gSystemServerSocketFd; if (socketFd >= 0) { // fill the message buffer struct UnsolicitedZygoteMessageSigChld data = {.header = {.type = UNSOLICITED_ZYGOTE_MESSAGE_TYPE_SIGCHLD}, .payload = {.pid = pid, .uid = uid, .status = status}}; if (TEMP_FAILURE_RETRY( sendto(socketFd, &data, sizeof(data), 0, reinterpret_cast<const struct sockaddr*>(&kSystemServerSockAddr), sizeof(kSystemServerSockAddr))) == -1) { async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "Zygote failed to write to system_server FD: %s", strerror(errno)); } } } // This signal handler is for zygote mode, since the zygote must reap its children static void SigChldHandler(int /*signal_number*/) { static void SigChldHandler(int /*signal_number*/, siginfo_t* info, void* /*ucontext*/) { pid_t pid; int status; int64_t usaps_removed = 0; Loading @@ -338,6 +394,8 @@ static void SigChldHandler(int /*signal_number*/) { int saved_errno = errno; while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { // Notify system_server that we received a SIGCHLD sendSigChildStatus(pid, info->si_uid, status); // Log process-death status that we care about. if (WIFEXITED(status)) { async_safe_format_log(ANDROID_LOG_INFO, LOG_TAG, Loading Loading @@ -411,8 +469,7 @@ static void SigChldHandler(int /*signal_number*/) { // This ends up being called repeatedly before each fork(), but there's // no real harm in that. static void SetSignalHandlers() { struct sigaction sig_chld = {}; sig_chld.sa_handler = SigChldHandler; struct sigaction sig_chld = {.sa_flags = SA_SIGINFO, .sa_sigaction = SigChldHandler}; if (sigaction(SIGCHLD, &sig_chld, nullptr) < 0) { ALOGW("Error setting SIGCHLD handler: %s", strerror(errno)); Loading Loading @@ -967,6 +1024,9 @@ static pid_t ForkCommon(JNIEnv* env, bool is_system_server, // Turn fdsan back on. android_fdsan_set_error_level(fdsan_error_level); // Reset the fd to the unsolicited zygote socket gSystemServerSocketFd = -1; } else { ALOGD("Forked child process %d", pid); } Loading Loading @@ -1146,6 +1206,10 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, } } if (is_child_zygote) { initUnsolSocketToSystemServer(); } env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags, is_system_server, is_child_zygote, managed_instruction_set); Loading Loading @@ -1391,6 +1455,11 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( fds_to_ignore.push_back(gUsapPoolEventFD); } if (gSystemServerSocketFd != -1) { fds_to_close.push_back(gSystemServerSocketFd); fds_to_ignore.push_back(gSystemServerSocketFd); } pid_t pid = ForkCommon(env, false, fds_to_close, fds_to_ignore, true); if (pid == 0) { Loading @@ -1416,6 +1485,11 @@ static jint com_android_internal_os_Zygote_nativeForkSystemServer( fds_to_ignore.push_back(gUsapPoolEventFD); } if (gSystemServerSocketFd != -1) { fds_to_close.push_back(gSystemServerSocketFd); fds_to_ignore.push_back(gSystemServerSocketFd); } pid_t pid = ForkCommon(env, true, fds_to_close, fds_to_ignore, Loading Loading @@ -1483,6 +1557,9 @@ static jint com_android_internal_os_Zygote_nativeForkUsap(JNIEnv* env, fds_to_close.push_back(gZygoteSocketFD); fds_to_close.push_back(gUsapPoolEventFD); fds_to_close.insert(fds_to_close.end(), session_socket_fds.begin(), session_socket_fds.end()); if (gSystemServerSocketFd != -1) { fds_to_close.push_back(gSystemServerSocketFd); } fds_to_ignore.push_back(gZygoteSocketFD); fds_to_ignore.push_back(gUsapPoolSocketFD); Loading @@ -1490,6 +1567,9 @@ static jint com_android_internal_os_Zygote_nativeForkUsap(JNIEnv* env, fds_to_ignore.push_back(read_pipe_fd); fds_to_ignore.push_back(write_pipe_fd); fds_to_ignore.insert(fds_to_ignore.end(), session_socket_fds.begin(), session_socket_fds.end()); if (gSystemServerSocketFd != -1) { fds_to_ignore.push_back(gSystemServerSocketFd); } pid_t usap_pid = ForkCommon(env, /* is_system_server= */ false, fds_to_close, fds_to_ignore, is_priority_fork == JNI_TRUE); Loading Loading @@ -1590,6 +1670,7 @@ static void com_android_internal_os_Zygote_nativeInitNativeState(JNIEnv* env, jc ALOGE("Unable to fetch USAP pool socket file descriptor"); } initUnsolSocketToSystemServer(); /* * Security Initialization */ Loading Loading @@ -1733,6 +1814,44 @@ static void com_android_internal_os_Zygote_nativeBoostUsapPriority(JNIEnv* env, setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MAX); } static jint com_android_internal_os_Zygote_nativeParseSigChld(JNIEnv* env, jclass, jbyteArray in, jint length, jintArray out) { if (length != sizeof(struct UnsolicitedZygoteMessageSigChld)) { // Apparently it's not the message we are expecting. return -1; } if (in == nullptr || out == nullptr) { // Invalid parameter jniThrowException(env, "java/lang/IllegalArgumentException", nullptr); return -1; } ScopedByteArrayRO source(env, in); if (source.size() < length) { // Invalid parameter jniThrowException(env, "java/lang/IllegalArgumentException", nullptr); return -1; } const struct UnsolicitedZygoteMessageSigChld* msg = reinterpret_cast<const struct UnsolicitedZygoteMessageSigChld*>(source.get()); switch (msg->header.type) { case UNSOLICITED_ZYGOTE_MESSAGE_TYPE_SIGCHLD: { ScopedIntArrayRW buf(env, out); if (buf.size() != 3) { jniThrowException(env, "java/lang/IllegalArgumentException", nullptr); return UNSOLICITED_ZYGOTE_MESSAGE_TYPE_RESERVED; } buf[0] = msg->payload.pid; buf[1] = msg->payload.uid; buf[2] = msg->payload.status; return 3; } default: break; } return -1; } static const JNINativeMethod gMethods[] = { { "nativeForkAndSpecialize", "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;)I", Loading Loading @@ -1769,7 +1888,9 @@ static const JNINativeMethod gMethods[] = { { "nativeUnblockSigTerm", "()V", (void* ) com_android_internal_os_Zygote_nativeUnblockSigTerm }, { "nativeBoostUsapPriority", "()V", (void* ) com_android_internal_os_Zygote_nativeBoostUsapPriority } (void* ) com_android_internal_os_Zygote_nativeBoostUsapPriority }, {"nativeParseSigChld", "([BI[I)I", (void* ) com_android_internal_os_Zygote_nativeParseSigChld}, }; int register_com_android_internal_os_Zygote(JNIEnv* env) { Loading services/core/java/com/android/server/am/ProcessList.java +100 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY; import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; import static android.app.ActivityThread.PROC_START_SEQ_IDENT; import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AUTO; import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT; import static android.os.Process.SYSTEM_UID; import static android.os.Process.THREAD_PRIORITY_BACKGROUND; import static android.os.Process.getFreeMemory; Loading Loading @@ -57,6 +58,8 @@ import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.res.Resources; import android.graphics.Point; import android.net.LocalSocket; import android.net.LocalSocketAddress; import android.os.AppZygote; import android.os.Binder; import android.os.Build; Loading @@ -74,6 +77,7 @@ import android.os.Trace; import android.os.UserHandle; import android.os.storage.StorageManager; import android.os.storage.StorageManagerInternal; import android.system.Os; import android.text.TextUtils; import android.util.ArrayMap; import android.util.EventLog; Loading Loading @@ -102,6 +106,7 @@ import com.android.server.wm.WindowManagerService; import dalvik.system.VMRuntime; import java.io.File; import java.io.FileDescriptor; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; Loading Loading @@ -245,6 +250,10 @@ public final class ProcessList { private static final String PROPERTY_USE_APP_IMAGE_STARTUP_CACHE = "persist.device_config.runtime_native.use_app_image_startup_cache"; // The socket path for zygote to send unsolicited msg. // Must keep sync with com_android_internal_os_Zygote.cpp. private static final String UNSOL_ZYGOTE_MSG_SOCKET_PATH = "/data/system/unsolzygotesocket"; // Low Memory Killer Daemon command codes. // These must be kept in sync with lmk_cmd definitions in lmkd.h // Loading Loading @@ -388,6 +397,28 @@ public final class ProcessList { private PlatformCompat mPlatformCompat = null; /** * The server socket in system_server, zygote will connect to it * in order to send unsolicited messages to system_server. */ private LocalSocket mSystemServerSocketForZygote; /** * Maximum number of bytes that an incoming unsolicited zygote message could be. * To be updated if new message type needs to be supported. */ private static final int MAX_ZYGOTE_UNSOLICITED_MESSAGE_SIZE = 16; /** * The buffer to be used to receive the incoming unsolicited zygote message. */ private final byte[] mZygoteUnsolicitedMessage = new byte[MAX_ZYGOTE_UNSOLICITED_MESSAGE_SIZE]; /** * The buffer to be used to receive the SIGCHLD data, it includes pid/uid/status. */ private final int[] mZygoteSigChldMessage = new int[3]; interface LmkdKillListener { /** * Called when there is a process kill by lmkd. Loading Loading @@ -645,6 +676,13 @@ public final class ProcessList { } } ); // Start listening on incoming connections from zygotes. mSystemServerSocketForZygote = createSystemServerSocketForZygote(); if (mSystemServerSocketForZygote != null) { sKillHandler.getLooper().getQueue().addOnFileDescriptorEventListener( mSystemServerSocketForZygote.getFileDescriptor(), EVENT_INPUT, this::handleZygoteMessages); } } } Loading Loading @@ -3267,4 +3305,66 @@ public final class ProcessList { } } } private void handleZygoteSigChld(int pid, int uid, int status) { // Just log it now. if (DEBUG_PROCESSES) { Slog.i(TAG, "Got SIGCHLD from zygote: pid=" + pid + ", uid=" + uid + ", status=" + Integer.toHexString(status)); } } /** * Create a server socket in system_server, zygote will connect to it * in order to send unsolicited messages to system_server. */ private LocalSocket createSystemServerSocketForZygote() { // The file system entity for this socket is created with 0666 perms, owned // by system:system. selinux restricts things so that only zygotes can // access it. final File socketFile = new File(UNSOL_ZYGOTE_MSG_SOCKET_PATH); if (socketFile.exists()) { socketFile.delete(); } LocalSocket serverSocket = null; try { serverSocket = new LocalSocket(LocalSocket.SOCKET_DGRAM); serverSocket.bind(new LocalSocketAddress( UNSOL_ZYGOTE_MSG_SOCKET_PATH, LocalSocketAddress.Namespace.FILESYSTEM)); Os.chmod(UNSOL_ZYGOTE_MSG_SOCKET_PATH, 0666); } catch (Exception e) { if (serverSocket != null) { try { serverSocket.close(); } catch (IOException ex) { } serverSocket = null; } } return serverSocket; } /** * Handle the unsolicited message from zygote. */ private int handleZygoteMessages(FileDescriptor fd, int events) { final int eventFd = fd.getInt$(); if ((events & EVENT_INPUT) != 0) { // An incoming message from zygote try { final int len = Os.read(fd, mZygoteUnsolicitedMessage, 0, mZygoteUnsolicitedMessage.length); if (len > 0 && mZygoteSigChldMessage.length == Zygote.nativeParseSigChld( mZygoteUnsolicitedMessage, len, mZygoteSigChldMessage)) { handleZygoteSigChld(mZygoteSigChldMessage[0] /* pid */, mZygoteSigChldMessage[1] /* uid */, mZygoteSigChldMessage[2] /* status */); } } catch (Exception e) { Slog.w(TAG, "Exception in reading unsolicited zygote message: " + e); } } return EVENT_INPUT; } } Loading
core/java/com/android/internal/os/Zygote.java +16 −0 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import android.system.ErrnoException; import android.system.Os; import android.util.Log; import dalvik.annotation.optimization.FastNative; import dalvik.system.ZygoteHooks; import libcore.io.IoUtils; Loading Loading @@ -969,4 +970,19 @@ public final class Zygote { command.append(" '").append(arg.replace("'", "'\\''")).append("'"); } } /** * Parse the given unsolicited zygote message as type SIGCHLD, * extract the payload information into the given output buffer. * * @param in The unsolicited zygote message to be parsed * @param length The number of bytes in the message * @param out The output buffer where the payload information will be placed * @return Number of elements being place into output buffer, or -1 if * either the message is malformed or not the type as expected here. * * @hide */ @FastNative public static native int nativeParseSigChld(byte[] in, int length, int[] out); }
core/jni/com_android_internal_os_Zygote.cpp +125 −4 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ #include <sys/stat.h> #include <sys/time.h> #include <sys/types.h> #include <sys/un.h> #include <sys/utsname.h> #include <sys/wait.h> #include <unistd.h> Loading Loading @@ -163,6 +164,12 @@ static std::atomic_uint32_t gUsapPoolCount = 0; */ static int gUsapPoolEventFD = -1; /** * The socket file descriptor used to send notifications to the * system_server. */ static int gSystemServerSocketFd = -1; /** * The maximum value that the gUSAPPoolSizeMax variable may take. This value * is a mirror of ZygoteServer.USAP_POOL_SIZE_MAX_LIMIT Loading Loading @@ -314,6 +321,26 @@ enum RuntimeFlags : uint32_t { PROFILE_FROM_SHELL = 1 << 15, }; enum UnsolicitedZygoteMessageTypes : uint32_t { UNSOLICITED_ZYGOTE_MESSAGE_TYPE_RESERVED = 0, UNSOLICITED_ZYGOTE_MESSAGE_TYPE_SIGCHLD = 1, }; struct UnsolicitedZygoteMessageSigChld { struct { UnsolicitedZygoteMessageTypes type; } header; struct { pid_t pid; uid_t uid; int status; } payload; }; // Keep sync with services/core/java/com/android/server/am/ProcessList.java static constexpr struct sockaddr_un kSystemServerSockAddr = {.sun_family = AF_LOCAL, .sun_path = "/data/system/unsolzygotesocket"}; // Forward declaration so we don't have to move the signal handler. static bool RemoveUsapTableEntry(pid_t usap_pid); Loading @@ -323,8 +350,37 @@ static void RuntimeAbort(JNIEnv* env, int line, const char* msg) { env->FatalError(oss.str().c_str()); } // Create the socket which is going to be used to send unsolicited message // to system_server, the socket will be closed post forking a child process. // It's expected to be called at each zygote's initialization. static void initUnsolSocketToSystemServer() { gSystemServerSocketFd = socket(AF_LOCAL, SOCK_DGRAM | SOCK_NONBLOCK, 0); if (gSystemServerSocketFd >= 0) { ALOGV("Zygote:systemServerSocketFD = %d", gSystemServerSocketFd); } else { ALOGE("Unable to create socket file descriptor to connect to system_server"); } } static void sendSigChildStatus(const pid_t pid, const uid_t uid, const int status) { int socketFd = gSystemServerSocketFd; if (socketFd >= 0) { // fill the message buffer struct UnsolicitedZygoteMessageSigChld data = {.header = {.type = UNSOLICITED_ZYGOTE_MESSAGE_TYPE_SIGCHLD}, .payload = {.pid = pid, .uid = uid, .status = status}}; if (TEMP_FAILURE_RETRY( sendto(socketFd, &data, sizeof(data), 0, reinterpret_cast<const struct sockaddr*>(&kSystemServerSockAddr), sizeof(kSystemServerSockAddr))) == -1) { async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "Zygote failed to write to system_server FD: %s", strerror(errno)); } } } // This signal handler is for zygote mode, since the zygote must reap its children static void SigChldHandler(int /*signal_number*/) { static void SigChldHandler(int /*signal_number*/, siginfo_t* info, void* /*ucontext*/) { pid_t pid; int status; int64_t usaps_removed = 0; Loading @@ -338,6 +394,8 @@ static void SigChldHandler(int /*signal_number*/) { int saved_errno = errno; while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { // Notify system_server that we received a SIGCHLD sendSigChildStatus(pid, info->si_uid, status); // Log process-death status that we care about. if (WIFEXITED(status)) { async_safe_format_log(ANDROID_LOG_INFO, LOG_TAG, Loading Loading @@ -411,8 +469,7 @@ static void SigChldHandler(int /*signal_number*/) { // This ends up being called repeatedly before each fork(), but there's // no real harm in that. static void SetSignalHandlers() { struct sigaction sig_chld = {}; sig_chld.sa_handler = SigChldHandler; struct sigaction sig_chld = {.sa_flags = SA_SIGINFO, .sa_sigaction = SigChldHandler}; if (sigaction(SIGCHLD, &sig_chld, nullptr) < 0) { ALOGW("Error setting SIGCHLD handler: %s", strerror(errno)); Loading Loading @@ -967,6 +1024,9 @@ static pid_t ForkCommon(JNIEnv* env, bool is_system_server, // Turn fdsan back on. android_fdsan_set_error_level(fdsan_error_level); // Reset the fd to the unsolicited zygote socket gSystemServerSocketFd = -1; } else { ALOGD("Forked child process %d", pid); } Loading Loading @@ -1146,6 +1206,10 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, } } if (is_child_zygote) { initUnsolSocketToSystemServer(); } env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags, is_system_server, is_child_zygote, managed_instruction_set); Loading Loading @@ -1391,6 +1455,11 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( fds_to_ignore.push_back(gUsapPoolEventFD); } if (gSystemServerSocketFd != -1) { fds_to_close.push_back(gSystemServerSocketFd); fds_to_ignore.push_back(gSystemServerSocketFd); } pid_t pid = ForkCommon(env, false, fds_to_close, fds_to_ignore, true); if (pid == 0) { Loading @@ -1416,6 +1485,11 @@ static jint com_android_internal_os_Zygote_nativeForkSystemServer( fds_to_ignore.push_back(gUsapPoolEventFD); } if (gSystemServerSocketFd != -1) { fds_to_close.push_back(gSystemServerSocketFd); fds_to_ignore.push_back(gSystemServerSocketFd); } pid_t pid = ForkCommon(env, true, fds_to_close, fds_to_ignore, Loading Loading @@ -1483,6 +1557,9 @@ static jint com_android_internal_os_Zygote_nativeForkUsap(JNIEnv* env, fds_to_close.push_back(gZygoteSocketFD); fds_to_close.push_back(gUsapPoolEventFD); fds_to_close.insert(fds_to_close.end(), session_socket_fds.begin(), session_socket_fds.end()); if (gSystemServerSocketFd != -1) { fds_to_close.push_back(gSystemServerSocketFd); } fds_to_ignore.push_back(gZygoteSocketFD); fds_to_ignore.push_back(gUsapPoolSocketFD); Loading @@ -1490,6 +1567,9 @@ static jint com_android_internal_os_Zygote_nativeForkUsap(JNIEnv* env, fds_to_ignore.push_back(read_pipe_fd); fds_to_ignore.push_back(write_pipe_fd); fds_to_ignore.insert(fds_to_ignore.end(), session_socket_fds.begin(), session_socket_fds.end()); if (gSystemServerSocketFd != -1) { fds_to_ignore.push_back(gSystemServerSocketFd); } pid_t usap_pid = ForkCommon(env, /* is_system_server= */ false, fds_to_close, fds_to_ignore, is_priority_fork == JNI_TRUE); Loading Loading @@ -1590,6 +1670,7 @@ static void com_android_internal_os_Zygote_nativeInitNativeState(JNIEnv* env, jc ALOGE("Unable to fetch USAP pool socket file descriptor"); } initUnsolSocketToSystemServer(); /* * Security Initialization */ Loading Loading @@ -1733,6 +1814,44 @@ static void com_android_internal_os_Zygote_nativeBoostUsapPriority(JNIEnv* env, setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MAX); } static jint com_android_internal_os_Zygote_nativeParseSigChld(JNIEnv* env, jclass, jbyteArray in, jint length, jintArray out) { if (length != sizeof(struct UnsolicitedZygoteMessageSigChld)) { // Apparently it's not the message we are expecting. return -1; } if (in == nullptr || out == nullptr) { // Invalid parameter jniThrowException(env, "java/lang/IllegalArgumentException", nullptr); return -1; } ScopedByteArrayRO source(env, in); if (source.size() < length) { // Invalid parameter jniThrowException(env, "java/lang/IllegalArgumentException", nullptr); return -1; } const struct UnsolicitedZygoteMessageSigChld* msg = reinterpret_cast<const struct UnsolicitedZygoteMessageSigChld*>(source.get()); switch (msg->header.type) { case UNSOLICITED_ZYGOTE_MESSAGE_TYPE_SIGCHLD: { ScopedIntArrayRW buf(env, out); if (buf.size() != 3) { jniThrowException(env, "java/lang/IllegalArgumentException", nullptr); return UNSOLICITED_ZYGOTE_MESSAGE_TYPE_RESERVED; } buf[0] = msg->payload.pid; buf[1] = msg->payload.uid; buf[2] = msg->payload.status; return 3; } default: break; } return -1; } static const JNINativeMethod gMethods[] = { { "nativeForkAndSpecialize", "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;)I", Loading Loading @@ -1769,7 +1888,9 @@ static const JNINativeMethod gMethods[] = { { "nativeUnblockSigTerm", "()V", (void* ) com_android_internal_os_Zygote_nativeUnblockSigTerm }, { "nativeBoostUsapPriority", "()V", (void* ) com_android_internal_os_Zygote_nativeBoostUsapPriority } (void* ) com_android_internal_os_Zygote_nativeBoostUsapPriority }, {"nativeParseSigChld", "([BI[I)I", (void* ) com_android_internal_os_Zygote_nativeParseSigChld}, }; int register_com_android_internal_os_Zygote(JNIEnv* env) { Loading
services/core/java/com/android/server/am/ProcessList.java +100 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY; import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; import static android.app.ActivityThread.PROC_START_SEQ_IDENT; import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AUTO; import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT; import static android.os.Process.SYSTEM_UID; import static android.os.Process.THREAD_PRIORITY_BACKGROUND; import static android.os.Process.getFreeMemory; Loading Loading @@ -57,6 +58,8 @@ import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.res.Resources; import android.graphics.Point; import android.net.LocalSocket; import android.net.LocalSocketAddress; import android.os.AppZygote; import android.os.Binder; import android.os.Build; Loading @@ -74,6 +77,7 @@ import android.os.Trace; import android.os.UserHandle; import android.os.storage.StorageManager; import android.os.storage.StorageManagerInternal; import android.system.Os; import android.text.TextUtils; import android.util.ArrayMap; import android.util.EventLog; Loading Loading @@ -102,6 +106,7 @@ import com.android.server.wm.WindowManagerService; import dalvik.system.VMRuntime; import java.io.File; import java.io.FileDescriptor; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; Loading Loading @@ -245,6 +250,10 @@ public final class ProcessList { private static final String PROPERTY_USE_APP_IMAGE_STARTUP_CACHE = "persist.device_config.runtime_native.use_app_image_startup_cache"; // The socket path for zygote to send unsolicited msg. // Must keep sync with com_android_internal_os_Zygote.cpp. private static final String UNSOL_ZYGOTE_MSG_SOCKET_PATH = "/data/system/unsolzygotesocket"; // Low Memory Killer Daemon command codes. // These must be kept in sync with lmk_cmd definitions in lmkd.h // Loading Loading @@ -388,6 +397,28 @@ public final class ProcessList { private PlatformCompat mPlatformCompat = null; /** * The server socket in system_server, zygote will connect to it * in order to send unsolicited messages to system_server. */ private LocalSocket mSystemServerSocketForZygote; /** * Maximum number of bytes that an incoming unsolicited zygote message could be. * To be updated if new message type needs to be supported. */ private static final int MAX_ZYGOTE_UNSOLICITED_MESSAGE_SIZE = 16; /** * The buffer to be used to receive the incoming unsolicited zygote message. */ private final byte[] mZygoteUnsolicitedMessage = new byte[MAX_ZYGOTE_UNSOLICITED_MESSAGE_SIZE]; /** * The buffer to be used to receive the SIGCHLD data, it includes pid/uid/status. */ private final int[] mZygoteSigChldMessage = new int[3]; interface LmkdKillListener { /** * Called when there is a process kill by lmkd. Loading Loading @@ -645,6 +676,13 @@ public final class ProcessList { } } ); // Start listening on incoming connections from zygotes. mSystemServerSocketForZygote = createSystemServerSocketForZygote(); if (mSystemServerSocketForZygote != null) { sKillHandler.getLooper().getQueue().addOnFileDescriptorEventListener( mSystemServerSocketForZygote.getFileDescriptor(), EVENT_INPUT, this::handleZygoteMessages); } } } Loading Loading @@ -3267,4 +3305,66 @@ public final class ProcessList { } } } private void handleZygoteSigChld(int pid, int uid, int status) { // Just log it now. if (DEBUG_PROCESSES) { Slog.i(TAG, "Got SIGCHLD from zygote: pid=" + pid + ", uid=" + uid + ", status=" + Integer.toHexString(status)); } } /** * Create a server socket in system_server, zygote will connect to it * in order to send unsolicited messages to system_server. */ private LocalSocket createSystemServerSocketForZygote() { // The file system entity for this socket is created with 0666 perms, owned // by system:system. selinux restricts things so that only zygotes can // access it. final File socketFile = new File(UNSOL_ZYGOTE_MSG_SOCKET_PATH); if (socketFile.exists()) { socketFile.delete(); } LocalSocket serverSocket = null; try { serverSocket = new LocalSocket(LocalSocket.SOCKET_DGRAM); serverSocket.bind(new LocalSocketAddress( UNSOL_ZYGOTE_MSG_SOCKET_PATH, LocalSocketAddress.Namespace.FILESYSTEM)); Os.chmod(UNSOL_ZYGOTE_MSG_SOCKET_PATH, 0666); } catch (Exception e) { if (serverSocket != null) { try { serverSocket.close(); } catch (IOException ex) { } serverSocket = null; } } return serverSocket; } /** * Handle the unsolicited message from zygote. */ private int handleZygoteMessages(FileDescriptor fd, int events) { final int eventFd = fd.getInt$(); if ((events & EVENT_INPUT) != 0) { // An incoming message from zygote try { final int len = Os.read(fd, mZygoteUnsolicitedMessage, 0, mZygoteUnsolicitedMessage.length); if (len > 0 && mZygoteSigChldMessage.length == Zygote.nativeParseSigChld( mZygoteUnsolicitedMessage, len, mZygoteSigChldMessage)) { handleZygoteSigChld(mZygoteSigChldMessage[0] /* pid */, mZygoteSigChldMessage[1] /* uid */, mZygoteSigChldMessage[2] /* status */); } } catch (Exception e) { Slog.w(TAG, "Exception in reading unsolicited zygote message: " + e); } } return EVENT_INPUT; } }