diff options
| -rw-r--r-- | core/java/android/os/Process.java | 33 | ||||
| -rw-r--r-- | core/jni/android_util_Process.cpp | 38 |
2 files changed, 57 insertions, 14 deletions
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 0f64c4531bc3..379d28cf10a0 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -1003,11 +1003,38 @@ public class Process { public static final int PROC_OUT_LONG = 0x2000; /** @hide */ public static final int PROC_OUT_FLOAT = 0x4000; - - /** @hide */ + + /** + * Read and parse a {@code proc} file in the given format. + * + * <p>The format is a list of integers, where every integer describes a variable in the file. It + * specifies how the variable is syntactically terminated (e.g. {@link Process#PROC_SPACE_TERM}, + * {@link Process#PROC_TAB_TERM}, {@link Process#PROC_ZERO_TERM}). + * + * <p>If the variable should be parsed and returned to the caller, the termination type should + * be binary OR'd with the type of output (e.g. {@link Process#PROC_OUT_STRING}, {@link + * Process#PROC_OUT_LONG}, {@link Process#PROC_OUT_FLOAT}. + * + * <p>If the variable is wrapped in quotation marks it should be binary OR'd with {@link + * Process#PROC_QUOTES}. If the variable is wrapped in parentheses it should be binary OR'd with + * {@link Process#PROC_PARENS}. + * + * <p>If the variable is not formatted as a string and should be cast directly from characters + * to a long, the {@link Process#PROC_CHAR} integer should be binary OR'd. + * + * <p>If the terminating character can be repeated, the {@link Process#PROC_COMBINE} integer + * should be binary OR'd. + * + * @param file the path of the {@code proc} file to read + * @param format the format of the file + * @param outStrings the parsed {@code String}s from the file + * @param outLongs the parsed {@code long}s from the file + * @param outFloats the parsed {@code float}s from the file + * @hide + */ public static final native boolean readProcFile(String file, int[] format, String[] outStrings, long[] outLongs, float[] outFloats); - + /** @hide */ public static final native boolean parseProcLine(byte[] buffer, int startIndex, int endIndex, int[] format, String[] outStrings, long[] outLongs, float[] outFloats); diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp index 62aa1f38ca30..4c7defbf7358 100644 --- a/core/jni/android_util_Process.cpp +++ b/core/jni/android_util_Process.cpp @@ -51,6 +51,8 @@ using namespace android; static const bool kDebugPolicy = false; static const bool kDebugProc = false; +// When reading `proc` files, how many bytes to read at a time +static const int kReadSize = 4096; #if GUARD_THREAD_PRIORITY Mutex gKeyCreateMutex; @@ -1034,21 +1036,35 @@ jboolean android_os_Process_readProcFile(JNIEnv* env, jobject clazz, } env->ReleaseStringUTFChars(file, file8); - char buffer[256]; - const int len = read(fd, buffer, sizeof(buffer)-1); - close(fd); - - if (len < 0) { - if (kDebugProc) { - ALOGW("Unable to open process file: %s fd=%d\n", file8, fd); + std::vector<char> fileBuffer(kReadSize); + int numBytesRead = 0; + while (true) { + // Resize buffer to make space for contents. This might be more than we need, but once we've + // read we resize back down + fileBuffer.resize(numBytesRead + kReadSize, 0); + // Read in contents + int len = TEMP_FAILURE_RETRY(read(fd, fileBuffer.data() + numBytesRead, kReadSize)); + numBytesRead += len; + if (len < 0) { + // If `len` is negative, an error occurred on read + if (kDebugProc) { + ALOGW("Unable to open process file: %s fd=%d\n", file8, fd); + } + close(fd); + return JNI_FALSE; + } else if (len == 0) { + // If nothing read, we're done + break; } - return JNI_FALSE; } - buffer[len] = 0; + // Resize back down to the amount we read + fileBuffer.resize(numBytesRead); + // Terminate buffer with null byte + fileBuffer.push_back('\0'); + close(fd); - return android_os_Process_parseProcLineArray(env, clazz, buffer, 0, len, + return android_os_Process_parseProcLineArray(env, clazz, fileBuffer.data(), 0, numBytesRead, format, outStrings, outLongs, outFloats); - } void android_os_Process_setApplicationObject(JNIEnv* env, jobject clazz, |