[FEATURE] Implement kernel -> user connection
[platform/core/system/swap-manager.git] / daemon / sys_stat.c
1 /*
2  *  DA manager
3  *
4  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  *
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>
13  *
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
17  *
18  * http://www.apache.org/licenses/LICENSE-2.0
19  *
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.
25  *
26  * Contributors:
27  * - S-Core Co., Ltd
28  * - Samsung RnD Institute Russia
29  *
30  */
31
32 #include <glob.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <stdbool.h>
37 #include <ctype.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <sys/time.h>
41 #include <sys/vfs.h>
42 #include <fcntl.h>
43 #include <unistd.h>
44 #include <dirent.h>
45 #include <errno.h>
46 #include <assert.h>
47 #include <inttypes.h>
48 #include <stdint.h>
49
50 #include "da_protocol.h"
51 #include "da_data.h"
52 #include "sys_stat.h"
53 #include "daemon.h"
54 #include "device_system_info.h"
55 #include "device_vconf.h"
56 #include "device_camera.h"
57 #include "debug.h"
58
59 // defines for runtime environment
60 #define FOR_EACH_CPU
61
62 #define BUFFER_MAX                      1024
63 #define LARGE_BUFFER            512
64 #define MIDDLE_BUFFER           256
65 #define SMALL_BUFFER            64
66 #define PROCPATH_MAX            32
67 #define STATUS_STRING_MAX       16
68 #define MAX_NUM_OF_FREQ         16
69
70 #define MEM_SLOT_TOTAL          0
71 #define MEM_SLOT_FREE           1
72 #define MEM_SLOT_BUFFER         2
73 #define MEM_SLOT_CACHED         3
74 #define MEM_SLOT_MAX            4
75
76 #define MIN_TICKS_FOR_LOAD      8
77 #define MIN_TOTAL_TICK          10
78 #define SYS_INFO_TICK           100     // TODO : change to (Hertz * profiling period)
79
80 #define CPUMHZ          "cpu MHz"
81 #define DA_PROBE_TIZEN_SONAME           "da_probe_tizen.so"
82 #define DA_PROBE_OSP_SONAME                     "da_probe_osp.so"
83
84 // define for correct difference of system feature vars
85 #define val_diff(v_new, v_old) ((v_new < v_old) ? v_new : v_new - v_old)
86
87 enum PROCESS_DATA
88 {
89         PROCDATA_STAT,
90         PROCDATA_SMAPS
91 };
92
93 // declared by greatim
94 static int Hertz = 0;
95 static int num_of_cpu = 0;
96 static int num_of_freq = 0;
97 static uint64_t mem_slot_array[MEM_SLOT_MAX];
98 static CPU_t* cpus = NULL;
99 static unsigned long probe_so_size = 0;
100
101
102 static int get_file_status_no_open(int pfd, const char *filename)
103 {
104         int status = 0;
105         char buf[STATUS_STRING_MAX];
106
107         if (unlikely(pfd < 0)) {
108                 // file is not open
109                 return 0;
110         }
111
112         lseek(pfd, 0, SEEK_SET);        // rewind to start of file
113
114         // read from file
115         if (unlikely(read(pfd, buf, STATUS_STRING_MAX) == -1))
116                 status =  -(errno);
117         else
118                 status = atoi(buf);
119
120         return status;
121 }
122 // daemon api : get status from file
123 // pfd must not be null
124 int get_file_status(int *pfd, const char *filename)
125 {
126         int status = 0;
127
128         if (likely(pfd != NULL)) {
129                 //open if is not open
130                 if (unlikely(*pfd < 0)) {
131                         // open file first
132                         *pfd = open(filename, O_RDONLY);
133                         if (unlikely(*pfd == -1)) {
134                                 /* This file may absent in the system */
135                                 return 0;
136                         }
137                 }
138
139                 if (unlikely(*pfd < 0)) {
140                         //file is open. lets read
141                         status = get_file_status_no_open(*pfd, filename);
142                 }
143
144         }
145
146         return status;
147 }
148
149 // =============================================================================
150 // device status information getter functions
151 // =============================================================================
152
153 static void init_brightness_status()
154 {
155 #ifdef DEVICE_ONLY
156         DIR *dir_info;
157         struct dirent *dir_entry;
158         char fullpath[PATH_MAX];
159
160         dir_info = opendir(BRIGHTNESS_PARENT_DIR);
161         if (dir_info != NULL) {
162                 while ((dir_entry = readdir(dir_info)) != NULL) {
163                         if (strcmp(dir_entry->d_name, ".") == 0 ||
164                             strcmp(dir_entry->d_name, "..") == 0)
165                                 continue;
166                         else { /* first directory */
167                                 sprintf(fullpath,
168                                         BRIGHTNESS_PARENT_DIR "/%s/"
169                                         BRIGHTNESS_FILENAME,
170                                         dir_entry->d_name);
171                                 get_file_status(&manager.fd.brightness,
172                                                 fullpath);
173                         }
174                 }
175                 closedir(dir_info);
176         } else {
177                 /* do nothing */
178         }
179 #else
180         get_file_status(&manager.fd.brightness, EMUL_BRIGHTNESSFD);
181 #endif
182 }
183
184 static int get_brightness_status()
185 {
186         return get_file_status_no_open(manager.fd.brightness, EMUL_BRIGHTNESSFD);
187 }
188
189 static int get_max_brightness()
190 {
191         int maxbrightnessfd = -1;
192         static int max_brightness = -1;
193
194         if (__builtin_expect(max_brightness < 0, 0)) {
195 #ifdef DEVICE_ONLY
196                 DIR* dir_info;
197                 struct dirent* dir_entry;
198                 char fullpath[PATH_MAX];
199
200                 dir_info = opendir(BRIGHTNESS_PARENT_DIR);
201                 if (dir_info != NULL) {
202                         while((dir_entry = readdir(dir_info)) != NULL) {
203                                 if (strcmp(dir_entry->d_name, ".") == 0 ||
204                                     strcmp(dir_entry->d_name, "..") == 0)
205                                         continue;
206                                 else { /* first */
207                                         sprintf(fullpath,
208                                                 BRIGHTNESS_PARENT_DIR "/%s/" MAX_BRIGHTNESS_FILENAME,
209                                                 dir_entry->d_name);
210                                         max_brightness = get_file_status(&maxbrightnessfd, fullpath);
211                                 }
212                         }
213                         closedir(dir_info);
214                 } else {
215                         // do nothing
216                 }
217 #else /* DEVICE_ONLY */
218                 max_brightness = get_file_status(&maxbrightnessfd, EMUL_MAX_BRIGHTNESSFD);
219 #endif /* DEVICE_ONLY */
220         }
221
222         if (maxbrightnessfd != -1)
223                 close(maxbrightnessfd);
224
225         return max_brightness;
226 }
227
228 static void init_video_status()
229 {
230         manager.fd.video = fopen(MFCFD, "r");
231 }
232
233 static int get_video_status()
234 {
235         int video_status = 0;
236         int ret;
237         FILE *video_fp = manager.fd.video;
238         char stat[256];
239
240         if (video_fp == NULL) // file is not open
241                 return 0;
242
243         rewind(video_fp);
244         fflush(video_fp);
245
246         ret = fscanf(video_fp, "%s", stat);
247
248         if (ret != EOF)
249                 if(strncmp(stat,"active",6) == 0)
250                         video_status = 1;
251
252         return video_status;
253 }
254
255 static void init_voltage_status()
256 {
257         get_file_status(&manager.fd.voltage, VOLTAGEFD);
258 }
259
260 static int get_voltage_status()
261 {
262         return get_file_status_no_open(manager.fd.voltage, VOLTAGEFD);
263 }
264
265 // =====================================================================
266 // cpu information getter functions
267 // =====================================================================
268 static void get_cpu_frequency(float *freqs)
269 {
270         char filename[MIDDLE_BUFFER];
271         char freq_str[SMALL_BUFFER];
272         FILE *f;
273         int cpu_n = 0;
274
275         //clean data array
276         for (cpu_n = 0; cpu_n < num_of_cpu; cpu_n++)
277                 freqs[cpu_n] = 0.0;
278
279         cpu_n = 0;
280         while (1) {
281                 //is CPU present
282                 snprintf(filename, MIDDLE_BUFFER,
283                          "/sys/devices/system/cpu/cpu%d/online", cpu_n);
284
285                 f = fopen(filename, "r");
286                 if (!f){
287                         LOGI_th_samp("file not found <%s\n>", filename);
288                         break;
289                 }
290                 fclose(f);
291
292                 //get CPU freq
293                 snprintf(filename, MIDDLE_BUFFER,
294                          "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_cur_freq", cpu_n);
295                 f = fopen(filename, "r");
296                 if (!f)
297                 {
298                         //core is disabled
299                         LOGI_th_samp("core #%d diasabled\n", cpu_n);
300                         freqs[cpu_n] = 0.0;
301                 } else {
302                         //core enabled, get frequency
303                         fscanf(f, "%s", freq_str);
304                         freqs[cpu_n] = atof(freq_str);
305                         LOGI_th_samp("core #%d freq = %.0f\n", cpu_n, freqs[cpu_n]);
306                         fclose(f);
307                 }
308
309                 //next core
310                 cpu_n++;
311
312         }
313 }
314
315 // ========================================================================
316 // get cpu and memory info for each process and whole system
317 // ========================================================================
318 typedef struct _proc_node {
319         proc_t proc_data;
320         unsigned long long saved_utime;
321         unsigned long long saved_stime;
322         int found;
323         struct _proc_node *next;
324 } procNode;
325
326 static procNode *prochead = NULL;
327 static procNode *thread_prochead = NULL;
328
329 static procNode* find_node(procNode *head, pid_t pid)
330 {
331         procNode *t = head;
332
333         while (t != NULL) {
334                 if (t->proc_data.pid == pid)
335                 {
336                         t->found = 1;
337                         break;
338                 }
339                 t = t->next;
340         }
341         return t;
342 }
343
344 static procNode* add_node(procNode **head, pid_t pid)
345 {
346         procNode *n;
347
348         n = (procNode *) malloc(sizeof(procNode));
349         if (n == NULL) {
350                 LOGE("Not enough memory, add cpu info node failied");
351                 return NULL;
352         }
353
354         n->proc_data.pid = pid;
355         n->found = 1;
356         n->next = *head;
357         *head = n;
358
359         return n;
360 }
361
362 static int del_node(procNode **head, pid_t pid)
363 {
364         procNode *t;
365         procNode *prev;
366
367         t = *head;
368         prev = NULL;
369 /*      LOGI("dell t=%d\n",t); */
370         while (t != NULL) {
371                 if (t->proc_data.pid == pid) {
372                         if (prev != NULL)
373                                 prev->next = t->next;
374                         else
375                                 *head = (*head)->next;
376                         free(t);
377                         break;
378                 }
379                 prev = t;
380                 t = t->next;
381         }
382
383 /*      LOGI("ret 0\n"); */
384         return 0;
385 }
386
387 static int del_notfound_node(procNode **head)
388 {
389         procNode *proc, *prev;
390         prev = NULL;
391         for(proc = *head; proc != NULL; )
392         {
393                 if(proc->found == 0)
394                 {
395                         if(prev != NULL)
396                         {
397                                 prev->next = proc->next;
398                                 free(proc);
399                                 proc = prev->next;
400                         }
401                         else
402                         {
403                                 *head = (*head)->next;
404                                 free(proc);
405                                 proc = *head;
406                         }
407                 }
408                 else
409                 {
410                         prev = proc;
411                         proc = proc->next;
412                 }
413         }
414         return 0;
415 }
416
417 static int reset_found_node(procNode *head)
418 {
419         procNode* proc;
420         for(proc = head; proc != NULL; proc = proc->next)
421         {
422                 proc->found = 0;
423         }
424         return 0;
425 }
426
427 // return 0 for normal case
428 // return negative value for error case
429 static int parse_proc_stat_file_bypid(char *path, proc_t* P)
430 {
431         char filename[PROCPATH_MAX];
432         char buf[BUFFER_MAX];
433         int fd, num;
434         char *abuf, *bbuf;
435
436         // read from stat file
437         sprintf(filename, "%s/stat", path);
438         fd = open(filename, O_RDONLY, 0);
439
440         if(unlikely(fd == -1)){
441                 return -1;
442         }
443
444         num = read(fd, buf, BUFFER_MAX);
445         close(fd);
446
447         if(unlikely(num <= 0)){
448                 LOGE("nothing read from '%s'\n", filename);
449                 return -1;
450         } else if(num == BUFFER_MAX)
451                 num -= 1;
452
453
454         buf[num] = '\0';
455
456         // scan from buffer
457         // copy command name
458         abuf = strchr(buf, '(') + 1;
459         bbuf = strrchr(buf, ')');
460         num = bbuf - abuf;
461         if(unlikely(num >= sizeof(P->command)))
462                 num = sizeof(P->command) - 1;
463         memcpy(P->command, abuf, num);
464         P->command[num] = '\0';
465         abuf = bbuf + 2;
466
467         // scan data
468
469         sscanf(abuf,
470                 "%c "
471                 "%d %d %d %d %d "
472                 "%lu %lu %lu %lu %lu "
473                 "%Lu %Lu %Lu %Lu "  // utime stime cutime cstime
474                 "%ld %ld "
475                 "%d "
476                 "%ld "
477                 "%Lu "  // start_time
478                 "%lu "
479                 "%ld",
480                 &P->state,
481                 &P->ppid, &P->pgrp, &P->sid, &P->tty_nr, &P->tty_pgrp,
482                 &P->flags, &P->minor_fault, &P->cminor_fault, &P->major_fault, &P->cmajor_fault,
483                 &P->utime, &P->stime, &P->cutime, &P->cstime,
484                 &P->priority, &P->nice,
485                 &P->numofthread,
486                 &P->dummy,
487                 &P->start_time,
488                 &P->vir_mem,
489                 &P->res_memblock
490                 );
491
492         if(P->numofthread == 0)
493                 P->numofthread = 1;
494
495         return 0;
496 }
497
498 // return 0 for normal case
499 // return negative value for error case
500 static int parse_proc_smaps_file_bypid(char *path, proc_t* P)
501 {
502 #define MIN_SMAP_BLOCKLINE      50
503
504         char filename[PROCPATH_MAX];
505         char buf[MIDDLE_BUFFER];
506         char numbuf[SMALL_BUFFER];
507         FILE* fp;
508
509         // reset pss size of proc_t
510         P->pss = 0;
511         P->sh_mem = 0;
512
513         // read from smaps file
514         sprintf(filename, "%s/smaps", path);
515         fp = fopen(filename, "r");
516
517         if(fp == NULL){
518                 return -1;
519         }
520
521         if(unlikely(probe_so_size == 0))        // probe so size is not abtained
522         {
523                 int is_probe_so = 0;
524                 while(fgets(buf, MIDDLE_BUFFER, fp) != NULL)
525                 {
526                         if(strncmp(buf, "Pss:", 4) == 0)        // line is started with "Pss:"
527                         {
528                                 sscanf(buf, "Pss:%s kB", numbuf);
529                                 P->pss += atoi(numbuf);
530                                 if(is_probe_so == 1)
531                                 {
532                                         probe_so_size += atoi(numbuf);
533                                         is_probe_so = 0;        // reset search flag
534                                 }
535                         }
536                         else if(strncmp(buf, "Shared", 6) == 0) // line is started with "Shared"
537                         {
538                                 char *p = buf;
539                                 p = strstr(buf, ":");
540                                 if (p != 0) {
541                                         sscanf(p, ":%s kB", numbuf);
542                                         P->sh_mem += atoi(numbuf);
543                                 }
544
545                         }
546                         else    // not Pss line
547                         {
548                                 if (is_probe_so == 0 && strlen(buf) > MIN_SMAP_BLOCKLINE)
549                                 {
550                                         // first we find probe so section
551                                         if(strstr(buf, DA_PROBE_TIZEN_SONAME) != NULL ||
552                                                         strstr(buf, DA_PROBE_OSP_SONAME) != NULL)
553                                         {
554                                                 // found probe.so
555                                                 is_probe_so = 1;
556                                         }
557                                         else
558                                         {
559                                                 // do nothing
560                                         }
561                                 }
562                                 else
563                                 {
564                                         // do nothing
565                                 }
566                         }
567                 }
568         }
569         else    // we know about probe.so size already
570         {
571                 while(fgets(buf, MIDDLE_BUFFER, fp) != NULL)
572                 {
573                         if(strncmp(buf, "Pss:", 4) == 0)
574                         {
575                                 sscanf(buf, "Pss:%s kB", numbuf);
576                                 P->pss += atoi(numbuf);
577                         }
578                         else if(strncmp(buf, "Shared", 6) == 0) // line is started with "Shared"
579                         {
580                                 char *p = buf;
581                                 p = strstr(buf, ":");
582                                 if (p != 0) {
583                                         sscanf(p, ":%s kB", numbuf);
584                                         P->sh_mem += atoi(numbuf);
585                                 }
586                         }
587                 }
588         }
589
590         P->pss -= probe_so_size;
591
592         fclose(fp);
593
594         return 0;
595 }
596
597 // return 0 for normal case
598 // return positive value for non critical case
599 // return negative value for critical case
600 static int update_process_data(int* pidarray, int pidcount, enum PROCESS_DATA datatype)
601 {
602         static struct stat sb;
603         int i, ret = 0;
604         char buf[PROCPATH_MAX];
605         procNode* procnode;
606
607         for(i = 0; i < pidcount; i++)
608         {
609 /*              LOGI("#%d\n", i); */
610                 if (pidarray[i] == 0)   // pid is invalid
611                 {
612                         ret = 1;
613                         continue;
614                 }
615
616                 sprintf(buf, "/proc/%d", pidarray[i]);
617 /*              LOGI("#->%s\n", buf); */
618                 if (unlikely(stat(buf, &sb) == -1))     // cannot access anymore
619                 {
620 /*                      LOGI("#del from prochead=%d\n", prochead); */
621                         del_node(&prochead, pidarray[i]);
622                         ret = errno;
623                         continue;
624                 }
625
626 /*              LOGI("find node = %d\n", procnode); */
627                 if ((procnode = find_node(prochead, pidarray[i])) == NULL)      // new process
628                 {
629 /*                      LOGI("proc node1 = %d\n", procnode); */
630                         procnode = add_node(&prochead, pidarray[i]);
631                         if(datatype == PROCDATA_STAT)
632                         {
633                                 if (unlikely((ret = parse_proc_stat_file_bypid(buf, &(procnode->proc_data))) < 0))
634                                 {
635                                         LOGE("Failed to get proc stat file by pid(%d)\n", pidarray[i]);
636                                 }
637                                 else
638                                 {
639                                         procnode->saved_utime = procnode->proc_data.utime;
640                                         procnode->saved_stime = procnode->proc_data.stime;
641                                 }
642                         }
643                         else if(datatype == PROCDATA_SMAPS)
644                         {
645                                 if (unlikely((ret = parse_proc_smaps_file_bypid(buf, &(procnode->proc_data))) < 0))
646                                 {
647                                         LOGE("Failed to get proc smaps file by pid(%d)\n", pidarray[i]);
648                                 }
649                                 else
650                                 {       // do nothing
651                                 }
652                         }
653                         else
654                         {       // impossible
655                         }
656                 }
657                 else
658                 {
659 /*                      LOGI("proc node2 = %d\n", procnode); */
660                         if(datatype == PROCDATA_STAT)
661                         {
662                                 if (unlikely((ret = parse_proc_stat_file_bypid(buf, &(procnode->proc_data))) < 0))
663                                 {
664                                         LOGE("Failed to get proc stat file by pid(%d)\n", pidarray[i]);
665                                 }
666                                 else
667                                 {       // do nothing
668                                 }
669                         }
670                         else if(datatype == PROCDATA_SMAPS)
671                         {
672                                 if (unlikely((ret = parse_proc_smaps_file_bypid(buf, &(procnode->proc_data))) < 0))
673                                 {
674                                         LOGE("Failed to get proc smaps file by pid(%d)\n", pidarray[i]);
675                                 }
676                                 else
677                                 {       // do nothing
678                                 }
679                         }
680                         else
681                         {       // impossible
682                         }
683                 }
684         }
685 /*      LOGI("del_notfound_node\n"); */
686         del_notfound_node(&prochead);
687 /*      LOGI("reset_found_node\n"); */
688         reset_found_node(prochead);
689
690 /*      LOGI("ret %d\n", ret); */
691         return ret;
692 }
693
694 static int update_system_cpu_frequency(int cur_index)
695 {
696         char buf[SMALL_BUFFER];
697         char filename[SMALL_BUFFER];
698         int i, j;
699         FILE* fp;
700
701         // execute this block only once
702         if(unlikely(num_of_freq <= 0))
703         {
704                 FILE* fp;
705                 num_of_freq = 0;
706                 if((fp = fopen(CPUNUM_OF_FREQ, "r")) != NULL)
707                 {
708                         while(fgets(buf, SMALL_BUFFER, fp) != NULL)
709                         {
710                                 num_of_freq++;
711                         }
712                         fclose(fp);
713                 }
714                 else
715                 {
716                         /* This file may absent in the system */
717                 }
718
719                 for(i = 0; i < num_of_cpu; i++)
720                 {
721                         if(cpus[i].pfreq == NULL && num_of_freq)
722                         {
723                                 cpus[i].pfreq = (cpufreq_t*) calloc(num_of_freq, sizeof(cpufreq_t));
724                         }
725                 }
726         }
727
728         sprintf(filename, CPUNUM_OF_FREQ);
729         // update cpu frequency information
730         for(i = 0; i < num_of_cpu; i++)
731         {
732                 filename[27] = (char)('0' + i);
733                 fp = fopen(filename, "r");
734                 if(fp != NULL)
735                 {
736                         for(j = 0; j < num_of_freq; j++)
737                         {
738                                 if(fgets(buf, SMALL_BUFFER, fp) != NULL)
739                                 {
740                                         sscanf(buf, "%lu %Lu", &(cpus[i].pfreq[j].freq),
741                                                         &(cpus[i].pfreq[j].tick));
742                                 }
743                                 else    // cannot read anymore from frequency info file
744                                         break;
745                         }
746
747                         fclose(fp);
748                         cpus[i].cur_freq_index = cur_index;
749                 }
750                 else    // cannot load cpu frequency information
751                 {       // do nothing
752                 }
753         }
754
755         return 0;
756 }
757
758 // return 0 for normal case
759 // return negative value for error
760 static void init_system_cpu_data()
761 {
762         manager.fd.procstat = fopen(PROCSTAT, "r");
763 }
764
765 static int update_system_cpu_data(int cur_index)
766 {
767 /*      LOGI(">\n"); */
768
769         FILE* fp = manager.fd.procstat;
770         int num;
771         char buf[BUFFER_MAX];
772
773         if(fp == NULL)
774                 return -1;
775
776         rewind(fp);
777         fflush(fp);
778
779         if(fgets(buf, sizeof(buf), fp) == NULL)
780         {
781                 LOGE("Failed to read first line of " PROCSTAT "\n");
782                 return -1;
783         }
784
785 /* LOGI("scan; cpus = %d\n", cpus); */
786
787         cpus[num_of_cpu].x = 0;
788         cpus[num_of_cpu].y = 0;
789         cpus[num_of_cpu].z = 0;
790         num = sscanf(buf, "cpu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu",
791                         &cpus[num_of_cpu].u,
792                         &cpus[num_of_cpu].n,
793                         &cpus[num_of_cpu].s,
794                         &cpus[num_of_cpu].i,
795                         &cpus[num_of_cpu].w,
796                         &cpus[num_of_cpu].x,
797                         &cpus[num_of_cpu].y,
798                         &cpus[num_of_cpu].z
799                         );
800         cpus[num_of_cpu].cur_load_index = cur_index;
801         if(num < 4)
802         {
803                 LOGE("Failed to read from " PROCSTAT "\n");
804                 return -1;
805         }
806
807 #ifdef FOR_EACH_CPU
808
809 /*      LOGI("cpu num = %d\n", num_of_cpu); */
810         // and just in case we're 2.2.xx compiled without SMP support...
811         if(num_of_cpu == 1)
812         {
813                 cpus[0].id = cpus[1].id = 0;
814                 memcpy(cpus, &cpus[1], sizeof(tic_t) * 8);
815                 cpus[0].cur_load_index = cur_index;
816         }
817         else if(num_of_cpu > 1)
818         {
819                 int i;
820                 // now value each separate cpu's tics
821                 for(i = 0; i < num_of_cpu; i++)
822                 {
823                         if(fgets(buf, sizeof(buf), fp) != NULL)
824                         {
825                                 cpus[i].x = 0;
826                                 cpus[i].y = 0;
827                                 cpus[i].z = 0;
828                                 num = sscanf(buf, "cpu%u %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu",
829                                                 &cpus[i].id,
830                                                 &cpus[i].u, &cpus[i].n, &cpus[i].s, &cpus[i].i,
831                                                 &cpus[i].w, &cpus[i].x, &cpus[i].y, &cpus[i].z);
832                                 if(num > 4)
833                                 {
834                                         LOGI_th_samp("Readed %d stats of %dth cpu\n", num, i);
835                                         cpus[i].cur_load_index = cur_index;
836                                 }
837                                 else    // buf is not cpu core tick information
838                                 {       // do nothing
839                                 }
840                         }
841                         else    // cannot read anymore from /proc/stat file
842                         {       // do nothing
843                         }
844                 }
845         }
846         else
847         {
848                 // not possible
849                 return -1;
850         }
851 #endif
852         return 0;
853 }
854
855 // return 0 for normal case
856 // return negative value for error
857 static void init_update_system_memory_data()
858 {
859         manager.fd.procmeminfo = open(PROCMEMINFO, O_RDONLY);
860 }
861
862 static int update_system_memory_data(uint64_t *memtotal, uint64_t *memused)
863 {
864         int meminfo_fd = manager.fd.procmeminfo;
865         char *head, *tail;
866         int i, num;
867         char buf[BUFFER_MAX];
868         static const mem_t mem_table[] = {
869                 {"Buffers",             (unsigned long *)&mem_slot_array[MEM_SLOT_BUFFER]},
870                 {"Cached",              (unsigned long *)&mem_slot_array[MEM_SLOT_CACHED]},
871                 {"MemFree",             (unsigned long *)&mem_slot_array[MEM_SLOT_FREE]},
872                 {"MemTotal",    (unsigned long *)&mem_slot_array[MEM_SLOT_TOTAL]},
873         };
874         const int mem_table_size = sizeof(mem_table) / sizeof(mem_t);
875
876         if (meminfo_fd == -1)
877                 return -1;
878
879         lseek(meminfo_fd, 0L, SEEK_SET);
880         if((num = read(meminfo_fd, buf, BUFFER_MAX)) < 0)
881         {
882                 LOGE("Failed to read from " PROCMEMINFO "\n");
883                 return -1;
884         }
885
886         if(num == BUFFER_MAX)
887                 num -= 1;
888
889         buf[num] = '\0';
890 //      LOGI("buffer=<%s>\n", buf);
891
892         num = 0;        // number of found element
893         head = buf;
894         for( ;num < mem_table_size ; )
895         {
896                 tail = strchr(head, ':');
897                 if(!tail)
898                         break;
899                 *tail = '\0';
900                 for(i = 0; i < mem_table_size; i++)
901                 {
902                         if(strcmp(head, mem_table[i].name) == 0)        // found
903                         {
904                                 head = tail + 1;
905                                 *(mem_table[i].slot) = strtoul(head, &tail, 10);
906                                 num++;
907                                 break;
908                         }
909                 }
910                 if(i == mem_table_size) // cannot find entry
911                 {
912                         head = tail + 1;
913                 }
914                 tail = strchr(head, '\n');
915                 if(tail == NULL)
916                         break;
917                 head = tail + 1;
918         }
919 /*              LOGI("Buffers = %016LX\n", mem_slot_array[MEM_SLOT_BUFFER]); */
920 /*              LOGI("Cached  = %016LX\n", mem_slot_array[MEM_SLOT_CACHED]); */
921 /*              LOGI("MemFree = %016LX\n", mem_slot_array[MEM_SLOT_FREE]); */
922 /*              LOGI("MemTotal= %016LX\n", mem_slot_array[MEM_SLOT_TOTAL]); */
923         if(num == mem_table_size)       // find all element
924         {
925                 *memtotal = mem_slot_array[MEM_SLOT_TOTAL];
926                 *memused = mem_slot_array[MEM_SLOT_TOTAL] - mem_slot_array[MEM_SLOT_FREE] -
927                         mem_slot_array[MEM_SLOT_BUFFER] - mem_slot_array[MEM_SLOT_CACHED];
928
929
930                 *memtotal *= 1024;      // change to Byte
931                 *memused *= 1024;       // change to Byte
932                 return 0;
933         }
934         else
935         {
936                 LOGE("Cannot find all neccessary element in meminfo\n");
937                 return -1;
938         }
939 }
940
941
942 // return 0 for error case
943 // return system total memory in MB
944 //static
945 static unsigned long get_system_total_memory(void)
946 {
947         int meminfo_fd = manager.fd.procmeminfo;
948         char *head, *tail;
949         int num;
950         char buf[BUFFER_MAX];
951         static const char* memtotalstr = "MemTotal";
952         unsigned long totalmem = 0;
953
954         if (meminfo_fd == -1)
955                 return 0;
956
957         lseek(meminfo_fd, 0L, SEEK_SET);
958
959         if((num = read(meminfo_fd, buf, BUFFER_MAX)) < 0)
960         {
961                 LOGE("Failed to read from " PROCMEMINFO "\n");
962                 return 0;
963         }
964
965         if(num == BUFFER_MAX)
966                 num -= 1;
967         buf[num] = '\0';
968
969         head = buf;
970         for( ; ; )
971         {
972                 tail = strchr(head, ':');
973                 if(!tail)
974                         break;
975                 *tail = '\0';
976                 if(strcmp(head, memtotalstr) == 0)      // found
977                 {
978                         head = tail + 1;
979                         totalmem = strtoul(head, &tail, 10);
980                         break;
981                 }
982
983                 head = tail + 1;
984                 tail = strchr(head, '\n');
985                 if(tail == NULL)
986                         break;
987                 head = tail + 1;
988         }
989
990         return (totalmem * 1024);
991 }
992
993 // ===============================================================
994 // disk information getter functions
995 // ===============================================================
996 static int get_fsinfo(const char* path, int type)
997 {
998         struct statfs buf;
999         int total;
1000         int free;
1001
1002         if (statfs(path, &buf) < 0)
1003         {
1004                 return -errno;
1005         }
1006
1007         total = (int)((long long)(buf.f_bsize / 1024LL * buf.f_blocks) / 1024LL);
1008         free = (int)((long long)(buf.f_bsize / 1024LL * buf.f_bavail) / 1024LL);
1009
1010 /*      LOGI("File storage total(%d), free(%d)\n", total, free); */
1011         if (type == FSINFO_TYPE_TOTAL)
1012         {
1013                 return total;
1014         }
1015         else if (type == FSINFO_TYPE_FREE)
1016         {
1017                 return free;
1018         }
1019
1020         return -1;
1021 }
1022
1023 static int stat_get_storageinfo(int type)
1024 {
1025         return get_fsinfo(UMSFD, type);
1026 }
1027
1028 static int stat_get_cardinfo(int type)
1029 {
1030         if (access(MMCBLKFD, F_OK) < 0)
1031         {
1032                 return -1;
1033         }
1034
1035         return get_fsinfo(MMCFD, type);
1036 }
1037
1038
1039 static int get_total_drive()
1040 {
1041         int total = 0;
1042         int storage = stat_get_storageinfo(FSINFO_TYPE_TOTAL);
1043         int card = stat_get_cardinfo(FSINFO_TYPE_TOTAL);
1044
1045         if (storage < 0 && card < 0)
1046         {
1047                 return -1;
1048         }
1049
1050         total = storage + card;
1051
1052         return total;
1053 }
1054
1055 static int get_total_used_drive()
1056 {
1057         int total = 0;
1058         int free = 0;
1059         int storage = stat_get_storageinfo(FSINFO_TYPE_FREE);
1060         int card = stat_get_cardinfo(FSINFO_TYPE_FREE);
1061
1062         if (storage < 0 && card < 0)
1063         {
1064                 LOGI_th_samp("total_used_drive = -1\n");
1065                 return -1;
1066         }
1067
1068         free = storage + card;
1069         total = get_total_drive() - free;
1070
1071         LOGI_th_samp("total_used_drive = %d\n", total);
1072
1073         return total;
1074 }
1075
1076 static int update_thread_data(int pid)
1077 {
1078         static struct stat sb;
1079         int ret = 0;
1080         char path[PROCPATH_MAX];
1081         char buf[PROCPATH_MAX];
1082         procNode* procnode;
1083         DIR *taskdir = NULL;
1084         struct dirent *entry = NULL;
1085         unsigned int tid;
1086
1087         sprintf(path, "/proc/%d/task", pid);
1088
1089         if(!(taskdir = opendir(path)))
1090         {
1091                 LOGE("task not found '%s'\n", path);
1092                 return -1;
1093         }
1094
1095         while((entry = readdir(taskdir)) != NULL)
1096         {
1097                 if(*entry->d_name > '0' &&      *entry->d_name <= '9')
1098                 {
1099                         tid = atoi(entry->d_name);
1100                         sprintf(buf, "/proc/%d/task/%d", pid, tid);
1101
1102                         if(unlikely(stat(buf, &sb) == -1))
1103                         {
1104                                 del_node(&thread_prochead, tid);
1105                                 ret = errno;
1106                                 continue;
1107                         }
1108
1109                         if((procnode = find_node(thread_prochead, tid)) == NULL)
1110                         {
1111                                 procnode = add_node(&thread_prochead, tid);
1112                                 if (unlikely((ret = parse_proc_stat_file_bypid(buf, &(procnode->proc_data))) < 0))
1113                                 {
1114                                         LOGE("Failed to get proc stat file by tid(%d). add node\n", tid);
1115                                 }
1116                                 else
1117                                 {
1118                                         procnode->saved_utime = procnode->proc_data.utime;
1119                                         procnode->saved_stime = procnode->proc_data.stime;
1120 /*                                      LOGI("data updated\n"); */
1121                                 }
1122                         }
1123                         else
1124                         {
1125                                 if (unlikely((ret = parse_proc_stat_file_bypid(buf, &(procnode->proc_data))) < 0))
1126                                 {
1127                                         LOGE("Failed to get proc stat file by tid(%d). node exist\n", tid);
1128                                 }
1129                         }
1130                 }
1131         }
1132
1133         del_notfound_node(&thread_prochead);
1134         reset_found_node(thread_prochead);
1135
1136         closedir(taskdir);
1137         return ret;
1138 }
1139
1140 // ========================================================================
1141 // overall information getter functions
1142 // ========================================================================
1143
1144 static int get_device_network_type(char* buf, int buflen)
1145 {
1146         int len = 0;
1147
1148         if (is_cdma_available())
1149                 len += sprintf(buf + len, "CDMA,");
1150
1151         if (is_edge_available())
1152                 len += sprintf(buf + len, "EDGE,");
1153
1154         if (is_gprs_available())
1155                 len += sprintf(buf + len, "GPRS,");
1156
1157         if (is_gsm_available())
1158                 len += sprintf(buf + len, "GSM,");
1159
1160         if (is_hsdpa_available())
1161                 len += sprintf(buf + len, "HSDPA,");
1162
1163         if (is_hspa_available())
1164                 len += sprintf(buf + len, "HSPA,");
1165
1166         if (is_hsupa_available())
1167                 len += sprintf(buf + len, "HSUPA,");
1168
1169         if (is_umts_available())
1170                 len += sprintf(buf + len, "UMTS,");
1171
1172         if (is_lte_available())
1173                 len += sprintf(buf + len, "LTE,");
1174
1175         if (len != 0)
1176                 buf[--len] = 0;
1177
1178         return len;
1179 }
1180
1181 static int update_cpus_info(int event_num, float elapsed)
1182 {
1183         int i = 0;
1184         CPU_t* cpuptr;
1185         // calculate for system cpu load
1186 #ifdef FOR_EACH_CPU
1187         for(i = 0; i < num_of_cpu; i++)
1188 #else
1189         for(i = num_of_cpu; i <= num_of_cpu; i++)
1190 #endif
1191         {
1192         LOGI_th_samp("CPU #%d\n", i);
1193                 cpuptr = &(cpus[i]);
1194
1195                 if(cpuptr->cur_load_index == event_num)
1196                 {
1197                         if(cpuptr->sav_load_index == event_num - 1)             // previous sampling is just before 1 period
1198                         {
1199                                 cpuptr->idle_ticks = cpuptr->i - cpuptr->i_sav;
1200                                 if(unlikely(cpuptr->idle_ticks < 0))
1201                                 {
1202                                         cpuptr->idle_ticks = 0;
1203                                 }
1204                                 cpuptr->total_ticks = (cpuptr->u - cpuptr->u_sav) +
1205                                         (cpuptr->s - cpuptr->s_sav) +
1206                                         (cpuptr->n - cpuptr->n_sav) +
1207                                         cpuptr->idle_ticks +
1208                                         (cpuptr->w - cpuptr->w_sav) +
1209                                         (cpuptr->x - cpuptr->x_sav) +
1210                                         (cpuptr->y - cpuptr->y_sav) +
1211                                         (cpuptr->z - cpuptr->z_sav);
1212                                 if(cpuptr->total_ticks < MIN_TOTAL_TICK)
1213                                 {
1214                                         cpuptr->cpu_usage = 0.0f;
1215                                 }
1216                                 else
1217                                 {
1218                                         cpuptr->cpu_usage = (1.0f - ((float)cpuptr->idle_ticks /
1219                                                                 (float)cpuptr->total_ticks)) * 100.0f;
1220                                 }
1221 //                              if(i != num_of_cpu)
1222 //                              {
1223 //                                      idle_tick_sum += cpuptr->idle_ticks;
1224 //                                      total_tick_sum += cpuptr->total_ticks;
1225 //                              }
1226                                 LOGI_th_samp("System cpu usage log : %d, %Ld, %Ld\n",
1227                                                 i, cpuptr->idle_ticks, cpuptr->total_ticks);
1228                                 if(unlikely(cpuptr->cpu_usage < 0))
1229                                 {
1230                                         cpuptr->cpu_usage = 0.0f;
1231                                 }
1232                         }
1233                         else    // previous sampling is not just before 1 period
1234                         {
1235                                 // assume non idle ticks happen in 1 profiling period
1236                                 // because sampling is not available just before 1 profiling period
1237                                 cpuptr->idle_ticks = (cpuptr->u - cpuptr->u_sav) +
1238                                         (cpuptr->s - cpuptr->s_sav) +
1239                                         (cpuptr->n - cpuptr->n_sav) +
1240                                         (cpuptr->w - cpuptr->w_sav) +
1241                                         (cpuptr->x - cpuptr->x_sav) +
1242                                         (cpuptr->y - cpuptr->y_sav) +
1243                                         (cpuptr->z - cpuptr->z_sav);
1244                                 cpuptr->total_ticks = (long long)(Hertz * elapsed);
1245                                 if(unlikely(cpuptr->total_ticks < 1))
1246                                         cpuptr->total_ticks = 1;
1247                                 cpuptr->cpu_usage = ((float)cpuptr->idle_ticks /
1248                                                 (float)cpuptr->total_ticks) * 100.0f;
1249                                 if(unlikely(cpuptr->cpu_usage > 100.0f))
1250                                 {
1251                                         cpuptr->cpu_usage = 100.0f;
1252                                 }
1253                         }
1254
1255                         // save new value
1256                         cpuptr->u_sav = cpuptr->u;
1257                         cpuptr->s_sav = cpuptr->s;
1258                         cpuptr->n_sav = cpuptr->n;
1259                         cpuptr->i_sav = cpuptr->i;
1260                         cpuptr->w_sav = cpuptr->w;
1261                         cpuptr->x_sav = cpuptr->x;
1262                         cpuptr->y_sav = cpuptr->y;
1263                         cpuptr->z_sav = cpuptr->z;
1264                         cpuptr->sav_load_index = cpuptr->cur_load_index;
1265                 }
1266                 else
1267                 {
1268                         cpuptr->cpu_usage = 0.0f;
1269                 }
1270         }
1271
1272         // calculate for cpu core load that failed to get tick information
1273 /*
1274         if(failed_cpu != 0)
1275         {
1276                 LOGI("ticks1 : %Ld, %Ld\n", idle_tick_sum, total_tick_sum);
1277                 idle_tick_sum = cpus[num_of_cpu].idle_ticks - idle_tick_sum;
1278                 total_tick_sum = cpus[num_of_cpu].total_ticks - total_tick_sum;
1279                 LOGI("ticks2 : %Ld, %Ld\n", idle_tick_sum, total_tick_sum);
1280                 if(total_tick_sum >= MIN_TICKS_FOR_LOAD)
1281                         sys_usage = (1.0f - ((float)idle_tick_sum / (float)total_tick_sum)) * 100.0f;
1282                 else
1283                         sys_usage = 0.0f;
1284                 if(sys_usage < 0.0f) sys_usage = 0.0f;
1285                 else if(sys_usage > 100.0f) sys_usage = 100.0f;
1286
1287                 for(i = 0; i < num_of_cpu; i++)
1288                 {
1289                         if(failed_cpu & (1 << i))
1290                         {
1291                                 cpus[i].cpu_usage = sys_usage;
1292                         }
1293                 }
1294         }
1295 */
1296         return 0;
1297 }
1298
1299 static int fill_system_processes_info(float factor, struct system_info_t * sys_info)
1300 {
1301         procNode* proc;
1302         int i = 0;
1303         float thread_load;
1304         // data variable
1305         unsigned long virtual = 0;
1306         unsigned long resident = 0;
1307         unsigned long shared = 0;
1308         unsigned long pssmem = 0;
1309         uint64_t ticks = 0;
1310         float app_cpu_usage = 0.0;
1311
1312         LOGI_th_samp("prochead = %X\n", (unsigned int)prochead);
1313         for(proc = prochead; proc != NULL; proc = proc->next)
1314         {
1315                 //increment process count
1316                 sys_info->count_of_processes++; //maybe wrong
1317         }
1318         sys_info->process_load = malloc (
1319                                                                                 sys_info->count_of_processes *
1320                                                                                 sizeof(*sys_info->process_load)
1321                                                                         );
1322         i = 0;
1323         for(proc = prochead; proc != NULL; proc = proc->next)
1324         {
1325                 LOGI_th_samp("proc#%d (%d %d),(%d %d) (%d) %f\n",
1326                                 i,
1327                                 (unsigned int)proc->proc_data.utime, (unsigned int)proc->proc_data.stime ,
1328                                 (unsigned int)proc->saved_utime, (unsigned int)proc->saved_stime,
1329                                 (int)(proc->proc_data.utime + proc->proc_data.stime - proc->saved_utime - proc->saved_stime),
1330                                 (float)(
1331                                         proc->saved_utime + proc->saved_stime -
1332                                         proc->proc_data.utime - proc->proc_data.stime
1333                                         ) * factor);
1334                 thread_load = (float)(proc->proc_data.utime + proc->proc_data.stime -
1335                                                                 proc->saved_utime - proc->saved_stime) * factor;
1336
1337                 if(thread_load > 100.0f)
1338                         thread_load = 100.0f;
1339
1340                 //num_thread += proc->proc_data.numofthread;
1341                 virtual += proc->proc_data.vir_mem;                                     // Byte
1342                 resident += (proc->proc_data.res_memblock * 4);         // KByte
1343                 pssmem += (proc->proc_data.pss);                                        // KByte
1344                 shared += (proc->proc_data.sh_mem);                                     // KByte
1345                 ticks += (proc->proc_data.utime + proc->proc_data.stime -
1346                                         proc->saved_utime - proc->saved_stime);
1347
1348                 proc->saved_utime = proc->proc_data.utime;
1349                 proc->saved_stime = proc->proc_data.stime;
1350
1351
1352                 sys_info->process_load[i].id = proc->proc_data.pid;
1353                 sys_info->process_load[i].load = thread_load;
1354                 i++;
1355
1356         }
1357
1358         app_cpu_usage = (float)ticks * factor;
1359         if(app_cpu_usage > 100.0f)
1360                 app_cpu_usage = 100.0f;
1361         resident = resident * 1024;             // change to Byte
1362         pssmem = pssmem * 1024;                 // change to Byte
1363         shared = shared * 1024;                 // change to Byte
1364
1365         sys_info->virtual_memory = virtual;
1366         sys_info->resident_memory = resident;
1367         sys_info->shared_memory = shared;
1368         sys_info->pss_memory = pssmem;
1369
1370         sys_info->app_cpu_usage = app_cpu_usage;
1371
1372         return 0;
1373
1374 }
1375
1376 // fill threads information
1377 static int fill_system_threads_info(float factor, struct system_info_t * sys_info)
1378 {
1379         procNode* proc;
1380         float thread_load;
1381
1382         for(proc = thread_prochead; proc != NULL; proc = proc->next)
1383                 //increment thread count
1384                 sys_info->count_of_threads++; //maybe wrong
1385
1386 /*      LOGI_th_samp("thread load\n"); */
1387         struct thread_info_t *pthread;
1388         if (sys_info->count_of_threads != 0)
1389         {
1390                 sys_info->thread_load = malloc( sys_info->count_of_threads * sizeof(*sys_info->thread_load) );
1391                 pthread = sys_info->thread_load;
1392         }
1393
1394         for(proc = thread_prochead; proc != NULL; proc = proc->next)
1395         {
1396                 thread_load = (float)(proc->proc_data.utime + proc->proc_data.stime -
1397                                                                 proc->saved_utime - proc->saved_stime)
1398                         * factor;
1399                 if(thread_load > 100.0f)
1400                         thread_load = 100.0f;
1401
1402                 pthread->pid = proc->proc_data.pid;
1403                 pthread->load = thread_load;
1404                 pthread++;
1405
1406 //              sprintf(thread_loadtmpbuf, "%d,%.1f,", proc->proc_data.pid, thread_load);
1407 //              strcat(thread_loadbuf, thread_loadtmpbuf);
1408
1409                 proc->saved_utime = proc->proc_data.utime;
1410                 proc->saved_stime = proc->proc_data.stime;
1411         }
1412
1413         return 0;
1414 }
1415
1416 //fill system cpu information
1417 static int fill_system_cpu_info(struct system_info_t *sys_info)
1418 {
1419         float sys_usage = 0.0f;
1420         int i = 0;
1421
1422         // calculate for whole cpu load by average all core load
1423         LOGI_th_samp("calculate for whole cpu load num_of_cpu=%d\n", num_of_cpu);
1424         for(i = 0 ; i < num_of_cpu; i++)
1425                 sys_usage += cpus[i].cpu_usage;
1426
1427         // fill cpu load
1428         float *pcpu_usage;
1429         if (num_of_cpu != 0)
1430         {
1431                 sys_info->cpu_load = malloc( num_of_cpu * sizeof(*sys_info->cpu_load) );
1432                 pcpu_usage = sys_info->cpu_load;
1433                 for(i = 0; i < num_of_cpu; i++)
1434                 {
1435                         LOGI_th_samp("cpu#%d : %.1f\n" , i,  cpus[i].cpu_usage);
1436                         *pcpu_usage = cpus[i].cpu_usage;
1437                         pcpu_usage++;
1438                 }
1439         }
1440
1441         //fill CPU frequency
1442         sys_info->cpu_frequency = malloc(num_of_cpu * sizeof(float));
1443         if (!sys_info->cpu_frequency) {
1444                 LOGE("Cannot alloc cpu freq\n");
1445                 return 1;
1446         }
1447         get_cpu_frequency(sys_info->cpu_frequency);
1448
1449         return 0;
1450 }
1451
1452 static void skip_lines(FILE * fp, unsigned int count)
1453 {
1454         char *buffer = NULL;
1455         size_t buflen;
1456         unsigned int index;
1457         for (index = 0; index != count; ++index)
1458                 getline(&buffer, &buflen, fp);
1459         free(buffer);
1460 }
1461
1462 static void skip_tokens(FILE * fp, unsigned int count)
1463 {
1464         unsigned int index;
1465
1466         for (index = 0; index != count; ++index)
1467                 fscanf(fp, "%*s");
1468 }
1469
1470 static void init_network_stat()
1471 {
1472         manager.fd.networkstat = fopen("/proc/net/dev", "r");
1473 }
1474
1475 static void get_network_stat(uint32_t *recv, uint32_t *send)
1476 {
1477         FILE *fp = manager.fd.networkstat;
1478         uintmax_t irecv, isend;
1479         char ifname[64];
1480         if (fp == NULL)
1481                 return;
1482
1483         rewind(fp);
1484         fflush(fp);
1485
1486         *recv = *send = 0;
1487         skip_lines(fp, 2);      /* strip header */
1488
1489         while (fscanf(fp, "%s", ifname) != EOF)
1490                 if (strcmp("lo:", ifname)) {
1491                         fscanf(fp, "%" SCNuMAX, &irecv);
1492                         skip_tokens(fp, 7);
1493
1494                         fscanf(fp, "%" SCNuMAX, &isend);
1495                         skip_tokens(fp, 7);
1496
1497                         *recv += irecv;
1498                         *send += isend;
1499                 } else
1500                         skip_tokens(fp, 16);
1501 }
1502
1503 static void peek_network_stat_diff(uint32_t *recv, uint32_t *send)
1504 {
1505         static uint32_t irecv_old, isend_old;
1506         uint32_t tmp;
1507
1508         get_network_stat(recv, send);
1509
1510         tmp = *recv;
1511         *recv = val_diff(tmp, irecv_old);
1512         irecv_old = tmp;
1513
1514         tmp = *send;
1515         *send = val_diff(tmp, isend_old);
1516         isend_old = tmp;
1517
1518 }
1519
1520 static void init_disk_stat(void)
1521 {
1522         manager.fd.diskstats = fopen("/proc/diskstats", "r");
1523 }
1524
1525 static void get_disk_stat(uint32_t *reads, uint32_t *sec_reads,
1526                           uint32_t *writes, uint32_t *sec_writes)
1527 {
1528         enum { partition_name_maxlength = 128 };
1529         FILE *fp = manager.fd.diskstats;
1530         char master_partition[partition_name_maxlength] = { 0 };
1531
1532         *reads = *writes = 0;
1533         *sec_reads = *sec_writes = 0;
1534
1535         if (fp == NULL)
1536                 return;
1537
1538
1539         rewind(fp);
1540         fflush(fp);
1541
1542         while (!feof(fp)) {
1543                 char partition[partition_name_maxlength];
1544                 uintmax_t preads, pwrites;
1545                 uintmax_t psec_read, psec_write;
1546                 skip_tokens(fp, 2);
1547                 fscanf(fp, "%s", partition);
1548                 if (*master_partition
1549                     && !strncmp(master_partition, partition,
1550                                strlen(master_partition))) {
1551                         /* subpartition */
1552                         skip_tokens(fp, 11);
1553                 } else {
1554                         //1
1555                         fscanf(fp, "%" SCNuMAX, &preads);
1556                         skip_tokens(fp, 1);
1557                         //3
1558                         fscanf(fp, "%" SCNuMAX, &psec_read);
1559                         skip_tokens(fp, 1);
1560                         //5
1561                         fscanf(fp, "%" SCNuMAX, &pwrites);
1562                         skip_tokens(fp, 1);
1563                         //7
1564                         fscanf(fp, "%" SCNuMAX, &psec_write);
1565                         skip_tokens(fp, 4);
1566
1567                         memcpy(master_partition, partition,
1568                                partition_name_maxlength);
1569                         // FIXME rw size is in sectors
1570                         // actualy different disks - different partition sector size (?)
1571                         // maybe need convert to bytes like this:
1572                         //*read += pread * sec_size;
1573                         //*write += pwrite * sec_size;
1574
1575                         *reads += (uint32_t)preads;
1576                         *writes += (uint32_t)pwrites;
1577
1578                         *sec_reads += (uint32_t)psec_read;
1579                         *sec_writes += (uint32_t)psec_write;
1580                 }
1581         }
1582
1583 }
1584
1585 static void peek_disk_stat_diff(uint32_t *reads, uint32_t *sec_reads,
1586                                 uint32_t *writes, uint32_t *sec_writes)
1587 {
1588         static uint32_t reads_old;
1589         static uint32_t sec_reads_old;
1590         static uint32_t writes_old;
1591         static uint32_t sec_writes_old;
1592
1593         uint32_t tmp;
1594
1595         //get cur values
1596         get_disk_stat(reads, sec_reads, writes, sec_writes);
1597
1598         tmp = *reads;
1599         *reads = val_diff(tmp, reads_old);
1600         reads_old = tmp;
1601
1602         tmp = *writes;
1603         *writes = val_diff(tmp, writes_old);
1604         writes_old = tmp;
1605
1606         tmp = *sec_reads;
1607         *sec_reads = val_diff(tmp, sec_reads_old);
1608         sec_reads_old = tmp;
1609
1610         tmp = *sec_writes;
1611         *sec_writes = val_diff(tmp, sec_writes_old);
1612         sec_writes_old = tmp;
1613
1614 }
1615
1616 static float get_elapsed(void)
1617 {
1618         static struct timeval old_time = {0, 0};
1619         struct timeval current_time;
1620         float elapsed;
1621
1622         gettimeofday(&current_time, NULL);
1623         elapsed = (current_time.tv_sec - old_time.tv_sec) +
1624                 ((float)(current_time.tv_usec - old_time.tv_usec) / 1000000.0f);
1625         old_time.tv_sec = current_time.tv_sec;
1626         old_time.tv_usec = current_time.tv_usec;
1627
1628         return elapsed;
1629 }
1630
1631 static float get_factor(float elapsed)
1632 {
1633         return 100.0f / ((float)Hertz * elapsed * num_of_cpu);
1634 }
1635
1636 static uint64_t read_int64_from_file(const char *fname)
1637 {
1638         FILE *fp = fopen(fname, "r");
1639         uint64_t value;
1640         if (!fp)
1641                 return 0;
1642         if (fscanf(fp, "%lld", &value) != 1)
1643                 value = 0;
1644         fclose(fp);
1645         return value;
1646 }
1647
1648 #define swap_sysfs_relpath(x) ("/sys/kernel/debug/swap/energy/" #x)
1649 #define swap_read_int64(x) (read_int64_from_file(swap_sysfs_relpath(x)))
1650 static uint64_t get_system_lcd_energy()
1651 {
1652         static const char *PROC_LCD_ENERGY_FILES_GLOBPATTERN =
1653                 "/sys/kernel/debug/swap/energy/lcd/*/system";
1654         uint64_t sum_energy = 0;
1655         glob_t glob_buf;
1656         size_t i;
1657         const int err = glob(PROC_LCD_ENERGY_FILES_GLOBPATTERN, 0,
1658                              NULL, &glob_buf);
1659
1660         if (err) {
1661                 LOG_ONCE_E("Globbing for LCD failed with error %d\n", err);
1662                 return 0;
1663         }
1664
1665         for (i = 0; i < glob_buf.gl_pathc; ++i)
1666                 sum_energy += read_int64_from_file(glob_buf.gl_pathv[i]);
1667
1668         globfree(&glob_buf);
1669         return sum_energy;
1670 }
1671 /*
1672  * Calculates difference between current and previous sample (system).
1673  * Stores mutable state in static variables.
1674  */
1675 static uint32_t pop_sys_energy_per_device(enum supported_device dev)
1676 {
1677         static uint64_t cpu_old, flash_old, lcd_old;
1678         uint64_t cpu_new, flash_new, lcd_new;
1679         uint64_t cpu_diff, flash_diff, lcd_diff;
1680
1681         switch (dev) {
1682         case DEVICE_CPU:
1683                 cpu_new = swap_read_int64(cpu_idle/system) +
1684                         swap_read_int64(cpu_running/system);
1685                 cpu_diff = val_diff(cpu_new, cpu_old);
1686                 cpu_old = cpu_new;
1687                 return (uint32_t)cpu_diff;
1688
1689         case DEVICE_FLASH:
1690                 flash_new = swap_read_int64(flash_read/system) +
1691                         swap_read_int64(flash_write/system);
1692                 flash_diff = val_diff(flash_new, flash_old);
1693                 flash_old = flash_new;
1694                 return (uint32_t)flash_diff;
1695         case DEVICE_LCD:
1696                 lcd_new = get_system_lcd_energy();
1697                 lcd_diff = val_diff(lcd_new, lcd_old);
1698                 lcd_old = lcd_new;
1699                 return (uint32_t)lcd_diff;
1700         default:
1701                 assert(0 && "Unknown device. This should not happen");
1702                 return -41;
1703         }
1704 }
1705
1706 // Calculates difference between current and previous sample (app).
1707 // Stores mutable state in static variables.
1708 static uint32_t pop_app_energy_per_device(enum supported_device dev)
1709 {
1710         static uint64_t cpu_old, flash_old;
1711         uint64_t cpu_new, flash_new;
1712         uint64_t cpu_diff, flash_diff;
1713
1714         switch (dev) {
1715         case DEVICE_CPU:
1716                 cpu_new = swap_read_int64(cpu_running/apps);
1717                 cpu_diff = val_diff(cpu_new, cpu_old);
1718                 cpu_old = cpu_new;
1719                 return (uint32_t)cpu_diff;
1720         case DEVICE_FLASH:
1721                 flash_new = swap_read_int64(flash_read/apps) +
1722                         swap_read_int64(flash_write/apps);
1723                 flash_diff = val_diff(flash_new, flash_old);
1724                 flash_old = flash_new;
1725                 return (uint32_t)flash_diff;
1726         case DEVICE_LCD:
1727                 /**
1728                  * Per-application energy accounting
1729                  * is not supported for LCD.
1730                  */
1731                 return 0;
1732         default:
1733                 assert(0 && "Unknown device. This should not happen");
1734                 return -41;
1735         }
1736 }
1737
1738 static int get_pid_array(int arr[], const int n)
1739 {
1740         DIR *d = opendir("/proc");
1741         struct dirent *dirent;
1742         int count = 0;
1743         pid_t self_pid = getpid();
1744
1745         if (!d) {
1746                 LOGW("Cannot open /proc dir (%s)\n", strerror(errno));
1747                 return 0;
1748         }
1749
1750         while ((dirent = readdir(d)) && (count < n)) {
1751                 if (dirent->d_type == DT_DIR) {
1752                         char *tmp;
1753                         pid_t pid = strtol(dirent->d_name, &tmp, 10);
1754                         if (*tmp == '\0' && pid != self_pid)
1755                                 arr[count++] = pid;
1756                 }
1757         }
1758
1759         closedir(d);
1760
1761         return count;
1762 }
1763
1764 static pid_t get_first_target_process(void)
1765 {
1766         pid_t pid = -1;
1767         int i;
1768
1769         for (i = 0; i < MAX_TARGET_COUNT; i++) {
1770                 if (manager.target[i].socket != -1 &&
1771                     manager.target[i].pid != -1) {
1772                         pid = manager.target[i].pid;
1773                         break;
1774                 }
1775         }
1776
1777         return pid;
1778 }
1779
1780 // return log length (>0) for normal case
1781 // return negative value for error
1782 int get_system_info(struct system_info_t *sys_info)
1783 {
1784         static int event_num = 0;
1785         uint64_t sysmemtotal = 0;
1786         uint64_t sysmemused = 0;
1787         int res = 0;
1788         float elapsed;
1789         float factor;
1790
1791         LOGI_th_samp("start\n");
1792
1793         memset(sys_info, 0, sizeof(*sys_info));
1794
1795         // common (cpu, processes, memory)
1796         if (IS_OPT_SET(FL_CPU) ||
1797             IS_OPT_SET(FL_PROCESSES) ||
1798             IS_OPT_SET(FL_MEMORY)) {
1799                 const int max_pid_num = 1024; /* ugly hardcode */
1800                 int pidarray[max_pid_num];
1801                 int pidcount = 0;
1802                 pid_t first_target_pid = -1;
1803
1804                 pidcount = get_pid_array(pidarray, max_pid_num);
1805                 LOGI_th_samp("PID count : %d\n", pidcount);
1806
1807                 if (update_process_data(pidarray, pidcount, PROCDATA_STAT) < 0) {
1808                         LOGE("Failed to update process stat data\n");
1809                         goto fail_exit;
1810                 }
1811                 /**
1812                  * This position is optimized position of timestamp. Just
1813                  * before get system cpu data and just after get process cpu
1814                  * data because cpu data is changed so fast and variance is so
1815                  * remarkable
1816                  */
1817                 elapsed = get_elapsed(); /* DO NOT MOVE THIS SENTENCE! */
1818                 factor = get_factor(elapsed);
1819
1820                 if (update_system_cpu_data(event_num) < 0) {
1821                         LOGE("Failed to update system cpu data\n");
1822                         goto fail_exit;
1823                 }
1824
1825                 if (update_system_cpu_frequency(event_num) < 0) {
1826                         LOGE("Failed to update system cpu freq data\n");
1827                         goto fail_exit;
1828                 }
1829
1830                 /**
1831                  * Memory data is changed slowly and variance is not
1832                  * remarkable, so memory data is less related with timestamp
1833                  * then cpu data
1834                  */
1835                 if (update_process_data(pidarray, pidcount, PROCDATA_SMAPS) < 0) {
1836                         LOGE("Failed to update process smaps data\n");
1837                         goto fail_exit;
1838                 }
1839
1840                 first_target_pid = get_first_target_process();
1841                 if (first_target_pid > 0)
1842                         if (update_thread_data(first_target_pid) < 0) {
1843                                 LOGE("Failed to update thread stat data\n");
1844                                 goto fail_exit;
1845                         }
1846
1847                 if (update_system_memory_data(&sysmemtotal, &sysmemused) < 0) {
1848                         LOGE("Failed to update system memory data\n");
1849                         goto fail_exit;
1850                 }
1851
1852                 if (update_cpus_info(event_num, elapsed) < 0) {
1853                         LOGE("Failed to update cpus info\n");
1854                         goto fail_exit;
1855                 }
1856
1857                 /* calculate process load, memory, app_cpu_usage */
1858                 if (fill_system_processes_info(factor, sys_info) < 0) {
1859                         LOGE("Failed to fill processes info\n");
1860                         goto fail_exit;
1861                 }
1862
1863                 /* calculate thread load */
1864                 if (fill_system_threads_info(factor, sys_info) < 0) {
1865                         LOGE("Failed to fill threads info\n");
1866                         goto fail_exit;
1867                 }
1868
1869                 if (fill_system_cpu_info(sys_info) < 0) {
1870                         LOGE("Failed to fill threads info\n");
1871                         goto fail_exit;
1872                 }
1873         }
1874
1875         if (IS_OPT_SET(FL_MEMORY)) {
1876                 sys_info->total_alloc_size = get_total_alloc_size();
1877                 sys_info->system_memory_total = sysmemtotal;
1878                 sys_info->system_memory_used = sysmemused;
1879         }
1880
1881         LOGI_th_samp("Fill result structure\n");
1882
1883         if (IS_OPT_SET(FL_DISK)) {
1884                 sys_info->total_used_drive = get_total_used_drive();
1885                 peek_disk_stat_diff(&sys_info->disk_reads,
1886                                     &sys_info->disk_sectors_read,
1887                                     &sys_info->disk_writes,
1888                                     &sys_info->disk_sectors_write);
1889         }
1890
1891         if (IS_OPT_SET(FL_NETWORK))
1892                 peek_network_stat_diff(&sys_info->network_send_size,
1893                                        &sys_info->network_receive_size);
1894
1895         if (IS_OPT_SET(FL_DEVICE)) {
1896                 sys_info->wifi_status = get_wifi_status();
1897                 sys_info->bt_status = get_bt_status();
1898                 sys_info->gps_status = get_gps_status();
1899                 sys_info->brightness_status = get_brightness_status();
1900                 sys_info->camera_status = get_camera_status();
1901                 sys_info->sound_status = get_sound_status();
1902                 sys_info->audio_status = get_audio_status();
1903                 sys_info->vibration_status = get_vibration_status();
1904                 sys_info->voltage_status = get_voltage_status();
1905                 sys_info->rssi_status = get_rssi_status();
1906                 sys_info->video_status = get_video_status();
1907                 sys_info->call_status = get_call_status();
1908                 sys_info->dnet_status = get_dnet_status();
1909         }
1910
1911         if (IS_OPT_SET(FL_ENERGY)) {
1912                 int i;
1913                 sys_info->energy = 0; /* not implemented */
1914                 for (i = 0; i != supported_devices_count; ++i) {
1915                         sys_info->energy_per_device[i] =
1916                                 pop_sys_energy_per_device(i);
1917                         sys_info->app_energy_per_device[i] = (i == DEVICE_LCD)
1918                                 ? sys_info->energy_per_device[i]
1919                                 : pop_app_energy_per_device(i);
1920                 }
1921         }
1922
1923 #ifdef THREAD_SAMPLING_DEBUG
1924         print_sys_info(sys_info);
1925 #endif
1926
1927         event_num++;
1928         LOGI_th_samp("exit\n");
1929         return res;
1930
1931 fail_exit:
1932         /* Some data corrupted. Free allocated data. */
1933         reset_system_info(sys_info);
1934         LOGI_th_samp("fail exit\n");
1935         return -1;
1936 }
1937
1938 int initialize_system_info(void)
1939 {
1940         int i;
1941
1942         num_of_cpu = sysconf(_SC_NPROCESSORS_CONF);
1943         if(num_of_cpu < 1)
1944                 num_of_cpu = 1;
1945         Hertz = sysconf(_SC_CLK_TCK);
1946         LOGI("Hertz : %d\n", Hertz);
1947
1948         // alloc for cpus
1949         if(cpus == NULL)
1950                 cpus = (CPU_t*) calloc((num_of_cpu + 1), sizeof(CPU_t));
1951         if(cpus != NULL)
1952         {
1953                 for(i = 0; i <= num_of_cpu; i++)
1954                 {
1955                         cpus[i].cur_load_index = cpus[i].sav_load_index = -1;
1956                         cpus[i].cur_freq_index = cpus[i].sav_freq_index = -1;
1957                 }
1958         }
1959         else
1960         {
1961                 LOGE("Failed to alloc memory for cpu information\n");
1962                 return -1;
1963         }
1964
1965         return 0;
1966 }
1967
1968 int finalize_system_info(void)
1969 {
1970         int i;
1971
1972         if(cpus != NULL)
1973         {
1974                 for(i = 0; i < num_of_cpu; i++)
1975                 {
1976                         if(cpus[i].pfreq != NULL)
1977                                 free(cpus[i].pfreq);
1978                 }
1979
1980                 free(cpus);
1981         }
1982
1983         return 0;
1984
1985 }
1986
1987 static void test_and_close(int *fd)
1988 {
1989         if (*fd > 0)
1990                 close(*fd);
1991         *fd = -1;
1992 }
1993
1994 static void ftest_and_close(FILE **fd)
1995 {
1996         if (*fd != NULL)
1997                 fclose(*fd);
1998         *fd = NULL;
1999 }
2000
2001 #define strr(x) #x
2002 #define str(x) strr(x)
2003 #define dtest_and_close(fd) do {LOGI("CLOSE " str(fd) "\n");test_and_close(fd);} while(0)
2004 #define dftest_and_close(fd) do {LOGI("CLOSE " str(fd) "\n");ftest_and_close(fd);} while(0)
2005 void close_system_file_descriptors(void)
2006 {
2007         dtest_and_close(&manager.fd.brightness);
2008         dtest_and_close(&manager.fd.voltage);
2009         dtest_and_close(&manager.fd.procmeminfo);
2010
2011         dftest_and_close(&manager.fd.video);
2012         dftest_and_close(&manager.fd.procstat);
2013         dftest_and_close(&manager.fd.networkstat);
2014         dftest_and_close(&manager.fd.diskstats);
2015 }
2016
2017 int init_system_file_descriptors(void)
2018 {
2019         //inits
2020         init_brightness_status();
2021         init_voltage_status();
2022         init_update_system_memory_data();
2023
2024         init_video_status();
2025         init_system_cpu_data();
2026         init_network_stat();
2027         init_disk_stat();
2028
2029         if (manager.fd.brightness < 0)
2030                 LOGW("brightness file not found\n");
2031         if (manager.fd.voltage < 0)
2032                 LOGW("voltage file not found\n");
2033         if (manager.fd.procmeminfo < 0)
2034                 LOGW("procmeminfo file not found\n");
2035
2036         if (manager.fd.video == NULL)
2037                 LOGW("video file not found\n");
2038         if (manager.fd.procstat == NULL)
2039                 LOGW("procstat file not found\n");
2040         if (manager.fd.networkstat == NULL)
2041                 LOGW("networkstat file not found\n");
2042         if (manager.fd.diskstats == NULL)
2043                 LOGW("diskstat file not found\n");
2044         return 0;
2045 }
2046
2047 //CMD SOCKET FUNCTIONS
2048 int fill_target_info(struct target_info_t *target_info)
2049 {
2050         /* system_info_get_value_bool() changes only 1 byte
2051            so we need to be sure that the integer as a whole is correct */
2052         target_info->bluetooth_supp = 0;
2053         target_info->gps_supp = 0;
2054         target_info->wifi_supp = 0;
2055         target_info->camera_count = 0;
2056         target_info->network_type[0] = 0;
2057
2058         target_info->sys_mem_size = get_system_total_memory();
2059         target_info->storage_size = stat_get_storageinfo(FSINFO_TYPE_TOTAL) *
2060                 1024 * 1024;
2061
2062         target_info->bluetooth_supp = is_bluetooth_available();
2063         target_info->gps_supp = is_gps_available();
2064         target_info->wifi_supp = is_wifi_available();
2065
2066         target_info->camera_count = get_camera_count();
2067
2068         get_device_network_type(target_info->network_type, NWTYPE_SIZE);
2069
2070
2071         target_info->max_brightness = get_max_brightness();
2072         target_info->cpu_core_count = sysconf(_SC_NPROCESSORS_CONF);
2073         return 0;
2074 }
2075
2076 int sys_stat_prepare(void)
2077 {
2078         uint32_t reads, writes, sec_reads, sec_writes;
2079         uint32_t recv, send;
2080
2081         peek_disk_stat_diff(&reads, &writes, &sec_reads, &sec_writes);
2082         peek_network_stat_diff(&recv, &send);
2083
2084         return 0;
2085 }
2086
2087 static uint32_t msg_data_payload_length(const struct system_info_t *sys_info)
2088 {
2089         uint32_t len = sizeof(*sys_info);
2090
2091         /* num_of_cpu is unknown at compile time */
2092         len += 2 * num_of_cpu * sizeof(float);
2093
2094         /* subtract pointers */
2095         len -= sizeof(sys_info->cpu_frequency) + sizeof(sys_info->cpu_load);
2096         len -= sizeof(sys_info->thread_load) + sizeof(sys_info->process_load);
2097
2098         if (IS_OPT_SET(FL_CPU))
2099                 len += sys_info->count_of_threads *
2100                         sizeof(*sys_info->thread_load);
2101
2102         if (IS_OPT_SET(FL_PROCESSES))
2103                 len += sys_info->count_of_processes *
2104                         sizeof(*sys_info->process_load);
2105
2106         return len;
2107 }
2108
2109 struct msg_data_t *pack_system_info(struct system_info_t *sys_info)
2110 {
2111         const int len = msg_data_payload_length(sys_info);
2112         struct msg_data_t *msg = NULL;
2113         char *p = NULL;
2114         int i = 0;
2115
2116         msg = malloc(MSG_DATA_HDR_LEN + len);
2117         if (!msg) {
2118                 LOGE("Cannot alloc message: %d bytes\n", len);
2119                 return NULL;
2120         }
2121
2122         fill_data_msg_head(msg, NMSG_SYSTEM, 0, len);
2123         p = msg->payload;
2124
2125         // CPU
2126         if (IS_OPT_SET(FL_CPU)) {
2127                 pack_float(p, sys_info->app_cpu_usage);
2128
2129                 for (i = 0; i < num_of_cpu; i++) {
2130                         if (sys_info->cpu_frequency)
2131                                 pack_float(p, sys_info->cpu_frequency[i]);
2132                         else
2133                                 pack_float(p, 0.0);
2134                 }
2135
2136                 for (i = 0; i < num_of_cpu; i++) {
2137                         if (sys_info->cpu_load)
2138                                 pack_float(p, sys_info->cpu_load[i]);
2139                         else
2140                                 pack_float(p, 0.0);
2141                 }
2142                 // thread
2143                 pack_int32(p, sys_info->count_of_threads);
2144                 for (i = 0; i < sys_info->count_of_threads; i++) {
2145                         if (sys_info->thread_load) {
2146                                 pack_int32(p, sys_info->thread_load[i].pid);
2147                                 pack_float(p, sys_info->thread_load[i].load);
2148                         } else {
2149                                 pack_int32(p, 0);
2150                                 pack_float(p, 0.0);
2151                         }
2152                 }
2153         } else {
2154                 pack_float(p, 0.0); /* pack app_cpu_usage */
2155
2156                 for (i = 0; i < num_of_cpu; i++) {
2157                         pack_float(p, 0.0); /* pack cpu_frequency */
2158                         pack_float(p, 0.0); /* pack cpu_load */
2159                 }
2160                 /* thread */
2161                 pack_int32(p, 0); /* pack count_of_threads */
2162         }
2163
2164         /* process */
2165         if (IS_OPT_SET(FL_PROCESSES)) {
2166                 pack_int32(p, sys_info->count_of_processes);
2167                 for (i = 0; i < sys_info->count_of_processes; i++) {
2168                         if (sys_info->process_load) {
2169                                 pack_int32(p, sys_info->process_load[i].id);
2170                                 pack_float(p, sys_info->process_load[i].load);
2171                         } else {
2172                                 pack_int32(p, 0);
2173                                 pack_float(p, 0.0);
2174                         }
2175                 }
2176         } else {
2177                 pack_int32(p, 0); /* pack count_of_processes */
2178         }
2179
2180         /* memory */
2181         if (IS_OPT_SET(FL_MEMORY)) {
2182                 pack_int32(p, sys_info->virtual_memory);
2183                 pack_int32(p, sys_info->resident_memory);
2184                 pack_int32(p, sys_info->shared_memory);
2185                 pack_int32(p, sys_info->pss_memory);
2186                 pack_int64(p, sys_info->total_alloc_size);
2187                 pack_int64(p, sys_info->system_memory_total);
2188                 pack_int64(p, sys_info->system_memory_used);
2189         } else {
2190                 pack_int32(p, 0); /* pack virtual_memory */
2191                 pack_int32(p, 0); /* pack resident_memory */
2192                 pack_int32(p, 0); /* pack shared_memory */
2193                 pack_int32(p, 0); /* pack pss_memory */
2194                 pack_int64(p, (uint64_t) 0); /* pack total_alloc_size */
2195                 pack_int64(p, (uint64_t) 0); /* pack system_memory_total */
2196                 pack_int64(p, (uint64_t) 0); /* pack system_memory_used */
2197         }
2198
2199         pack_int32(p, sys_info->total_used_drive);
2200         pack_int32(p, sys_info->disk_reads);
2201         pack_int32(p, sys_info->disk_sectors_read);
2202         pack_int32(p, sys_info->disk_writes);
2203         pack_int32(p, sys_info->disk_sectors_write);
2204
2205         pack_int32(p, sys_info->network_send_size);
2206         pack_int32(p, sys_info->network_receive_size);
2207
2208         pack_int32(p, sys_info->wifi_status);
2209         pack_int32(p, sys_info->bt_status);
2210         pack_int32(p, sys_info->gps_status);
2211         pack_int32(p, sys_info->brightness_status);
2212         pack_int32(p, sys_info->camera_status);
2213         pack_int32(p, sys_info->sound_status);
2214         pack_int32(p, sys_info->audio_status);
2215         pack_int32(p, sys_info->vibration_status);
2216         pack_int32(p, sys_info->voltage_status);
2217         pack_int32(p, sys_info->rssi_status);
2218         pack_int32(p, sys_info->video_status);
2219         pack_int32(p, sys_info->call_status);
2220         pack_int32(p, sys_info->dnet_status);
2221
2222         pack_int32(p, sys_info->energy);
2223         for (i = 0; i != supported_devices_count; ++i)
2224                 pack_int32(p, sys_info->energy_per_device[i]);
2225         for (i = 0; i != supported_devices_count; ++i)
2226                 pack_int32(p, sys_info->app_energy_per_device[i]);
2227
2228         return msg;
2229 }