• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* //device/libs/android_runtime/android_util_Process.cpp
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17 
18 #define LOG_TAG "Process"
19 
20 // To make sure cpu_set_t is included from sched.h
21 #define _GNU_SOURCE 1
22 #include <utils/Log.h>
23 #include <binder/IPCThreadState.h>
24 #include <binder/IServiceManager.h>
25 #include <utils/String8.h>
26 #include <utils/Vector.h>
27 #include <meminfo/procmeminfo.h>
28 #include <meminfo/sysmeminfo.h>
29 #include <processgroup/processgroup.h>
30 #include <processgroup/sched_policy.h>
31 #include <android-base/unique_fd.h>
32 
33 #include <algorithm>
34 #include <array>
35 #include <limits>
36 #include <memory>
37 #include <string>
38 #include <vector>
39 
40 #include "core_jni_helpers.h"
41 
42 #include "android_util_Binder.h"
43 #include <nativehelper/JNIHelp.h>
44 #include "android_os_Debug.h"
45 
46 #include <dirent.h>
47 #include <fcntl.h>
48 #include <grp.h>
49 #include <inttypes.h>
50 #include <pwd.h>
51 #include <signal.h>
52 #include <string.h>
53 #include <sys/epoll.h>
54 #include <sys/errno.h>
55 #include <sys/pidfd.h>
56 #include <sys/resource.h>
57 #include <sys/stat.h>
58 #include <sys/syscall.h>
59 #include <sys/sysinfo.h>
60 #include <sys/types.h>
61 #include <time.h>
62 #include <unistd.h>
63 
64 #define GUARD_THREAD_PRIORITY 0
65 
66 using namespace android;
67 
68 static constexpr bool kDebugPolicy = false;
69 static constexpr bool kDebugProc = false;
70 
71 // Stack reservation for reading small proc files.  Most callers of
72 // readProcFile() are reading files under this threshold, e.g.,
73 // /proc/pid/stat.  /proc/pid/time_in_state ends up being about 520
74 // bytes, so use 1024 for the stack to provide a bit of slack.
75 static constexpr ssize_t kProcReadStackBufferSize = 1024;
76 
77 // The other files we read from proc tend to be a bit larger (e.g.,
78 // /proc/stat is about 3kB), so once we exhaust the stack buffer,
79 // retry with a relatively large heap-allocated buffer.  We double
80 // this size and retry until the whole file fits.
81 static constexpr ssize_t kProcReadMinHeapBufferSize = 4096;
82 
83 #if GUARD_THREAD_PRIORITY
84 Mutex gKeyCreateMutex;
85 static pthread_key_t gBgKey = -1;
86 #endif
87 
88 // For both of these, err should be in the errno range (positive), not a status_t (negative)
signalExceptionForError(JNIEnv * env,int err,int tid)89 static void signalExceptionForError(JNIEnv* env, int err, int tid) {
90     switch (err) {
91         case EINVAL:
92             jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
93                                  "Invalid argument: %d", tid);
94             break;
95         case ESRCH:
96             jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
97                                  "Given thread %d does not exist", tid);
98             break;
99         case EPERM:
100             jniThrowExceptionFmt(env, "java/lang/SecurityException",
101                                  "No permission to modify given thread %d", tid);
102             break;
103         default:
104             jniThrowException(env, "java/lang/RuntimeException", "Unknown error");
105             break;
106     }
107 }
108 
signalExceptionForPriorityError(JNIEnv * env,int err,int tid)109 static void signalExceptionForPriorityError(JNIEnv* env, int err, int tid) {
110     switch (err) {
111         case EACCES:
112             jniThrowExceptionFmt(env, "java/lang/SecurityException",
113                                  "No permission to set the priority of %d", tid);
114             break;
115         default:
116             signalExceptionForError(env, err, tid);
117             break;
118     }
119 
120 }
121 
signalExceptionForGroupError(JNIEnv * env,int err,int tid)122 static void signalExceptionForGroupError(JNIEnv* env, int err, int tid) {
123     switch (err) {
124         case EACCES:
125             jniThrowExceptionFmt(env, "java/lang/SecurityException",
126                                  "No permission to set the group of %d", tid);
127             break;
128         default:
129             signalExceptionForError(env, err, tid);
130             break;
131     }
132 }
133 
android_os_Process_getUidForName(JNIEnv * env,jobject clazz,jstring name)134 jint android_os_Process_getUidForName(JNIEnv* env, jobject clazz, jstring name)
135 {
136     if (name == NULL) {
137         jniThrowNullPointerException(env, NULL);
138         return -1;
139     }
140 
141     const jchar* str16 = env->GetStringCritical(name, 0);
142     String8 name8;
143     if (str16) {
144         name8 = String8(reinterpret_cast<const char16_t*>(str16),
145                         env->GetStringLength(name));
146         env->ReleaseStringCritical(name, str16);
147     }
148 
149     const size_t N = name8.size();
150     if (N > 0) {
151         const char* str = name8.string();
152         for (size_t i=0; i<N; i++) {
153             if (str[i] < '0' || str[i] > '9') {
154                 struct passwd* pwd = getpwnam(str);
155                 if (pwd == NULL) {
156                     return -1;
157                 }
158                 return pwd->pw_uid;
159             }
160         }
161         return atoi(str);
162     }
163     return -1;
164 }
165 
android_os_Process_getGidForName(JNIEnv * env,jobject clazz,jstring name)166 jint android_os_Process_getGidForName(JNIEnv* env, jobject clazz, jstring name)
167 {
168     if (name == NULL) {
169         jniThrowNullPointerException(env, NULL);
170         return -1;
171     }
172 
173     const jchar* str16 = env->GetStringCritical(name, 0);
174     String8 name8;
175     if (str16) {
176         name8 = String8(reinterpret_cast<const char16_t*>(str16),
177                         env->GetStringLength(name));
178         env->ReleaseStringCritical(name, str16);
179     }
180 
181     const size_t N = name8.size();
182     if (N > 0) {
183         const char* str = name8.string();
184         for (size_t i=0; i<N; i++) {
185             if (str[i] < '0' || str[i] > '9') {
186                 struct group* grp = getgrnam(str);
187                 if (grp == NULL) {
188                     return -1;
189                 }
190                 return grp->gr_gid;
191             }
192         }
193         return atoi(str);
194     }
195     return -1;
196 }
197 
verifyGroup(JNIEnv * env,int grp)198 static bool verifyGroup(JNIEnv* env, int grp)
199 {
200     if (grp < SP_DEFAULT || grp  >= SP_CNT) {
201         signalExceptionForError(env, EINVAL, grp);
202         return false;
203     }
204     return true;
205 }
206 
android_os_Process_setThreadGroup(JNIEnv * env,jobject clazz,int tid,jint grp)207 void android_os_Process_setThreadGroup(JNIEnv* env, jobject clazz, int tid, jint grp)
208 {
209     ALOGV("%s tid=%d grp=%" PRId32, __func__, tid, grp);
210     if (!verifyGroup(env, grp)) {
211         return;
212     }
213 
214     int res = SetTaskProfiles(tid, {get_sched_policy_profile_name((SchedPolicy)grp)}, true) ? 0 : -1;
215 
216     if (res != NO_ERROR) {
217         signalExceptionForGroupError(env, -res, tid);
218     }
219 }
220 
android_os_Process_setThreadGroupAndCpuset(JNIEnv * env,jobject clazz,int tid,jint grp)221 void android_os_Process_setThreadGroupAndCpuset(JNIEnv* env, jobject clazz, int tid, jint grp)
222 {
223     ALOGV("%s tid=%d grp=%" PRId32, __func__, tid, grp);
224     if (!verifyGroup(env, grp)) {
225         return;
226     }
227 
228     int res = SetTaskProfiles(tid, {get_cpuset_policy_profile_name((SchedPolicy)grp)}, true) ? 0 : -1;
229 
230     if (res != NO_ERROR) {
231         signalExceptionForGroupError(env, -res, tid);
232     }
233 }
234 
android_os_Process_setProcessGroup(JNIEnv * env,jobject clazz,int pid,jint grp)235 void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jint grp)
236 {
237     ALOGV("%s pid=%d grp=%" PRId32, __func__, pid, grp);
238     char proc_path[255];
239 
240     if (!verifyGroup(env, grp)) {
241         return;
242     }
243 
244     if (grp == SP_FOREGROUND) {
245         signalExceptionForGroupError(env, EINVAL, pid);
246         return;
247     }
248 
249     if (grp < 0) {
250         grp = SP_FOREGROUND;
251     }
252 
253     if (kDebugPolicy) {
254         char cmdline[32];
255         int fd;
256 
257         strcpy(cmdline, "unknown");
258 
259         sprintf(proc_path, "/proc/%d/cmdline", pid);
260         fd = open(proc_path, O_RDONLY | O_CLOEXEC);
261         if (fd >= 0) {
262             ssize_t rc = read(fd, cmdline, sizeof(cmdline) - 1);
263             if (rc < 0) {
264                 ALOGE("read /proc/%d/cmdline (%s)", pid, strerror(errno));
265             } else {
266                 cmdline[rc] = 0;
267             }
268             close(fd);
269         }
270 
271         if (grp == SP_BACKGROUND) {
272             ALOGD("setProcessGroup: vvv pid %d (%s)", pid, cmdline);
273         } else {
274             ALOGD("setProcessGroup: ^^^ pid %d (%s)", pid, cmdline);
275         }
276     }
277 
278     if (!SetProcessProfilesCached(0, pid, {get_cpuset_policy_profile_name((SchedPolicy)grp)}))
279         signalExceptionForGroupError(env, errno ? errno : EPERM, pid);
280 }
281 
android_os_Process_setProcessFrozen(JNIEnv * env,jobject clazz,jint pid,jint uid,jboolean freeze)282 void android_os_Process_setProcessFrozen(
283         JNIEnv *env, jobject clazz, jint pid, jint uid, jboolean freeze)
284 {
285     bool success = true;
286 
287     if (freeze) {
288         success = SetProcessProfiles(uid, pid, {"Frozen"});
289     } else {
290         success = SetProcessProfiles(uid, pid, {"Unfrozen"});
291     }
292 
293     if (!success) {
294         signalExceptionForGroupError(env, EINVAL, pid);
295     }
296 }
297 
android_os_Process_getProcessGroup(JNIEnv * env,jobject clazz,jint pid)298 jint android_os_Process_getProcessGroup(JNIEnv* env, jobject clazz, jint pid)
299 {
300     SchedPolicy sp;
301     if (get_sched_policy(pid, &sp) != 0) {
302         signalExceptionForGroupError(env, errno, pid);
303     }
304     return (int) sp;
305 }
306 
android_os_Process_createProcessGroup(JNIEnv * env,jobject clazz,jint uid,jint pid)307 jint android_os_Process_createProcessGroup(JNIEnv* env, jobject clazz, jint uid, jint pid) {
308     return createProcessGroup(uid, pid);
309 }
310 
311 /** Sample CPUset list format:
312  *  0-3,4,6-8
313  */
parse_cpuset_cpus(char * cpus,cpu_set_t * cpu_set)314 static void parse_cpuset_cpus(char *cpus, cpu_set_t *cpu_set) {
315     unsigned int start, end, matched, i;
316     char *cpu_range = strtok(cpus, ",");
317     while (cpu_range != NULL) {
318         start = end = 0;
319         matched = sscanf(cpu_range, "%u-%u", &start, &end);
320         cpu_range = strtok(NULL, ",");
321         if (start >= CPU_SETSIZE) {
322             ALOGE("parse_cpuset_cpus: ignoring CPU number larger than %d.", CPU_SETSIZE);
323             continue;
324         } else if (end >= CPU_SETSIZE) {
325             ALOGE("parse_cpuset_cpus: ignoring CPU numbers larger than %d.", CPU_SETSIZE);
326             end = CPU_SETSIZE - 1;
327         }
328         if (matched == 1) {
329             CPU_SET(start, cpu_set);
330         } else if (matched == 2) {
331             for (i = start; i <= end; i++) {
332                 CPU_SET(i, cpu_set);
333             }
334         } else {
335             ALOGE("Failed to match cpus");
336         }
337     }
338     return;
339 }
340 
341 /**
342  * Stores the CPUs assigned to the cpuset corresponding to the
343  * SchedPolicy in the passed in cpu_set.
344  */
get_cpuset_cores_for_policy(SchedPolicy policy,cpu_set_t * cpu_set)345 static void get_cpuset_cores_for_policy(SchedPolicy policy, cpu_set_t *cpu_set)
346 {
347     FILE *file;
348     std::string filename;
349 
350     CPU_ZERO(cpu_set);
351 
352     switch (policy) {
353         case SP_BACKGROUND:
354             if (!CgroupGetAttributePath("LowCapacityCPUs", &filename)) {
355                 return;
356             }
357             break;
358         case SP_FOREGROUND:
359         case SP_AUDIO_APP:
360         case SP_AUDIO_SYS:
361         case SP_RT_APP:
362             if (!CgroupGetAttributePath("HighCapacityCPUs", &filename)) {
363                 return;
364             }
365             break;
366         case SP_TOP_APP:
367             if (!CgroupGetAttributePath("MaxCapacityCPUs", &filename)) {
368                 return;
369             }
370             break;
371         default:
372             return;
373     }
374 
375     file = fopen(filename.c_str(), "re");
376     if (file != NULL) {
377         // Parse cpus string
378         char *line = NULL;
379         size_t len = 0;
380         ssize_t num_read = getline(&line, &len, file);
381         fclose (file);
382         if (num_read > 0) {
383             parse_cpuset_cpus(line, cpu_set);
384         } else {
385             ALOGE("Failed to read %s", filename.c_str());
386         }
387         free(line);
388     }
389     return;
390 }
391 
392 
393 /**
394  * Determine CPU cores exclusively assigned to the
395  * cpuset corresponding to the SchedPolicy and store
396  * them in the passed in cpu_set_t
397  */
get_exclusive_cpuset_cores(SchedPolicy policy,cpu_set_t * cpu_set)398 void get_exclusive_cpuset_cores(SchedPolicy policy, cpu_set_t *cpu_set) {
399     if (cpusets_enabled()) {
400         int i;
401         cpu_set_t tmp_set;
402         get_cpuset_cores_for_policy(policy, cpu_set);
403         for (i = 0; i < SP_CNT; i++) {
404             if ((SchedPolicy) i == policy) continue;
405             get_cpuset_cores_for_policy((SchedPolicy)i, &tmp_set);
406             // First get cores exclusive to one set or the other
407             CPU_XOR(&tmp_set, cpu_set, &tmp_set);
408             // Then get the ones only in cpu_set
409             CPU_AND(cpu_set, cpu_set, &tmp_set);
410         }
411     } else {
412         CPU_ZERO(cpu_set);
413     }
414     return;
415 }
416 
android_os_Process_getExclusiveCores(JNIEnv * env,jobject clazz)417 jintArray android_os_Process_getExclusiveCores(JNIEnv* env, jobject clazz) {
418     SchedPolicy sp;
419     cpu_set_t cpu_set;
420     jintArray cpus;
421     int pid = getpid();
422     if (get_sched_policy(pid, &sp) != 0) {
423         signalExceptionForGroupError(env, errno, pid);
424         return NULL;
425     }
426     get_exclusive_cpuset_cores(sp, &cpu_set);
427     int num_cpus = CPU_COUNT(&cpu_set);
428     cpus = env->NewIntArray(num_cpus);
429     if (cpus == NULL) {
430         jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
431         return NULL;
432     }
433 
434     jint* cpu_elements = env->GetIntArrayElements(cpus, 0);
435     int count = 0;
436     for (int i = 0; i < CPU_SETSIZE && count < num_cpus; i++) {
437         if (CPU_ISSET(i, &cpu_set)) {
438             cpu_elements[count++] = i;
439         }
440     }
441 
442     env->ReleaseIntArrayElements(cpus, cpu_elements, 0);
443     return cpus;
444 }
445 
android_os_Process_setCanSelfBackground(JNIEnv * env,jobject clazz,jboolean bgOk)446 static void android_os_Process_setCanSelfBackground(JNIEnv* env, jobject clazz, jboolean bgOk) {
447     // Establishes the calling thread as illegal to put into the background.
448     // Typically used only for the system process's main looper.
449 #if GUARD_THREAD_PRIORITY
450     ALOGV("Process.setCanSelfBackground(%d) : tid=%d", bgOk, gettid());
451     {
452         Mutex::Autolock _l(gKeyCreateMutex);
453         if (gBgKey == -1) {
454             pthread_key_create(&gBgKey, NULL);
455         }
456     }
457 
458     // inverted:  not-okay, we set a sentinel value
459     pthread_setspecific(gBgKey, (void*)(bgOk ? 0 : 0xbaad));
460 #endif
461 }
462 
android_os_Process_getThreadScheduler(JNIEnv * env,jclass clazz,jint tid)463 jint android_os_Process_getThreadScheduler(JNIEnv* env, jclass clazz,
464                                               jint tid)
465 {
466     int policy = 0;
467 // linux has sched_getscheduler(), others don't.
468 #if defined(__linux__)
469     errno = 0;
470     policy = sched_getscheduler(tid);
471     if (errno != 0) {
472         signalExceptionForPriorityError(env, errno, tid);
473     }
474 #else
475     signalExceptionForPriorityError(env, ENOSYS, tid);
476 #endif
477     return policy;
478 }
479 
android_os_Process_setThreadScheduler(JNIEnv * env,jclass clazz,jint tid,jint policy,jint pri)480 void android_os_Process_setThreadScheduler(JNIEnv* env, jclass clazz,
481                                               jint tid, jint policy, jint pri)
482 {
483 // linux has sched_setscheduler(), others don't.
484 #if defined(__linux__)
485     struct sched_param param;
486     param.sched_priority = pri;
487     int rc = sched_setscheduler(tid, policy, &param);
488     if (rc) {
489         signalExceptionForPriorityError(env, errno, tid);
490     }
491 #else
492     signalExceptionForPriorityError(env, ENOSYS, tid);
493 #endif
494 }
495 
android_os_Process_setThreadPriority(JNIEnv * env,jobject clazz,jint pid,jint pri)496 void android_os_Process_setThreadPriority(JNIEnv* env, jobject clazz,
497                                               jint pid, jint pri)
498 {
499 #if GUARD_THREAD_PRIORITY
500     // if we're putting the current thread into the background, check the TLS
501     // to make sure this thread isn't guarded.  If it is, raise an exception.
502     if (pri >= ANDROID_PRIORITY_BACKGROUND) {
503         if (pid == gettid()) {
504             void* bgOk = pthread_getspecific(gBgKey);
505             if (bgOk == ((void*)0xbaad)) {
506                 ALOGE("Thread marked fg-only put self in background!");
507                 jniThrowException(env, "java/lang/SecurityException", "May not put this thread into background");
508                 return;
509             }
510         }
511     }
512 #endif
513 
514     int rc = androidSetThreadPriority(pid, pri);
515     if (rc != 0) {
516         if (rc == INVALID_OPERATION) {
517             signalExceptionForPriorityError(env, errno, pid);
518         } else {
519             signalExceptionForGroupError(env, errno, pid);
520         }
521     }
522 
523     //ALOGI("Setting priority of %" PRId32 ": %" PRId32 ", getpriority returns %d\n",
524     //     pid, pri, getpriority(PRIO_PROCESS, pid));
525 }
526 
android_os_Process_setCallingThreadPriority(JNIEnv * env,jobject clazz,jint pri)527 void android_os_Process_setCallingThreadPriority(JNIEnv* env, jobject clazz,
528                                                         jint pri)
529 {
530     android_os_Process_setThreadPriority(env, clazz, gettid(), pri);
531 }
532 
android_os_Process_getThreadPriority(JNIEnv * env,jobject clazz,jint pid)533 jint android_os_Process_getThreadPriority(JNIEnv* env, jobject clazz,
534                                               jint pid)
535 {
536     errno = 0;
537     jint pri = getpriority(PRIO_PROCESS, pid);
538     if (errno != 0) {
539         signalExceptionForPriorityError(env, errno, pid);
540     }
541     //ALOGI("Returning priority of %" PRId32 ": %" PRId32 "\n", pid, pri);
542     return pri;
543 }
544 
android_os_Process_setSwappiness(JNIEnv * env,jobject clazz,jint pid,jboolean is_increased)545 jboolean android_os_Process_setSwappiness(JNIEnv *env, jobject clazz,
546                                           jint pid, jboolean is_increased)
547 {
548     char text[64];
549 
550     if (is_increased) {
551         strcpy(text, "/sys/fs/cgroup/memory/sw/tasks");
552     } else {
553         strcpy(text, "/sys/fs/cgroup/memory/tasks");
554     }
555 
556     struct stat st;
557     if (stat(text, &st) || !S_ISREG(st.st_mode)) {
558         return false;
559     }
560 
561     int fd = open(text, O_WRONLY | O_CLOEXEC);
562     if (fd >= 0) {
563         sprintf(text, "%" PRId32, pid);
564         write(fd, text, strlen(text));
565         close(fd);
566     }
567 
568     return true;
569 }
570 
android_os_Process_setArgV0(JNIEnv * env,jobject clazz,jstring name)571 void android_os_Process_setArgV0(JNIEnv* env, jobject clazz, jstring name)
572 {
573     if (name == NULL) {
574         jniThrowNullPointerException(env, NULL);
575         return;
576     }
577 
578     const jchar* str = env->GetStringCritical(name, 0);
579     String8 name8;
580     if (str) {
581         name8 = String8(reinterpret_cast<const char16_t*>(str),
582                         env->GetStringLength(name));
583         env->ReleaseStringCritical(name, str);
584     }
585 
586     if (!name8.isEmpty()) {
587         AndroidRuntime::getRuntime()->setArgv0(name8.string(), true /* setProcName */);
588     }
589 }
590 
android_os_Process_setUid(JNIEnv * env,jobject clazz,jint uid)591 jint android_os_Process_setUid(JNIEnv* env, jobject clazz, jint uid)
592 {
593     return setuid(uid) == 0 ? 0 : errno;
594 }
595 
android_os_Process_setGid(JNIEnv * env,jobject clazz,jint uid)596 jint android_os_Process_setGid(JNIEnv* env, jobject clazz, jint uid)
597 {
598     return setgid(uid) == 0 ? 0 : errno;
599 }
600 
pid_compare(const void * v1,const void * v2)601 static int pid_compare(const void* v1, const void* v2)
602 {
603     //ALOGI("Compare %" PRId32 " vs %" PRId32 "\n", *((const jint*)v1), *((const jint*)v2));
604     return *((const jint*)v1) - *((const jint*)v2);
605 }
606 
android_os_Process_getFreeMemory(JNIEnv * env,jobject clazz)607 static jlong android_os_Process_getFreeMemory(JNIEnv* env, jobject clazz)
608 {
609     std::array<std::string_view, 2> memFreeTags = {
610         ::android::meminfo::SysMemInfo::kMemFree,
611         ::android::meminfo::SysMemInfo::kMemCached,
612     };
613     std::vector<uint64_t> mem(memFreeTags.size());
614     ::android::meminfo::SysMemInfo smi;
615 
616     if (!smi.ReadMemInfo(memFreeTags.size(),
617                          memFreeTags.data(),
618                          mem.data())) {
619         jniThrowRuntimeException(env, "SysMemInfo read failed to get Free Memory");
620         return -1L;
621     }
622 
623     jlong sum = 0;
624     std::for_each(mem.begin(), mem.end(), [&](uint64_t val) { sum += val; });
625     return sum * 1024;
626 }
627 
android_os_Process_getTotalMemory(JNIEnv * env,jobject clazz)628 static jlong android_os_Process_getTotalMemory(JNIEnv* env, jobject clazz)
629 {
630     struct sysinfo si;
631     if (sysinfo(&si) == -1) {
632         ALOGE("sysinfo failed: %s", strerror(errno));
633         return -1;
634     }
635 
636     return static_cast<jlong>(si.totalram) * si.mem_unit;
637 }
638 
639 /*
640  * The outFields array is initialized to -1 to allow the caller to identify
641  * when the status file (and therefore the process) they specified is invalid.
642  * This array should not be overwritten or cleared before we know that the
643  * status file can be read.
644  */
android_os_Process_readProcLines(JNIEnv * env,jobject clazz,jstring fileStr,jobjectArray reqFields,jlongArray outFields)645 void android_os_Process_readProcLines(JNIEnv* env, jobject clazz, jstring fileStr,
646                                       jobjectArray reqFields, jlongArray outFields)
647 {
648     //ALOGI("getMemInfo: %p %p", reqFields, outFields);
649 
650     if (fileStr == NULL || reqFields == NULL || outFields == NULL) {
651         jniThrowNullPointerException(env, NULL);
652         return;
653     }
654 
655     const char* file8 = env->GetStringUTFChars(fileStr, NULL);
656     if (file8 == NULL) {
657         return;
658     }
659     String8 file(file8);
660     env->ReleaseStringUTFChars(fileStr, file8);
661 
662     jsize count = env->GetArrayLength(reqFields);
663     if (count > env->GetArrayLength(outFields)) {
664         jniThrowException(env, "java/lang/IllegalArgumentException", "Array lengths differ");
665         return;
666     }
667 
668     Vector<String8> fields;
669     int i;
670 
671     for (i=0; i<count; i++) {
672         jobject obj = env->GetObjectArrayElement(reqFields, i);
673         if (obj != NULL) {
674             const char* str8 = env->GetStringUTFChars((jstring)obj, NULL);
675             //ALOGI("String at %d: %p = %s", i, obj, str8);
676             if (str8 == NULL) {
677                 jniThrowNullPointerException(env, "Element in reqFields");
678                 return;
679             }
680             fields.add(String8(str8));
681             env->ReleaseStringUTFChars((jstring)obj, str8);
682         } else {
683             jniThrowNullPointerException(env, "Element in reqFields");
684             return;
685         }
686     }
687 
688     jlong* sizesArray = env->GetLongArrayElements(outFields, 0);
689     if (sizesArray == NULL) {
690         return;
691     }
692 
693     int fd = open(file.string(), O_RDONLY | O_CLOEXEC);
694 
695     if (fd >= 0) {
696         //ALOGI("Clearing %" PRId32 " sizes", count);
697         for (i=0; i<count; i++) {
698             sizesArray[i] = 0;
699         }
700 
701         const size_t BUFFER_SIZE = 4096;
702         char* buffer = (char*)malloc(BUFFER_SIZE);
703         int len = read(fd, buffer, BUFFER_SIZE-1);
704         close(fd);
705 
706         if (len < 0) {
707             ALOGW("Unable to read %s", file.string());
708             len = 0;
709         }
710         buffer[len] = 0;
711 
712         int foundCount = 0;
713 
714         char* p = buffer;
715         while (*p && foundCount < count) {
716             bool skipToEol = true;
717             //ALOGI("Parsing at: %s", p);
718             for (i=0; i<count; i++) {
719                 const String8& field = fields[i];
720                 if (strncmp(p, field.string(), field.length()) == 0) {
721                     p += field.length();
722                     while (*p == ' ' || *p == '\t') p++;
723                     char* num = p;
724                     while (*p >= '0' && *p <= '9') p++;
725                     skipToEol = *p != '\n';
726                     if (*p != 0) {
727                         *p = 0;
728                         p++;
729                     }
730                     char* end;
731                     sizesArray[i] = strtoll(num, &end, 10);
732                     //ALOGI("Field %s = %" PRId64, field.string(), sizesArray[i]);
733                     foundCount++;
734                     break;
735                 }
736             }
737             if (skipToEol) {
738                 while (*p && *p != '\n') {
739                     p++;
740                 }
741                 if (*p == '\n') {
742                     p++;
743                 }
744             }
745         }
746 
747         free(buffer);
748     } else {
749         ALOGW("Unable to open %s", file.string());
750     }
751 
752     //ALOGI("Done!");
753     env->ReleaseLongArrayElements(outFields, sizesArray, 0);
754 }
755 
android_os_Process_getPids(JNIEnv * env,jobject clazz,jstring file,jintArray lastArray)756 jintArray android_os_Process_getPids(JNIEnv* env, jobject clazz,
757                                      jstring file, jintArray lastArray)
758 {
759     if (file == NULL) {
760         jniThrowNullPointerException(env, NULL);
761         return NULL;
762     }
763 
764     const char* file8 = env->GetStringUTFChars(file, NULL);
765     if (file8 == NULL) {
766         jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
767         return NULL;
768     }
769 
770     DIR* dirp = opendir(file8);
771 
772     env->ReleaseStringUTFChars(file, file8);
773 
774     if(dirp == NULL) {
775         return NULL;
776     }
777 
778     jsize curCount = 0;
779     jint* curData = NULL;
780     if (lastArray != NULL) {
781         curCount = env->GetArrayLength(lastArray);
782         curData = env->GetIntArrayElements(lastArray, 0);
783     }
784 
785     jint curPos = 0;
786 
787     struct dirent* entry;
788     while ((entry=readdir(dirp)) != NULL) {
789         const char* p = entry->d_name;
790         while (*p) {
791             if (*p < '0' || *p > '9') break;
792             p++;
793         }
794         if (*p != 0) continue;
795 
796         char* end;
797         int pid = strtol(entry->d_name, &end, 10);
798         //ALOGI("File %s pid=%d\n", entry->d_name, pid);
799         if (curPos >= curCount) {
800             jsize newCount = (curCount == 0) ? 10 : (curCount*2);
801             jintArray newArray = env->NewIntArray(newCount);
802             if (newArray == NULL) {
803                 closedir(dirp);
804                 jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
805                 return NULL;
806             }
807             jint* newData = env->GetIntArrayElements(newArray, 0);
808             if (curData != NULL) {
809                 memcpy(newData, curData, sizeof(jint)*curCount);
810                 env->ReleaseIntArrayElements(lastArray, curData, 0);
811             }
812             lastArray = newArray;
813             curCount = newCount;
814             curData = newData;
815         }
816 
817         curData[curPos] = pid;
818         curPos++;
819     }
820 
821     closedir(dirp);
822 
823     if (curData != NULL && curPos > 0) {
824         qsort(curData, curPos, sizeof(jint), pid_compare);
825     }
826 
827     while (curPos < curCount) {
828         curData[curPos] = -1;
829         curPos++;
830     }
831 
832     if (curData != NULL) {
833         env->ReleaseIntArrayElements(lastArray, curData, 0);
834     }
835 
836     return lastArray;
837 }
838 
839 enum {
840     PROC_TERM_MASK = 0xff,
841     PROC_ZERO_TERM = 0,
842     PROC_SPACE_TERM = ' ',
843     PROC_COMBINE = 0x100,
844     PROC_PARENS = 0x200,
845     PROC_QUOTES = 0x400,
846     PROC_CHAR = 0x800,
847     PROC_OUT_STRING = 0x1000,
848     PROC_OUT_LONG = 0x2000,
849     PROC_OUT_FLOAT = 0x4000,
850 };
851 
android_os_Process_parseProcLineArray(JNIEnv * env,jobject clazz,char * buffer,jint startIndex,jint endIndex,jintArray format,jobjectArray outStrings,jlongArray outLongs,jfloatArray outFloats)852 jboolean android_os_Process_parseProcLineArray(JNIEnv* env, jobject clazz,
853         char* buffer, jint startIndex, jint endIndex, jintArray format,
854         jobjectArray outStrings, jlongArray outLongs, jfloatArray outFloats)
855 {
856 
857     const jsize NF = env->GetArrayLength(format);
858     const jsize NS = outStrings ? env->GetArrayLength(outStrings) : 0;
859     const jsize NL = outLongs ? env->GetArrayLength(outLongs) : 0;
860     const jsize NR = outFloats ? env->GetArrayLength(outFloats) : 0;
861 
862     jint* formatData = env->GetIntArrayElements(format, 0);
863     jlong* longsData = outLongs ?
864         env->GetLongArrayElements(outLongs, 0) : NULL;
865     jfloat* floatsData = outFloats ?
866         env->GetFloatArrayElements(outFloats, 0) : NULL;
867     if (formatData == NULL || (NL > 0 && longsData == NULL)
868             || (NR > 0 && floatsData == NULL)) {
869         if (formatData != NULL) {
870             env->ReleaseIntArrayElements(format, formatData, 0);
871         }
872         if (longsData != NULL) {
873             env->ReleaseLongArrayElements(outLongs, longsData, 0);
874         }
875         if (floatsData != NULL) {
876             env->ReleaseFloatArrayElements(outFloats, floatsData, 0);
877         }
878         jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
879         return JNI_FALSE;
880     }
881 
882     jsize i = startIndex;
883     jsize di = 0;
884 
885     jboolean res = JNI_TRUE;
886 
887     for (jsize fi=0; fi<NF; fi++) {
888         jint mode = formatData[fi];
889         if ((mode&PROC_PARENS) != 0) {
890             i++;
891         } else if ((mode&PROC_QUOTES) != 0) {
892             if (buffer[i] == '"') {
893                 i++;
894             } else {
895                 mode &= ~PROC_QUOTES;
896             }
897         }
898         const char term = (char)(mode&PROC_TERM_MASK);
899         const jsize start = i;
900         if (i >= endIndex) {
901             if (kDebugProc) {
902                 ALOGW("Ran off end of data @%d", i);
903             }
904             res = JNI_FALSE;
905             break;
906         }
907 
908         jsize end = -1;
909         if ((mode&PROC_PARENS) != 0) {
910             while (i < endIndex && buffer[i] != ')') {
911                 i++;
912             }
913             end = i;
914             i++;
915         } else if ((mode&PROC_QUOTES) != 0) {
916             while (i < endIndex && buffer[i] != '"') {
917                 i++;
918             }
919             end = i;
920             i++;
921         }
922         while (i < endIndex && buffer[i] != term) {
923             i++;
924         }
925         if (end < 0) {
926             end = i;
927         }
928 
929         if (i < endIndex) {
930             i++;
931             if ((mode&PROC_COMBINE) != 0) {
932                 while (i < endIndex && buffer[i] == term) {
933                     i++;
934                 }
935             }
936         }
937 
938         //ALOGI("Field %" PRId32 ": %" PRId32 "-%" PRId32 " dest=%" PRId32 " mode=0x%" PRIx32 "\n", i, start, end, di, mode);
939 
940         if ((mode&(PROC_OUT_FLOAT|PROC_OUT_LONG|PROC_OUT_STRING)) != 0) {
941             char c = buffer[end];
942             buffer[end] = 0;
943             if ((mode&PROC_OUT_FLOAT) != 0 && di < NR) {
944                 char* end;
945                 floatsData[di] = strtof(buffer+start, &end);
946             }
947             if ((mode&PROC_OUT_LONG) != 0 && di < NL) {
948                 if ((mode&PROC_CHAR) != 0) {
949                     // Caller wants single first character returned as one long.
950                     longsData[di] = buffer[start];
951                 } else {
952                     char* end;
953                     longsData[di] = strtoll(buffer+start, &end, 10);
954                 }
955             }
956             if ((mode&PROC_OUT_STRING) != 0 && di < NS) {
957                 jstring str = env->NewStringUTF(buffer+start);
958                 env->SetObjectArrayElement(outStrings, di, str);
959             }
960             buffer[end] = c;
961             di++;
962         }
963     }
964 
965     env->ReleaseIntArrayElements(format, formatData, 0);
966     if (longsData != NULL) {
967         env->ReleaseLongArrayElements(outLongs, longsData, 0);
968     }
969     if (floatsData != NULL) {
970         env->ReleaseFloatArrayElements(outFloats, floatsData, 0);
971     }
972 
973     return res;
974 }
975 
android_os_Process_parseProcLine(JNIEnv * env,jobject clazz,jbyteArray buffer,jint startIndex,jint endIndex,jintArray format,jobjectArray outStrings,jlongArray outLongs,jfloatArray outFloats)976 jboolean android_os_Process_parseProcLine(JNIEnv* env, jobject clazz,
977         jbyteArray buffer, jint startIndex, jint endIndex, jintArray format,
978         jobjectArray outStrings, jlongArray outLongs, jfloatArray outFloats)
979 {
980         jbyte* bufferArray = env->GetByteArrayElements(buffer, NULL);
981 
982         jboolean result = android_os_Process_parseProcLineArray(env, clazz,
983                 (char*) bufferArray, startIndex, endIndex, format, outStrings,
984                 outLongs, outFloats);
985 
986         env->ReleaseByteArrayElements(buffer, bufferArray, 0);
987 
988         return result;
989 }
990 
android_os_Process_readProcFile(JNIEnv * env,jobject clazz,jstring file,jintArray format,jobjectArray outStrings,jlongArray outLongs,jfloatArray outFloats)991 jboolean android_os_Process_readProcFile(JNIEnv* env, jobject clazz,
992         jstring file, jintArray format, jobjectArray outStrings,
993         jlongArray outLongs, jfloatArray outFloats)
994 {
995     if (file == NULL || format == NULL) {
996         jniThrowNullPointerException(env, NULL);
997         return JNI_FALSE;
998     }
999 
1000     const char* file8 = env->GetStringUTFChars(file, NULL);
1001     if (file8 == NULL) {
1002         jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
1003         return JNI_FALSE;
1004     }
1005 
1006     ::android::base::unique_fd fd(open(file8, O_RDONLY | O_CLOEXEC));
1007     if (!fd.ok()) {
1008         if (kDebugProc) {
1009             ALOGW("Unable to open process file: %s\n", file8);
1010         }
1011         env->ReleaseStringUTFChars(file, file8);
1012         return JNI_FALSE;
1013     }
1014     env->ReleaseStringUTFChars(file, file8);
1015 
1016     // Most proc files we read are small, so we only go through the
1017     // loop once and use the stack buffer.  We allocate a buffer big
1018     // enough for the whole file.
1019 
1020     char readBufferStack[kProcReadStackBufferSize];
1021     std::unique_ptr<char[]> readBufferHeap;
1022     char* readBuffer = &readBufferStack[0];
1023     ssize_t readBufferSize = kProcReadStackBufferSize;
1024     ssize_t numberBytesRead;
1025     for (;;) {
1026         // By using pread, we can avoid an lseek to rewind the FD
1027         // before retry, saving a system call.
1028         numberBytesRead = pread(fd, readBuffer, readBufferSize, 0);
1029         if (numberBytesRead < 0 && errno == EINTR) {
1030             continue;
1031         }
1032         if (numberBytesRead < 0) {
1033             if (kDebugProc) {
1034                 ALOGW("Unable to open process file: %s fd=%d\n", file8, fd.get());
1035             }
1036             return JNI_FALSE;
1037         }
1038         if (numberBytesRead < readBufferSize) {
1039             break;
1040         }
1041         if (readBufferSize > std::numeric_limits<ssize_t>::max() / 2) {
1042             if (kDebugProc) {
1043                 ALOGW("Proc file too big: %s fd=%d\n", file8, fd.get());
1044             }
1045             return JNI_FALSE;
1046         }
1047         readBufferSize = std::max(readBufferSize * 2,
1048                                   kProcReadMinHeapBufferSize);
1049         readBufferHeap.reset();  // Free address space before getting more.
1050         readBufferHeap = std::make_unique<char[]>(readBufferSize);
1051         if (!readBufferHeap) {
1052             jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
1053             return JNI_FALSE;
1054         }
1055         readBuffer = readBufferHeap.get();
1056     }
1057 
1058     // parseProcLineArray below modifies the buffer while parsing!
1059     return android_os_Process_parseProcLineArray(
1060         env, clazz, readBuffer, 0, numberBytesRead,
1061         format, outStrings, outLongs, outFloats);
1062 }
1063 
android_os_Process_setApplicationObject(JNIEnv * env,jobject clazz,jobject binderObject)1064 void android_os_Process_setApplicationObject(JNIEnv* env, jobject clazz,
1065                                              jobject binderObject)
1066 {
1067     if (binderObject == NULL) {
1068         jniThrowNullPointerException(env, NULL);
1069         return;
1070     }
1071 
1072     sp<IBinder> binder = ibinderForJavaObject(env, binderObject);
1073 }
1074 
android_os_Process_sendSignal(JNIEnv * env,jobject clazz,jint pid,jint sig)1075 void android_os_Process_sendSignal(JNIEnv* env, jobject clazz, jint pid, jint sig)
1076 {
1077     if (pid > 0) {
1078         ALOGI("Sending signal. PID: %" PRId32 " SIG: %" PRId32, pid, sig);
1079         kill(pid, sig);
1080     }
1081 }
1082 
android_os_Process_sendSignalQuiet(JNIEnv * env,jobject clazz,jint pid,jint sig)1083 void android_os_Process_sendSignalQuiet(JNIEnv* env, jobject clazz, jint pid, jint sig)
1084 {
1085     if (pid > 0) {
1086         kill(pid, sig);
1087     }
1088 }
1089 
android_os_Process_getElapsedCpuTime(JNIEnv * env,jobject clazz)1090 static jlong android_os_Process_getElapsedCpuTime(JNIEnv* env, jobject clazz)
1091 {
1092     struct timespec ts;
1093 
1094     int res = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
1095 
1096     if (res != 0) {
1097         return (jlong) 0;
1098     }
1099 
1100     nsecs_t when = seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec;
1101     return (jlong) nanoseconds_to_milliseconds(when);
1102 }
1103 
android_os_Process_getPss(JNIEnv * env,jobject clazz,jint pid)1104 static jlong android_os_Process_getPss(JNIEnv* env, jobject clazz, jint pid)
1105 {
1106     ::android::meminfo::ProcMemInfo proc_mem(pid);
1107     uint64_t pss;
1108     if (!proc_mem.SmapsOrRollupPss(&pss)) {
1109         return (jlong) -1;
1110     }
1111 
1112     // Return the Pss value in bytes, not kilobytes
1113     return pss * 1024;
1114 }
1115 
android_os_Process_getRss(JNIEnv * env,jobject clazz,jint pid)1116 static jlongArray android_os_Process_getRss(JNIEnv* env, jobject clazz, jint pid)
1117 {
1118     // total, file, anon, swap
1119     jlong rss[4] = {0, 0, 0, 0};
1120     std::string status_path =
1121             android::base::StringPrintf("/proc/%d/status", pid);
1122     UniqueFile file = MakeUniqueFile(status_path.c_str(), "re");
1123 
1124     char line[256];
1125     while (file != nullptr && fgets(line, sizeof(line), file.get())) {
1126         jlong v;
1127         if ( sscanf(line, "VmRSS: %" SCNd64 " kB", &v) == 1) {
1128             rss[0] = v;
1129         } else if ( sscanf(line, "RssFile: %" SCNd64 " kB", &v) == 1) {
1130             rss[1] = v;
1131         } else if ( sscanf(line, "RssAnon: %" SCNd64 " kB", &v) == 1) {
1132             rss[2] = v;
1133         } else if ( sscanf(line, "VmSwap: %" SCNd64 " kB", &v) == 1) {
1134             rss[3] = v;
1135         }
1136     }
1137 
1138     jlongArray rssArray = env->NewLongArray(4);
1139     if (rssArray == NULL) {
1140         jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
1141         return NULL;
1142     }
1143 
1144     env->SetLongArrayRegion(rssArray, 0, 4, rss);
1145 
1146     return rssArray;
1147 }
1148 
android_os_Process_getPidsForCommands(JNIEnv * env,jobject clazz,jobjectArray commandNames)1149 jintArray android_os_Process_getPidsForCommands(JNIEnv* env, jobject clazz,
1150         jobjectArray commandNames)
1151 {
1152     if (commandNames == NULL) {
1153         jniThrowNullPointerException(env, NULL);
1154         return NULL;
1155     }
1156 
1157     Vector<String8> commands;
1158 
1159     jsize count = env->GetArrayLength(commandNames);
1160 
1161     for (int i=0; i<count; i++) {
1162         jobject obj = env->GetObjectArrayElement(commandNames, i);
1163         if (obj != NULL) {
1164             const char* str8 = env->GetStringUTFChars((jstring)obj, NULL);
1165             if (str8 == NULL) {
1166                 jniThrowNullPointerException(env, "Element in commandNames");
1167                 return NULL;
1168             }
1169             commands.add(String8(str8));
1170             env->ReleaseStringUTFChars((jstring)obj, str8);
1171         } else {
1172             jniThrowNullPointerException(env, "Element in commandNames");
1173             return NULL;
1174         }
1175     }
1176 
1177     Vector<jint> pids;
1178 
1179     DIR *proc = opendir("/proc");
1180     if (proc == NULL) {
1181         fprintf(stderr, "/proc: %s\n", strerror(errno));
1182         return NULL;
1183     }
1184 
1185     struct dirent *d;
1186     while ((d = readdir(proc))) {
1187         int pid = atoi(d->d_name);
1188         if (pid <= 0) continue;
1189 
1190         char path[PATH_MAX];
1191         char data[PATH_MAX];
1192         snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
1193 
1194         int fd = open(path, O_RDONLY | O_CLOEXEC);
1195         if (fd < 0) {
1196             continue;
1197         }
1198         const int len = read(fd, data, sizeof(data)-1);
1199         close(fd);
1200 
1201         if (len < 0) {
1202             continue;
1203         }
1204         data[len] = 0;
1205 
1206         for (int i=0; i<len; i++) {
1207             if (data[i] == ' ') {
1208                 data[i] = 0;
1209                 break;
1210             }
1211         }
1212 
1213         for (size_t i=0; i<commands.size(); i++) {
1214             if (commands[i] == data) {
1215                 pids.add(pid);
1216                 break;
1217             }
1218         }
1219     }
1220 
1221     closedir(proc);
1222 
1223     jintArray pidArray = env->NewIntArray(pids.size());
1224     if (pidArray == NULL) {
1225         jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
1226         return NULL;
1227     }
1228 
1229     if (pids.size() > 0) {
1230         env->SetIntArrayRegion(pidArray, 0, pids.size(), pids.array());
1231     }
1232 
1233     return pidArray;
1234 }
1235 
android_os_Process_killProcessGroup(JNIEnv * env,jobject clazz,jint uid,jint pid)1236 jint android_os_Process_killProcessGroup(JNIEnv* env, jobject clazz, jint uid, jint pid)
1237 {
1238     return killProcessGroup(uid, pid, SIGKILL);
1239 }
1240 
android_os_Process_sendSignalToProcessGroup(JNIEnv * env,jobject clazz,jint uid,jint pid,jint signal)1241 jint android_os_Process_sendSignalToProcessGroup(JNIEnv* env, jobject clazz, jint uid, jint pid,
1242                                                  jint signal) {
1243     return sendSignalToProcessGroup(uid, pid, signal);
1244 }
1245 
android_os_Process_removeAllProcessGroups(JNIEnv * env,jobject clazz)1246 void android_os_Process_removeAllProcessGroups(JNIEnv* env, jobject clazz)
1247 {
1248     return removeAllProcessGroups();
1249 }
1250 
android_os_Process_nativePidFdOpen(JNIEnv * env,jobject,jint pid,jint flags)1251 static jint android_os_Process_nativePidFdOpen(JNIEnv* env, jobject, jint pid, jint flags) {
1252     int fd = pidfd_open(pid, flags);
1253     if (fd < 0) {
1254         jniThrowErrnoException(env, "nativePidFdOpen", errno);
1255         return -1;
1256     }
1257     return fd;
1258 }
1259 
android_os_Process_freezeCgroupUID(JNIEnv * env,jobject clazz,jint uid,jboolean freeze)1260 void android_os_Process_freezeCgroupUID(JNIEnv* env, jobject clazz, jint uid, jboolean freeze) {
1261     bool success = true;
1262 
1263     if (freeze) {
1264         success = SetUserProfiles(uid, {"Frozen"});
1265     } else {
1266         success = SetUserProfiles(uid, {"Unfrozen"});
1267     }
1268 
1269     if (!success) {
1270         jniThrowRuntimeException(env, "Could not apply user profile");
1271     }
1272 }
1273 
1274 static const JNINativeMethod methods[] = {
1275         {"getUidForName", "(Ljava/lang/String;)I", (void*)android_os_Process_getUidForName},
1276         {"getGidForName", "(Ljava/lang/String;)I", (void*)android_os_Process_getGidForName},
1277         {"setThreadPriority", "(II)V", (void*)android_os_Process_setThreadPriority},
1278         {"setThreadScheduler", "(III)V", (void*)android_os_Process_setThreadScheduler},
1279         {"setCanSelfBackground", "(Z)V", (void*)android_os_Process_setCanSelfBackground},
1280         {"setThreadPriority", "(I)V", (void*)android_os_Process_setCallingThreadPriority},
1281         {"getThreadPriority", "(I)I", (void*)android_os_Process_getThreadPriority},
1282         {"getThreadScheduler", "(I)I", (void*)android_os_Process_getThreadScheduler},
1283         {"setThreadGroup", "(II)V", (void*)android_os_Process_setThreadGroup},
1284         {"setThreadGroupAndCpuset", "(II)V", (void*)android_os_Process_setThreadGroupAndCpuset},
1285         {"setProcessGroup", "(II)V", (void*)android_os_Process_setProcessGroup},
1286         {"getProcessGroup", "(I)I", (void*)android_os_Process_getProcessGroup},
1287         {"createProcessGroup", "(II)I", (void*)android_os_Process_createProcessGroup},
1288         {"getExclusiveCores", "()[I", (void*)android_os_Process_getExclusiveCores},
1289         {"setSwappiness", "(IZ)Z", (void*)android_os_Process_setSwappiness},
1290         {"setArgV0Native", "(Ljava/lang/String;)V", (void*)android_os_Process_setArgV0},
1291         {"setUid", "(I)I", (void*)android_os_Process_setUid},
1292         {"setGid", "(I)I", (void*)android_os_Process_setGid},
1293         {"sendSignal", "(II)V", (void*)android_os_Process_sendSignal},
1294         {"sendSignalQuiet", "(II)V", (void*)android_os_Process_sendSignalQuiet},
1295         {"setProcessFrozen", "(IIZ)V", (void*)android_os_Process_setProcessFrozen},
1296         {"getFreeMemory", "()J", (void*)android_os_Process_getFreeMemory},
1297         {"getTotalMemory", "()J", (void*)android_os_Process_getTotalMemory},
1298         {"readProcLines", "(Ljava/lang/String;[Ljava/lang/String;[J)V",
1299          (void*)android_os_Process_readProcLines},
1300         {"getPids", "(Ljava/lang/String;[I)[I", (void*)android_os_Process_getPids},
1301         {"readProcFile", "(Ljava/lang/String;[I[Ljava/lang/String;[J[F)Z",
1302          (void*)android_os_Process_readProcFile},
1303         {"parseProcLine", "([BII[I[Ljava/lang/String;[J[F)Z",
1304          (void*)android_os_Process_parseProcLine},
1305         {"getElapsedCpuTime", "()J", (void*)android_os_Process_getElapsedCpuTime},
1306         {"getPss", "(I)J", (void*)android_os_Process_getPss},
1307         {"getRss", "(I)[J", (void*)android_os_Process_getRss},
1308         {"getPidsForCommands", "([Ljava/lang/String;)[I",
1309          (void*)android_os_Process_getPidsForCommands},
1310         //{"setApplicationObject", "(Landroid/os/IBinder;)V",
1311         //(void*)android_os_Process_setApplicationObject},
1312         {"killProcessGroup", "(II)I", (void*)android_os_Process_killProcessGroup},
1313         {"sendSignalToProcessGroup", "(III)I", (void*)android_os_Process_sendSignalToProcessGroup},
1314         {"removeAllProcessGroups", "()V", (void*)android_os_Process_removeAllProcessGroups},
1315         {"nativePidFdOpen", "(II)I", (void*)android_os_Process_nativePidFdOpen},
1316         {"freezeCgroupUid", "(IZ)V", (void*)android_os_Process_freezeCgroupUID},
1317 };
1318 
register_android_os_Process(JNIEnv * env)1319 int register_android_os_Process(JNIEnv* env)
1320 {
1321     return RegisterMethodsOrDie(env, "android/os/Process", methods, NELEM(methods));
1322 }
1323