summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/os/Process.java33
-rw-r--r--core/jni/android_util_Process.cpp38
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,