4 * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
8 * Jaewon Lim <jaewon81.lim@samsung.com>
9 * Woojin Jung <woojin2.jung@samsung.com>
10 * Juyoung Kim <j0.kim@samsung.com>
11 * Cherepanov Vitaliy <v.cherepanov@samsung.com>
12 * Nikita Kalyazin <n.kalyazin@samsung.com>
14 * Licensed under the Apache License, Version 2.0 (the "License");
15 * you may not use this file except in compliance with the License.
16 * You may obtain a copy of the License at
18 * http://www.apache.org/licenses/LICENSE-2.0
20 * Unless required by applicable law or agreed to in writing, software
21 * distributed under the License is distributed on an "AS IS" BASIS,
22 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 * See the License for the specific language governing permissions and
24 * limitations under the License.
28 * - Samsung RnD Institute Russia
38 #include <sys/types.h>
50 #include <system_info.h>
51 #include <runtime_info.h>
52 #include <telephony_network.h>
55 #include "da_protocol.h"
64 // defines for runtime environment
67 #define BUFFER_MAX 1024
68 #define LARGE_BUFFER 512
69 #define MIDDLE_BUFFER 256
70 #define SMALL_BUFFER 64
71 #define PROCPATH_MAX 32
72 #define STATUS_STRING_MAX 16
73 #define MAX_NUM_OF_FREQ 16
75 #define MEM_SLOT_TOTAL 0
76 #define MEM_SLOT_FREE 1
77 #define MEM_SLOT_BUFFER 2
78 #define MEM_SLOT_CACHED 3
79 #define MEM_SLOT_MAX 4
81 #define MIN_TICKS_FOR_LOAD 8
82 #define MIN_TOTAL_TICK 10
83 #define SYS_INFO_TICK 100 // TODO : change to (Hertz * profiling period)
85 #define CPUMHZ "cpu MHz"
86 #define DA_PROBE_TIZEN_SONAME "da_probe_tizen.so"
87 #define DA_PROBE_OSP_SONAME "da_probe_osp.so"
88 #define CAMCORDER_FILE "/usr/etc/mmfw_camcorder.ini"
89 #define CAMERA_COUNT_STR "DeviceCount"
91 // define for correct difference of system feature vars
92 #define val_diff(v_new, v_old) ((v_new < v_old) ? v_new : v_new - v_old)
100 // declared by greatim
101 static int Hertz = 0;
102 static int num_of_cpu = 0;
103 static int num_of_freq = 0;
104 static uint64_t mem_slot_array[MEM_SLOT_MAX];
105 static CPU_t* cpus = NULL;
106 static unsigned long probe_so_size = 0;
109 int get_file_status_no_open(int pfd, const char *filename)
112 char buf[STATUS_STRING_MAX];
114 if (unlikely(pfd < 0)) {
119 lseek(pfd, 0, SEEK_SET); // rewind to start of file
122 if (unlikely(read(pfd, buf, STATUS_STRING_MAX) == -1))
129 // daemon api : get status from file
130 // pfd must not be null
131 int get_file_status(int *pfd, const char *filename)
135 if (likely(pfd != NULL)) {
136 //open if is not open
137 if (unlikely(*pfd < 0)) {
139 *pfd = open(filename, O_RDONLY);
140 if (unlikely(*pfd == -1)) {
141 /* This file may absent in the system */
146 if (unlikely(*pfd < 0)) {
147 //file is open. lets read
148 status = get_file_status_no_open(*pfd, filename);
156 // =============================================================================
157 // device status information getter functions
158 // =============================================================================
159 static int get_wifi_status()
164 res = vconf_get_int(VCONFKEY_WIFI_STATE, &wifi_status);
165 if (unlikely(res < 0)) {
166 LOG_ONCE_W("get error #%d\n", res);
167 wifi_status = VCONFKEY_WIFI_OFF;
173 static int get_bt_status()
175 int bt_status = false;
178 res = vconf_get_int(VCONFKEY_BT_STATUS, &bt_status);
179 if (unlikely(res < 0)) {
180 LOG_ONCE_W("get error #%d\n", res);
181 bt_status = VCONFKEY_BT_STATUS_OFF;
187 static int get_gps_status()
192 res = vconf_get_int(VCONFKEY_LOCATION_ENABLED, &gps_status);
193 if(unlikely(res < 0)) {
194 LOG_ONCE_W("get error #%d\n", res);
195 gps_status = VCONFKEY_LOCATION_GPS_OFF;
196 } else if(gps_status != 0) {
197 res = vconf_get_int(VCONFKEY_LOCATION_GPS_STATE, &gps_status);
198 if (unlikely(res < 0)) {
199 LOG_ONCE_W("get error #%d\n", res);
200 gps_status = VCONFKEY_LOCATION_GPS_OFF;
207 static void init_brightness_status()
211 struct dirent *dir_entry;
212 char fullpath[PATH_MAX];
214 dir_info = opendir(BRIGHTNESS_PARENT_DIR);
215 if (dir_info != NULL) {
216 while ((dir_entry = readdir(dir_info)) != NULL) {
217 if (strcmp(dir_entry->d_name, ".") == 0 ||
218 strcmp(dir_entry->d_name, "..") == 0)
220 else { /* first directory */
222 BRIGHTNESS_PARENT_DIR "/%s/"
225 get_file_status(&manager.fd.brightness,
234 get_file_status(&manager.fd.brightness, EMUL_BRIGHTNESSFD);
238 static int get_brightness_status()
240 return get_file_status_no_open(manager.fd.brightness, EMUL_BRIGHTNESSFD);
243 static int get_max_brightness()
245 int maxbrightnessfd = -1;
246 static int max_brightness = -1;
248 if (__builtin_expect(max_brightness < 0, 0)) {
251 struct dirent* dir_entry;
252 char fullpath[PATH_MAX];
254 dir_info = opendir(BRIGHTNESS_PARENT_DIR);
255 if (dir_info != NULL) {
256 while((dir_entry = readdir(dir_info)) != NULL) {
257 if (strcmp(dir_entry->d_name, ".") == 0 ||
258 strcmp(dir_entry->d_name, "..") == 0)
262 BRIGHTNESS_PARENT_DIR "/%s/" MAX_BRIGHTNESS_FILENAME,
264 max_brightness = get_file_status(&maxbrightnessfd, fullpath);
271 #else /* DEVICE_ONLY */
272 max_brightness = get_file_status(&maxbrightnessfd, EMUL_MAX_BRIGHTNESSFD);
273 #endif /* DEVICE_ONLY */
276 if (maxbrightnessfd != -1)
277 close(maxbrightnessfd);
279 return max_brightness;
282 static void init_video_status()
284 manager.fd.video = fopen(MFCFD, "r");
287 static int get_video_status()
289 int video_status = 0;
291 FILE *video_fp = manager.fd.video;
294 if (video_fp == NULL) // file is not open
300 ret = fscanf(video_fp, "%s", stat);
303 if(strncmp(stat,"active",6) == 0)
309 static int get_rssi_status()
312 int flightmode_status;
316 res = vconf_get_bool(VCONFKEY_TELEPHONY_FLIGHT_MODE,
318 if(unlikely(res < 0)) {
319 LOG_ONCE_W("get err #%d <%s>\n", res,
320 VCONFKEY_TELEPHONY_FLIGHT_MODE);
321 flightmode_status = 0;
324 if(!flightmode_status) {
325 res = vconf_get_int(VCONFKEY_TELEPHONY_RSSI, &rssi_status);
326 if(unlikely(res < 0)) {
327 LOG_ONCE_W("rssi get err #%d\n", res);
328 rssi_status = VCONFKEY_TELEPHONY_RSSI_0;
331 rssi_status = VCONFKEY_TELEPHONY_RSSI_0;
339 static int get_call_status()
344 res = vconf_get_int(VCONFKEY_CALL_STATE, &call_status);
345 if(unlikely(res < 0)) {
346 LOG_ONCE_W("get err #%d\n", res);
347 call_status = VCONFKEY_CALL_OFF;
354 static int get_dnet_status()
356 int dnet_status = false;
359 res = vconf_get_int(VCONFKEY_DNET_STATE, &dnet_status);
360 if(unlikely(res < 0)) {
361 LOG_ONCE_W("get err #%d <%s>\n", res, VCONFKEY_DNET_STATE);
362 dnet_status = VCONFKEY_DNET_OFF;
368 static int get_camera_status()
370 int camera_status = 0;
372 if (unlikely(vconf_get_int(VCONFKEY_CAMERA_STATE, &camera_status) < 0)) {
373 camera_status = VCONFKEY_CAMERA_STATE_NULL;
376 return camera_status;
379 // this means silent mode?
380 static int get_sound_status()
382 int sound_status = 0;
385 res = vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL,
387 if (unlikely(res < 0)) {
388 LOG_ONCE_W("get err #%d\n", res);
395 static int get_audio_status()
400 res = vconf_get_int(VCONFKEY_SOUND_STATUS,
402 if (unlikely(res < 0)) {
403 LOG_ONCE_W("get err #%d\n", res);
407 return !!audio_state;
410 static int get_vibration_status()
412 int vibration_status = 0;
415 res = vconf_get_bool(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL,
417 if(unlikely(res < 0)) {
418 LOG_ONCE_W("get err #%d\n", res);
419 vibration_status = 0;
422 return vibration_status;
425 static void init_voltage_status()
427 get_file_status(&manager.fd.voltage, VOLTAGEFD);
430 static int get_voltage_status()
432 return get_file_status_no_open(manager.fd.voltage, VOLTAGEFD);
435 // =====================================================================
436 // cpu information getter functions
437 // =====================================================================
438 static void get_cpu_frequency(float *freqs)
440 char filename[MIDDLE_BUFFER];
441 char freq_str[SMALL_BUFFER];
446 for (cpu_n = 0; cpu_n < num_of_cpu; cpu_n++)
452 snprintf(filename, MIDDLE_BUFFER,
453 "/sys/devices/system/cpu/cpu%d/online", cpu_n);
455 f = fopen(filename, "r");
457 LOGI_th_samp("file not found <%s\n>", filename);
463 snprintf(filename, MIDDLE_BUFFER,
464 "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_cur_freq", cpu_n);
465 f = fopen(filename, "r");
469 LOGI_th_samp("core #%d diasabled\n", cpu_n);
472 //core enabled, get frequency
473 fscanf(f, "%s", freq_str);
474 freqs[cpu_n] = atof(freq_str);
475 LOGI_th_samp("core #%d freq = %.0f\n", cpu_n, freqs[cpu_n]);
485 // ========================================================================
486 // get cpu and memory info for each process and whole system
487 // ========================================================================
488 typedef struct _proc_node {
490 unsigned long long saved_utime;
491 unsigned long long saved_stime;
493 struct _proc_node *next;
496 static procNode *prochead = NULL;
497 static procNode *thread_prochead = NULL;
499 static procNode* find_node(procNode *head, pid_t pid)
504 if (t->proc_data.pid == pid)
514 static procNode* add_node(procNode **head, pid_t pid)
518 n = (procNode *) malloc(sizeof(procNode));
520 LOGE("Not enough memory, add cpu info node failied");
524 n->proc_data.pid = pid;
532 static int del_node(procNode **head, pid_t pid)
539 /* LOGI("dell t=%d\n",t); */
541 if (t->proc_data.pid == pid) {
543 prev->next = t->next;
545 *head = (*head)->next;
553 /* LOGI("ret 0\n"); */
557 static int del_notfound_node(procNode **head)
559 procNode *proc, *prev;
561 for(proc = *head; proc != NULL; )
567 prev->next = proc->next;
573 *head = (*head)->next;
587 static int reset_found_node(procNode *head)
590 for(proc = head; proc != NULL; proc = proc->next)
597 // return 0 for normal case
598 // return negative value for error case
599 static int parse_proc_stat_file_bypid(char *path, proc_t* P)
601 char filename[PROCPATH_MAX];
602 char buf[BUFFER_MAX];
606 // read from stat file
607 sprintf(filename, "%s/stat", path);
608 fd = open(filename, O_RDONLY, 0);
610 if(unlikely(fd == -1)){
614 num = read(fd, buf, BUFFER_MAX);
617 if(unlikely(num <= 0)){
618 LOGE("nothing read from '%s'\n", filename);
620 } else if(num == BUFFER_MAX)
628 abuf = strchr(buf, '(') + 1;
629 bbuf = strrchr(buf, ')');
631 if(unlikely(num >= sizeof(P->command)))
632 num = sizeof(P->command) - 1;
633 memcpy(P->command, abuf, num);
634 P->command[num] = '\0';
642 "%lu %lu %lu %lu %lu "
643 "%Lu %Lu %Lu %Lu " // utime stime cutime cstime
651 &P->ppid, &P->pgrp, &P->sid, &P->tty_nr, &P->tty_pgrp,
652 &P->flags, &P->minor_fault, &P->cminor_fault, &P->major_fault, &P->cmajor_fault,
653 &P->utime, &P->stime, &P->cutime, &P->cstime,
654 &P->priority, &P->nice,
662 if(P->numofthread == 0)
668 // return 0 for normal case
669 // return negative value for error case
670 static int parse_proc_smaps_file_bypid(char *path, proc_t* P)
672 #define MIN_SMAP_BLOCKLINE 50
674 char filename[PROCPATH_MAX];
675 char buf[MIDDLE_BUFFER];
676 char numbuf[SMALL_BUFFER];
679 // reset pss size of proc_t
683 // read from smaps file
684 sprintf(filename, "%s/smaps", path);
685 fp = fopen(filename, "r");
691 if(unlikely(probe_so_size == 0)) // probe so size is not abtained
694 while(fgets(buf, MIDDLE_BUFFER, fp) != NULL)
696 if(strncmp(buf, "Pss:", 4) == 0) // line is started with "Pss:"
698 sscanf(buf, "Pss:%s kB", numbuf);
699 P->pss += atoi(numbuf);
702 probe_so_size += atoi(numbuf);
703 is_probe_so = 0; // reset search flag
706 else if(strncmp(buf, "Shared", 6) == 0) // line is started with "Shared"
709 p = strstr(buf, ":");
711 sscanf(p, ":%s kB", numbuf);
712 P->sh_mem += atoi(numbuf);
718 if (is_probe_so == 0 && strlen(buf) > MIN_SMAP_BLOCKLINE)
720 // first we find probe so section
721 if(strstr(buf, DA_PROBE_TIZEN_SONAME) != NULL ||
722 strstr(buf, DA_PROBE_OSP_SONAME) != NULL)
739 else // we know about probe.so size already
741 while(fgets(buf, MIDDLE_BUFFER, fp) != NULL)
743 if(strncmp(buf, "Pss:", 4) == 0)
745 sscanf(buf, "Pss:%s kB", numbuf);
746 P->pss += atoi(numbuf);
748 else if(strncmp(buf, "Shared", 6) == 0) // line is started with "Shared"
751 p = strstr(buf, ":");
753 sscanf(p, ":%s kB", numbuf);
754 P->sh_mem += atoi(numbuf);
760 P->pss -= probe_so_size;
767 // return 0 for normal case
768 // return positive value for non critical case
769 // return negative value for critical case
770 static int update_process_data(int* pidarray, int pidcount, enum PROCESS_DATA datatype)
772 static struct stat sb;
774 char buf[PROCPATH_MAX];
777 for(i = 0; i < pidcount; i++)
779 /* LOGI("#%d\n", i); */
780 if (pidarray[i] == 0) // pid is invalid
786 sprintf(buf, "/proc/%d", pidarray[i]);
787 /* LOGI("#->%s\n", buf); */
788 if (unlikely(stat(buf, &sb) == -1)) // cannot access anymore
790 /* LOGI("#del from prochead=%d\n", prochead); */
791 del_node(&prochead, pidarray[i]);
796 /* LOGI("find node = %d\n", procnode); */
797 if ((procnode = find_node(prochead, pidarray[i])) == NULL) // new process
799 /* LOGI("proc node1 = %d\n", procnode); */
800 procnode = add_node(&prochead, pidarray[i]);
801 if(datatype == PROCDATA_STAT)
803 if (unlikely((ret = parse_proc_stat_file_bypid(buf, &(procnode->proc_data))) < 0))
805 LOGE("Failed to get proc stat file by pid(%d)\n", pidarray[i]);
809 procnode->saved_utime = procnode->proc_data.utime;
810 procnode->saved_stime = procnode->proc_data.stime;
813 else if(datatype == PROCDATA_SMAPS)
815 if (unlikely((ret = parse_proc_smaps_file_bypid(buf, &(procnode->proc_data))) < 0))
817 LOGE("Failed to get proc smaps file by pid(%d)\n", pidarray[i]);
829 /* LOGI("proc node2 = %d\n", procnode); */
830 if(datatype == PROCDATA_STAT)
832 if (unlikely((ret = parse_proc_stat_file_bypid(buf, &(procnode->proc_data))) < 0))
834 LOGE("Failed to get proc stat file by pid(%d)\n", pidarray[i]);
840 else if(datatype == PROCDATA_SMAPS)
842 if (unlikely((ret = parse_proc_smaps_file_bypid(buf, &(procnode->proc_data))) < 0))
844 LOGE("Failed to get proc smaps file by pid(%d)\n", pidarray[i]);
855 /* LOGI("del_notfound_node\n"); */
856 del_notfound_node(&prochead);
857 /* LOGI("reset_found_node\n"); */
858 reset_found_node(prochead);
860 /* LOGI("ret %d\n", ret); */
864 static int update_system_cpu_frequency(int cur_index)
866 char buf[SMALL_BUFFER];
867 char filename[SMALL_BUFFER];
871 // execute this block only once
872 if(unlikely(num_of_freq <= 0))
876 if((fp = fopen(CPUNUM_OF_FREQ, "r")) != NULL)
878 while(fgets(buf, SMALL_BUFFER, fp) != NULL)
886 /* This file may absent in the system */
889 for(i = 0; i < num_of_cpu; i++)
891 if(cpus[i].pfreq == NULL && num_of_freq)
893 cpus[i].pfreq = (cpufreq_t*) calloc(num_of_freq, sizeof(cpufreq_t));
898 sprintf(filename, CPUNUM_OF_FREQ);
899 // update cpu frequency information
900 for(i = 0; i < num_of_cpu; i++)
902 filename[27] = (char)('0' + i);
903 fp = fopen(filename, "r");
906 for(j = 0; j < num_of_freq; j++)
908 if(fgets(buf, SMALL_BUFFER, fp) != NULL)
910 sscanf(buf, "%lu %Lu", &(cpus[i].pfreq[j].freq),
911 &(cpus[i].pfreq[j].tick));
913 else // cannot read anymore from frequency info file
918 cpus[i].cur_freq_index = cur_index;
920 else // cannot load cpu frequency information
928 // return 0 for normal case
929 // return negative value for error
930 static void init_system_cpu_data()
932 manager.fd.procstat = fopen(PROCSTAT, "r");
935 static int update_system_cpu_data(int cur_index)
939 FILE* fp = manager.fd.procstat;
941 char buf[BUFFER_MAX];
949 if(fgets(buf, sizeof(buf), fp) == NULL)
951 LOGE("Failed to read first line of " PROCSTAT "\n");
955 /* LOGI("scan; cpus = %d\n", cpus); */
957 cpus[num_of_cpu].x = 0;
958 cpus[num_of_cpu].y = 0;
959 cpus[num_of_cpu].z = 0;
960 num = sscanf(buf, "cpu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu",
970 cpus[num_of_cpu].cur_load_index = cur_index;
973 LOGE("Failed to read from " PROCSTAT "\n");
979 /* LOGI("cpu num = %d\n", num_of_cpu); */
980 // and just in case we're 2.2.xx compiled without SMP support...
983 cpus[0].id = cpus[1].id = 0;
984 memcpy(cpus, &cpus[1], sizeof(tic_t) * 8);
985 cpus[0].cur_load_index = cur_index;
987 else if(num_of_cpu > 1)
990 // now value each separate cpu's tics
991 for(i = 0; i < num_of_cpu; i++)
993 if(fgets(buf, sizeof(buf), fp) != NULL)
998 num = sscanf(buf, "cpu%u %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu",
1000 &cpus[i].u, &cpus[i].n, &cpus[i].s, &cpus[i].i,
1001 &cpus[i].w, &cpus[i].x, &cpus[i].y, &cpus[i].z);
1004 LOGI_th_samp("Readed %d stats of %dth cpu\n", num, i);
1005 cpus[i].cur_load_index = cur_index;
1007 else // buf is not cpu core tick information
1011 else // cannot read anymore from /proc/stat file
1025 // return 0 for normal case
1026 // return negative value for error
1027 static void init_update_system_memory_data()
1029 manager.fd.procmeminfo = open(PROCMEMINFO, O_RDONLY);
1032 static int update_system_memory_data(uint64_t *memtotal, uint64_t *memused)
1034 int meminfo_fd = manager.fd.procmeminfo;
1037 char buf[BUFFER_MAX];
1038 static const mem_t mem_table[] = {
1039 {"Buffers", (unsigned long *)&mem_slot_array[MEM_SLOT_BUFFER]},
1040 {"Cached", (unsigned long *)&mem_slot_array[MEM_SLOT_CACHED]},
1041 {"MemFree", (unsigned long *)&mem_slot_array[MEM_SLOT_FREE]},
1042 {"MemTotal", (unsigned long *)&mem_slot_array[MEM_SLOT_TOTAL]},
1044 const int mem_table_size = sizeof(mem_table) / sizeof(mem_t);
1046 if (meminfo_fd == -1)
1049 lseek(meminfo_fd, 0L, SEEK_SET);
1050 if((num = read(meminfo_fd, buf, BUFFER_MAX)) < 0)
1052 LOGE("Failed to read from " PROCMEMINFO "\n");
1056 if(num == BUFFER_MAX)
1060 // LOGI("buffer=<%s>\n", buf);
1062 num = 0; // number of found element
1064 for( ;num < mem_table_size ; )
1066 tail = strchr(head, ':');
1070 for(i = 0; i < mem_table_size; i++)
1072 if(strcmp(head, mem_table[i].name) == 0) // found
1075 *(mem_table[i].slot) = strtoul(head, &tail, 10);
1080 if(i == mem_table_size) // cannot find entry
1084 tail = strchr(head, '\n');
1089 /* LOGI("Buffers = %016LX\n", mem_slot_array[MEM_SLOT_BUFFER]); */
1090 /* LOGI("Cached = %016LX\n", mem_slot_array[MEM_SLOT_CACHED]); */
1091 /* LOGI("MemFree = %016LX\n", mem_slot_array[MEM_SLOT_FREE]); */
1092 /* LOGI("MemTotal= %016LX\n", mem_slot_array[MEM_SLOT_TOTAL]); */
1093 if(num == mem_table_size) // find all element
1095 *memtotal = mem_slot_array[MEM_SLOT_TOTAL];
1096 *memused = mem_slot_array[MEM_SLOT_TOTAL] - mem_slot_array[MEM_SLOT_FREE] -
1097 mem_slot_array[MEM_SLOT_BUFFER] - mem_slot_array[MEM_SLOT_CACHED];
1100 *memtotal *= 1024; // change to Byte
1101 *memused *= 1024; // change to Byte
1106 LOGE("Cannot find all neccessary element in meminfo\n");
1112 // return 0 for error case
1113 // return system total memory in MB
1115 unsigned long get_system_total_memory()
1117 int meminfo_fd = manager.fd.procmeminfo;
1120 char buf[BUFFER_MAX];
1121 static const char* memtotalstr = "MemTotal";
1122 unsigned long totalmem = 0;
1124 if (meminfo_fd == -1)
1127 lseek(meminfo_fd, 0L, SEEK_SET);
1129 if((num = read(meminfo_fd, buf, BUFFER_MAX)) < 0)
1131 LOGE("Failed to read from " PROCMEMINFO "\n");
1135 if(num == BUFFER_MAX)
1142 tail = strchr(head, ':');
1146 if(strcmp(head, memtotalstr) == 0) // found
1149 totalmem = strtoul(head, &tail, 10);
1154 tail = strchr(head, '\n');
1160 return (totalmem * 1024);
1163 // ===============================================================
1164 // disk information getter functions
1165 // ===============================================================
1166 static int get_fsinfo(const char* path, int type)
1172 if (statfs(path, &buf) < 0)
1177 total = (int)((long long)(buf.f_bsize / 1024LL * buf.f_blocks) / 1024LL);
1178 free = (int)((long long)(buf.f_bsize / 1024LL * buf.f_bavail) / 1024LL);
1180 /* LOGI("File storage total(%d), free(%d)\n", total, free); */
1181 if (type == FSINFO_TYPE_TOTAL)
1185 else if (type == FSINFO_TYPE_FREE)
1193 static int stat_get_storageinfo(int type)
1195 return get_fsinfo(UMSFD, type);
1198 static int stat_get_cardinfo(int type)
1200 if (access(MMCBLKFD, F_OK) < 0)
1205 return get_fsinfo(MMCFD, type);
1209 static int get_total_drive()
1212 int storage = stat_get_storageinfo(FSINFO_TYPE_TOTAL);
1213 int card = stat_get_cardinfo(FSINFO_TYPE_TOTAL);
1215 if (storage < 0 && card < 0)
1220 total = storage + card;
1225 static int get_total_used_drive()
1229 int storage = stat_get_storageinfo(FSINFO_TYPE_FREE);
1230 int card = stat_get_cardinfo(FSINFO_TYPE_FREE);
1232 if (storage < 0 && card < 0)
1234 LOGI_th_samp("total_used_drive = -1\n");
1238 free = storage + card;
1239 total = get_total_drive() - free;
1241 LOGI_th_samp("total_used_drive = %d\n", total);
1246 static int update_thread_data(int pid)
1248 static struct stat sb;
1250 char path[PROCPATH_MAX];
1251 char buf[PROCPATH_MAX];
1253 DIR *taskdir = NULL;
1254 struct dirent *entry = NULL;
1257 sprintf(path, "/proc/%d/task", pid);
1259 if(!(taskdir = opendir(path)))
1261 LOGE("task not found '%s'\n", path);
1265 while((entry = readdir(taskdir)) != NULL)
1267 if(*entry->d_name > '0' && *entry->d_name <= '9')
1269 tid = atoi(entry->d_name);
1270 sprintf(buf, "/proc/%d/task/%d", pid, tid);
1272 if(unlikely(stat(buf, &sb) == -1))
1274 del_node(&thread_prochead, tid);
1279 if((procnode = find_node(thread_prochead, tid)) == NULL)
1281 procnode = add_node(&thread_prochead, tid);
1282 if (unlikely((ret = parse_proc_stat_file_bypid(buf, &(procnode->proc_data))) < 0))
1284 LOGE("Failed to get proc stat file by tid(%d). add node\n", tid);
1288 procnode->saved_utime = procnode->proc_data.utime;
1289 procnode->saved_stime = procnode->proc_data.stime;
1290 /* LOGI("data updated\n"); */
1295 if (unlikely((ret = parse_proc_stat_file_bypid(buf, &(procnode->proc_data))) < 0))
1297 LOGE("Failed to get proc stat file by tid(%d). node exist\n", tid);
1303 del_notfound_node(&thread_prochead);
1304 reset_found_node(thread_prochead);
1310 // ========================================================================
1311 // overall information getter functions
1312 // ========================================================================
1314 // this code is not necessary anymore
1316 static void get_app_info(const char* binary_path, char* width,
1317 char* height, char* theme, char* version,
1318 char* scale, char* removable,
1325 char pkg_info_path [PATH_MAX];
1326 char buffer [BUFFER_MAX];
1328 sprintf(pkg_info_path, "/opt/share/applications/%s.desktop", pkg_name);
1330 fd = open(pkg_info_path, O_RDONLY);
1333 LOGE("Cannot open %s", pkg_info_path);
1337 fcntl( fd, F_SETFD, FD_CLOEXEC );
1339 LOGI("get_app_info - After open pkg_info_path\n");
1343 res = read(fd, buffer, BUFFER_MAX);
1356 LOGI("read buffer ===%s===\n", buffer);
1357 for (i = 0; i < res; i++)
1359 if (i < res - 22 && strncmp(&buffer[i], "X-SLP-BaseLayoutWidth=", 22) == 0)
1361 for (j = 0; j < res; j ++)
1363 if (buffer[i+j] == '\n' || buffer[i+j] == '\t')
1365 LOGI("width :::: ");
1366 strncpy(width, &(buffer[i+22]), j-22);
1367 LOGI("%s\n", width);
1373 else if (i < res - 23 && strncmp(&buffer[i], "X-SLP-BaseLayoutHeight=", 23) == 0)
1375 for (j = 0; j < res; j ++)
1377 if (buffer[i+j] == '\n' || buffer[i+j] == '\t')
1379 LOGI("height :::: ");
1380 strncpy(height, &(buffer[i+23]), j-23);
1381 LOGI("%s\n", height);
1387 else if (i < res - 6 && (strncmp(&buffer[i], "theme=", 6) == 0 || strncmp(&buffer[i], "Theme=", 6) == 0))
1389 for (j = 0; j < res; j ++)
1391 if (buffer[i+j] == '\n' || buffer[i+j] == '\t')
1393 LOGI("theme :::: ");
1394 strncpy(theme, &(buffer[i+6]), j-6);
1395 LOGI("%s\n", theme);
1401 else if (i < res - 8 && (strncmp(&buffer[i], "Version=", 8) == 0 || strncmp(&buffer[i], "version=", 8) == 0))
1403 for (j = 0; j < res; j ++)
1405 if (buffer[i+j] == '\n' || buffer[i+j] == '\t')
1407 LOGI("version :::: ");
1408 strncpy(version, &(buffer[i+8]), j-8);
1409 LOGI("%s\n", version);
1415 else if (i < res - 24 && strncmp(&buffer[i], "X-SLP-IsHorizontalScale=", 24) == 0)
1417 for (j = 0; j < res; j ++)
1419 if (buffer[i+j] == '\n' || buffer[i+j] == '\t')
1421 LOGI("scale :::: ");
1422 strncpy(scale, &(buffer[i+24]), j-24);
1423 LOGI("%s\n", scale);
1429 else if (i < res - 16 && strncmp(&buffer[i], "X-SLP-Removable=", 16) == 0)
1431 for (j = 0; j < res; j ++)
1433 if (buffer[i+j] == '\n' || buffer[i+j] == '\t')
1435 LOGI("removable :::: ");
1436 strncpy(removable, &(buffer[i+16]), j-16);
1437 LOGI("%s\n", removable);
1443 else if (i < res - 8 && (strncmp(&buffer[i], "Comment=", 8) == 0 || strncmp(&buffer[i], "comment=", 8) == 0))
1445 for (j = 0; j < res; j ++)
1447 if (buffer[i+j] == '\n' || buffer[i+j] == '\t')
1449 LOGI("comments :::: ");
1450 strncpy(comment, &(buffer[i+8]), j-8);
1451 LOGI("%s\n", comment);
1463 int get_camera_count()
1468 char buf[BUFFER_MAX];
1470 fp = fopen(CAMCORDER_FILE, "r");
1473 size = strlen(CAMERA_COUNT_STR);
1475 while(fgets(buf, BUFFER_MAX, fp) != NULL)
1477 if(strncmp(buf, CAMERA_COUNT_STR, size) == 0) {
1478 sscanf(buf, CAMERA_COUNT_STR " = %d", &count);
1491 static int get_device_network_type(char* buf, int buflen)
1496 system_info_get_platform_bool("tizen.org/feature/network.telephony.service.cdma", &bool_var);
1497 if(bool_var) len += sprintf(buf + len, "CDMA,");
1498 system_info_get_platform_bool("tizen.org/feature/network.telephony.service.edge", &bool_var);
1499 if(bool_var) len += sprintf(buf + len, "EDGE,");
1500 system_info_get_platform_bool("tizen.org/feature/network.telephony.service.gprs", &bool_var);
1501 if(bool_var) len += sprintf(buf + len, "GPRS,");
1502 system_info_get_platform_bool("tizen.org/feature/network.telephony.service.gsm", &bool_var);
1503 if(bool_var) len += sprintf(buf + len, "GSM,");
1504 system_info_get_platform_bool("tizen.org/feature/network.telephony.service.hsdpa", &bool_var);
1505 if(bool_var) len += sprintf(buf + len, "HSDPA,");
1506 system_info_get_platform_bool("tizen.org/feature/network.telephony.service.hspa", &bool_var);
1507 if(bool_var) len += sprintf(buf + len, "HSPA,");
1508 system_info_get_platform_bool("tizen.org/feature/network.telephony.service.hsupa", &bool_var);
1509 if(bool_var) len += sprintf(buf + len, "HSUPA,");
1510 system_info_get_platform_bool("tizen.org/feature/network.telephony.service.umts", &bool_var);
1511 if(bool_var) len += sprintf(buf + len, "UMTS,");
1512 system_info_get_platform_bool("tizen.org/feature/network.telephony.service.lte", &bool_var);
1513 if(bool_var) len += sprintf(buf + len, "LTE,");
1522 static int get_device_availability_info(char* buf, int buflen)
1524 int camera_count = 0;
1525 bool blue_support = false;
1526 bool gps_support = false;
1527 bool wifi_support = false;
1528 char* networktype = NULL;
1530 char network_type[128];
1533 system_info_get_platform_bool("tizen.org/feature/network.bluetooth", &blue_support);
1534 camera_count = get_camera_count();
1535 system_info_get_platform_bool("tizen.org/feature/location.gps", &gps_support);
1536 network_len = get_device_network_type(networktype, 128);
1537 system_info_get_platform_bool("tizen.org/feature/network.wifi", &wifi_support);
1539 loglen += sprintf(buf, "%d`,%d`,%d`,%d`,",
1545 if(network_type != NULL && network_len > 0) {
1546 loglen += sprintf(buf + loglen, "%s", networktype);
1553 int get_device_info(char* buffer, int buffer_len)
1557 char width[BUFFER_MAX];
1558 char height[BUFFER_MAX];
1559 char theme[BUFFER_MAX];
1560 char version[BUFFER_MAX];
1561 char scale[BUFFER_MAX];
1562 char removable[BUFFER_MAX];
1563 char comment[BUFFER_MAX * 2];
1565 memset(width, 0, sizeof(width));
1566 memset(height, 0, sizeof(height));
1567 memset(theme, 0, sizeof(theme));
1568 memset(version, 0, sizeof(version));
1569 memset(scale, 0, sizeof(scale));
1570 memset(removable, 0, sizeof(removable));
1571 memset(comment, 0, sizeof(comment));
1573 res += sprintf(buffer, "%lu`,%d`,", get_system_total_memory(), get_total_drive());
1574 res += get_device_availability_info(buffer + res, buffer_len - res);
1575 res += sprintf(buffer + res, "`,%d", get_max_brightness());
1577 res += sprintf(buffer + res, "`,`,`,`,`,`,`,");
1578 // res += sprintf(buffer + res, "`,%s`,%s`,%s`,%s`,%s`,%s`,%s", width, height, theme, version, scale, removable, comment);
1583 int update_cpus_info(int event_num, float elapsed)
1587 // calculate for system cpu load
1589 for(i = 0; i < num_of_cpu; i++)
1591 for(i = num_of_cpu; i <= num_of_cpu; i++)
1594 LOGI_th_samp("CPU #%d\n", i);
1595 cpuptr = &(cpus[i]);
1597 if(cpuptr->cur_load_index == event_num)
1599 if(cpuptr->sav_load_index == event_num - 1) // previous sampling is just before 1 period
1601 cpuptr->idle_ticks = cpuptr->i - cpuptr->i_sav;
1602 if(unlikely(cpuptr->idle_ticks < 0))
1604 cpuptr->idle_ticks = 0;
1606 cpuptr->total_ticks = (cpuptr->u - cpuptr->u_sav) +
1607 (cpuptr->s - cpuptr->s_sav) +
1608 (cpuptr->n - cpuptr->n_sav) +
1609 cpuptr->idle_ticks +
1610 (cpuptr->w - cpuptr->w_sav) +
1611 (cpuptr->x - cpuptr->x_sav) +
1612 (cpuptr->y - cpuptr->y_sav) +
1613 (cpuptr->z - cpuptr->z_sav);
1614 if(cpuptr->total_ticks < MIN_TOTAL_TICK)
1616 cpuptr->cpu_usage = 0.0f;
1620 cpuptr->cpu_usage = (1.0f - ((float)cpuptr->idle_ticks /
1621 (float)cpuptr->total_ticks)) * 100.0f;
1623 // if(i != num_of_cpu)
1625 // idle_tick_sum += cpuptr->idle_ticks;
1626 // total_tick_sum += cpuptr->total_ticks;
1628 LOGI_th_samp("System cpu usage log : %d, %Ld, %Ld\n",
1629 i, cpuptr->idle_ticks, cpuptr->total_ticks);
1630 if(unlikely(cpuptr->cpu_usage < 0))
1632 cpuptr->cpu_usage = 0.0f;
1635 else // previous sampling is not just before 1 period
1637 // assume non idle ticks happen in 1 profiling period
1638 // because sampling is not available just before 1 profiling period
1639 cpuptr->idle_ticks = (cpuptr->u - cpuptr->u_sav) +
1640 (cpuptr->s - cpuptr->s_sav) +
1641 (cpuptr->n - cpuptr->n_sav) +
1642 (cpuptr->w - cpuptr->w_sav) +
1643 (cpuptr->x - cpuptr->x_sav) +
1644 (cpuptr->y - cpuptr->y_sav) +
1645 (cpuptr->z - cpuptr->z_sav);
1646 cpuptr->total_ticks = (long long)(Hertz * elapsed);
1647 if(unlikely(cpuptr->total_ticks < 1))
1648 cpuptr->total_ticks = 1;
1649 cpuptr->cpu_usage = ((float)cpuptr->idle_ticks /
1650 (float)cpuptr->total_ticks) * 100.0f;
1651 if(unlikely(cpuptr->cpu_usage > 100.0f))
1653 cpuptr->cpu_usage = 100.0f;
1658 cpuptr->u_sav = cpuptr->u;
1659 cpuptr->s_sav = cpuptr->s;
1660 cpuptr->n_sav = cpuptr->n;
1661 cpuptr->i_sav = cpuptr->i;
1662 cpuptr->w_sav = cpuptr->w;
1663 cpuptr->x_sav = cpuptr->x;
1664 cpuptr->y_sav = cpuptr->y;
1665 cpuptr->z_sav = cpuptr->z;
1666 cpuptr->sav_load_index = cpuptr->cur_load_index;
1670 cpuptr->cpu_usage = 0.0f;
1674 // calculate for cpu core load that failed to get tick information
1678 LOGI("ticks1 : %Ld, %Ld\n", idle_tick_sum, total_tick_sum);
1679 idle_tick_sum = cpus[num_of_cpu].idle_ticks - idle_tick_sum;
1680 total_tick_sum = cpus[num_of_cpu].total_ticks - total_tick_sum;
1681 LOGI("ticks2 : %Ld, %Ld\n", idle_tick_sum, total_tick_sum);
1682 if(total_tick_sum >= MIN_TICKS_FOR_LOAD)
1683 sys_usage = (1.0f - ((float)idle_tick_sum / (float)total_tick_sum)) * 100.0f;
1686 if(sys_usage < 0.0f) sys_usage = 0.0f;
1687 else if(sys_usage > 100.0f) sys_usage = 100.0f;
1689 for(i = 0; i < num_of_cpu; i++)
1691 if(failed_cpu & (1 << i))
1693 cpus[i].cpu_usage = sys_usage;
1701 int fill_system_processes_info(float factor, struct system_info_t * sys_info)
1707 unsigned long virtual = 0;
1708 unsigned long resident = 0;
1709 unsigned long shared = 0;
1710 unsigned long pssmem = 0;
1712 float app_cpu_usage = 0.0;
1714 LOGI_th_samp("prochead = %X\n", (unsigned int)prochead);
1715 for(proc = prochead; proc != NULL; proc = proc->next)
1717 //increment process count
1718 sys_info->count_of_processes++; //maybe wrong
1720 sys_info->process_load = malloc (
1721 sys_info->count_of_processes *
1722 sizeof(*sys_info->process_load)
1725 for(proc = prochead; proc != NULL; proc = proc->next)
1727 LOGI_th_samp("proc#%d (%d %d),(%d %d) (%d) %f\n",
1729 (unsigned int)proc->proc_data.utime, (unsigned int)proc->proc_data.stime ,
1730 (unsigned int)proc->saved_utime, (unsigned int)proc->saved_stime,
1731 (int)(proc->proc_data.utime + proc->proc_data.stime - proc->saved_utime - proc->saved_stime),
1733 proc->saved_utime + proc->saved_stime -
1734 proc->proc_data.utime - proc->proc_data.stime
1736 thread_load = (float)(proc->proc_data.utime + proc->proc_data.stime -
1737 proc->saved_utime - proc->saved_stime) * factor;
1739 if(thread_load > 100.0f)
1740 thread_load = 100.0f;
1742 //num_thread += proc->proc_data.numofthread;
1743 virtual += proc->proc_data.vir_mem; // Byte
1744 resident += (proc->proc_data.res_memblock * 4); // KByte
1745 pssmem += (proc->proc_data.pss); // KByte
1746 shared += (proc->proc_data.sh_mem); // KByte
1747 ticks += (proc->proc_data.utime + proc->proc_data.stime -
1748 proc->saved_utime - proc->saved_stime);
1750 proc->saved_utime = proc->proc_data.utime;
1751 proc->saved_stime = proc->proc_data.stime;
1754 sys_info->process_load[i].id = proc->proc_data.pid;
1755 sys_info->process_load[i].load = thread_load;
1760 app_cpu_usage = (float)ticks * factor;
1761 if(app_cpu_usage > 100.0f)
1762 app_cpu_usage = 100.0f;
1763 resident = resident * 1024; // change to Byte
1764 pssmem = pssmem * 1024; // change to Byte
1765 shared = shared * 1024; // change to Byte
1767 sys_info->virtual_memory = virtual;
1768 sys_info->resident_memory = resident;
1769 sys_info->shared_memory = shared;
1770 sys_info->pss_memory = pssmem;
1772 sys_info->app_cpu_usage = app_cpu_usage;
1778 // fill threads information
1779 int fill_system_threads_info(float factor, struct system_info_t * sys_info)
1784 for(proc = thread_prochead; proc != NULL; proc = proc->next)
1785 //increment thread count
1786 sys_info->count_of_threads++; //maybe wrong
1788 /* LOGI_th_samp("thread load\n"); */
1789 struct thread_info_t *pthread;
1790 if (sys_info->count_of_threads != 0)
1792 sys_info->thread_load = malloc( sys_info->count_of_threads * sizeof(*sys_info->thread_load) );
1793 pthread = sys_info->thread_load;
1796 for(proc = thread_prochead; proc != NULL; proc = proc->next)
1798 thread_load = (float)(proc->proc_data.utime + proc->proc_data.stime -
1799 proc->saved_utime - proc->saved_stime)
1801 if(thread_load > 100.0f)
1802 thread_load = 100.0f;
1804 pthread->pid = proc->proc_data.pid;
1805 pthread->load = thread_load;
1808 // sprintf(thread_loadtmpbuf, "%d,%.1f,", proc->proc_data.pid, thread_load);
1809 // strcat(thread_loadbuf, thread_loadtmpbuf);
1811 proc->saved_utime = proc->proc_data.utime;
1812 proc->saved_stime = proc->proc_data.stime;
1818 //fill system cpu information
1819 int fill_system_cpu_info(struct system_info_t *sys_info)
1821 float sys_usage = 0.0f;
1824 // calculate for whole cpu load by average all core load
1825 LOGI_th_samp("calculate for whole cpu load num_of_cpu=%d\n", num_of_cpu);
1826 for(i = 0 ; i < num_of_cpu; i++)
1827 sys_usage += cpus[i].cpu_usage;
1831 if (num_of_cpu != 0)
1833 sys_info->cpu_load = malloc( num_of_cpu * sizeof(*sys_info->cpu_load) );
1834 pcpu_usage = sys_info->cpu_load;
1835 for(i = 0; i < num_of_cpu; i++)
1837 LOGI_th_samp("cpu#%d : %.1f\n" , i, cpus[i].cpu_usage);
1838 *pcpu_usage = cpus[i].cpu_usage;
1843 //fill CPU frequency
1844 sys_info->cpu_frequency = malloc(num_of_cpu * sizeof(float));
1845 if (!sys_info->cpu_frequency) {
1846 LOGE("Cannot alloc cpu freq\n");
1849 get_cpu_frequency(sys_info->cpu_frequency);
1855 //fill cpu frequency based on cpu tick count in different cpu frequence states
1856 int fill_cpu_frequecy(int event_num)
1858 // calculate for system cpu frequency
1859 float sys_usage = 0.0f;
1860 uint64_t ticks = 0, freqsum = 0;
1864 for(i = 0; i < num_of_cpu; i++)
1866 cpuptr = &(cpus[i]);
1868 if(cpuptr->cur_freq_index == event_num)
1870 if(cpuptr->sav_freq_index == event_num - 1)
1872 for(j = 0; j < num_of_freq; j++)
1874 freqsum += (cpuptr->pfreq[j].freq *
1875 (cpuptr->pfreq[j].tick - cpuptr->pfreq[j].tick_sav));
1876 ticks += (cpuptr->pfreq[j].tick - cpuptr->pfreq[j].tick_sav);
1883 for(j = 0; j < num_of_freq; j++)
1885 cpuptr->pfreq[j].tick_sav = cpuptr->pfreq[j].tick; // restore last tick value
1887 cpuptr->sav_freq_index = cpuptr->cur_freq_index;
1893 if(sys_usage == 0.0f)
1894 sys_usage = (float)freqsum / (float)ticks;
1895 // TODO use sys_usage as cpu #i core freq
1899 //freqbufpos += sprintf(freqbuf + freqbufpos, "%.0f,", sys_usage);
1909 static void skip_lines(FILE * fp, unsigned int count)
1911 char *buffer = NULL;
1914 for (index = 0; index != count; ++index)
1915 getline(&buffer, &buflen, fp);
1919 static void skip_tokens(FILE * fp, unsigned int count)
1923 for (index = 0; index != count; ++index)
1927 static void init_network_stat()
1929 manager.fd.networkstat = fopen("/proc/net/dev", "r");
1932 static void get_network_stat(uint32_t *recv, uint32_t *send)
1934 FILE *fp = manager.fd.networkstat;
1935 uintmax_t irecv, isend;
1944 skip_lines(fp, 2); /* strip header */
1946 while (fscanf(fp, "%s", ifname) != EOF)
1947 if (strcmp("lo:", ifname)) {
1948 fscanf(fp, "%" SCNuMAX, &irecv);
1951 fscanf(fp, "%" SCNuMAX, &isend);
1957 skip_tokens(fp, 16);
1960 static void peek_network_stat_diff(uint32_t *recv, uint32_t *send)
1962 static uint32_t irecv_old, isend_old;
1965 get_network_stat(recv, send);
1968 *recv = val_diff(tmp, irecv_old);
1972 *send = val_diff(tmp, isend_old);
1977 static void init_disk_stat(void)
1979 manager.fd.diskstats = fopen("/proc/diskstats", "r");
1982 //function return partition sector size
1985 // <size> if no errors
1986 static int get_partition_sector_size(const char * partition_name)
1990 char sec_size_buff[LARGE_BUFFER];
1992 sprintf(sec_size_buff, "/sys/block/%s/queue/hw_sector_size", partition_name);
1993 sfp = fopen(sec_size_buff, "r");
1995 LOGE("cannot detect sector size for <%s> (%s)\n",
1996 partition_name, sec_size_buff);
1999 fscanf(sfp, "%d", &sec_size);
2002 LOGE("cannot detect sector size for <%s> (%s)\n",
2003 partition_name, sec_size_buff);
2010 static void get_disk_stat(uint32_t *reads, uint32_t *sec_reads,
2011 uint32_t *writes, uint32_t *sec_writes)
2013 enum { partition_name_maxlength = 128 };
2014 FILE *fp = manager.fd.diskstats;
2015 char master_partition[partition_name_maxlength] = { 0 };
2017 *reads = *writes = 0;
2018 *sec_reads = *sec_writes = 0;
2028 char partition[partition_name_maxlength];
2029 uintmax_t preads, pwrites;
2030 uintmax_t psec_read, psec_write;
2032 fscanf(fp, "%s", partition);
2033 if (*master_partition
2034 && !strncmp(master_partition, partition,
2035 strlen(master_partition))) {
2037 skip_tokens(fp, 11);
2039 // FIXME it is not good way call this func
2040 // each time to get partition sector size
2041 /*sec_size = get_partition_sector_size(partition);
2045 LOGE("get RW error\n");
2051 fscanf(fp, "%" SCNuMAX, &preads);
2054 fscanf(fp, "%" SCNuMAX, &psec_read);
2057 fscanf(fp, "%" SCNuMAX, &pwrites);
2060 fscanf(fp, "%" SCNuMAX, &psec_write);
2063 memcpy(master_partition, partition,
2064 partition_name_maxlength);
2065 // FIXME rw size is in sectors
2066 // actualy different disks - different partition sector size (?)
2067 // maybe need convert to bytes like this:
2068 //*read += pread * sec_size;
2069 //*write += pwrite * sec_size;
2071 *reads += (uint32_t)preads;
2072 *writes += (uint32_t)pwrites;
2074 *sec_reads += (uint32_t)psec_read;
2075 *sec_writes += (uint32_t)psec_write;
2081 static void peek_disk_stat_diff(uint32_t *reads, uint32_t *sec_reads,
2082 uint32_t *writes, uint32_t *sec_writes)
2084 static uint32_t reads_old;
2085 static uint32_t sec_reads_old;
2086 static uint32_t writes_old;
2087 static uint32_t sec_writes_old;
2092 get_disk_stat(reads, sec_reads, writes, sec_writes);
2095 *reads = val_diff(tmp, reads_old);
2099 *writes = val_diff(tmp, writes_old);
2103 *sec_reads = val_diff(tmp, sec_reads_old);
2104 sec_reads_old = tmp;
2107 *sec_writes = val_diff(tmp, sec_writes_old);
2108 sec_writes_old = tmp;
2112 static float get_elapsed(void)
2114 static struct timeval old_time = {0, 0};
2115 struct timeval current_time;
2118 gettimeofday(¤t_time, NULL);
2119 elapsed = (current_time.tv_sec - old_time.tv_sec) +
2120 ((float)(current_time.tv_usec - old_time.tv_usec) / 1000000.0f);
2121 old_time.tv_sec = current_time.tv_sec;
2122 old_time.tv_usec = current_time.tv_usec;
2127 static float get_factor(float elapsed)
2129 return 100.0f / ((float)Hertz * elapsed * num_of_cpu);
2132 static uint64_t read_int64_from_file(const char *fname)
2134 FILE *fp = fopen(fname, "r");
2138 if (fscanf(fp, "%lld", &value) != 1)
2144 #define swap_sysfs_relpath(x) ("/sys/kernel/debug/swap/energy/" #x)
2145 #define swap_read_int64(x) (read_int64_from_file(swap_sysfs_relpath(x)))
2146 static uint64_t get_system_lcd_energy()
2148 static const char *PROC_LCD_ENERGY_FILES_GLOBPATTERN =
2149 "/sys/kernel/debug/swap/energy/lcd/*/system";
2150 uint64_t sum_energy = 0;
2153 const int err = glob(PROC_LCD_ENERGY_FILES_GLOBPATTERN, 0,
2157 LOG_ONCE_E("Globbing for LCD failed with error %d\n", err);
2161 for (i = 0; i < glob_buf.gl_pathc; ++i)
2162 sum_energy += read_int64_from_file(glob_buf.gl_pathv[i]);
2164 globfree(&glob_buf);
2168 * Calculates difference between current and previous sample (system).
2169 * Stores mutable state in static variables.
2171 static uint32_t pop_sys_energy_per_device(enum supported_device dev)
2173 static uint64_t cpu_old, flash_old, lcd_old;
2174 uint64_t cpu_new, flash_new, lcd_new;
2175 uint64_t cpu_diff, flash_diff, lcd_diff;
2179 cpu_new = swap_read_int64(cpu_idle/system) +
2180 swap_read_int64(cpu_running/system);
2181 cpu_diff = val_diff(cpu_new, cpu_old);
2183 return (uint32_t)cpu_diff;
2186 flash_new = swap_read_int64(flash_read/system) +
2187 swap_read_int64(flash_write/system);
2188 flash_diff = val_diff(flash_new, flash_old);
2189 flash_old = flash_new;
2190 return (uint32_t)flash_diff;
2192 lcd_new = get_system_lcd_energy();
2193 lcd_diff = val_diff(lcd_new, lcd_old);
2195 return (uint32_t)lcd_diff;
2197 assert(0 && "Unknown device. This should not happen");
2202 // Calculates difference between current and previous sample (app).
2203 // Stores mutable state in static variables.
2204 static uint32_t pop_app_energy_per_device(enum supported_device dev)
2206 static uint64_t cpu_old, flash_old;
2207 uint64_t cpu_new, flash_new;
2208 uint64_t cpu_diff, flash_diff;
2212 cpu_new = swap_read_int64(cpu_running/apps);
2213 cpu_diff = val_diff(cpu_new, cpu_old);
2215 return (uint32_t)cpu_diff;
2217 flash_new = swap_read_int64(flash_read/apps) +
2218 swap_read_int64(flash_write/apps);
2219 flash_diff = val_diff(flash_new, flash_old);
2220 flash_old = flash_new;
2221 return (uint32_t)flash_diff;
2224 * Per-application energy accounting
2225 * is not supported for LCD.
2229 assert(0 && "Unknown device. This should not happen");
2234 int get_pid_array(int arr[], const int n)
2236 DIR *d = opendir("/proc");
2237 struct dirent *dirent;
2239 pid_t self_pid = getpid();
2242 LOGW("Cannot open /proc dir (%s)\n", strerror(errno));
2246 while ((dirent = readdir(d)) && (count < n)) {
2247 if (dirent->d_type == DT_DIR) {
2249 pid_t pid = strtol(dirent->d_name, &tmp, 10);
2250 if (*tmp == '\0' && pid != self_pid)
2260 static pid_t get_first_target_process(void)
2265 for (i = 0; i < MAX_TARGET_COUNT; i++) {
2266 if (manager.target[i].socket != -1 &&
2267 manager.target[i].pid != -1) {
2268 pid = manager.target[i].pid;
2272 /* Calling code must guarantee this */
2278 // return log length (>0) for normal case
2279 // return negative value for error
2280 int get_system_info(struct system_info_t *sys_info, int* pidarray, int pidcount)
2282 static int event_num = 0;
2283 uint64_t sysmemtotal = 0;
2284 uint64_t sysmemused = 0;
2289 LOGI_th_samp("start\n");
2290 LOGI_th_samp("PID count : %d\n", pidcount);
2292 memset(sys_info, 0, sizeof(*sys_info));
2294 // common (cpu, processes, memory)
2295 if (IS_OPT_SET(FL_CPU) ||
2296 IS_OPT_SET(FL_PROCESSES) ||
2297 IS_OPT_SET(FL_MEMORY)) {
2298 if (update_process_data(pidarray, pidcount, PROCDATA_STAT) < 0) {
2299 LOGE("Failed to update process stat data\n");
2303 * This position is optimized position of timestamp. Just
2304 * before get system cpu data and just after get process cpu
2305 * data because cpu data is changed so fast and variance is so
2308 elapsed = get_elapsed(); /* DO NOT MOVE THIS SENTENCE! */
2309 factor = get_factor(elapsed);
2311 if (update_system_cpu_data(event_num) < 0) {
2312 LOGE("Failed to update system cpu data\n");
2316 if (update_system_cpu_frequency(event_num) < 0) {
2317 LOGE("Failed to update system cpu freq data\n");
2322 * Memory data is changed slowly and variance is not
2323 * remarkable, so memory data is less related with timestamp
2326 if (update_process_data(pidarray, pidcount, PROCDATA_SMAPS) < 0) {
2327 LOGE("Failed to update process smaps data\n");
2332 if (update_thread_data(get_first_target_process()) < 0) {
2333 LOGE("Failed to update thread stat data\n");
2337 if (update_system_memory_data(&sysmemtotal, &sysmemused) < 0) {
2338 LOGE("Failed to update system memory data\n");
2342 if (update_cpus_info(event_num, elapsed) < 0) {
2343 LOGE("Failed to update cpus info\n");
2347 /* calculate process load, memory, app_cpu_usage */
2348 if (fill_system_processes_info(factor, sys_info) < 0) {
2349 LOGE("Failed to fill processes info\n");
2353 /* calculate thread load */
2354 if (fill_system_threads_info(factor, sys_info) < 0) {
2355 LOGE("Failed to fill threads info\n");
2359 if (fill_system_cpu_info(sys_info) < 0) {
2360 LOGE("Failed to fill threads info\n");
2365 if (IS_OPT_SET(FL_MEMORY)) {
2366 sys_info->total_alloc_size = get_total_alloc_size();
2367 sys_info->system_memory_total = sysmemtotal;
2368 sys_info->system_memory_used = sysmemused;
2371 LOGI_th_samp("Fill result structure\n");
2373 if (IS_OPT_SET(FL_DISK)) {
2374 sys_info->total_used_drive = get_total_used_drive();
2375 peek_disk_stat_diff(&sys_info->disk_reads,
2376 &sys_info->disk_sectors_read,
2377 &sys_info->disk_writes,
2378 &sys_info->disk_sectors_write);
2381 if (IS_OPT_SET(FL_NETWORK))
2382 peek_network_stat_diff(&sys_info->network_send_size,
2383 &sys_info->network_receive_size);
2385 if (IS_OPT_SET(FL_DEVICE)) {
2386 sys_info->wifi_status = get_wifi_status();
2387 sys_info->bt_status = get_bt_status();
2388 sys_info->gps_status = get_gps_status();
2389 sys_info->brightness_status = get_brightness_status();
2390 sys_info->camera_status = get_camera_status();
2391 sys_info->sound_status = get_sound_status();
2392 sys_info->audio_status = get_audio_status();
2393 sys_info->vibration_status = get_vibration_status();
2394 sys_info->voltage_status = get_voltage_status();
2395 sys_info->rssi_status = get_rssi_status();
2396 sys_info->video_status = get_video_status();
2397 sys_info->call_status = get_call_status();
2398 sys_info->dnet_status = get_dnet_status();
2401 if (IS_OPT_SET(FL_ENERGY)) {
2403 sys_info->energy = 0; /* not implemented */
2404 for (i = 0; i != supported_devices_count; ++i) {
2405 sys_info->energy_per_device[i] =
2406 pop_sys_energy_per_device(i);
2407 sys_info->app_energy_per_device[i] = (i == DEVICE_LCD)
2408 ? sys_info->energy_per_device[i]
2409 : pop_app_energy_per_device(i);
2413 #ifdef THREAD_SAMPLING_DEBUG
2414 print_sys_info(sys_info);
2418 LOGI_th_samp("exit\n");
2422 /* Some data corrupted. Free allocated data. */
2423 reset_system_info(sys_info);
2424 LOGI_th_samp("fail exit\n");
2428 int initialize_system_info()
2432 num_of_cpu = sysconf(_SC_NPROCESSORS_CONF);
2435 Hertz = sysconf(_SC_CLK_TCK);
2436 LOGI("Hertz : %d\n", Hertz);
2440 cpus = (CPU_t*) calloc((num_of_cpu + 1), sizeof(CPU_t));
2443 for(i = 0; i <= num_of_cpu; i++)
2445 cpus[i].cur_load_index = cpus[i].sav_load_index = -1;
2446 cpus[i].cur_freq_index = cpus[i].sav_freq_index = -1;
2451 LOGE("Failed to alloc memory for cpu information\n");
2458 int finalize_system_info()
2464 for(i = 0; i < num_of_cpu; i++)
2466 if(cpus[i].pfreq != NULL)
2467 free(cpus[i].pfreq);
2477 static void test_and_close(int *fd)
2484 static void ftest_and_close(FILE **fd)
2492 #define str(x) strr(x)
2493 #define dtest_and_close(fd) do {LOGI("CLOSE " str(fd) "\n");test_and_close(fd);} while(0)
2494 #define dftest_and_close(fd) do {LOGI("CLOSE " str(fd) "\n");ftest_and_close(fd);} while(0)
2495 void close_system_file_descriptors()
2497 dtest_and_close(&manager.fd.brightness);
2498 dtest_and_close(&manager.fd.voltage);
2499 dtest_and_close(&manager.fd.procmeminfo);
2501 dftest_and_close(&manager.fd.video);
2502 dftest_and_close(&manager.fd.procstat);
2503 dftest_and_close(&manager.fd.networkstat);
2504 dftest_and_close(&manager.fd.diskstats);
2507 int init_system_file_descriptors()
2510 init_brightness_status();
2511 init_voltage_status();
2512 init_update_system_memory_data();
2514 init_video_status();
2515 init_system_cpu_data();
2516 init_network_stat();
2519 if (manager.fd.brightness < 0)
2520 LOGW("brightness file not found\n");
2521 if (manager.fd.voltage < 0)
2522 LOGW("voltage file not found\n");
2523 if (manager.fd.procmeminfo < 0)
2524 LOGW("procmeminfo file not found\n");
2526 if (manager.fd.video == NULL)
2527 LOGW("video file not found\n");
2528 if (manager.fd.procstat == NULL)
2529 LOGW("procstat file not found\n");
2530 if (manager.fd.networkstat == NULL)
2531 LOGW("networkstat file not found\n");
2532 if (manager.fd.diskstats == NULL)
2533 LOGW("diskstat file not found\n");
2537 //CMD SOCKET FUNCTIONS
2538 int fill_target_info(struct target_info_t *target_info)
2540 /* system_info_get_value_bool() changes only 1 byte
2541 so we need to be sure that the integer as a whole is correct */
2542 target_info->bluetooth_supp = 0;
2543 target_info->gps_supp = 0;
2544 target_info->wifi_supp = 0;
2545 target_info->camera_count = 0;
2546 target_info->network_type[0] = 0;
2548 target_info->sys_mem_size = get_system_total_memory();
2549 target_info->storage_size = stat_get_storageinfo(FSINFO_TYPE_TOTAL) *
2552 system_info_get_platform_bool("tizen.org/feature/network.bluetooth",
2553 (_Bool *)&target_info->bluetooth_supp);
2556 system_info_get_platform_bool("tizen.org/feature/location.gps",
2557 (_Bool *)&target_info->gps_supp);
2559 system_info_get_platform_bool("tizen.org/feature/network.wifi",
2560 (_Bool *)&target_info->wifi_supp);
2562 target_info->camera_count = get_camera_count();
2564 get_device_network_type(target_info->network_type, NWTYPE_SIZE);
2567 target_info->max_brightness = get_max_brightness();
2568 target_info->cpu_core_count = sysconf(_SC_NPROCESSORS_CONF);
2572 int sys_stat_prepare(void)
2574 uint32_t reads, writes, sec_reads, sec_writes;
2575 uint32_t recv, send;
2577 peek_disk_stat_diff(&reads, &writes, &sec_reads, &sec_writes);
2578 peek_network_stat_diff(&recv, &send);
2583 static uint32_t msg_data_payload_length(const struct system_info_t *sys_info)
2585 uint32_t len = sizeof(*sys_info);
2587 /* num_of_cpu is unknown at compile time */
2588 len += 2 * num_of_cpu * sizeof(float);
2590 /* subtract pointers */
2591 len -= sizeof(sys_info->cpu_frequency) + sizeof(sys_info->cpu_load);
2592 len -= sizeof(sys_info->thread_load) + sizeof(sys_info->process_load);
2594 if (IS_OPT_SET(FL_CPU))
2595 len += sys_info->count_of_threads *
2596 sizeof(*sys_info->thread_load);
2598 if (IS_OPT_SET(FL_PROCESSES))
2599 len += sys_info->count_of_processes *
2600 sizeof(*sys_info->process_load);
2605 struct msg_data_t *pack_system_info(struct system_info_t *sys_info)
2607 const int len = msg_data_payload_length(sys_info);
2608 struct msg_data_t *msg = NULL;
2612 msg = malloc(MSG_DATA_HDR_LEN + len);
2614 LOGE("Cannot alloc message: %d bytes\n", len);
2618 fill_data_msg_head(msg, NMSG_SYSTEM, 0, len);
2622 if (IS_OPT_SET(FL_CPU)) {
2623 pack_float(p, sys_info->app_cpu_usage);
2625 for (i = 0; i < num_of_cpu; i++) {
2626 if (sys_info->cpu_frequency)
2627 pack_float(p, sys_info->cpu_frequency[i]);
2632 for (i = 0; i < num_of_cpu; i++) {
2633 if (sys_info->cpu_load)
2634 pack_float(p, sys_info->cpu_load[i]);
2639 pack_int32(p, sys_info->count_of_threads);
2640 for (i = 0; i < sys_info->count_of_threads; i++) {
2641 if (sys_info->thread_load) {
2642 pack_int32(p, sys_info->thread_load[i].pid);
2643 pack_float(p, sys_info->thread_load[i].load);
2650 pack_float(p, 0.0); /* pack app_cpu_usage */
2652 for (i = 0; i < num_of_cpu; i++) {
2653 pack_float(p, 0.0); /* pack cpu_frequency */
2654 pack_float(p, 0.0); /* pack cpu_load */
2657 pack_int32(p, 0); /* pack count_of_threads */
2661 if (IS_OPT_SET(FL_PROCESSES)) {
2662 pack_int32(p, sys_info->count_of_processes);
2663 for (i = 0; i < sys_info->count_of_processes; i++) {
2664 if (sys_info->process_load) {
2665 pack_int32(p, sys_info->process_load[i].id);
2666 pack_float(p, sys_info->process_load[i].load);
2673 pack_int32(p, 0); /* pack count_of_processes */
2677 if (IS_OPT_SET(FL_MEMORY)) {
2678 pack_int32(p, sys_info->virtual_memory);
2679 pack_int32(p, sys_info->resident_memory);
2680 pack_int32(p, sys_info->shared_memory);
2681 pack_int32(p, sys_info->pss_memory);
2682 pack_int64(p, sys_info->total_alloc_size);
2683 pack_int64(p, sys_info->system_memory_total);
2684 pack_int64(p, sys_info->system_memory_used);
2686 pack_int32(p, 0); /* pack virtual_memory */
2687 pack_int32(p, 0); /* pack resident_memory */
2688 pack_int32(p, 0); /* pack shared_memory */
2689 pack_int32(p, 0); /* pack pss_memory */
2690 pack_int64(p, (uint64_t) 0); /* pack total_alloc_size */
2691 pack_int64(p, (uint64_t) 0); /* pack system_memory_total */
2692 pack_int64(p, (uint64_t) 0); /* pack system_memory_used */
2695 pack_int32(p, sys_info->total_used_drive);
2696 pack_int32(p, sys_info->disk_reads);
2697 pack_int32(p, sys_info->disk_sectors_read);
2698 pack_int32(p, sys_info->disk_writes);
2699 pack_int32(p, sys_info->disk_sectors_write);
2701 pack_int32(p, sys_info->network_send_size);
2702 pack_int32(p, sys_info->network_receive_size);
2704 pack_int32(p, sys_info->wifi_status);
2705 pack_int32(p, sys_info->bt_status);
2706 pack_int32(p, sys_info->gps_status);
2707 pack_int32(p, sys_info->brightness_status);
2708 pack_int32(p, sys_info->camera_status);
2709 pack_int32(p, sys_info->sound_status);
2710 pack_int32(p, sys_info->audio_status);
2711 pack_int32(p, sys_info->vibration_status);
2712 pack_int32(p, sys_info->voltage_status);
2713 pack_int32(p, sys_info->rssi_status);
2714 pack_int32(p, sys_info->video_status);
2715 pack_int32(p, sys_info->call_status);
2716 pack_int32(p, sys_info->dnet_status);
2718 pack_int32(p, sys_info->energy);
2719 for (i = 0; i != supported_devices_count; ++i)
2720 pack_int32(p, sys_info->energy_per_device[i]);
2721 for (i = 0; i != supported_devices_count; ++i)
2722 pack_int32(p, sys_info->app_energy_per_device[i]);