GoogleGit

blob: 28307249249fc2522900c7f10a2718d20663ce07 [file] [log] [blame]
  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. #define LOG_TAG "Process"
  18. #include <utils/Log.h>
  19. #include <binder/IPCThreadState.h>
  20. #include <binder/IServiceManager.h>
  21. #include <cutils/process_name.h>
  22. #include <cutils/sched_policy.h>
  23. #include <utils/String8.h>
  24. #include <utils/Vector.h>
  25. #include <processgroup/processgroup.h>
  26. #include "core_jni_helpers.h"
  27. #include "android_util_Binder.h"
  28. #include "JNIHelp.h"
  29. #include <dirent.h>
  30. #include <fcntl.h>
  31. #include <grp.h>
  32. #include <inttypes.h>
  33. #include <pwd.h>
  34. #include <signal.h>
  35. #include <sys/errno.h>
  36. #include <sys/resource.h>
  37. #include <sys/stat.h>
  38. #include <sys/types.h>
  39. #include <unistd.h>
  40. #define GUARD_THREAD_PRIORITY 0
  41. using namespace android;
  42. static const bool kDebugPolicy = false;
  43. static const bool kDebugProc = false;
  44. #if GUARD_THREAD_PRIORITY
  45. Mutex gKeyCreateMutex;
  46. static pthread_key_t gBgKey = -1;
  47. #endif
  48. // For both of these, err should be in the errno range (positive), not a status_t (negative)
  49. static void signalExceptionForPriorityError(JNIEnv* env, int err)
  50. {
  51. switch (err) {
  52. case EINVAL:
  53. jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
  54. break;
  55. case ESRCH:
  56. jniThrowException(env, "java/lang/IllegalArgumentException", "Given thread does not exist");
  57. break;
  58. case EPERM:
  59. jniThrowException(env, "java/lang/SecurityException", "No permission to modify given thread");
  60. break;
  61. case EACCES:
  62. jniThrowException(env, "java/lang/SecurityException", "No permission to set to given priority");
  63. break;
  64. default:
  65. jniThrowException(env, "java/lang/RuntimeException", "Unknown error");
  66. break;
  67. }
  68. }
  69. static void signalExceptionForGroupError(JNIEnv* env, int err)
  70. {
  71. switch (err) {
  72. case EINVAL:
  73. jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
  74. break;
  75. case ESRCH:
  76. jniThrowException(env, "java/lang/IllegalArgumentException", "Given thread does not exist");
  77. break;
  78. case EPERM:
  79. jniThrowException(env, "java/lang/SecurityException", "No permission to modify given thread");
  80. break;
  81. case EACCES:
  82. jniThrowException(env, "java/lang/SecurityException", "No permission to set to given group");
  83. break;
  84. default:
  85. jniThrowException(env, "java/lang/RuntimeException", "Unknown error");
  86. break;
  87. }
  88. }
  89. jint android_os_Process_getUidForName(JNIEnv* env, jobject clazz, jstring name)
  90. {
  91. if (name == NULL) {
  92. jniThrowNullPointerException(env, NULL);
  93. return -1;
  94. }
  95. const jchar* str16 = env->GetStringCritical(name, 0);
  96. String8 name8;
  97. if (str16) {
  98. name8 = String8(reinterpret_cast<const char16_t*>(str16),
  99. env->GetStringLength(name));
  100. env->ReleaseStringCritical(name, str16);
  101. }
  102. const size_t N = name8.size();
  103. if (N > 0) {
  104. const char* str = name8.string();
  105. for (size_t i=0; i<N; i++) {
  106. if (str[i] < '0' || str[i] > '9') {
  107. struct passwd* pwd = getpwnam(str);
  108. if (pwd == NULL) {
  109. return -1;
  110. }
  111. return pwd->pw_uid;
  112. }
  113. }
  114. return atoi(str);
  115. }
  116. return -1;
  117. }
  118. jint android_os_Process_getGidForName(JNIEnv* env, jobject clazz, jstring name)
  119. {
  120. if (name == NULL) {
  121. jniThrowNullPointerException(env, NULL);
  122. return -1;
  123. }
  124. const jchar* str16 = env->GetStringCritical(name, 0);
  125. String8 name8;
  126. if (str16) {
  127. name8 = String8(reinterpret_cast<const char16_t*>(str16),
  128. env->GetStringLength(name));
  129. env->ReleaseStringCritical(name, str16);
  130. }
  131. const size_t N = name8.size();
  132. if (N > 0) {
  133. const char* str = name8.string();
  134. for (size_t i=0; i<N; i++) {
  135. if (str[i] < '0' || str[i] > '9') {
  136. struct group* grp = getgrnam(str);
  137. if (grp == NULL) {
  138. return -1;
  139. }
  140. return grp->gr_gid;
  141. }
  142. }
  143. return atoi(str);
  144. }
  145. return -1;
  146. }
  147. void android_os_Process_setThreadGroup(JNIEnv* env, jobject clazz, int tid, jint grp)
  148. {
  149. ALOGV("%s tid=%d grp=%" PRId32, __func__, tid, grp);
  150. SchedPolicy sp = (SchedPolicy) grp;
  151. int res = set_sched_policy(tid, sp);
  152. if (res != NO_ERROR) {
  153. signalExceptionForGroupError(env, -res);
  154. }
  155. }
  156. void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jint grp)
  157. {
  158. ALOGV("%s pid=%d grp=%" PRId32, __func__, pid, grp);
  159. DIR *d;
  160. char proc_path[255];
  161. struct dirent *de;
  162. if ((grp == SP_FOREGROUND) || (grp > SP_MAX)) {
  163. signalExceptionForGroupError(env, EINVAL);
  164. return;
  165. }
  166. bool isDefault = false;
  167. if (grp < 0) {
  168. grp = SP_FOREGROUND;
  169. isDefault = true;
  170. }
  171. SchedPolicy sp = (SchedPolicy) grp;
  172. if (kDebugPolicy) {
  173. char cmdline[32];
  174. int fd;
  175. strcpy(cmdline, "unknown");
  176. sprintf(proc_path, "/proc/%d/cmdline", pid);
  177. fd = open(proc_path, O_RDONLY);
  178. if (fd >= 0) {
  179. int rc = read(fd, cmdline, sizeof(cmdline)-1);
  180. cmdline[rc] = 0;
  181. close(fd);
  182. }
  183. if (sp == SP_BACKGROUND) {
  184. ALOGD("setProcessGroup: vvv pid %d (%s)", pid, cmdline);
  185. } else {
  186. ALOGD("setProcessGroup: ^^^ pid %d (%s)", pid, cmdline);
  187. }
  188. }
  189. sprintf(proc_path, "/proc/%d/task", pid);
  190. if (!(d = opendir(proc_path))) {
  191. // If the process exited on us, don't generate an exception
  192. if (errno != ENOENT)
  193. signalExceptionForGroupError(env, errno);
  194. return;
  195. }
  196. while ((de = readdir(d))) {
  197. int t_pid;
  198. int t_pri;
  199. if (de->d_name[0] == '.')
  200. continue;
  201. t_pid = atoi(de->d_name);
  202. if (!t_pid) {
  203. ALOGE("Error getting pid for '%s'\n", de->d_name);
  204. continue;
  205. }
  206. t_pri = getpriority(PRIO_PROCESS, t_pid);
  207. if (t_pri <= ANDROID_PRIORITY_AUDIO) {
  208. int scheduler = sched_getscheduler(t_pid);
  209. if ((scheduler == SCHED_FIFO) || (scheduler == SCHED_RR)) {
  210. // This task wants to stay in it's current audio group so it can keep it's budget
  211. continue;
  212. }
  213. }
  214. if (isDefault) {
  215. if (t_pri >= ANDROID_PRIORITY_BACKGROUND) {
  216. // This task wants to stay at background
  217. continue;
  218. }
  219. }
  220. int err = set_sched_policy(t_pid, sp);
  221. if (err != NO_ERROR) {
  222. signalExceptionForGroupError(env, -err);
  223. break;
  224. }
  225. }
  226. closedir(d);
  227. }
  228. jint android_os_Process_getProcessGroup(JNIEnv* env, jobject clazz, jint pid)
  229. {
  230. SchedPolicy sp;
  231. if (get_sched_policy(pid, &sp) != 0) {
  232. signalExceptionForGroupError(env, errno);
  233. }
  234. return (int) sp;
  235. }
  236. static void android_os_Process_setCanSelfBackground(JNIEnv* env, jobject clazz, jboolean bgOk) {
  237. // Establishes the calling thread as illegal to put into the background.
  238. // Typically used only for the system process's main looper.
  239. #if GUARD_THREAD_PRIORITY
  240. ALOGV("Process.setCanSelfBackground(%d) : tid=%d", bgOk, gettid());
  241. {
  242. Mutex::Autolock _l(gKeyCreateMutex);
  243. if (gBgKey == -1) {
  244. pthread_key_create(&gBgKey, NULL);
  245. }
  246. }
  247. // inverted: not-okay, we set a sentinel value
  248. pthread_setspecific(gBgKey, (void*)(bgOk ? 0 : 0xbaad));
  249. #endif
  250. }
  251. void android_os_Process_setThreadScheduler(JNIEnv* env, jclass clazz,
  252. jint tid, jint policy, jint pri)
  253. {
  254. // linux has sched_setscheduler(), others don't.
  255. #if defined(__linux__)
  256. struct sched_param param;
  257. param.sched_priority = pri;
  258. int rc = sched_setscheduler(tid, policy, &param);
  259. if (rc) {
  260. signalExceptionForPriorityError(env, errno);
  261. }
  262. #else
  263. signalExceptionForPriorityError(env, ENOSYS);
  264. #endif
  265. }
  266. void android_os_Process_setThreadPriority(JNIEnv* env, jobject clazz,
  267. jint pid, jint pri)
  268. {
  269. #if GUARD_THREAD_PRIORITY
  270. // if we're putting the current thread into the background, check the TLS
  271. // to make sure this thread isn't guarded. If it is, raise an exception.
  272. if (pri >= ANDROID_PRIORITY_BACKGROUND) {
  273. if (pid == gettid()) {
  274. void* bgOk = pthread_getspecific(gBgKey);
  275. if (bgOk == ((void*)0xbaad)) {
  276. ALOGE("Thread marked fg-only put self in background!");
  277. jniThrowException(env, "java/lang/SecurityException", "May not put this thread into background");
  278. return;
  279. }
  280. }
  281. }
  282. #endif
  283. int rc = androidSetThreadPriority(pid, pri);
  284. if (rc != 0) {
  285. if (rc == INVALID_OPERATION) {
  286. signalExceptionForPriorityError(env, errno);
  287. } else {
  288. signalExceptionForGroupError(env, errno);
  289. }
  290. }
  291. //ALOGI("Setting priority of %" PRId32 ": %" PRId32 ", getpriority returns %d\n",
  292. // pid, pri, getpriority(PRIO_PROCESS, pid));
  293. }
  294. void android_os_Process_setCallingThreadPriority(JNIEnv* env, jobject clazz,
  295. jint pri)
  296. {
  297. android_os_Process_setThreadPriority(env, clazz, gettid(), pri);
  298. }
  299. jint android_os_Process_getThreadPriority(JNIEnv* env, jobject clazz,
  300. jint pid)
  301. {
  302. errno = 0;
  303. jint pri = getpriority(PRIO_PROCESS, pid);
  304. if (errno != 0) {
  305. signalExceptionForPriorityError(env, errno);
  306. }
  307. //ALOGI("Returning priority of %" PRId32 ": %" PRId32 "\n", pid, pri);
  308. return pri;
  309. }
  310. jboolean android_os_Process_setSwappiness(JNIEnv *env, jobject clazz,
  311. jint pid, jboolean is_increased)
  312. {
  313. char text[64];
  314. if (is_increased) {
  315. strcpy(text, "/sys/fs/cgroup/memory/sw/tasks");
  316. } else {
  317. strcpy(text, "/sys/fs/cgroup/memory/tasks");
  318. }
  319. struct stat st;
  320. if (stat(text, &st) || !S_ISREG(st.st_mode)) {
  321. return false;
  322. }
  323. int fd = open(text, O_WRONLY);
  324. if (fd >= 0) {
  325. sprintf(text, "%" PRId32, pid);
  326. write(fd, text, strlen(text));
  327. close(fd);
  328. }
  329. return true;
  330. }
  331. void android_os_Process_setArgV0(JNIEnv* env, jobject clazz, jstring name)
  332. {
  333. if (name == NULL) {
  334. jniThrowNullPointerException(env, NULL);
  335. return;
  336. }
  337. const jchar* str = env->GetStringCritical(name, 0);
  338. String8 name8;
  339. if (str) {
  340. name8 = String8(reinterpret_cast<const char16_t*>(str),
  341. env->GetStringLength(name));
  342. env->ReleaseStringCritical(name, str);
  343. }
  344. if (name8.size() > 0) {
  345. const char* procName = name8.string();
  346. set_process_name(procName);
  347. AndroidRuntime::getRuntime()->setArgv0(procName);
  348. }
  349. }
  350. jint android_os_Process_setUid(JNIEnv* env, jobject clazz, jint uid)
  351. {
  352. return setuid(uid) == 0 ? 0 : errno;
  353. }
  354. jint android_os_Process_setGid(JNIEnv* env, jobject clazz, jint uid)
  355. {
  356. return setgid(uid) == 0 ? 0 : errno;
  357. }
  358. static int pid_compare(const void* v1, const void* v2)
  359. {
  360. //ALOGI("Compare %" PRId32 " vs %" PRId32 "\n", *((const jint*)v1), *((const jint*)v2));
  361. return *((const jint*)v1) - *((const jint*)v2);
  362. }
  363. static jlong getFreeMemoryImpl(const char* const sums[], const size_t sumsLen[], size_t num)
  364. {
  365. int fd = open("/proc/meminfo", O_RDONLY);
  366. if (fd < 0) {
  367. ALOGW("Unable to open /proc/meminfo");
  368. return -1;
  369. }
  370. char buffer[256];
  371. const int len = read(fd, buffer, sizeof(buffer)-1);
  372. close(fd);
  373. if (len < 0) {
  374. ALOGW("Unable to read /proc/meminfo");
  375. return -1;
  376. }
  377. buffer[len] = 0;
  378. size_t numFound = 0;
  379. jlong mem = 0;
  380. char* p = buffer;
  381. while (*p && numFound < num) {
  382. int i = 0;
  383. while (sums[i]) {
  384. if (strncmp(p, sums[i], sumsLen[i]) == 0) {
  385. p += sumsLen[i];
  386. while (*p == ' ') p++;
  387. char* num = p;
  388. while (*p >= '0' && *p <= '9') p++;
  389. if (*p != 0) {
  390. *p = 0;
  391. p++;
  392. if (*p == 0) p--;
  393. }
  394. mem += atoll(num) * 1024;
  395. numFound++;
  396. break;
  397. }
  398. i++;
  399. }
  400. p++;
  401. }
  402. return numFound > 0 ? mem : -1;
  403. }
  404. static jlong android_os_Process_getFreeMemory(JNIEnv* env, jobject clazz)
  405. {
  406. static const char* const sums[] = { "MemFree:", "Cached:", NULL };
  407. static const size_t sumsLen[] = { strlen("MemFree:"), strlen("Cached:"), 0 };
  408. return getFreeMemoryImpl(sums, sumsLen, 2);
  409. }
  410. static jlong android_os_Process_getTotalMemory(JNIEnv* env, jobject clazz)
  411. {
  412. static const char* const sums[] = { "MemTotal:", NULL };
  413. static const size_t sumsLen[] = { strlen("MemTotal:"), 0 };
  414. return getFreeMemoryImpl(sums, sumsLen, 1);
  415. }
  416. void android_os_Process_readProcLines(JNIEnv* env, jobject clazz, jstring fileStr,
  417. jobjectArray reqFields, jlongArray outFields)
  418. {
  419. //ALOGI("getMemInfo: %p %p", reqFields, outFields);
  420. if (fileStr == NULL || reqFields == NULL || outFields == NULL) {
  421. jniThrowNullPointerException(env, NULL);
  422. return;
  423. }
  424. const char* file8 = env->GetStringUTFChars(fileStr, NULL);
  425. if (file8 == NULL) {
  426. return;
  427. }
  428. String8 file(file8);
  429. env->ReleaseStringUTFChars(fileStr, file8);
  430. jsize count = env->GetArrayLength(reqFields);
  431. if (count > env->GetArrayLength(outFields)) {
  432. jniThrowException(env, "java/lang/IllegalArgumentException", "Array lengths differ");
  433. return;
  434. }
  435. Vector<String8> fields;
  436. int i;
  437. for (i=0; i<count; i++) {
  438. jobject obj = env->GetObjectArrayElement(reqFields, i);
  439. if (obj != NULL) {
  440. const char* str8 = env->GetStringUTFChars((jstring)obj, NULL);
  441. //ALOGI("String at %d: %p = %s", i, obj, str8);
  442. if (str8 == NULL) {
  443. jniThrowNullPointerException(env, "Element in reqFields");
  444. return;
  445. }
  446. fields.add(String8(str8));
  447. env->ReleaseStringUTFChars((jstring)obj, str8);
  448. } else {
  449. jniThrowNullPointerException(env, "Element in reqFields");
  450. return;
  451. }
  452. }
  453. jlong* sizesArray = env->GetLongArrayElements(outFields, 0);
  454. if (sizesArray == NULL) {
  455. return;
  456. }
  457. //ALOGI("Clearing %" PRId32 " sizes", count);
  458. for (i=0; i<count; i++) {
  459. sizesArray[i] = 0;
  460. }
  461. int fd = open(file.string(), O_RDONLY);
  462. if (fd >= 0) {
  463. const size_t BUFFER_SIZE = 2048;
  464. char* buffer = (char*)malloc(BUFFER_SIZE);
  465. int len = read(fd, buffer, BUFFER_SIZE-1);
  466. close(fd);
  467. if (len < 0) {
  468. ALOGW("Unable to read %s", file.string());
  469. len = 0;
  470. }
  471. buffer[len] = 0;
  472. int foundCount = 0;
  473. char* p = buffer;
  474. while (*p && foundCount < count) {
  475. bool skipToEol = true;
  476. //ALOGI("Parsing at: %s", p);
  477. for (i=0; i<count; i++) {
  478. const String8& field = fields[i];
  479. if (strncmp(p, field.string(), field.length()) == 0) {
  480. p += field.length();
  481. while (*p == ' ' || *p == '\t') p++;
  482. char* num = p;
  483. while (*p >= '0' && *p <= '9') p++;
  484. skipToEol = *p != '\n';
  485. if (*p != 0) {
  486. *p = 0;
  487. p++;
  488. }
  489. char* end;
  490. sizesArray[i] = strtoll(num, &end, 10);
  491. //ALOGI("Field %s = %" PRId64, field.string(), sizesArray[i]);
  492. foundCount++;
  493. break;
  494. }
  495. }
  496. if (skipToEol) {
  497. while (*p && *p != '\n') {
  498. p++;
  499. }
  500. if (*p == '\n') {
  501. p++;
  502. }
  503. }
  504. }
  505. free(buffer);
  506. } else {
  507. ALOGW("Unable to open %s", file.string());
  508. }
  509. //ALOGI("Done!");
  510. env->ReleaseLongArrayElements(outFields, sizesArray, 0);
  511. }
  512. jintArray android_os_Process_getPids(JNIEnv* env, jobject clazz,
  513. jstring file, jintArray lastArray)
  514. {
  515. if (file == NULL) {
  516. jniThrowNullPointerException(env, NULL);
  517. return NULL;
  518. }
  519. const char* file8 = env->GetStringUTFChars(file, NULL);
  520. if (file8 == NULL) {
  521. jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
  522. return NULL;
  523. }
  524. DIR* dirp = opendir(file8);
  525. env->ReleaseStringUTFChars(file, file8);
  526. if(dirp == NULL) {
  527. return NULL;
  528. }
  529. jsize curCount = 0;
  530. jint* curData = NULL;
  531. if (lastArray != NULL) {
  532. curCount = env->GetArrayLength(lastArray);
  533. curData = env->GetIntArrayElements(lastArray, 0);
  534. }
  535. jint curPos = 0;
  536. struct dirent* entry;
  537. while ((entry=readdir(dirp)) != NULL) {
  538. const char* p = entry->d_name;
  539. while (*p) {
  540. if (*p < '0' || *p > '9') break;
  541. p++;
  542. }
  543. if (*p != 0) continue;
  544. char* end;
  545. int pid = strtol(entry->d_name, &end, 10);
  546. //ALOGI("File %s pid=%d\n", entry->d_name, pid);
  547. if (curPos >= curCount) {
  548. jsize newCount = (curCount == 0) ? 10 : (curCount*2);
  549. jintArray newArray = env->NewIntArray(newCount);
  550. if (newArray == NULL) {
  551. closedir(dirp);
  552. jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
  553. return NULL;
  554. }
  555. jint* newData = env->GetIntArrayElements(newArray, 0);
  556. if (curData != NULL) {
  557. memcpy(newData, curData, sizeof(jint)*curCount);
  558. env->ReleaseIntArrayElements(lastArray, curData, 0);
  559. }
  560. lastArray = newArray;
  561. curCount = newCount;
  562. curData = newData;
  563. }
  564. curData[curPos] = pid;
  565. curPos++;
  566. }
  567. closedir(dirp);
  568. if (curData != NULL && curPos > 0) {
  569. qsort(curData, curPos, sizeof(jint), pid_compare);
  570. }
  571. while (curPos < curCount) {
  572. curData[curPos] = -1;
  573. curPos++;
  574. }
  575. if (curData != NULL) {
  576. env->ReleaseIntArrayElements(lastArray, curData, 0);
  577. }
  578. return lastArray;
  579. }
  580. enum {
  581. PROC_TERM_MASK = 0xff,
  582. PROC_ZERO_TERM = 0,
  583. PROC_SPACE_TERM = ' ',
  584. PROC_COMBINE = 0x100,
  585. PROC_PARENS = 0x200,
  586. PROC_QUOTES = 0x400,
  587. PROC_OUT_STRING = 0x1000,
  588. PROC_OUT_LONG = 0x2000,
  589. PROC_OUT_FLOAT = 0x4000,
  590. };
  591. jboolean android_os_Process_parseProcLineArray(JNIEnv* env, jobject clazz,
  592. char* buffer, jint startIndex, jint endIndex, jintArray format,
  593. jobjectArray outStrings, jlongArray outLongs, jfloatArray outFloats)
  594. {
  595. const jsize NF = env->GetArrayLength(format);
  596. const jsize NS = outStrings ? env->GetArrayLength(outStrings) : 0;
  597. const jsize NL = outLongs ? env->GetArrayLength(outLongs) : 0;
  598. const jsize NR = outFloats ? env->GetArrayLength(outFloats) : 0;
  599. jint* formatData = env->GetIntArrayElements(format, 0);
  600. jlong* longsData = outLongs ?
  601. env->GetLongArrayElements(outLongs, 0) : NULL;
  602. jfloat* floatsData = outFloats ?
  603. env->GetFloatArrayElements(outFloats, 0) : NULL;
  604. if (formatData == NULL || (NL > 0 && longsData == NULL)
  605. || (NR > 0 && floatsData == NULL)) {
  606. if (formatData != NULL) {
  607. env->ReleaseIntArrayElements(format, formatData, 0);
  608. }
  609. if (longsData != NULL) {
  610. env->ReleaseLongArrayElements(outLongs, longsData, 0);
  611. }
  612. if (floatsData != NULL) {
  613. env->ReleaseFloatArrayElements(outFloats, floatsData, 0);
  614. }
  615. jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
  616. return JNI_FALSE;
  617. }
  618. jsize i = startIndex;
  619. jsize di = 0;
  620. jboolean res = JNI_TRUE;
  621. for (jsize fi=0; fi<NF; fi++) {
  622. jint mode = formatData[fi];
  623. if ((mode&PROC_PARENS) != 0) {
  624. i++;
  625. } else if ((mode&PROC_QUOTES) != 0) {
  626. if (buffer[i] == '"') {
  627. i++;
  628. } else {
  629. mode &= ~PROC_QUOTES;
  630. }
  631. }
  632. const char term = (char)(mode&PROC_TERM_MASK);
  633. const jsize start = i;
  634. if (i >= endIndex) {
  635. if (kDebugProc) {
  636. ALOGW("Ran off end of data @%d", i);
  637. }
  638. res = JNI_FALSE;
  639. break;
  640. }
  641. jsize end = -1;
  642. if ((mode&PROC_PARENS) != 0) {
  643. while (i < endIndex && buffer[i] != ')') {
  644. i++;
  645. }
  646. end = i;
  647. i++;
  648. } else if ((mode&PROC_QUOTES) != 0) {
  649. while (buffer[i] != '"' && i < endIndex) {
  650. i++;
  651. }
  652. end = i;
  653. i++;
  654. }
  655. while (i < endIndex && buffer[i] != term) {
  656. i++;
  657. }
  658. if (end < 0) {
  659. end = i;
  660. }
  661. if (i < endIndex) {
  662. i++;
  663. if ((mode&PROC_COMBINE) != 0) {
  664. while (i < endIndex && buffer[i] == term) {
  665. i++;
  666. }
  667. }
  668. }
  669. //ALOGI("Field %" PRId32 ": %" PRId32 "-%" PRId32 " dest=%" PRId32 " mode=0x%" PRIx32 "\n", i, start, end, di, mode);
  670. if ((mode&(PROC_OUT_FLOAT|PROC_OUT_LONG|PROC_OUT_STRING)) != 0) {
  671. char c = buffer[end];
  672. buffer[end] = 0;
  673. if ((mode&PROC_OUT_FLOAT) != 0 && di < NR) {
  674. char* end;
  675. floatsData[di] = strtof(buffer+start, &end);
  676. }
  677. if ((mode&PROC_OUT_LONG) != 0 && di < NL) {
  678. char* end;
  679. longsData[di] = strtoll(buffer+start, &end, 10);
  680. }
  681. if ((mode&PROC_OUT_STRING) != 0 && di < NS) {
  682. jstring str = env->NewStringUTF(buffer+start);
  683. env->SetObjectArrayElement(outStrings, di, str);
  684. }
  685. buffer[end] = c;
  686. di++;
  687. }
  688. }
  689. env->ReleaseIntArrayElements(format, formatData, 0);
  690. if (longsData != NULL) {
  691. env->ReleaseLongArrayElements(outLongs, longsData, 0);
  692. }
  693. if (floatsData != NULL) {
  694. env->ReleaseFloatArrayElements(outFloats, floatsData, 0);
  695. }
  696. return res;
  697. }
  698. jboolean android_os_Process_parseProcLine(JNIEnv* env, jobject clazz,
  699. jbyteArray buffer, jint startIndex, jint endIndex, jintArray format,
  700. jobjectArray outStrings, jlongArray outLongs, jfloatArray outFloats)
  701. {
  702. jbyte* bufferArray = env->GetByteArrayElements(buffer, NULL);
  703. jboolean result = android_os_Process_parseProcLineArray(env, clazz,
  704. (char*) bufferArray, startIndex, endIndex, format, outStrings,
  705. outLongs, outFloats);
  706. env->ReleaseByteArrayElements(buffer, bufferArray, 0);
  707. return result;
  708. }
  709. jboolean android_os_Process_readProcFile(JNIEnv* env, jobject clazz,
  710. jstring file, jintArray format, jobjectArray outStrings,
  711. jlongArray outLongs, jfloatArray outFloats)
  712. {
  713. if (file == NULL || format == NULL) {
  714. jniThrowNullPointerException(env, NULL);
  715. return JNI_FALSE;
  716. }
  717. const char* file8 = env->GetStringUTFChars(file, NULL);
  718. if (file8 == NULL) {
  719. jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
  720. return JNI_FALSE;
  721. }
  722. int fd = open(file8, O_RDONLY);
  723. if (fd < 0) {
  724. if (kDebugProc) {
  725. ALOGW("Unable to open process file: %s\n", file8);
  726. }
  727. env->ReleaseStringUTFChars(file, file8);
  728. return JNI_FALSE;
  729. }
  730. env->ReleaseStringUTFChars(file, file8);
  731. char buffer[256];
  732. const int len = read(fd, buffer, sizeof(buffer)-1);
  733. close(fd);
  734. if (len < 0) {
  735. if (kDebugProc) {
  736. ALOGW("Unable to open process file: %s fd=%d\n", file8, fd);
  737. }
  738. return JNI_FALSE;
  739. }
  740. buffer[len] = 0;
  741. return android_os_Process_parseProcLineArray(env, clazz, buffer, 0, len,
  742. format, outStrings, outLongs, outFloats);
  743. }
  744. void android_os_Process_setApplicationObject(JNIEnv* env, jobject clazz,
  745. jobject binderObject)
  746. {
  747. if (binderObject == NULL) {
  748. jniThrowNullPointerException(env, NULL);
  749. return;
  750. }
  751. sp<IBinder> binder = ibinderForJavaObject(env, binderObject);
  752. }
  753. void android_os_Process_sendSignal(JNIEnv* env, jobject clazz, jint pid, jint sig)
  754. {
  755. if (pid > 0) {
  756. ALOGI("Sending signal. PID: %" PRId32 " SIG: %" PRId32, pid, sig);
  757. kill(pid, sig);
  758. }
  759. }
  760. void android_os_Process_sendSignalQuiet(JNIEnv* env, jobject clazz, jint pid, jint sig)
  761. {
  762. if (pid > 0) {
  763. kill(pid, sig);
  764. }
  765. }
  766. static jlong android_os_Process_getElapsedCpuTime(JNIEnv* env, jobject clazz)
  767. {
  768. struct timespec ts;
  769. int res = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
  770. if (res != 0) {
  771. return (jlong) 0;
  772. }
  773. nsecs_t when = seconds_to_nanoseconds(ts.tv_sec) + ts.tv_nsec;
  774. return (jlong) nanoseconds_to_milliseconds(when);
  775. }
  776. static jlong android_os_Process_getPss(JNIEnv* env, jobject clazz, jint pid)
  777. {
  778. char filename[64];
  779. snprintf(filename, sizeof(filename), "/proc/%" PRId32 "/smaps", pid);
  780. FILE * file = fopen(filename, "r");
  781. if (!file) {
  782. return (jlong) -1;
  783. }
  784. // Tally up all of the Pss from the various maps
  785. char line[256];
  786. jlong pss = 0;
  787. while (fgets(line, sizeof(line), file)) {
  788. jlong v;
  789. if (sscanf(line, "Pss: %" SCNd64 " kB", &v) == 1) {
  790. pss += v;
  791. }
  792. }
  793. fclose(file);
  794. // Return the Pss value in bytes, not kilobytes
  795. return pss * 1024;
  796. }
  797. jintArray android_os_Process_getPidsForCommands(JNIEnv* env, jobject clazz,
  798. jobjectArray commandNames)
  799. {
  800. if (commandNames == NULL) {
  801. jniThrowNullPointerException(env, NULL);
  802. return NULL;
  803. }
  804. Vector<String8> commands;
  805. jsize count = env->GetArrayLength(commandNames);
  806. for (int i=0; i<count; i++) {
  807. jobject obj = env->GetObjectArrayElement(commandNames, i);
  808. if (obj != NULL) {
  809. const char* str8 = env->GetStringUTFChars((jstring)obj, NULL);
  810. if (str8 == NULL) {
  811. jniThrowNullPointerException(env, "Element in commandNames");
  812. return NULL;
  813. }
  814. commands.add(String8(str8));
  815. env->ReleaseStringUTFChars((jstring)obj, str8);
  816. } else {
  817. jniThrowNullPointerException(env, "Element in commandNames");
  818. return NULL;
  819. }
  820. }
  821. Vector<jint> pids;
  822. DIR *proc = opendir("/proc");
  823. if (proc == NULL) {
  824. fprintf(stderr, "/proc: %s\n", strerror(errno));
  825. return NULL;
  826. }
  827. struct dirent *d;
  828. while ((d = readdir(proc))) {
  829. int pid = atoi(d->d_name);
  830. if (pid <= 0) continue;
  831. char path[PATH_MAX];
  832. char data[PATH_MAX];
  833. snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
  834. int fd = open(path, O_RDONLY);
  835. if (fd < 0) {
  836. continue;
  837. }
  838. const int len = read(fd, data, sizeof(data)-1);
  839. close(fd);
  840. if (len < 0) {
  841. continue;
  842. }
  843. data[len] = 0;
  844. for (int i=0; i<len; i++) {
  845. if (data[i] == ' ') {
  846. data[i] = 0;
  847. break;
  848. }
  849. }
  850. for (size_t i=0; i<commands.size(); i++) {
  851. if (commands[i] == data) {
  852. pids.add(pid);
  853. break;
  854. }
  855. }
  856. }
  857. closedir(proc);
  858. jintArray pidArray = env->NewIntArray(pids.size());
  859. if (pidArray == NULL) {
  860. jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
  861. return NULL;
  862. }
  863. if (pids.size() > 0) {
  864. env->SetIntArrayRegion(pidArray, 0, pids.size(), pids.array());
  865. }
  866. return pidArray;
  867. }
  868. jint android_os_Process_killProcessGroup(JNIEnv* env, jobject clazz, jint uid, jint pid)
  869. {
  870. return killProcessGroup(uid, pid, SIGKILL);
  871. }
  872. void android_os_Process_removeAllProcessGroups(JNIEnv* env, jobject clazz)
  873. {
  874. return removeAllProcessGroups();
  875. }
  876. static const JNINativeMethod methods[] = {
  877. {"getUidForName", "(Ljava/lang/String;)I", (void*)android_os_Process_getUidForName},
  878. {"getGidForName", "(Ljava/lang/String;)I", (void*)android_os_Process_getGidForName},
  879. {"setThreadPriority", "(II)V", (void*)android_os_Process_setThreadPriority},
  880. {"setThreadScheduler", "(III)V", (void*)android_os_Process_setThreadScheduler},
  881. {"setCanSelfBackground", "(Z)V", (void*)android_os_Process_setCanSelfBackground},
  882. {"setThreadPriority", "(I)V", (void*)android_os_Process_setCallingThreadPriority},
  883. {"getThreadPriority", "(I)I", (void*)android_os_Process_getThreadPriority},
  884. {"setThreadGroup", "(II)V", (void*)android_os_Process_setThreadGroup},
  885. {"setProcessGroup", "(II)V", (void*)android_os_Process_setProcessGroup},
  886. {"getProcessGroup", "(I)I", (void*)android_os_Process_getProcessGroup},
  887. {"setSwappiness", "(IZ)Z", (void*)android_os_Process_setSwappiness},
  888. {"setArgV0", "(Ljava/lang/String;)V", (void*)android_os_Process_setArgV0},
  889. {"setUid", "(I)I", (void*)android_os_Process_setUid},
  890. {"setGid", "(I)I", (void*)android_os_Process_setGid},
  891. {"sendSignal", "(II)V", (void*)android_os_Process_sendSignal},
  892. {"sendSignalQuiet", "(II)V", (void*)android_os_Process_sendSignalQuiet},
  893. {"getFreeMemory", "()J", (void*)android_os_Process_getFreeMemory},
  894. {"getTotalMemory", "()J", (void*)android_os_Process_getTotalMemory},
  895. {"readProcLines", "(Ljava/lang/String;[Ljava/lang/String;[J)V", (void*)android_os_Process_readProcLines},
  896. {"getPids", "(Ljava/lang/String;[I)[I", (void*)android_os_Process_getPids},
  897. {"readProcFile", "(Ljava/lang/String;[I[Ljava/lang/String;[J[F)Z", (void*)android_os_Process_readProcFile},
  898. {"parseProcLine", "([BII[I[Ljava/lang/String;[J[F)Z", (void*)android_os_Process_parseProcLine},
  899. {"getElapsedCpuTime", "()J", (void*)android_os_Process_getElapsedCpuTime},
  900. {"getPss", "(I)J", (void*)android_os_Process_getPss},
  901. {"getPidsForCommands", "([Ljava/lang/String;)[I", (void*)android_os_Process_getPidsForCommands},
  902. //{"setApplicationObject", "(Landroid/os/IBinder;)V", (void*)android_os_Process_setApplicationObject},
  903. {"killProcessGroup", "(II)I", (void*)android_os_Process_killProcessGroup},
  904. {"removeAllProcessGroups", "()V", (void*)android_os_Process_removeAllProcessGroups},
  905. };
  906. int register_android_os_Process(JNIEnv* env)
  907. {
  908. return RegisterMethodsOrDie(env, "android/os/Process", methods, NELEM(methods));
  909. }