X Tutup
/* * Copyright (C) 2015-present, Ant Financial Services Group * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // // Created by Cathor on 17/8/29. // /* DO NOT EDIT THIS FILE - it is machine generated */ #include #include #include #include #include #define TAG "CPU_JNI" // 这个是自定义的LOG的标识 #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__) // 定义LOGD类型 #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__) // 定义LOGI类型 #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__) // 定义LOGI类型 typedef struct PidData{ struct PidData* next; int pid; long long previousAppUsage; } PidData; static PidData root = { .next = NULL, .pid = -1, .previousAppUsage = 0 }; static long long previousTotalUsage = 0; static long long previousIdle = 0; /* * 获取总CPU占用率 * Class: com_alipay_hulu_shared_display_items_CPUTools * Method: getTotalUsage * Signature: ()F */ jfloat Java_com_alipay_hulu_shared_display_items_CPUTools_getTotalUsage(JNIEnv* env, jclass clz) { FILE * pFile; char* filename = "/proc/stat"; pFile = fopen(filename, "r"); if (pFile == NULL) { return 0; } char* line = (char*) malloc(1024); char* tmp; fgets(line, 1024, pFile); char* pch = strtok_r(line," \n", &tmp); int count = 0; long long currentTotalUsage = 0; long long currentIdle = 0; while (pch != NULL) { if (count > 7) { break; } if (count == 4) { currentIdle = atoll(pch); } if (count > 0) { currentTotalUsage += atoll(pch); } pch = strtok_r(NULL, " \n", &tmp); count++; } free(line); fclose(pFile); if (previousTotalUsage == 0L) { previousTotalUsage = currentTotalUsage; previousIdle = currentIdle; return 0; } // 计算时间段内cpu运行时间与idle时间 long cpuTotalTime = currentTotalUsage - previousTotalUsage; long cpuIdleTime = currentIdle - previousIdle; // 转化为double计算结果 double result = 100 * (cpuTotalTime - cpuIdleTime) / (double) cpuTotalTime; // 同步到上一次结果 previousTotalUsage = currentTotalUsage; previousIdle = currentIdle; return (float)result; } static int count = 0; /* * 获取应用CPU占用率与CPU总占用率 * Class: com_alipay_hulu_shared_display_items_CPUTools * Method: getAppTotalUsage * Signature: (I)[F */ jfloatArray Java_com_alipay_hulu_shared_display_items_CPUTools_getAppTotalUsage(JNIEnv *env, jclass clz, jintArray pids) { jboolean b; jint *realPids = (*env)->GetIntArrayElements(env, pids, &b); int length = (*env)->GetArrayLength(env, pids); FILE *cpuFile; FILE **appFiles = (FILE**) malloc(sizeof(FILE*) * length); float *data = (float *) malloc(sizeof(float) * (1 + length)); // 尽量保证同时打开文件,同时获取文件数据 cpuFile = fopen("/proc/stat", "r"); if (cpuFile == NULL) { free(appFiles); LOGI("Open CPU file failed"); jfloatArray result = (*env)->NewFloatArray(env, 0); free(data); (*env)->ReleaseIntArrayElements(env, pids, realPids, 0); return result; } // 逐项格式化文件名 for (int i = 0; i < length; ++i) { char filename[20]; sprintf(filename, "/proc/%d/stat", realPids[i]); appFiles[i] = fopen(filename, "r"); } // // 存在文件不能打开的情况,Android 7.0以上无法直接打开/proc/pid/stat // if (appFile == NULL) { // fclose(cpuFile); // jfloat cpuUsage = Java_com_alipay_hulu_display_CPUTools_getTotalUsage(env, clz); // LOGI("Open app file failed"); // jfloatArray result = (*env)->NewFloatArray(env, cpuUsage); // free(data); // return result; // } // 获取第一行数据 char *cpuLine = (char *) malloc(256); fgets(cpuLine, 256, cpuFile); char **appLines = (char **) malloc(sizeof(char *) * length); for (int i = 0; i < length; ++i) { if (appFiles[i] != NULL) { char *appLine = (char *) malloc(256); fgets(appLine, 256, appFiles[i]); appLines[i] = appLine; } else { appLines[i] = NULL; } } // 文件读取完毕,关闭文件 fclose(cpuFile); for (int i = 0; i < length; ++i) { if (appFiles[i] != NULL) { fclose(appFiles[i]); } } free(appFiles); // 解析CPU数据 char* tmp; char *pch = strtok_r(cpuLine, " \n", &tmp); int count = 0; long long currentTotalUsage = 0; long long currentIdle = 0; // 第2-8位为CPU各项运行时间,第5位为CPU空闲时间 while (pch != NULL) { if (!pch || *pch == '\0') { continue; } if (count > 7) { break; } if (count == 4) { currentIdle = atoll(pch); } if (count > 0) { currentTotalUsage += atoll(pch); } pch = strtok_r(NULL, " \n", &tmp); count++; } // 清理CPU行内存 free(cpuLine); if (previousTotalUsage == 0L) { previousTotalUsage = currentTotalUsage; previousIdle = currentIdle; jfloatArray result = (*env)->NewFloatArray(env, 0); free(data); (*env)->ReleaseIntArrayElements(env, pids, realPids, 0); return result; } // 计算时间段内cpu运行时间与idle时间 long cpuTotalTime = currentTotalUsage - previousTotalUsage; long cpuIdleTime = currentIdle - previousIdle; double cpuUsage = 100 * (cpuTotalTime - cpuIdleTime) / (double) cpuTotalTime; // 替换前一次数据 previousTotalUsage = currentTotalUsage; previousIdle = currentIdle; // 存入结果 data[length] = (float) cpuUsage; for (int i = 0; i < length; ++i) { // 对于空数据,直接跳过 if (appLines[i] == NULL) { data[i] = 0; continue; } char* save_tmp; pch = strtok_r(appLines[i], " \n", &save_tmp); count = 0; long long currentAppUsage = 0; // 计算应用占用总时间,从13到16位分别为用户态运行,核心态运行时间,已死线程用户态运行时间,已死线程核心态运行时间 while (pch != NULL) { // 空字符,忽略 if (!pch || *pch == '\0') { continue; } if (count > 16) { break; } if (count > 12) { currentAppUsage += atoll(pch); } pch = strtok_r(NULL, " \n", &save_tmp); count++; } // 清理应用行内存 free(appLines[i]); PidData *currentPidData = &root; while (currentPidData->pid != realPids[i] && currentPidData->next != NULL) { currentPidData = currentPidData->next; } LOGD("Pid: %d with data: %lld", realPids[i], currentAppUsage); // 当pid不为目标pid,说明未找到,在末尾添加新的PidData if (currentPidData->pid != realPids[i]) { PidData *newItem = (PidData *) malloc(sizeof(PidData)); newItem->next = NULL; newItem->previousAppUsage = 0; newItem->pid = realPids[i]; currentPidData->next = newItem; currentPidData = newItem; } // 未初始化,清理 if (currentPidData->previousAppUsage == 0) { currentPidData->previousAppUsage = currentAppUsage; data[i] = 0; continue; } long appTime = currentAppUsage - currentPidData->previousAppUsage; double appUsage = 100 * appTime / (double) cpuTotalTime; data[i] = (float) appUsage; // 替换前一次数据 currentPidData->previousAppUsage = currentAppUsage; } // 拷贝结果数据 jfloatArray result = (*env)->NewFloatArray(env, length + 1); (*env)->SetFloatArrayRegion(env, result, 0, length + 1, data); free(data); (*env)->ReleaseIntArrayElements(env, pids, realPids, 0); return result; }
X Tutup