tizen 2.3 release tizen_2.3 submit/tizen_2.3/20150202.063927 tizen_2.3_release
authorjk7744.park <jk7744.park@samsung.com>
Sat, 31 Jan 2015 07:42:46 +0000 (16:42 +0900)
committerjk7744.park <jk7744.park@samsung.com>
Sat, 31 Jan 2015 07:42:46 +0000 (16:42 +0900)
56 files changed:
AUTHOR [new file with mode: 0644]
LICENSE [new file with mode: 0644]
NOTICE [new file with mode: 0644]
daemon/Makefile [new file with mode: 0644]
daemon/buffer.c [new file with mode: 0644]
daemon/buffer.h [new file with mode: 0644]
daemon/da_data.c [new file with mode: 0644]
daemon/da_data.h [new file with mode: 0644]
daemon/da_debug.c [new file with mode: 0644]
daemon/da_inst.c [new file with mode: 0644]
daemon/da_inst.h [new file with mode: 0644]
daemon/da_protocol.c [new file with mode: 0644]
daemon/da_protocol.h [new file with mode: 0644]
daemon/da_protocol_check.c [new file with mode: 0644]
daemon/da_protocol_check.h [new file with mode: 0644]
daemon/da_protocol_inst.c [new file with mode: 0644]
daemon/da_protocol_inst.h [new file with mode: 0644]
daemon/daemon.c [new file with mode: 0644]
daemon/daemon.h [new file with mode: 0644]
daemon/debug.c [new file with mode: 0644]
daemon/debug.h [new file with mode: 0644]
daemon/device_camera.c [new file with mode: 0644]
daemon/device_camera.h [new file with mode: 0644]
daemon/device_system_info.c [new file with mode: 0644]
daemon/device_system_info.h [new file with mode: 0644]
daemon/device_vconf.c [new file with mode: 0644]
daemon/device_vconf.h [new file with mode: 0644]
daemon/elf.c [new file with mode: 0644]
daemon/elf.h [new file with mode: 0644]
daemon/input_events.c [new file with mode: 0644]
daemon/input_events.h [new file with mode: 0644]
daemon/ioctl_commands.c [new file with mode: 0644]
daemon/ioctl_commands.h [new file with mode: 0644]
daemon/main.c [new file with mode: 0644]
daemon/malloc_debug.c [new file with mode: 0644]
daemon/malloc_debug.h [new file with mode: 0644]
daemon/md5.c [new file with mode: 0644]
daemon/md5.h [new file with mode: 0644]
daemon/smack.c [new file with mode: 0644]
daemon/smack.h [new file with mode: 0644]
daemon/start.sh [new file with mode: 0755]
daemon/stop.sh [new file with mode: 0755]
daemon/sys_stat.c [new file with mode: 0644]
daemon/sys_stat.h [new file with mode: 0644]
daemon/target.c [new file with mode: 0644]
daemon/target.h [new file with mode: 0644]
daemon/thread.c [new file with mode: 0644]
daemon/thread.h [new file with mode: 0644]
daemon/threads.c [new file with mode: 0644]
daemon/threads.h [new file with mode: 0644]
daemon/transfer_thread.c [new file with mode: 0644]
daemon/transfer_thread.h [new file with mode: 0644]
daemon/utils.c [new file with mode: 0644]
daemon/utils.h [new file with mode: 0644]
packaging/swap-manager.spec [new file with mode: 0644]
swap-manager.manifest [new file with mode: 0644]

diff --git a/AUTHOR b/AUTHOR
new file mode 100644 (file)
index 0000000..06d608b
--- /dev/null
+++ b/AUTHOR
@@ -0,0 +1,10 @@
+Jaewon Lim <jaewon81.lim@samsung.com>
+Woojin Jung <woojin2.jung@samsung.com>
+Yeongtaik Byeon <yeongtaik.byeon@samsung.com>
+Jooyoul Lee <jy.exe.lee@samsung.com>
+Sanghyun Lee <sanghyunnim.lee@samsung.com>
+Juyoung Kim <j0.kim@samsung.com>
+HyunGoo Kang <hyungoo1.kang@samsung.com>
+Nikita Kalyazin <n.kalyazin@samsung.com>
+Vitaliy Cherepanov <v.cherepanov@samsung.com>
+Dmitry Bogatov <d.bogatov@samsung.com>
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..5554685
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,204 @@
+                                 Apache License\r
+                           Version 2.0, January 2004\r
+                        http://www.apache.org/licenses/\r
+\r
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\r
+\r
+   1. Definitions.\r
+\r
+      "License" shall mean the terms and conditions for use, reproduction,\r
+      and distribution as defined by Sections 1 through 9 of this document.\r
+\r
+      "Licensor" shall mean the copyright owner or entity authorized by\r
+      the copyright owner that is granting the License.\r
+\r
+      "Legal Entity" shall mean the union of the acting entity and all\r
+      other entities that control, are controlled by, or are under common\r
+      control with that entity. For the purposes of this definition,\r
+      "control" means (i) the power, direct or indirect, to cause the\r
+      direction or management of such entity, whether by contract or\r
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the\r
+      outstanding shares, or (iii) beneficial ownership of such entity.\r
+\r
+      "You" (or "Your") shall mean an individual or Legal Entity\r
+      exercising permissions granted by this License.\r
+\r
+      "Source" form shall mean the preferred form for making modifications,\r
+      including but not limited to software source code, documentation\r
+      source, and configuration files.\r
+\r
+      "Object" form shall mean any form resulting from mechanical\r
+      transformation or translation of a Source form, including but\r
+      not limited to compiled object code, generated documentation,\r
+      and conversions to other media types.\r
+\r
+      "Work" shall mean the work of authorship, whether in Source or\r
+      Object form, made available under the License, as indicated by a\r
+      copyright notice that is included in or attached to the work\r
+      (an example is provided in the Appendix below).\r
+\r
+      "Derivative Works" shall mean any work, whether in Source or Object\r
+      form, that is based on (or derived from) the Work and for which the\r
+      editorial revisions, annotations, elaborations, or other modifications\r
+      represent, as a whole, an original work of authorship. For the purposes\r
+      of this License, Derivative Works shall not include works that remain\r
+      separable from, or merely link (or bind by name) to the interfaces of,\r
+      the Work and Derivative Works thereof.\r
+\r
+      "Contribution" shall mean any work of authorship, including\r
+      the original version of the Work and any modifications or additions\r
+      to that Work or Derivative Works thereof, that is intentionally\r
+      submitted to Licensor for inclusion in the Work by the copyright owner\r
+      or by an individual or Legal Entity authorized to submit on behalf of\r
+      the copyright owner. For the purposes of this definition, "submitted"\r
+      means any form of electronic, verbal, or written communication sent\r
+      to the Licensor or its representatives, including but not limited to\r
+      communication on electronic mailing lists, source code control systems,\r
+      and issue tracking systems that are managed by, or on behalf of, the\r
+      Licensor for the purpose of discussing and improving the Work, but\r
+      excluding communication that is conspicuously marked or otherwise\r
+      designated in writing by the copyright owner as "Not a Contribution."\r
+\r
+      "Contributor" shall mean Licensor and any individual or Legal Entity\r
+      on behalf of whom a Contribution has been received by Licensor and\r
+      subsequently incorporated within the Work.\r
+\r
+   2. Grant of Copyright License. Subject to the terms and conditions of\r
+      this License, each Contributor hereby grants to You a perpetual,\r
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\r
+      copyright license to reproduce, prepare Derivative Works of,\r
+      publicly display, publicly perform, sublicense, and distribute the\r
+      Work and such Derivative Works in Source or Object form.\r
+\r
+   3. Grant of Patent License. Subject to the terms and conditions of\r
+      this License, each Contributor hereby grants to You a perpetual,\r
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\r
+      (except as stated in this section) patent license to make, have made,\r
+      use, offer to sell, sell, import, and otherwise transfer the Work,\r
+      where such license applies only to those patent claims licensable\r
+      by such Contributor that are necessarily infringed by their\r
+      Contribution(s) alone or by combination of their Contribution(s)\r
+      with the Work to which such Contribution(s) was submitted. If You\r
+      institute patent litigation against any entity (including a\r
+      cross-claim or counterclaim in a lawsuit) alleging that the Work\r
+      or a Contribution incorporated within the Work constitutes direct\r
+      or contributory patent infringement, then any patent licenses\r
+      granted to You under this License for that Work shall terminate\r
+      as of the date such litigation is filed.\r
+\r
+   4. Redistribution. You may reproduce and distribute copies of the\r
+      Work or Derivative Works thereof in any medium, with or without\r
+      modifications, and in Source or Object form, provided that You\r
+      meet the following conditions:\r
+\r
+      (a) You must give any other recipients of the Work or\r
+          Derivative Works a copy of this License; and\r
+\r
+      (b) You must cause any modified files to carry prominent notices\r
+          stating that You changed the files; and\r
+\r
+      (c) You must retain, in the Source form of any Derivative Works\r
+          that You distribute, all copyright, patent, trademark, and\r
+          attribution notices from the Source form of the Work,\r
+          excluding those notices that do not pertain to any part of\r
+          the Derivative Works; and\r
+\r
+      (d) If the Work includes a "NOTICE" text file as part of its\r
+          distribution, then any Derivative Works that You distribute must\r
+          include a readable copy of the attribution notices contained\r
+          within such NOTICE file, excluding those notices that do not\r
+          pertain to any part of the Derivative Works, in at least one\r
+          of the following places: within a NOTICE text file distributed\r
+          as part of the Derivative Works; within the Source form or\r
+          documentation, if provided along with the Derivative Works; or,\r
+          within a display generated by the Derivative Works, if and\r
+          wherever such third-party notices normally appear. The contents\r
+          of the NOTICE file are for informational purposes only and\r
+          do not modify the License. You may add Your own attribution\r
+          notices within Derivative Works that You distribute, alongside\r
+          or as an addendum to the NOTICE text from the Work, provided\r
+          that such additional attribution notices cannot be construed\r
+          as modifying the License.\r
+\r
+      You may add Your own copyright statement to Your modifications and\r
+      may provide additional or different license terms and conditions\r
+      for use, reproduction, or distribution of Your modifications, or\r
+      for any such Derivative Works as a whole, provided Your use,\r
+      reproduction, and distribution of the Work otherwise complies with\r
+      the conditions stated in this License.\r
+\r
+   5. Submission of Contributions. Unless You explicitly state otherwise,\r
+      any Contribution intentionally submitted for inclusion in the Work\r
+      by You to the Licensor shall be under the terms and conditions of\r
+      this License, without any additional terms or conditions.\r
+      Notwithstanding the above, nothing herein shall supersede or modify\r
+      the terms of any separate license agreement you may have executed\r
+      with Licensor regarding such Contributions.\r
+\r
+   6. Trademarks. This License does not grant permission to use the trade\r
+      names, trademarks, service marks, or product names of the Licensor,\r
+      except as required for reasonable and customary use in describing the\r
+      origin of the Work and reproducing the content of the NOTICE file.\r
+\r
+   7. Disclaimer of Warranty. Unless required by applicable law or\r
+      agreed to in writing, Licensor provides the Work (and each\r
+      Contributor provides its Contributions) on an "AS IS" BASIS,\r
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\r
+      implied, including, without limitation, any warranties or conditions\r
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\r
+      PARTICULAR PURPOSE. You are solely responsible for determining the\r
+      appropriateness of using or redistributing the Work and assume any\r
+      risks associated with Your exercise of permissions under this License.\r
+\r
+   8. Limitation of Liability. In no event and under no legal theory,\r
+      whether in tort (including negligence), contract, or otherwise,\r
+      unless required by applicable law (such as deliberate and grossly\r
+      negligent acts) or agreed to in writing, shall any Contributor be\r
+      liable to You for damages, including any direct, indirect, special,\r
+      incidental, or consequential damages of any character arising as a\r
+      result of this License or out of the use or inability to use the\r
+      Work (including but not limited to damages for loss of goodwill,\r
+      work stoppage, computer failure or malfunction, or any and all\r
+      other commercial damages or losses), even if such Contributor\r
+      has been advised of the possibility of such damages.\r
+\r
+   9. Accepting Warranty or Additional Liability. While redistributing\r
+      the Work or Derivative Works thereof, You may choose to offer,\r
+      and charge a fee for, acceptance of support, warranty, indemnity,\r
+      or other liability obligations and/or rights consistent with this\r
+      License. However, in accepting such obligations, You may act only\r
+      on Your own behalf and on Your sole responsibility, not on behalf\r
+      of any other Contributor, and only if You agree to indemnify,\r
+      defend, and hold each Contributor harmless for any liability\r
+      incurred by, or claims asserted against, such Contributor by reason\r
+      of your accepting any such warranty or additional liability.\r
+\r
+   END OF TERMS AND CONDITIONS\r
+\r
+   APPENDIX: How to apply the Apache License to your work.\r
+\r
+      To apply the Apache License to your work, attach the following\r
+      boilerplate notice, with the fields enclosed by brackets "[]"\r
+      replaced with your own identifying information. (Don't include\r
+      the brackets!)  The text should be enclosed in the appropriate\r
+      comment syntax for the file format. We also recommend that a\r
+      file or class name and description of purpose be included on the\r
+      same "printed page" as the copyright notice for easier\r
+      identification within third-party archives.\r
+\r
+   Copyright [yyyy] [name of copyright owner]\r
+\r
+   Licensed under the Apache License, Version 2.0 (the "License");\r
+   you may not use this file except in compliance with the License.\r
+   You may obtain a copy of the License at\r
+\r
+       http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+\r
+\r
+\r
diff --git a/NOTICE b/NOTICE
new file mode 100644 (file)
index 0000000..9b940fb
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,4 @@
+Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved.
+Except as noted, this software is licensed under Apache License, Version 2.
+Please, see the LICENSE.APLv2 file for Apache License terms and conditions.
diff --git a/daemon/Makefile b/daemon/Makefile
new file mode 100644 (file)
index 0000000..5b8cf08
--- /dev/null
@@ -0,0 +1,81 @@
+CC :=gcc
+DEBUG_CPPFLAGS =                               \
+               -DDEBUG                                 \
+               -DUSE_LOG_ONCE                  \
+#              -DMALLOC_DEBUG_LEVEL=1          \#
+#              -DMALLOC_DEBUG_LEVEL=2          \#
+#              -DDEB_PRINTBUF                  \#
+#              -DPARSE_DEBUG_ON                \#
+#              -DTHREAD_SAMPLING_DEBUG \#
+#              -DTHREAD_REPLAY_DEBUG   #
+
+CPPFLAGS :=    -I/usr/include          \
+               -I/usr/include/system   \
+               -I/usr/include/capi-system-info \
+               -I/usr/include/capi-system-runtime-info \
+               -I/usr/include/vconf    \
+               $(DEBUG_CPPFLAGS)
+ifeq (arm, $(findstring arm, $(shell uname -sm)))
+       CPPFLAGS += -DDEVICE_ONLY
+endif
+
+COMMON_LIBS := -lglib-2.0 -lpthread
+TARGET_LIBS := $(COMMON_LIBS) -lvconf -lsmack -lcapi-system-info -lecore -leina -lpthread
+CFLAGS := -Wall -pthread -g -O0 \
+                 -I/usr/include/ecore-1 \
+                 -I/usr/include/eina-1 \
+                 -I/usr/include/eina-1/eina \
+                 -I/usr/include/efl-1 \
+                 -I/usr/include/eo-1
+
+DAEMON_SRCS =                  \
+       buffer.c                \
+       da_data.c               \
+       da_debug.c              \
+       da_protocol.c           \
+       da_protocol_inst.c      \
+       da_inst.c               \
+       daemon.c                \
+       debug.c                 \
+       elf.c                   \
+       ioctl_commands.c        \
+       main.c                  \
+       sys_stat.c              \
+       threads.c               \
+       transfer_thread.c       \
+       utils.c                 \
+       da_protocol_check.c     \
+       md5.c                   \
+       input_events.c          \
+       device_vconf.c          \
+       device_system_info.c    \
+       device_camera.c         \
+       smack.c                                 \
+       malloc_debug.c \
+       target.c \
+       thread.c
+
+DAEMON_OBJS = $(patsubst %.c,%.o, $(DAEMON_SRCS))
+
+TARGET = da_manager
+START_SH = start.sh
+STOP_SH = stop.sh
+
+all: debug
+debug release: $(TARGET_LIBS)
+release: CPPFLAGS += -DNOLOGI=1
+debug release: $(DAEMON_OBJS)
+       $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $(TARGET)
+
+install: BINDIR = $(DESTDIR)/usr/bin
+install: OPTDIR = $(DESTDIR)/opt/swap/sdk
+install: $(TARGET)
+       mkdir -p $(BINDIR)
+       mkdir -p $(OPTDIR)
+       install $(TARGET) -t $(BINDIR)
+       install -m 755 $(START_SH) $(STOP_SH) -t $(OPTDIR)
+
+clean:
+       rm -f $(TARGET) $(DAEMON_OBJS)
+
+.PHONY: all debug release clean install
diff --git a/daemon/buffer.c b/daemon/buffer.c
new file mode 100644 (file)
index 0000000..e304cd4
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ * Nikita Kalyazin    <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include "daemon.h"
+#include "buffer.h"
+#include "ioctl_commands.h"
+#include "debug.h"
+
+#define SUBBUF_SIZE 32 * 1024
+#define SUBBUF_NUM 8
+
+static int open_tasks_dev(void)
+{
+       if (manager.fd.inst_tasks == NULL) {
+               manager.fd.inst_tasks = fopen(INST_PID_FILENAME, "re");
+               if (manager.fd.inst_tasks == NULL) {
+                       GETSTRERROR(errno, buf);
+                       LOGE("Cannot open tasks dev: %s\n", buf);
+                       return 1;
+               }
+               LOGI("tasks dev opened: %s, %d\n", BUF_FILENAME, manager.buf_fd);
+       } else {
+               LOGW("tasks dev double open try: <%s>\n", INST_PID_FILENAME);
+       }
+
+       return 0;
+}
+
+static void close_tasks_dev(void)
+{
+       LOGI("close tasks dev (%d)\n", manager.fd.inst_tasks);
+       if (manager.fd.inst_tasks != NULL) {
+               fclose(manager.fd.inst_tasks);
+               manager.fd.inst_tasks = NULL;
+       } else {
+               LOGW("manager.fd.inst_tasks alredy closed or not opened\n");
+       }
+}
+
+static int open_buf_ctl(void)
+{
+       manager.buf_fd = open(BUF_FILENAME, O_RDONLY | O_CLOEXEC);
+       if (manager.buf_fd == -1) {
+               GETSTRERROR(errno, buf);
+               LOGE("Cannot open buffer: %s\n", buf);
+               return 1;
+       }
+       LOGI("buffer opened: %s, %d\n", BUF_FILENAME, manager.buf_fd);
+
+       manager.user_ev_fd = open(USER_EVENT_FILENAME, O_WRONLY | O_CLOEXEC);
+       if (manager.user_ev_fd == -1) {
+               GETSTRERROR(errno, buf);
+               LOGE("Cannot open user event sysfs file: %s\n", buf);
+               return 1;
+       }
+       LOGI("user event sysfs file opened: %s, %d\n", USER_EVENT_FILENAME,
+            manager.user_ev_fd);
+
+       return 0;
+}
+
+static void close_buf_ctl(void)
+{
+       LOGI("close buffer (%d)\n", manager.buf_fd);
+       close(manager.buf_fd);
+
+       LOGI("close user event sysfs file (%d)\n", manager.user_ev_fd);
+       close(manager.user_ev_fd);
+}
+
+static int insert_buf_modules(void)
+{
+       if (system("cd /opt/swap/sdk && ./start.sh")) {
+               LOGE("Cannot insert swap modules\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+int init_buf(void)
+{
+       struct buffer_initialize init = {
+               .size = SUBBUF_SIZE,
+               .count = SUBBUF_NUM,
+       };
+
+       if (insert_buf_modules() != 0) {
+               LOGE("Cannot insert buffer modules\n");
+               return 1;
+       }
+
+       if (open_buf_ctl() != 0) {
+               LOGE("Cannot open buffer\n");
+               return 1;
+       }
+
+       if (ioctl(manager.buf_fd, SWAP_DRIVER_BUFFER_INITIALIZE, &init) == -1) {
+               GETSTRERROR(errno, buf);
+               LOGE("Cannot init buffer: %s\n", buf);
+               return 1;
+       }
+
+       if (open_tasks_dev() != 0) {
+               GETSTRERROR(errno, buf);
+               LOGE("Cannot open tasks: %s\n", buf);
+               return 1;
+       }
+
+       return 0;
+}
+
+void exit_buf(void)
+{
+       LOGI("Uninit driver (%d)\n", manager.buf_fd);
+       if (ioctl(manager.buf_fd, SWAP_DRIVER_BUFFER_UNINITIALIZE) == -1) {
+               GETSTRERROR(errno, buf);
+               LOGW("Cannot uninit driver: %s\n", buf);
+       }
+
+       close_buf_ctl();
+       close_tasks_dev();
+}
+
+void flush_buf(void)
+{
+       if (ioctl(manager.buf_fd, SWAP_DRIVER_FLUSH_BUFFER) == -1) {
+               GETSTRERROR(errno, buf);
+               LOGW("Cannot send flush to driver: %s\n", buf);
+       }
+}
+
+void wake_up_buf(void)
+{
+       if (ioctl(manager.buf_fd, SWAP_DRIVER_WAKE_UP) == -1) {
+               GETSTRERROR(errno, buf);
+               LOGW("Cannot send wake up to driver: %s\n", buf);
+       }
+}
+
+int write_to_buf(struct msg_data_t *msg)
+{
+       uint32_t total_len = MSG_DATA_HDR_LEN + msg->len;
+
+       if (write(manager.user_ev_fd, msg, total_len) == -1) {
+               GETSTRERROR(errno, buf);
+               LOGE("write to buf (user_ev_fd=%d, msg=%p, len=%d) %s\n",
+                    manager.user_ev_fd, msg, total_len, buf);
+               return 1;
+       }
+       return 0;
+}
diff --git a/daemon/buffer.h b/daemon/buffer.h
new file mode 100644 (file)
index 0000000..f509e07
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ * Nikita Kalyazin    <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#ifndef _BUFFER_
+#define _BUFFER_
+
+#include "da_protocol.h"
+
+#define USER_EVENT_FILENAME "/sys/kernel/debug/swap/writer/raw"
+#define BUF_FILENAME "/dev/swap_device"
+#define INST_PID_FILENAME "/sys/kernel/debug/swap/us_manager/tasks"
+
+int init_buf(void);
+void exit_buf(void);
+void flush_buf(void);
+void wake_up_buf(void);
+int write_to_buf(struct msg_data_t *msg);
+
+#endif /* _BUFFER_ */
diff --git a/daemon/da_data.c b/daemon/da_data.c
new file mode 100644 (file)
index 0000000..f0a630d
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ * Nikita Kalyazin    <:wn.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#include "da_protocol.h"
+#include "daemon.h"
+#include "da_data.h"
+#include "debug.h"
+
+#include <sys/time.h>
+
+int print_sys_info(struct system_info_t * sys_info)
+{
+       int i = 0;
+       /* //FOR DEBUG
+       sys_info->energy=0x1;
+       sys_info->wifi_status=0x2;
+       sys_info->bt_status=0x3;
+       sys_info->gps_status=0x4;
+       sys_info->brightness_status=0x5;
+
+       sys_info->camera_status=0x6;
+       sys_info->sound_status=0x7;
+       sys_info->audio_status=0x8;
+       sys_info->vibration_status=0x9;
+       sys_info->voltage_status=0x10;
+
+       sys_info->rssi_status=0x11;
+       sys_info->video_status=0x12;
+       sys_info->call_status=0x13;
+       sys_info->dnet_status=0x14;
+       sys_info->cpu_frequency=0x15;
+
+       sys_info->app_cpu_usage=0.0;
+       sys_info->cpu_load=0x17;
+       sys_info->virtual_memory=0x18;
+       sys_info->resident_memory=0x19;
+       sys_info->shared_memory=0x20;
+
+       sys_info->pss_memory=0x21;
+       sys_info->total_alloc_size=(uint64_t)0x22;
+       sys_info->system_memory_total=(uint64_t)0x23;
+       sys_info->system_memory_used=(uint64_t)0x24;
+       sys_info->total_used_drive=0x25;
+
+       sys_info->count_of_threads=0x26;
+       sys_info->thread_load=0x27;
+       sys_info->count_of_processes=0x28;
+       sys_info->process_load=0x29;
+       sys_info->disk_read_size=0x30;
+
+       sys_info->disk_write_size=0x31;
+       sys_info->network_send_size=0x32;
+       sys_info->network_receive_size=0x33;
+       */
+
+       // TODO do it
+       /*
+       LOGI("sysinfo:\n\
+\
+       energy = 0x%X\n\
+       wifi_status = 0x%X\n\
+       bt_status = 0x%X\n\
+       gps_status = 0x%X\n\
+       brightness_status = 0x%X\n\
+\
+       camera_status = 0x%X\n\
+       sound_status = 0x%X\n\
+       audio_status = 0x%X\n\
+       vibration_status = 0x%X\n\
+       voltage_status = 0x%X\n\
+\
+       rssi_status = 0x%X\n\
+       video_status = 0x%X\n\
+       call_status = 0x%X\n\
+       dnet_status = 0x%X\n\
+       cpu_frequency (pointer)= 0x%X\n\
+\
+       app_cpu_usage = %f\n\
+       cpu_load (pointer)= 0x%X\n\
+       virtual_memory = 0x%X\n\
+       resident_memory = 0x%X\n\
+       shared_memory = 0x%X\n\
+\
+       pss_memory = 0x%X\n\
+       total_alloc_size = 0x%X\n\
+       system_memory_total = %llu\n\
+       system_memory_used = %llu\n\
+       total_used_drive = %d\n\
+\
+       count_of_threads = %u\n\
+       thread_load (pointer)= 0x%X\n\
+       count_of_processes = %u\n\
+       process_load = 0x%X\n\
+       disk_reads = 0x%X\n\
+\
+       disk_sectors_read = 0x%X\n\
+       disk_writes = 0x%X\n\
+       disk_sectors_write = 0x%X\n\
+       network_send_size = 0x%X\n\
+       network_receive_size = 0x%X\n",
+
+       sys_info->energy,
+       sys_info->wifi_status,
+       sys_info->bt_status,
+       sys_info->gps_status,
+       sys_info->brightness_status,
+
+       sys_info->camera_status,
+       sys_info->sound_status,
+       sys_info->audio_status,
+       sys_info->vibration_status,
+       sys_info->voltage_status,
+
+       sys_info->rssi_status,
+       sys_info->video_status,
+       sys_info->call_status,
+       sys_info->dnet_status,
+       (unsigned int)sys_info->cpu_frequency,
+
+       sys_info->app_cpu_usage,
+       (unsigned int)sys_info->cpu_load,
+       sys_info->virtual_memory,
+       sys_info->resident_memory,
+       sys_info->shared_memory,
+
+       sys_info->pss_memory,
+       sys_info->total_alloc_size,
+       sys_info->system_memory_total,
+       sys_info->system_memory_used,
+       sys_info->total_used_drive,
+
+       sys_info->count_of_threads,
+       (unsigned int)sys_info->thread_load,
+       sys_info->count_of_processes,
+       (unsigned int)sys_info->process_load,
+       sys_info->disk_reads,
+
+       sys_info->disk_sectors_read,
+       sys_info->disk_writes,
+       sys_info->disk_sectors_write,
+       sys_info->network_send_size,
+       sys_info->network_receive_size
+       );
+       LOGI_("->\n");
+       for ( i=0; i<sys_info->count_of_processes; i++)
+       {
+               LOGI_("\tpr %016X : %f\n",
+               sys_info->process_load[i].id,
+               sys_info->process_load[i].load
+               );
+       }
+       for ( i=0; i<sys_info->count_of_threads; i++)
+       {
+               LOGI_("\tth %016X : %f\n",
+               sys_info->thread_load[i].pid,
+               sys_info->thread_load[i].load
+               );
+       }
+
+       // FIXME CPU core num hardcoded
+       for ( i=0; i<4; i++)
+       {
+               LOGI_("\tCPU load #%d : %f\n",
+               i,
+               sys_info->cpu_load[i]
+               );
+       }
+       // FIXME CPU core num hardcoded
+       for ( i=0; i<4; i++)
+       {
+               LOGI_("\tCPU freq #%d : %f\n",
+               i,
+               sys_info->cpu_frequency[i]
+               );
+       }
+//     char *p = sys_info;
+       printBuf((char*)sys_info, sizeof(*sys_info));
+*/
+       return 0;
+}
+
+int fill_data_msg_head (struct msg_data_t *data, uint32_t msgid,
+                                                       uint32_t seq, uint32_t len)
+{
+       struct timeval time;
+       data->id = msgid;
+       data->seq_num = seq; // TODO fill good value
+       gettimeofday(&time, NULL);
+       data->sec = time.tv_sec;
+       data->nsec = time.tv_usec * 1000;
+       data->len = len;
+       return 0;
+}
+
+
+//allocate memory, need free!!!
+struct msg_data_t *gen_message_terminate(uint32_t id)
+{
+       uint32_t payload_len = sizeof(uint32_t);
+       struct msg_data_t *data = malloc(sizeof(*data) + payload_len);
+       char *p;
+       fill_data_msg_head(data,NMSG_TERMINATE, 0, payload_len);
+       // TODO fill good value
+       p = data->payload;
+       pack_int32(p, id);
+       return data;
+}
+
+//allocate memory, need free!!!
+struct msg_data_t *gen_message_error(const char * err_msg)
+{
+       int payload_len = strlen(err_msg)+1;
+       struct msg_data_t *data = malloc(sizeof(*data) + payload_len);
+       char *p;
+       fill_data_msg_head(data, NMSG_ERROR, 0, payload_len);
+
+       p = data->payload;
+       pack_str(p,err_msg);
+       return data;
+}
+
+//allocatr memory, need free!!!
+struct msg_data_t *gen_message_event(
+                     struct input_event *events,
+                     uint32_t events_count,
+                     uint32_t id)
+{
+       uint32_t i = 0;
+       uint32_t payload_len = events_count * (sizeof(id) * 4) +
+                                                       sizeof(events_count);
+       struct msg_data_t *data = malloc(sizeof(*data) + payload_len);
+       memset(data,0,sizeof(*data) + payload_len);
+       char *p;
+
+       fill_data_msg_head(data, NMSG_RECORD, 0, payload_len);
+
+       p = data->payload;
+       pack_int32(p, events_count);
+
+       /* FIXME events[i].type, events[i].code should be uint16_t */
+       for (i=0; i<events_count; i++){
+               pack_int32(p,id);
+               pack_int32(p, (int32_t) events[i].type);
+               pack_int32(p, (int32_t) events[i].code);
+               pack_int32(p,events[i].value);
+       }
+
+       return data;
+}
+
+void inline free_msg_data(struct msg_data_t *msg)
+{
+       free(msg);
+};
diff --git a/daemon/da_data.h b/daemon/da_data.h
new file mode 100644 (file)
index 0000000..036b78e
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ * Nikita Kalyazin    <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#ifndef _DA_DATA_H_
+#define _DA_DATA_H_
+int fill_data_msg_head (struct msg_data_t *data, uint32_t msgid,
+                                               uint32_t seq, uint32_t len);
+//allocate memory, need free!!!
+struct msg_data_t *gen_message_terminate(uint32_t id);
+
+//allocatr memory, need free!!!
+struct msg_data_t *gen_message_event(
+                     struct input_event *events,
+                     uint32_t events_count,
+                     uint32_t id);
+
+
+struct msg_data_t *gen_message_error(const char * err_msg);
+
+struct msg_data_t *gen_message_event(
+                     struct input_event *events,
+                     uint32_t events_count,
+                     uint32_t id);
+
+int reset_data_msg(struct msg_data_t *data);
+
+//DEBUGS
+int print_sys_info(struct system_info_t * sys_info);
+#endif //#ifndef _DA_DATA_H_
diff --git a/daemon/da_debug.c b/daemon/da_debug.c
new file mode 100644 (file)
index 0000000..0315511
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Jaewon Lim <jaewon81.lim@samsung.com>
+ * Woojin Jung <woojin2.jung@samsung.com>
+ * Juyoung Kim <j0.kim@samsung.com>
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ * Nikita Kalyazin    <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ * - Samsung RnD Institute Russia
+ *
+ */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "daemon.h"
+#include "debug.h"
+#include <errno.h>
+
+#define DEBUG_LOGFILE          "/tmp/daemonlog.da"
+
+#if DEBUG
+static inline int close_on_exec_dup(int old, int new)
+{
+       int ret = -1;
+
+       if (dup2(old, new) != -1) {
+               unsigned long flags = fcntl(new, F_GETFD);
+               if (flags == -1) {
+                       LOGE("can not get flags fd #%d errno <%d>\n", new,
+                            errno);
+                       goto err_ret;
+               }
+
+               if (fcntl(new, F_SETFD, flags | FD_CLOEXEC) == -1) {
+                       LOGE("can not get flags fd #%d errno <%d>\n", new,
+                            errno);
+                       goto err_ret;
+               }
+       } else {
+               LOGE("dup2 fail\n");
+               goto err_ret;
+       }
+
+       /* success */
+       ret = 0;
+
+err_ret:
+       return ret;
+}
+
+int initialize_log(void)
+{
+       /* TODO fix problem with ecore and redirect stderr to DEBUG_LOGFILE back
+        *
+        * error sample
+        * *** IN FUNCTION: _ecore_main_fdh_epoll_mark_active()
+        * ERR<2328>:ecore ecore.c:572 _ecore_magic_fail()   Input handle has already been freed!
+        * ERR<2328>:ecore ecore.c:581 _ecore_magic_fail() *** NAUGHTY PROGRAMMER!!!
+        * *** SPANK SPANK SPANK!!!
+        *
+        */
+       int ret = 0;
+       int fd = -1;
+       int fd_null = -1;
+
+       if (remove(DEBUG_LOGFILE))
+               LOGE("remove(%s), return error, errno=%d\n",
+                    DEBUG_LOGFILE, errno);
+
+       fd = open(DEBUG_LOGFILE, O_WRONLY | O_CREAT | O_TRUNC, 0777);
+       fd_null = open("/dev/null", O_WRONLY | O_CREAT | O_TRUNC, 0777);
+
+       if (fd != -1 && fd_null != -1) {
+               if (close_on_exec_dup(fd_null, 1) != 0 ||
+                   close_on_exec_dup(fd, 2) != 0) {
+                       LOGE("duplicate fd fail\n");
+                       ret = -1;
+               }
+       } else {
+               close(1);
+               close(2);
+       }
+
+       if (fd_null != -1)
+               close(fd_null);
+
+       if (fd != -1)
+               close(fd);
+
+       close(0);
+       return ret;
+}
+
+#else
+int initialize_log(void)
+{
+       return 0;
+}
+#endif
diff --git a/daemon/da_inst.c b/daemon/da_inst.c
new file mode 100644 (file)
index 0000000..78446cd
--- /dev/null
@@ -0,0 +1,837 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+// TODO check memory (malloc, free)
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <linux/limits.h>
+
+#include "da_inst.h"
+#include "da_protocol.h"
+#include "da_protocol_inst.h"
+#include "debug.h"
+#include "daemon.h"
+
+struct lib_list_t *new_lib_inst_list = NULL;
+
+uint32_t app_count = 0;
+char *packed_app_list = NULL;
+char *packed_lib_list = NULL;
+
+static struct _msg_target_t *lib_maps_message = NULL;
+static pthread_mutex_t lib_inst_list_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t lib_maps_message_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+uint32_t libs_count;
+
+//----------------------------------- lists ----------------------------------
+
+static int data_list_add_probe_to_hash(struct data_list_t *to, struct probe_list_t *probe)
+{
+       // TODO add hash
+       return 0;
+}
+
+// create hash for lib
+static int data_list_make_hash(struct data_list_t *what)
+{
+       struct probe_list_t *p;
+
+       for (p = what->list; p != NULL; p = p->next)
+               data_list_add_probe_to_hash(what, p);
+       return 0;
+}
+
+//------------ create - destroy
+static struct data_list_t *new_data(void)
+{
+       struct data_list_t *lib = malloc(sizeof(*lib));
+       lib->next = NULL;
+       lib->prev = NULL;
+       lib->hash = 0;
+       lib->size = 0;
+       lib->list = NULL;
+       return lib;
+}
+
+struct lib_list_t *new_lib(void)
+{
+       struct lib_list_t *lib = (struct lib_list_t *)new_data();
+       lib->lib = malloc(sizeof(*lib->lib));
+       memset(lib->lib, 0, sizeof(*lib->lib));
+       return lib;
+}
+
+struct app_list_t *new_app(void)
+{
+       struct app_list_t *app = (struct app_list_t *)new_data();
+       app->app = malloc(sizeof(*app->app));
+       memset(app->app, 0, sizeof(*app->app));
+       return app;
+}
+
+struct probe_list_t *new_probe(void)
+{
+       struct probe_list_t *probe = malloc(sizeof(*probe));
+       probe->next = NULL;
+       probe->prev = NULL;
+       probe->size = 0;
+       probe->func = NULL;
+       return probe;
+}
+
+static void free_probe_element(struct probe_list_t *probe)
+{
+       free(probe->func);
+       free(probe);
+}
+
+static void free_data_element(struct data_list_t *lib)
+{
+       free(lib->data);
+       free(lib);
+}
+
+static void free_probe_list(struct probe_list_t *probe)
+{
+       struct probe_list_t *next;
+       while (probe != NULL) {
+               next = probe->next;
+               free_probe_element(probe);
+               probe = next;
+       }
+}
+
+static void free_data(struct data_list_t *lib)
+{
+       free_probe_list(lib->list);
+       free_data_element(lib);
+}
+
+void free_data_list(struct data_list_t **data)
+{
+       struct data_list_t *next;
+       while (*data != NULL) {
+               next = (*data)->next;
+               free_data(*data);
+               *data = next;
+       }
+}
+
+//------------- add - remove
+int data_list_append(struct data_list_t **to, struct data_list_t *from)
+{
+       struct data_list_t *p = NULL;
+       if (*to == NULL) {
+               // empty list
+               *to = from;
+       } else {
+               p = *to;
+               *to = from;
+               from->next = (void *)p;
+               p->prev = (void *)from;
+       }
+       return 0;
+}
+
+
+static int data_list_append_probes_hash(struct data_list_t *to, struct data_list_t *from)
+{
+       struct probe_list_t *p = from->list;
+       struct probe_list_t *last = p;
+
+       to->size += p->size;
+       to->func_num += from->func_num;
+       for (p = from->list; p != NULL; p = p->next) {
+               data_list_add_probe_to_hash(to, p);
+               last = p;
+       }
+
+       last->next = to->list;
+       to->list->prev = last;
+       to->list = from->list;
+
+       return 1;
+}
+
+int probe_list_append(struct data_list_t *to, struct probe_list_t *from)
+{
+       struct probe_list_t **list = &(to->list);
+       struct probe_list_t *p = NULL;
+       uint32_t num = 0;
+       if (*list == NULL) {
+               // empty list
+               *list = from;
+       } else {
+               p = *list;
+               *list = from;
+               from->next = (void *)p;
+               p->prev = (void *)from;
+       }
+       to->size += from->size;
+
+       num = 0;
+       for (p = from; p != NULL; p = p->next)
+               num++;
+       to->func_num += num;
+       return 0;
+}
+
+static struct probe_list_t *probe_list_rm_element(struct data_list_t *list, struct probe_list_t *element)
+{
+       struct probe_list_t *prev = element->prev;
+       struct probe_list_t *next = element->next;
+
+       if (prev != NULL)
+               prev->next = next;
+       else
+               list->list = next;
+
+       if (next != NULL)
+               next->prev = prev;
+
+       list->size -= element->size;
+
+       list->func_num--;
+       free_probe_element(element);
+       return next;
+}
+
+static struct data_list_t *data_list_unlink_data(struct data_list_t **list, struct data_list_t *element)
+{
+       struct data_list_t *prev = element->prev;
+       struct data_list_t *next = element->next;
+
+       if (prev != NULL)
+               /* prev != null, next == null */
+               /* prev != null, next != null */
+               prev->next = next;
+       else
+               /* prev == null, next == null */
+               /* prev == null, next != null */
+               *list = next;
+
+       if (next != NULL)
+               next->prev = (struct lib_list_t *)prev;
+
+       element->prev = NULL;
+       element->next = NULL;
+
+       return next;
+}
+
+static struct data_list_t *data_list_rm_data(struct data_list_t **list, struct data_list_t *element)
+{
+       struct data_list_t *next = NULL;
+
+       next = data_list_unlink_data(list, element);
+       free_data_element(element);
+
+       return next;
+}
+
+// find
+static struct data_list_t *data_list_find_data(struct data_list_t *whered, struct data_list_t *whatd, cmp_data_f cmp)
+{
+       struct data_list_t *where;
+       struct data_list_t *what = whatd;
+       for (where = whered; where != NULL; where = where->next) {
+               if (where->hash == what->hash) {
+                       if (cmp(where, what))
+                               return where;
+               }
+       }
+       return NULL;
+}
+
+static struct probe_list_t *find_probe(struct data_list_t *where, struct probe_list_t *probe)
+{
+       struct probe_list_t *p ;
+       for (p = where->list; p != NULL; p = p->next)
+               if (p->size == probe->size)
+                       if (p->func->func_addr == probe->func->func_addr)
+                               if (strcmp(p->func->args, probe->func->args) == 0)
+                                       break;
+
+       return p;
+}
+
+// "from" will be destroyed after this call
+static int data_list_move_with_hash(struct data_list_t **to, struct data_list_t **from, cmp_data_f cmp)
+{
+
+       struct data_list_t *p = *from;
+       struct data_list_t *next = NULL;
+       struct data_list_t *sch = NULL;
+       while (p != NULL) {
+               sch = data_list_find_data(*to, p, cmp);
+               next = data_list_unlink_data(from, p);
+               if (sch == NULL) {
+                       data_list_make_hash(p);
+                       data_list_append(to, p);
+               } else {
+                       data_list_append_probes_hash(sch, p);
+               }
+               p = next;
+       }
+       return 1;
+}
+
+//---------------------------- collisions resolve ------------------------------
+
+static int cmp_libs(struct data_list_t *el_1, struct data_list_t *el_2)
+{
+       return (strcmp(
+                       ((struct lib_list_t *)el_1)->lib->bin_path,
+                       ((struct lib_list_t *)el_2)->lib->bin_path
+                       ) == 0);
+}
+
+///////////////////////////////////////////////////////////////////////////
+// function removes from new list all probes which are already installed
+//
+// cur - current state (lib list with probes)
+// new - additional probes which were received with MSG_SWAP_INST_ADD msg
+//       (lib list with probes)
+// this function removes all probes which are present in cur and new list from
+// new list so after this function call in new list will be only probes which are
+// not present in cur list
+static int resolve_collisions_for_add_msg(struct lib_list_t **cur, struct lib_list_t **new)
+{
+       struct data_list_t *p = (struct data_list_t *)*new;
+       struct data_list_t *sch = NULL;
+
+       struct probe_list_t *pr = NULL;
+       struct probe_list_t *next_pr = NULL;
+
+       // remove collisions from list "new"
+       while (p != NULL) {
+               sch = data_list_find_data((struct data_list_t *)*cur, p, cmp_libs);
+               if (sch == NULL) {
+                       // lib not found in cur config
+               } else {
+                       // lib found in cur config so resolve collisions
+                       pr = p->list;
+                       while (pr != NULL) {
+                               // remove collisions
+                               if (find_probe(sch, pr) != NULL) {
+                                       // probe already exist
+                                       // rm from new config
+                                       next_pr = probe_list_rm_element(p, pr);
+                                       pr = next_pr;
+                               } else {
+                                       pr = pr->next;
+                               }
+                       }
+
+                       // rm lib if it is empty
+                       if (p->list == NULL) {
+                               p = data_list_rm_data((struct data_list_t **)new, p);
+                               continue;
+                       }
+               }
+               p = p->next;
+       }
+       return 1;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// function removes from cur list all probes which are in list "new"
+//         and removes from "new" all probes which are not instaled
+//
+// cur - current state (lib list with probes)
+// new - list for probes remove which were received with MSG_SWAP_INST_REMOVE msg
+//
+// this function removes all probes which are present in cur and new list from
+// cur list and removes all probes which are present in new but not present in
+// cur list so after this function call in new list will be only probes which are
+// present in cur list
+static int resolve_collisions_for_rm_msg(struct lib_list_t **cur, struct lib_list_t **new)
+{
+       struct data_list_t *p = (struct data_list_t *)*new;
+       struct data_list_t *next_l = NULL;
+       struct data_list_t *sch = NULL;
+
+       struct probe_list_t *pr = NULL;
+       struct probe_list_t *next_pr = NULL;
+       struct probe_list_t *tmp = NULL;
+
+       // remove collisions from list "new"
+       while (p != NULL) {
+               sch = data_list_find_data((struct data_list_t *)*cur, p, cmp_libs);
+               if (sch == NULL) {
+                       //lib not found so no probes remove
+                       next_l = data_list_rm_data((struct data_list_t **)new, p);
+               } else {
+                       //lib found so we need remove collisions
+                       pr = p->list;
+                       if (pr == NULL) {
+                               // if rm probe list is empty that is mean we need
+                               // to remove all probes on this lib
+                               data_list_unlink_data((struct data_list_t **)cur, sch);
+                               data_list_append((struct data_list_t **)new, sch);
+                               next_l = data_list_rm_data((struct data_list_t **)cur, p);
+                       } else {
+                               // lib is not empty so merge
+                               while (pr != NULL) {
+                                       // remove collisions
+                                       if ((tmp = find_probe(sch, pr)) != NULL) {
+                                               // probe found so remove probe
+                                               // from cur state
+                                               probe_list_rm_element(sch, tmp);
+                                               pr = pr->next;
+                                       } else {
+                                               // probe no found so remove it
+                                               // from new state
+                                               next_pr = probe_list_rm_element(p, pr);
+                                               pr = next_pr;
+                                       }
+                               }
+                               // rm lib if it is empty
+                               if (sch->list == NULL) {
+                                       data_list_rm_data((struct data_list_t **)cur, sch);
+                               }
+                               next_l = p->next;
+                       }
+               }
+               p = next_l;
+       }
+       return 1;
+}
+
+//--------------------------------------pack ----------------------------------
+
+static char *pack_lib_head_to_array(char *to, void *data)
+{
+       struct us_lib_inst_t *lib = data;
+       pack_str(to, lib->bin_path);
+       return to;
+}
+
+static char *pack_app_head_to_array(char *to, void *data)
+{
+       struct app_info_t *app = data;
+       pack_int32(to, app->app_type);
+       pack_str(to, app->app_id);
+       pack_str(to, app->exe_path);
+       return to;
+}
+
+static char *pack_data_to_array(struct data_list_t *data, char *to, pack_head_t pack_head)
+{
+       struct probe_list_t *p;
+
+       to = pack_head(to, data->data);
+       pack_int32(to, data->func_num);
+       for (p = data->list; p != NULL; p = p->next) {
+               memcpy(to, p->func, p->size);
+               to += p->size;
+       }
+       return to;
+}
+
+static char *pack_data_list_to_array(struct data_list_t *list, uint32_t *len, uint32_t *count, pack_head_t pack)
+{
+       char *res = NULL;
+       char *to = NULL;
+       uint32_t size = 0;
+       uint32_t cnt = 0;
+       struct data_list_t *p = list;
+
+       for (p = list; p != NULL; p = p->next) {
+               size += p->size;
+               cnt++;
+       }
+
+       size += sizeof(uint32_t);
+       *len = size;
+       *count = cnt;
+
+       if (size != 0) {
+               res = malloc(size);
+               to = res;
+               if (to != NULL) {
+                       pack_int32(to, cnt);
+                       for (p = list; p != NULL; p = p->next)
+                               to = pack_data_to_array(p, to, pack);
+               } else {
+                       LOGE("can not malloc buffer for data list packing\n");
+               }
+       }
+       return res;
+}
+
+static char *pack_lib_list_to_array(struct lib_list_t *list, uint32_t *size, uint32_t *count)
+{
+       return pack_data_list_to_array((struct data_list_t *)list, size,
+                                       count, pack_lib_head_to_array);
+}
+
+static char *pack_app_list_to_array(struct app_list_t *list, uint32_t *size, uint32_t *count)
+{
+       return pack_data_list_to_array((struct data_list_t *)list, size,
+                                       count,  pack_app_head_to_array);
+}
+
+static int generate_msg(struct msg_t **msg, struct lib_list_t *lib_list, struct app_list_t *app_list)
+{
+       uint32_t i,
+                size = 0,
+                libs_size = 0,
+                apps_size = 0,
+                libs_count = 0,
+                apps_count = 0;
+       char     *p = NULL;
+
+       packed_lib_list = pack_lib_list_to_array(lib_list, &libs_size, &libs_count);
+       // print_buf(packed_lib_list, libs_size, "LIBS");
+
+       packed_app_list = pack_app_list_to_array(app_list, &apps_size, &apps_count);
+       // print_buf(packed_app_list, apps_size, "APPS");
+
+       size = apps_count * libs_size + apps_size;
+
+       LOGI("size = %d, apps= %d, libs = %d\n", size, apps_count, libs_count);
+
+       // add header size
+       *msg = malloc(size + sizeof(**msg));
+       memset(*msg, '*', size);
+
+       p = (char *)*msg;
+       pack_int32(p, 0);               // msg id
+       pack_int32(p, size);            // payload size
+       pack_int32(p, apps_count);
+
+       struct app_list_t *app = app_list;
+       char *app_p = packed_app_list + sizeof(((struct user_space_inst_t *)0)->app_num);
+
+       for (i = 0; i < apps_count; i++) {
+               memcpy(p, app_p, app->size);
+               p += app->size;
+               memcpy(p, packed_lib_list, libs_size);
+               p += libs_size;
+
+               app_p += app->size;
+               app = app->next;
+       }
+
+       free(packed_lib_list);
+       free(packed_app_list);
+
+       // print_buf((char *)*msg, size, "ANSWER");
+       return 1;
+}
+
+static void lock_lib_maps_message()
+{
+       pthread_mutex_lock(&lib_inst_list_mutex);
+}
+
+static void unlock_lib_maps_message()
+{
+       pthread_mutex_unlock(&lib_inst_list_mutex);
+}
+
+static void lock_lib_list()
+{
+       pthread_mutex_lock(&lib_maps_message_mutex);
+}
+
+static void unlock_lib_list()
+{
+       pthread_mutex_unlock(&lib_maps_message_mutex);
+}
+
+static void generate_maps_inst_msg(struct user_space_inst_t *us_inst)
+{
+       lock_lib_maps_message();
+
+       struct lib_list_t *lib = us_inst->lib_inst_list;
+       struct app_list_t *app = us_inst->app_inst_list;
+       char *p, *resolved;
+       uint32_t total_maps_count = 0;
+       uint32_t total_len = sizeof(total_maps_count) + sizeof(*lib_maps_message);
+       char real_path_buf[PATH_MAX];
+
+       /* total message len calculate */
+       while (lib != NULL) {
+               p = lib->lib->bin_path;
+               total_len += strlen(p) + 1;
+               total_maps_count++;
+               LOGI("lib #%u <%s>\n", total_maps_count, p);
+               lib = (struct lib_list_t *)lib->next;
+       }
+
+       while (app != NULL) {
+               p = app->app->exe_path;
+               resolved = realpath((const char *)p, real_path_buf);
+               if (resolved != NULL) {
+                       total_len += strlen(real_path_buf) + 1;
+                       total_maps_count++;
+                       LOGI("app #%u <%s>\n", total_maps_count, resolved);
+               } else {
+                       LOGE("cannot resolve bin path <%s>\n", p);
+               }
+
+               app = (struct app_list_t *)app->next;
+       }
+
+       if (lib_maps_message != NULL)
+               free(lib_maps_message);
+
+       lib_maps_message = malloc(total_len);
+       lib_maps_message->type = MSG_MAPS_INST_LIST;
+       lib_maps_message->length = total_len;
+
+       /* pack data */
+       p = lib_maps_message->data;
+       pack_int32(p, total_maps_count);
+
+       lib = us_inst->lib_inst_list;
+       while (lib != NULL) {
+               pack_str(p, lib->lib->bin_path);
+               lib = (struct lib_list_t *)lib->next;
+       }
+
+       app = us_inst->app_inst_list;
+       while (app != NULL) {
+               resolved = realpath(app->app->exe_path, real_path_buf);
+               if (resolved != NULL)
+                       pack_str(p, real_path_buf);
+               app = (struct app_list_t *)app->next;
+       }
+
+       LOGI("total_len = %u\n", total_len);
+       print_buf((char *)lib_maps_message, total_len, "lib_maps_message");
+
+       unlock_lib_maps_message();
+}
+
+void send_maps_inst_msg_to(struct target *t)
+{
+       lock_lib_maps_message();
+       target_send_msg(t, (struct msg_target_t *)lib_maps_message);
+       unlock_lib_maps_message();
+}
+
+static void send_maps_inst_msg_to_all_targets()
+{
+       lock_lib_maps_message();
+       target_send_msg_to_all(lib_maps_message);
+       unlock_lib_maps_message();
+}
+
+//-----------------------------------------------------------------------------
+struct app_info_t *app_info_get_first(struct app_list_t **app_list)
+{
+       *app_list = prof_session.user_space_inst.app_inst_list;
+       if (*app_list == NULL) {
+               return NULL;
+       }
+
+       return (*app_list)->app;
+}
+
+struct app_info_t *app_info_get_next(struct app_list_t **app_list)
+{
+       if (*app_list == NULL)
+               return NULL;
+
+       if ((*app_list = (*app_list)->next) == NULL)
+               return NULL;
+
+       return (*app_list)->app;
+}
+
+//-----------------------------------------------------------------------------
+int msg_start(struct msg_buf_t *data, struct user_space_inst_t *us_inst,
+             struct msg_t **msg, enum ErrorCode *err)
+{
+       int res = 0;
+       char *p = NULL;
+       *msg = NULL;
+
+       /* lock list access */
+       lock_lib_list();
+
+       if (!parse_app_inst_list(data, &us_inst->app_num, &us_inst->app_inst_list)) {
+               *err = ERR_WRONG_MESSAGE_FORMAT;
+               LOGE("parse app inst\n");
+               res = 1;
+               goto msg_start_exit;
+       }
+
+       generate_msg(msg, us_inst->lib_inst_list, us_inst->app_inst_list);
+
+       if (*msg != NULL) {
+               p = (char *)*msg;
+               pack_int32(p, NMSG_START);
+       } else {
+               *err = ERR_CANNOT_START_PROFILING;
+               res = 1;
+               goto msg_start_exit;
+       }
+
+       generate_maps_inst_msg(us_inst);
+
+msg_start_exit:
+       /* unlock list access */
+       unlock_lib_list();
+
+       return res;
+}
+
+int msg_swap_inst_add(struct msg_buf_t *data, struct user_space_inst_t *us_inst,
+                     struct msg_t **msg, enum ErrorCode *err)
+{
+       int res = 0;
+       uint32_t lib_num = 0;
+       char *p = NULL;
+
+       *err = ERR_UNKNOWN;
+
+       /* lock list access */
+       lock_lib_list();
+
+       if (!parse_lib_inst_list(data, &lib_num, &us_inst->lib_inst_list)) {
+               *err = ERR_WRONG_MESSAGE_FORMAT;
+               LOGE("parse lib inst list fail\n");
+               res = 1;
+               goto msg_swap_inst_add_exit;
+       }
+       // rm probes from new if its presents in cur
+       if (!resolve_collisions_for_add_msg(&us_inst->lib_inst_list, &new_lib_inst_list)) {
+               LOGE("resolve collision\n");
+               res = 1;
+               goto msg_swap_inst_add_exit;
+       };
+
+       // generate msg to send
+       if (us_inst->app_inst_list != NULL) {
+               generate_msg(msg, new_lib_inst_list, us_inst->app_inst_list);
+               p = (char *)*msg;
+               pack_int32(p, NMSG_SWAP_INST_ADD);
+       }
+       // apply changes to cur state
+       if (!data_list_move_with_hash(
+               (struct data_list_t **)&us_inst->lib_inst_list,
+               (struct data_list_t **)&new_lib_inst_list,
+               cmp_libs))
+       {
+               LOGE("data move\n");
+               res = 1;
+               goto msg_swap_inst_add_exit;
+       };
+
+       // free new_list
+       free_data_list((struct data_list_t **)&new_lib_inst_list);
+       new_lib_inst_list = NULL;
+       *err = ERR_NO;
+
+       generate_maps_inst_msg(us_inst);
+       send_maps_inst_msg_to_all_targets();
+
+msg_swap_inst_add_exit:
+       /* unlock list access */
+       unlock_lib_list();
+
+       return res;
+}
+
+int msg_swap_inst_remove(struct msg_buf_t *data, struct user_space_inst_t *us_inst,
+                        struct msg_t **msg, enum ErrorCode *err)
+{
+       int res = 0;
+       uint32_t lib_num = 0;
+       char *p = NULL;
+       *err = ERR_UNKNOWN;
+
+       /* lock list access */
+       lock_lib_list();
+
+       if (!parse_lib_inst_list(data, &lib_num, &new_lib_inst_list)) {
+               *err = ERR_WRONG_MESSAGE_FORMAT;
+               LOGE("parse lib inst\n");
+               res = 1;
+               goto msg_swap_inst_remove_exit;
+       }
+
+       if (!resolve_collisions_for_rm_msg(&us_inst->lib_inst_list, &new_lib_inst_list)) {
+               LOGE("resolve collisions\n");
+               res = 1;
+               goto msg_swap_inst_remove_exit;
+       }
+
+       if (us_inst->app_inst_list != NULL) {
+               if (!generate_msg(msg, new_lib_inst_list, us_inst->app_inst_list)) {
+                       LOGE("generate msg\n");
+                       res = 1;
+                       goto msg_swap_inst_remove_exit;
+               }
+               p = (char *)*msg;
+               pack_int32(p, NMSG_SWAP_INST_ADD);
+       }
+
+       free_data_list((struct data_list_t **)&new_lib_inst_list);
+       new_lib_inst_list = NULL;
+       *err = ERR_NO;
+
+       generate_maps_inst_msg(us_inst);
+       send_maps_inst_msg_to_all_targets();
+
+msg_swap_inst_remove_exit:
+       /* unlock list access */
+       unlock_lib_list();
+
+       return res;
+}
+
+void msg_swap_free_all_data(struct user_space_inst_t *us_inst)
+{
+       LOGI("new_lib_inst_list %p\n", new_lib_inst_list);
+       if (new_lib_inst_list != NULL) {
+               LOGI("free new_lib_inst_list start\n");
+               free_data_list(&new_lib_inst_list);
+               new_lib_inst_list = NULL;
+               LOGI("free new_lib_inst_list finish\n");
+       }
+
+       LOGI("us_inst->lib_inst_list %p\n", us_inst->lib_inst_list);
+       if (us_inst->lib_inst_list != NULL) {
+               LOGI("free us_inst->lib_inst_list start\n");
+               free_data_list(&us_inst->lib_inst_list);
+               us_inst->lib_inst_list = NULL;
+               LOGI("free us_isnt->lib_inst_list finish\n");
+       }
+
+       LOGI("us_inst->app_inst_list %p\n", us_inst->app_inst_list);
+       if (us_inst->app_inst_list != NULL) {
+               LOGI("free us_inst->app_inst_list start\n");
+               free_data_list(&us_inst->app_inst_list);
+               LOGI("free us_inst->app_isnt_list finish\n");
+       }
+}
diff --git a/daemon/da_inst.h b/daemon/da_inst.h
new file mode 100644 (file)
index 0000000..bf26b54
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+#ifndef __DA_INST_H__
+#define __DA_INST_H__
+
+#include <stdint.h>
+#include <sys/types.h>
+#include "da_protocol.h"
+
+//LISTS
+struct probe_list_t {
+       void *next;
+       void *prev;
+       uint32_t size;                          //for message generate
+       struct us_func_inst_plane_t *func;
+};
+
+struct lib_list_t {
+       void *next;
+       void *prev;
+       uint32_t hash;
+       uint32_t size;                          //for message generate
+       struct us_lib_inst_t *lib;
+       uint32_t func_num;
+       struct probe_list_t *list;
+};
+
+struct app_list_t {
+       void *next;
+       void *prev;
+       uint32_t hash;
+       uint32_t size;                          //for message generate
+       struct app_info_t *app;
+       uint32_t func_num;
+       struct probe_list_t *list;
+};
+
+
+struct data_list_t {
+       void *next;
+       void *prev;
+       uint32_t hash;
+       uint32_t size;                          //for message generate
+       void *data;
+       uint32_t func_num;
+       struct probe_list_t *list;
+};
+
+typedef int (cmp_data_f) (struct data_list_t *el_1, struct data_list_t *el_2);
+typedef char *(*pack_head_t) (char *to, void *data);
+
+extern int msg_swap_inst_remove(struct msg_buf_t *data, struct user_space_inst_t *us_inst,
+                               struct msg_t **msg, enum ErrorCode *err);
+extern int msg_swap_inst_add(struct msg_buf_t *data, struct user_space_inst_t *us_inst,
+                            struct msg_t **msg, enum ErrorCode *err);
+extern int msg_start(struct msg_buf_t *data, struct user_space_inst_t *us_inst,
+                    struct msg_t **msg, enum ErrorCode *err);
+
+struct probe_list_t *new_probe(void);
+struct lib_list_t *new_lib(void);
+struct app_list_t *new_app(void);
+int probe_list_append(struct data_list_t *to, struct probe_list_t *from);
+int data_list_append(struct data_list_t **to, struct data_list_t *from);
+void free_data_list(struct data_list_t **data);
+
+struct app_info_t *app_info_get_first(struct app_list_t **app_list);
+struct app_info_t *app_info_get_next(struct app_list_t **app_list);
+
+struct target; // move
+void send_maps_inst_msg_to(struct target *t);
+
+#endif /* __DA_INST_H__*/
diff --git a/daemon/da_protocol.c b/daemon/da_protocol.c
new file mode 100644 (file)
index 0000000..f99d0e6
--- /dev/null
@@ -0,0 +1,1335 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ * Nikita Kalyazin    <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <sys/sysinfo.h>
+
+#include "da_protocol.h"
+#include "da_inst.h"
+#include "da_protocol_check.h"
+#include "daemon.h"
+#include "sys_stat.h"
+#include "transfer_thread.h"
+#include "elf.h"
+#include "ioctl_commands.h"
+#include "debug.h"
+#include "md5.h"
+#include "da_data.h"
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <ctype.h>
+
+static pthread_mutex_t stop_all_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static void inline free_msg(struct msg_t *msg)
+{
+       free(msg);
+}
+
+struct prof_session_t prof_session;
+
+static void print_conf(struct conf_t *conf);
+//DEBUG FUNCTIONS
+#define dstr(x) #x
+#define check_and_return(check) if ( ID == check ) {return dstr(check);}
+
+char *msg_ID_str(enum HostMessageT ID)
+{
+       check_and_return(NMSG_KEEP_ALIVE);
+       check_and_return(NMSG_START);
+       check_and_return(NMSG_STOP);
+       check_and_return(NMSG_CONFIG);
+       check_and_return(NMSG_BINARY_INFO);
+       check_and_return(NMSG_GET_TARGET_INFO);
+       check_and_return(NMSG_SWAP_INST_ADD);
+       check_and_return(NMSG_SWAP_INST_REMOVE);
+       check_and_return(NMSG_GET_SCREENSHOT);
+       check_and_return(NMSG_GET_PROCESS_ADD_INFO);
+
+       check_and_return(NMSG_KEEP_ALIVE_ACK);
+       check_and_return(NMSG_START_ACK);
+       check_and_return(NMSG_STOP_ACK);
+       check_and_return(NMSG_CONFIG_ACK);
+       check_and_return(NMSG_BINARY_INFO_ACK);
+       check_and_return(NMSG_SWAP_INST_ACK);
+       check_and_return(NMSG_GET_TARGET_INFO_ACK);
+       check_and_return(NMSG_SWAP_INST_ADD_ACK);
+       check_and_return(NMSG_SWAP_INST_REMOVE_ACK);
+       check_and_return(NMSG_GET_PROCESS_ADD_INFO_ACK);
+
+       check_and_return(NMSG_PROCESS_INFO);
+       check_and_return(NMSG_TERMINATE);
+       check_and_return(NMSG_ERROR);
+       check_and_return(NMSG_SAMPLE);
+       check_and_return(NMSG_SYSTEM);
+       check_and_return(NMSG_IMAGE);
+       check_and_return(NMSG_RECORD);
+       check_and_return(NMSG_FUNCTION_ENTRY);
+       check_and_return(NMSG_FUNCTION_EXIT);
+       check_and_return(NMSG_CONTEXT_SWITCH_ENTRY);
+       check_and_return(NMSG_CONTEXT_SWITCH_EXIT);
+       return "HZ";
+}
+
+
+static char *msgErrStr(enum ErrorCode err)
+{
+       switch (err) {
+       case ERR_NO:
+               return "success";
+       case ERR_LOCKFILE_CREATE_FAILED:
+               return "lock file create failed";
+       case ERR_ALREADY_RUNNING:
+               return "already running";
+       case ERR_INITIALIZE_SYSTEM_INFO_FAILED:
+               return "initialize system info failed";
+       case ERR_HOST_SERVER_SOCKET_CREATE_FAILED:
+               return "host server socket create failed";
+       case ERR_TARGET_SERVER_SOCKET_CREATE_FAILED:
+               return "target server socket create failed";
+       case ERR_SIGNAL_MASK_SETTING_FAILED: //TODO del (old parametr)
+               return "ERR SIGNAL MASK SETTING FAILED";
+       case ERR_WRONG_MESSAGE_FORMAT:
+               return "wrong message format";
+       case ERR_WRONG_MESSAGE_TYPE:
+               return "wrong message type";
+       case ERR_WRONG_MESSAGE_DATA:
+               return "wrong message data";
+       case ERR_CANNOT_START_PROFILING:
+               return "cannot start profiling";
+       case ERR_SERV_SOCK_CREATE:
+               return "server socket creation failed (written in /tmp/da.port file)";
+       case ERR_SERV_SOCK_BIND:
+               return "server socket bind failed (written in /tmp/da.port file)";
+       case ERR_SERV_SOCK_LISTEN:
+               return "server socket listen failed (written in /tmp/da.port file)";
+       case ERR_UNKNOWN:
+       default:
+               return "unknown error";
+       }
+}
+
+
+#define print_feature(f,in,to,delim)                                   \
+       if (f & in) {                                                   \
+               if (strlen(dstr(f) delim) + 1 < buflen ) {              \
+                       lenin = snprintf(to, buflen, dstr(f) delim );   \
+                       to += lenin;                                    \
+                       buflen -= lenin;                                \
+               } else {                                                \
+                       goto err_exit;                                  \
+               }                                                       \
+       }
+#define print_feature_0(f) print_feature(f, feature0, to, ", \n\t")
+static void feature_code_str(uint64_t feature0, uint64_t feature1, char *to,
+                            uint32_t buflen)
+{
+       int lenin = 0;
+       print_feature_0(FL_FUNCTION_PROFILING);
+       print_feature_0(FL_MEMORY_ALLOC_PROBING);
+       print_feature_0(FL_FILE_API_PROBING);
+       print_feature_0(FL_THREAD_API_PROBING);
+       print_feature_0(FL_OSP_UI_API_PROBING);
+       print_feature_0(FL_SCREENSHOT);
+       print_feature_0(FL_USER_EVENT);
+       print_feature_0(FL_RECORDING);
+       print_feature_0(FL_SYSTCALL_FILE);
+       print_feature_0(FL_SYSTCALL_IPC);
+       print_feature_0(FL_SYSTCALL_PROCESS);
+       print_feature_0(FL_SYSTCALL_SIGNAL);
+       print_feature_0(FL_SYSTCALL_NETWORK);
+       print_feature_0(FL_SYSTCALL_DESC);
+       print_feature_0(FL_CONTEXT_SWITCH);
+       print_feature_0(FL_NETWORK_API_PROBING);
+       print_feature_0(FL_OPENGL_API_PROBING);
+       print_feature_0(FL_FUNCTION_SAMPLING);
+       print_feature_0(FL_MEMORY_ALLOC_ALWAYS_PROBING);
+       print_feature_0(FL_FILE_API_ALWAYS_PROBING);
+       print_feature_0(FL_THREAD_API_ALWAYS_PROBING);
+       print_feature_0(FL_OSP_UI_API_ALWAYS_PROBING);
+       print_feature_0(FL_NETWORK_API_ALWAYS_PROBING);
+       print_feature_0(FL_OPENGL_API_ALWAYS_PROBING);
+       print_feature_0(FL_SYSTEM_CPU);
+       print_feature_0(FL_SYSTEM_MEMORY);
+       print_feature_0(FL_SYSTEM_PROCESS);
+       print_feature_0(FL_SYSTEM_THREAD_LOAD);
+       print_feature_0(FL_SYSTEM_PROCESSES_LOAD);
+       print_feature_0(FL_SYSTEM_DISK);
+       print_feature_0(FL_SYSTEM_NETWORK);
+       print_feature_0(FL_SYSTEM_DEVICE);
+       print_feature_0(FL_SYSTEM_ENERGY);
+
+       goto exit;
+err_exit:
+       LOGE("Not enought mem to print\n");
+exit:
+       return;
+}
+
+
+//PARSE FUNCTIONS
+static inline uint32_t get_avail_msg_size(struct msg_buf_t *msg)
+{
+       return (uint32_t)(msg->end - msg->cur_pos);
+}
+
+static inline uint32_t get_msg_cur_size(struct msg_buf_t *msg)
+{
+       return (uint32_t) (msg->cur_pos - msg->payload);
+}
+
+int parse_string(struct msg_buf_t *msg, char **str)
+{
+       parse_deb("size = %d\n", get_avail_msg_size(msg));
+       int len = strlen(msg->cur_pos) + 1;
+
+       if (get_avail_msg_size(msg) < len)
+               return 0;
+
+       *str = strdup(msg->cur_pos);
+       parse_deb("<%s>\n", *str);
+       msg->cur_pos += len;
+       return 1;
+}
+
+static const char* parse_string_inplace(struct msg_buf_t *msg)
+{
+       const char *str = msg->cur_pos;
+       int avail_size = get_avail_msg_size(msg);
+       int len = strnlen(str, avail_size);
+
+       /* Malformed string or exhaused buffer. Strlen is at least one byte
+        * less, that availiable space. If it is not, string is lacking
+        * terminating null char.
+        */
+
+       if (len == avail_size)
+               return NULL;
+
+       msg->cur_pos += len + 1;
+       return str;
+}
+
+int parse_string_no_alloc(struct msg_buf_t *msg, char *str)
+{
+       parse_deb("size = %d\n", get_avail_msg_size(msg));
+       int len = strlen(msg->cur_pos) + 1;
+
+       if (get_avail_msg_size(msg) < len)
+               return 0;
+
+       memcpy(str, msg->cur_pos, len);
+       parse_deb("<%s>\n", str);
+       msg->cur_pos += len;
+       return 1;
+}
+
+int parse_int8(struct msg_buf_t *msg, uint8_t *val)
+{
+       parse_deb("size = %d\n", get_avail_msg_size(msg));
+       if (get_avail_msg_size(msg) < sizeof(*val))
+               return 0;
+       *val = *(uint8_t *)msg->cur_pos;
+       msg->cur_pos += sizeof(uint8_t);
+
+       parse_deb("<%d><0x%08X>\n", *val, *val);
+       return 1;
+}
+
+
+
+int parse_int32(struct msg_buf_t *msg, uint32_t *val)
+{
+       parse_deb("size = %d\n", get_avail_msg_size(msg));
+       if (get_avail_msg_size(msg) < sizeof(*val))
+               return 0;
+       *val = *(uint32_t *)msg->cur_pos;
+       msg->cur_pos += sizeof(uint32_t);
+
+
+       parse_deb("<%d><0x%08X>\n", *val, *val);
+       return 1;
+}
+
+
+int parse_int64(struct msg_buf_t *msg, uint64_t *val)
+{
+       parse_deb("size = %d\n", get_avail_msg_size(msg));
+       if (get_avail_msg_size(msg) < sizeof(*val))
+               return 0;
+
+       *val = *(uint64_t *)msg->cur_pos;
+
+       parse_deb("<%llu><0x%016llX>\n", *val, *val);
+       msg->cur_pos += sizeof(uint64_t);
+       return 1;
+}
+
+static int parse_conf(struct msg_buf_t *msg, struct conf_t *conf)
+{
+
+       parse_deb("parse_conf\n");
+       if (!parse_int64(msg, &conf->use_features0)) {
+               LOGE("use features0 error\n");
+               return 0;
+       }
+
+       if (!parse_int64(msg, &conf->use_features1)) {
+               LOGE("use features1 parsing error\n");
+               return 0;
+       }
+       //Check features value
+       if (!check_conf_features(conf->use_features0, conf->use_features1)) {
+               LOGE("check features fail\n");
+               return 0;
+       }
+
+       if (!parse_int32( msg, &conf->system_trace_period) ||
+               !check_conf_systrace_period(conf->system_trace_period))
+       {
+               LOGE("system trace period error\n");
+               return 0;
+       }
+
+       if (!parse_int32( msg, &conf->data_message_period) ||
+               !check_conf_datamsg_period(conf->data_message_period))
+       {
+               LOGE("data message period error\n");
+               return 0;
+       }
+       //print_conf(conf);
+       return 1;
+}
+
+//REPLAY EVENTS PARSE
+static int parse_timeval(struct msg_buf_t *msg, struct timeval *tv)
+{
+       uint32_t nsec = 0;
+
+       parse_deb("time\n");
+
+       if (!parse_int32(msg, (uint32_t *)&tv->tv_sec)) {
+               LOGE("sec parsing error\n");
+               return 0;
+       }
+
+       if (!parse_int32(msg, &nsec)) {
+               LOGE("usec parsing error\n");
+               return 0;
+       }
+       tv->tv_usec = nsec / 1000;
+
+       return 1;
+}
+
+static int parse_replay_event(struct msg_buf_t *msg,
+                                   struct replay_event_t *re)
+{
+       uint32_t dummy;
+
+       if (!parse_timeval(msg, &re->ev.time)) {
+               LOGE("time parsing error\n");
+               return 0;
+       }
+
+       if (!parse_int32(msg, &re->id)) {
+               LOGE("id parsing error\n");
+               return 0;
+       }
+
+       /* FIXME ev.type, ev.code should be uint16_t */
+       if (!parse_int32(msg, &dummy)) {
+               LOGE("type parsing error\n");
+               return 0;
+       }
+       re->ev.type = (uint16_t)dummy;
+
+       if (!parse_int32(msg, &dummy)) {
+               LOGE("code parsing error\n");
+               return 0;
+       }
+       re->ev.code = (uint16_t)dummy;
+
+       if (!parse_int32(msg, (uint32_t *)&re->ev.value)) {
+               LOGE("value parsing error\n");
+               return 0;
+       }
+
+       return 1;
+}
+
+void reset_replay_event_seq(struct replay_event_seq_t *res)
+{
+       res->enabled = 0;
+       res->tv = (struct timeval){0, 0};
+       if (res->event_num != 0)
+               free(res->events);
+       res->event_num = 0;
+}
+
+int parse_replay_event_seq(struct msg_buf_t *msg,
+                          struct replay_event_seq_t *res)
+{
+       int i = 0;
+       parse_deb("REPLAY\n");
+       if (!parse_int32(msg, &res->enabled)) {
+               LOGE("enabled parsing error\n");
+               return 0;
+       }
+
+       if(res->enabled == 0) {
+               parse_deb("disable\n");
+               return 1;
+       }
+
+       parse_deb("time main\n");
+       if (!parse_timeval(msg, &res->tv)) {
+               LOGE("time parsing error\n");
+               return 0;
+       }
+
+       parse_deb("count\n");
+       if (!parse_int32(msg, &res->event_num)) {
+               LOGE("event num parsing error\n");
+               return 0;
+       }
+       parse_deb("events num=%d\n", res->event_num);
+
+       LOGI("Replay events: count = %u; total_size = %u\n",
+            res->event_num, res->event_num * sizeof(*res->events));
+
+       res->events = (struct replay_event_t *)malloc(res->event_num *
+                                                     sizeof(*res->events));
+       if (!res->events) {
+               LOGE("events alloc error\n");
+               return 0;
+       }
+
+       for (i = 0; i < res->event_num; i++) {
+               parse_deb("sub_rep\n");
+               if (!parse_replay_event(msg, &res->events[i])) {
+                       LOGE("event #%d parsing error\n", i + 1);
+                       free(res->events);
+                       res->event_num = 0;
+                       return 0;
+               }
+       }
+
+       return 1;
+}
+
+//*REPLAY EVENT PARSE
+
+static int parse_msg_config(struct msg_buf_t *msg_payload,
+                             struct conf_t *conf)
+{
+       if (!parse_conf(msg_payload, conf)) {
+               LOGE("conf parsing error\n");
+               return 0;
+       }
+
+       print_conf(conf);
+       return 1;
+}
+
+static void init_parse_control(struct msg_buf_t *buf, struct msg_t *msg)
+{
+       buf->payload = msg->payload;
+       buf->len = msg->len;
+       buf->end = msg->payload + msg->len;
+       buf->cur_pos = msg->payload;
+}
+
+static void reset_target_info(struct target_info_t *target_info)
+{
+       return;
+}
+
+static void running_status_on(struct prof_session_t *prof_session)
+{
+       prof_session->running_status = 1;
+}
+
+static void running_status_off(struct prof_session_t *prof_session)
+{
+       prof_session->running_status = 0;
+}
+
+int check_running_status(const struct prof_session_t *prof_session)
+{
+       return prof_session->running_status;
+}
+
+static void reset_app_inst(struct user_space_inst_t *us_inst)
+{
+       free_data_list((struct data_list_t **)&us_inst->app_inst_list);
+       us_inst->app_num = 0;
+       us_inst->app_inst_list = NULL;
+}
+
+void reset_system_info(struct system_info_t *sys_info)
+{
+       if (sys_info->cpu_frequency)
+               free(sys_info->cpu_frequency);
+       if (sys_info->cpu_load)
+               free(sys_info->cpu_load);
+       memset(sys_info, 0, sizeof(*sys_info));
+}
+
+void init_prof_session(struct prof_session_t *prof_session)
+{
+       memset(prof_session, 0, sizeof(*prof_session));
+}
+
+static size_t str_array_getsize(const char **strings, size_t len)
+{
+       /*!
+        * Calculate about of memory to place array
+        * of \0 delimited strings
+        */
+       size_t size = 0;
+       unsigned int index;
+       for (index = 0; index != len; ++index)
+               size += strlen(strings[index]) + 1;
+       return size;
+}
+
+
+static struct msg_t *gen_target_info_reply(struct target_info_t *target_info)
+{
+       struct msg_t *msg;
+       char *p = NULL;
+       uint32_t ret_id = ERR_NO;
+
+       msg = malloc(sizeof(*msg) +
+                    sizeof(ret_id) +
+                    sizeof(*target_info) -
+                    sizeof(target_info->network_type) +
+                    strlen(target_info->network_type) + 1 +
+                    sizeof(uint32_t) + /* devices count */
+                    str_array_getsize(supported_devices_strings,
+                                      supported_devices_count));
+       if (!msg) {
+               LOGE("Cannot alloc target info msg\n");
+               free(msg);
+               return NULL;
+       }
+
+       msg->id = NMSG_GET_TARGET_INFO_ACK;
+       p = msg->payload;
+
+       pack_int32(p, ret_id);
+       pack_int64(p, target_info->sys_mem_size);
+       pack_int64(p, target_info->storage_size);
+       pack_int32(p, target_info->bluetooth_supp);
+       pack_int32(p, target_info->gps_supp);
+       pack_int32(p, target_info->wifi_supp);
+       pack_int32(p, target_info->camera_count);
+       pack_str(p, target_info->network_type);
+       pack_int32(p, target_info->max_brightness);
+       pack_int32(p, target_info->cpu_core_count);
+       pack_int32(p, supported_devices_count);
+       p = pack_str_array(p, supported_devices_strings,
+                          supported_devices_count);
+
+       msg->len = p - msg->payload;
+
+       return msg;
+}
+
+static int send_reply(struct msg_t *msg)
+{
+       printBuf((char *)msg, msg->len + sizeof (*msg));
+       if (send(manager.host.control_socket,
+                msg, MSG_CMD_HDR_LEN + msg->len, MSG_NOSIGNAL) == -1) {
+               GETSTRERROR(errno, buf);
+               LOGE("Cannot send reply : %s\n", buf);
+               return -1;
+       }
+
+       return 0;
+}
+
+static void write_msg_error(const char *err_str)
+{
+       struct msg_data_t *err_msg = gen_message_error(err_str);
+       if (write_to_buf(err_msg) != 0)
+               LOGE("write to buf fail\n");
+       free_msg_data(err_msg);
+}
+
+static enum HostMessageT get_ack_msg_id(const enum HostMessageT id)
+{
+       switch (id) {
+       case NMSG_KEEP_ALIVE:
+               return NMSG_KEEP_ALIVE_ACK;
+       case NMSG_START:
+               return NMSG_START_ACK;
+       case NMSG_STOP:
+               return NMSG_STOP_ACK;
+       case NMSG_CONFIG:
+               return NMSG_CONFIG_ACK;
+       case NMSG_BINARY_INFO:
+               return NMSG_BINARY_INFO_ACK;
+       case NMSG_GET_TARGET_INFO:
+               return NMSG_GET_TARGET_INFO_ACK;
+       case NMSG_SWAP_INST_ADD:
+               return NMSG_SWAP_INST_ADD_ACK;
+       case NMSG_SWAP_INST_REMOVE:
+               return NMSG_SWAP_INST_REMOVE_ACK;
+       case NMSG_GET_PROCESS_ADD_INFO:
+               return NMSG_GET_PROCESS_ADD_INFO_ACK;
+       default:
+               LOGE("Fatal: unknown message ID [0x%X]\n", id);
+               exit(EXIT_FAILURE);
+       }
+}
+
+int sendACKToHost(enum HostMessageT resp, enum ErrorCode err_code,
+                       char *payload, int payload_size)
+{
+       if (manager.host.control_socket != -1) {
+               struct msg_t *msg;
+               uint32_t err = err_code;
+               int loglen = sizeof(*msg) - sizeof(msg->payload) +
+                                        sizeof(err) + //return ID
+                                        payload_size;
+               msg = malloc(loglen);
+               char *p = msg->payload;
+
+               resp = get_ack_msg_id(resp);
+
+               //set message id
+               msg->id = resp;
+               //set payload lenth
+               msg->len = payload_size + sizeof(err);
+               //set return id
+               pack_int32(p, err);
+               //copy payload data
+               memcpy(p, payload, payload_size);
+
+               LOGI("ACK (%s) errcode<%s> payload=0x%08X; size=%d\n", msg_ID_str(resp),
+                               msgErrStr(err_code), (int)payload, payload_size);
+               printBuf((char *)msg, loglen);
+
+               if (send(manager.host.control_socket, msg,
+                        loglen, MSG_NOSIGNAL) == -1) {
+                       GETSTRERROR(errno, buf);
+                       LOGE("Cannot send reply: %s\n", buf);
+                       free(msg);
+                       return 1;
+               }
+               free(msg);
+               return 0;
+       } else
+               return 1;
+}
+
+static struct msg_t *gen_stop_msg(void)
+{
+       struct msg_t *res = malloc(sizeof(*res));
+       memset(res, 0, sizeof(*res));
+       res->id = NMSG_STOP;
+       res->len = 0;
+       return res;
+}
+
+
+enum ErrorCode stop_all_no_lock(void)
+{
+       enum ErrorCode error_code = ERR_NO;
+       struct msg_t *msg;
+
+       // stop all only if it has not been called yet
+       if (check_running_status(&prof_session)) {
+               msg = gen_stop_msg();
+               terminate_all();
+               stop_profiling();
+               stop_replay();
+
+               if (msg == NULL) {
+                       LOGE("cannot generate stop message\n");
+                       error_code = ERR_UNKNOWN;
+                       goto stop_all_exit;
+               } else {
+                       if (ioctl_send_msg(msg) != 0) {
+                               LOGE("ioctl send failed\n");
+                               error_code = ERR_UNKNOWN;
+                               free_msg(msg);
+                               goto stop_all_exit;
+                       }
+                       free_msg(msg);
+               }
+
+               // we reset only app inst no lib no confing reset
+               reset_app_inst(&prof_session.user_space_inst);
+               stop_transfer();
+               running_status_off(&prof_session);
+       } else
+               LOGI("already stopped\n");
+
+stop_all_exit:
+       LOGI("finished: ret = %d\n", error_code);
+       return error_code;
+}
+
+int stop_all_in_process(void)
+{
+       return (pthread_mutex_trylock(&stop_all_mutex) != 0);
+}
+
+void stop_all_done(void)
+{
+       pthread_mutex_unlock(&stop_all_mutex);
+}
+
+static void stop_web_apps(void)
+{
+       const struct app_info_t *app_info;
+       struct app_list_t *app = NULL;
+
+       app_info = app_info_get_first(&app);
+       while (app_info) {
+               if (app_info->app_type == APP_TYPE_WEB)
+                       kill_app_web(app_info->app_id);
+               app_info = app_info_get_next(&app);
+       }
+}
+
+enum ErrorCode stop_all(void)
+{
+       enum ErrorCode error_code = ERR_NO;
+
+       stop_web_apps();
+
+       pthread_mutex_lock(&stop_all_mutex);
+       error_code = stop_all_no_lock();
+       pthread_mutex_unlock(&stop_all_mutex);
+
+       return error_code;
+}
+
+struct binary_ack {
+       uint32_t type;
+       char *binpath;
+       md5_byte_t digest[16];
+};
+
+static void binary_ack_free(struct binary_ack *ba)
+{
+       if (ba)
+               free(ba->binpath);
+       free(ba);
+}
+
+static size_t binary_ack_size(const struct binary_ack *ba)
+{
+       /* MD5 is 16 bytes, so 16*2 hex digits */
+       return sizeof(uint32_t) + strlen(ba->binpath) + 1
+               + 2*16 + 1;
+}
+
+static size_t binary_ack_pack(char *s, const struct binary_ack *ba)
+{
+       unsigned int len = strlen(ba->binpath) + 1;
+       int i;
+       *(uint32_t *) s = ba->type;
+       s += sizeof(uint32_t);
+
+       if (len)
+               memcpy(s, ba->binpath, len);
+       s += len;
+
+       for (i = 0; i!= 16; ++i) {
+               /* we should use snprintf, snprintf prints data including
+                * terminate '\0' so we need print 3 symbols
+                */
+               snprintf(s, 3, "%02x", ba->digest[i]);
+               s += 2;
+       }
+       *s = '\0';
+
+       return sizeof(uint32_t) + len + 2*16 + 1;
+}
+
+static void get_file_md5sum(md5_byte_t digest[16], const char *filename)
+{
+       md5_byte_t buffer[1024];
+       ssize_t size;
+       md5_state_t md5_state;
+       int fd = open(filename, O_RDONLY);
+
+       md5_init(&md5_state);
+       if (fd >= 0) {
+               while ((size = read(fd, buffer, sizeof(buffer))) > 0)
+                       md5_append(&md5_state, buffer, size);
+               close(fd);
+       } else {
+               LOGW("File does not exists <%s>\n", filename);
+       }
+
+       md5_finish(&md5_state, digest);
+}
+
+static const char* basename(const char *filename)
+{
+       const char *p = strrchr(filename, '/');
+       return p ? p + 1 : NULL;
+}
+
+/**
+ * Checks whether it is Windows-style path or not.
+ *
+ * @return 1 if path is Windows-style one, 0 otherwise.
+ */
+static int check_windows_path(const char *path)
+{
+       size_t len;
+
+       len = strlen(path);
+       if (len > 3 && isalpha(path[0]) && !(strncmp(&(path[1]), ":\\", 2)))
+               return 1;
+
+       return 0;
+}
+
+static struct binary_ack* binary_ack_alloc(const char *filename)
+{
+       struct binary_ack *ba = malloc(sizeof(*ba));
+       struct stat decoy;
+       char builddir[PATH_MAX];
+       char binpath[PATH_MAX];
+
+       builddir[0]='\0';
+       binpath[0]='\0';
+
+       if (stat(filename, &decoy) == 0) {
+               ba->type = get_binary_type(filename);
+
+               if (ba->type != BINARY_TYPE_UNKNOWN)
+                       get_build_dir(builddir, filename);
+
+               if (builddir[0] != '\0')
+                       snprintf(binpath, sizeof(binpath), check_windows_path(builddir) ?
+                                "%s\\%s" : "%s/%s", builddir, basename(filename) ?: "");
+
+               ba->binpath = strdup(binpath);
+               get_file_md5sum(ba->digest, filename);
+       } else {
+               ba->type = BINARY_TYPE_FILE_NOT_EXIST;
+               ba->binpath = strdup(filename);
+               memset(ba->digest, 0x00, sizeof(ba->digest));
+       }
+
+       return ba;
+}
+
+static int process_msg_binary_info(struct msg_buf_t *msg)
+{
+       uint32_t i, bincount;
+       enum ErrorCode error_code = ERR_NO;
+
+       printBuf(msg->cur_pos, msg->len);
+
+       if (!parse_int32(msg, &bincount)) {
+               LOGE("MSG_BINARY_INFO error: No binaries count\n");
+               return -1;
+       }
+
+       struct binary_ack *acks[bincount];
+       struct binary_ack *new;
+       size_t total_size = 0;
+       for (i = 0; i != bincount; ++i) {
+               const char *str = parse_string_inplace(msg);
+               if (!str) {
+                       LOGE("MSG_BINARY_INFO error: No enough binaries\n");
+                       return -1;
+               }
+               new = binary_ack_alloc(str);
+               /* check for errors */
+               if (new->type == BINARY_TYPE_FILE_NOT_EXIST) {
+                       error_code = ERR_WRONG_MESSAGE_DATA;
+                       LOGW("binary file not exists <%s>\n", str);
+               } else if (new->type == BINARY_TYPE_UNKNOWN) {
+                       error_code = ERR_WRONG_MESSAGE_DATA;
+                       LOGW("binary is not ELF binary <%s>\n", str);
+               }
+
+               if (new->binpath[0] == '\0')
+                       LOGW("section '.debug_str' not found in <%s>\n", str);
+               acks[i] = new;
+               total_size += binary_ack_size(new);
+       }
+       typedef uint32_t return_id;
+       typedef uint32_t binary_ack_count;
+       struct msg_t *msg_reply = malloc(sizeof(struct msg_t)
+                                        + sizeof(return_id)
+                                        + sizeof(binary_ack_count)
+                                        + total_size);
+       char *p = msg_reply->payload;
+
+       msg_reply->id = NMSG_BINARY_INFO_ACK;
+       msg_reply->len = total_size + sizeof(return_id)
+                                   + sizeof(binary_ack_count);
+
+       pack_int32(p, error_code);
+       pack_int32(p, bincount);
+
+       for (i = 0; i != bincount; ++i) {
+               p += binary_ack_pack(p, acks[i]);
+               binary_ack_free(acks[i]);
+       }
+
+       printBuf(msg_reply, msg_reply->len + sizeof(*msg_reply));
+       int err = send_reply(msg_reply);
+       free(msg_reply);
+       return err;
+}
+
+static void get_serialized_time(uint32_t dst[2])
+{
+       struct timeval tv;
+       gettimeofday(&tv, NULL);
+       dst[0] = tv.tv_sec;
+       dst[1] = tv.tv_usec * 1000;
+}
+
+static int process_msg_start(struct msg_buf_t *msg_control)
+{
+       enum ErrorCode err_code = ERR_CANNOT_START_PROFILING;
+       struct msg_t *msg_reply = NULL;
+       uint32_t serialized_time[2];
+
+       //get start profiling time
+       get_serialized_time(serialized_time);
+
+       if (check_running_status(&prof_session) == 1) {
+               LOGW("Profiling has already been started\n");
+               err_code = ERR_ALREADY_RUNNING;
+               goto send_ack;
+       }
+
+       if (!check_conf(&prof_session.conf)) {
+               LOGE("wrong profile config\n");
+               goto send_ack;
+       }
+
+       if (msg_start(msg_control, &prof_session.user_space_inst,
+                     &msg_reply, &err_code) != 0) {
+               LOGE("parse error\n");
+               goto send_ack;
+       }
+
+       if (prepare_profiling() != 0) {
+               LOGE("failed to prepare profiling\n");
+               goto send_ack;
+       }
+
+       if (start_transfer() != 0) {
+               LOGE("Cannot start transfer\n");
+               goto send_ack;
+       }
+
+       //get time right before ioctl for more accurate start time value
+       get_serialized_time(serialized_time);
+
+       if (ioctl_send_msg(msg_reply) != 0) {
+               LOGE("cannot send message to device\n");
+               goto send_ack;
+       }
+
+       running_status_on(&prof_session);
+
+       if (start_profiling() < 0) {
+               LOGE("cannot start profiling\n");
+               if (stop_all() != ERR_NO) {
+                       LOGE("Stop failed\n");
+                       write_msg_error("Stop failed");
+               }
+               goto send_ack;
+       }
+
+       err_code = ERR_NO;
+send_ack:
+       sendACKToHost(NMSG_START, err_code, (void *)&serialized_time,
+                     sizeof(serialized_time));
+       if (msg_reply != NULL)
+               free(msg_reply);
+       return -(err_code != ERR_NO);
+}
+
+int send_msg_to_sock(int sock, struct msg_target_t *msg)
+{
+       ssize_t ret;
+       size_t n;
+       int err = 0;
+
+       n = sizeof(struct _msg_target_t) + msg->length;
+       ret = send(sock, msg, n, MSG_NOSIGNAL);
+       if (ret != n) {
+               LOGE("fail to send data to socket(%d) n=%u, ret=%d\n",
+                    sock, n, ret);
+               err = 1;
+       }
+
+       return err;
+}
+
+int recv_msg_from_sock(int sock, struct msg_target_t *msg)
+{
+       ssize_t ret;
+
+       ret = recv(sock, msg, MSG_HEADER_LEN, MSG_WAITALL);
+       if (ret != MSG_HEADER_LEN)
+               return 1;
+
+       if (IS_PROBE_MSG(msg->type)) {
+               struct msg_data_t *msg_data = (struct msg_data_t *)msg;
+               size_t n = MSG_DATA_HDR_LEN - MSG_HEADER_LEN;
+
+               ret = recv(sock, (char *)msg_data + MSG_HEADER_LEN,
+                          n, MSG_WAITALL);
+               if (ret != n)
+                       return 1;
+
+               /* TODO: check msg_data->len */
+               ret = recv(sock, msg_data->payload,
+                          msg_data->len, MSG_WAITALL);
+
+               if (ret != msg_data->len)
+                       return 1;
+
+               return 0;
+       }
+
+       if (msg->length > 0) {
+               /* TODO: check msg->length */
+               ret = recv(sock, msg->data, msg->length, MSG_WAITALL);
+               if (ret != msg->length)
+                       return 1;
+       }
+
+       return 0;
+}
+
+static int process_msg_get_screenshot(struct msg_buf_t *msg_control)
+{
+       uint32_t log_len;
+       struct msg_target_t sendlog;
+       enum ErrorCode err_code = ERR_UNKNOWN;
+
+       // send config message to target process
+       sendlog.type = MSG_CAPTURE_SCREEN;
+       sendlog.length = 0;
+       log_len = sizeof(sendlog.type) + sizeof(sendlog.length) + sendlog.length;
+
+       if (target_send_msg_to_all(&sendlog) == 1)
+               err_code = ERR_NO;
+
+       return -(err_code != ERR_NO);
+}
+
+static char *get_process_cmd_line(uint32_t pid)
+{
+       char buf[MAX_FILENAME];
+       int f;
+       ssize_t count;
+
+       snprintf(buf, sizeof(buf), "/proc/%u/cmdline", pid);
+       f = open(buf, O_RDONLY);
+       if (f != -1) {
+               count = read(f, buf, sizeof(buf));
+               if (count >= sizeof(buf))
+                       count = sizeof(buf) - 1;
+               buf[count] = '\0';
+               close(f);
+       } else {
+               LOGE("file not found <%s>\n", buf);
+               buf[0] = '\0';
+       }
+       return strdup(buf);
+}
+
+static int process_msg_get_process_add_info(struct msg_buf_t *msg)
+{
+       uint32_t i, count, total_len;
+       uint32_t *pidarr = NULL;
+       char **cmd_line_arr = NULL;
+       char *payload, *p;
+       struct msg_target_t sendlog;
+       enum ErrorCode err_code = ERR_UNKNOWN;
+
+       /* get pid count */
+       if (!parse_int32(msg, &count)) {
+               LOGE("NMSG_GET_PROCESS_ADD_INFO error: No process count\n");
+               err_code = ERR_WRONG_MESSAGE_DATA;
+               goto send_fail;
+       }
+
+       /* alloc array for pids */
+       pidarr = malloc(count * sizeof(*pidarr));
+       cmd_line_arr = malloc(count * sizeof(*cmd_line_arr));
+       if (pidarr == NULL) {
+               LOGE("can not alloc pid array (%u)", count);
+               goto send_fail;
+       }
+       if (cmd_line_arr == NULL) {
+               LOGE("can not alloc cmd line array (%u)", count);
+               goto send_fail;
+       }
+
+       /* parse all pids */
+       for (i = 0; i != count; i++) {
+               if (!parse_int32(msg, &pidarr[i])) {
+                       LOGE("can not parse pid #%u", i);
+                       goto send_fail;
+               }
+       }
+
+       total_len = i * sizeof(*pidarr) + sizeof(count);
+       for (i = 0; i != count; i++) {
+               cmd_line_arr[i] = get_process_cmd_line(pidarr[i]);
+               total_len += strlen(cmd_line_arr[i]) + 1;
+       }
+
+       payload = malloc(total_len);
+       if (payload == NULL)
+               goto send_fail;
+       /* pack payload data */
+       p = payload;
+       pack_int32(p, count);
+       for (i = 0; i != count; i++) {
+               pack_int32(p, pidarr[i]);
+               pack_str(p, cmd_line_arr[i]);
+               free(cmd_line_arr[i]);
+       }
+
+       /* success */
+       err_code = ERR_NO;
+       goto send_ack;
+
+send_fail:
+       /* fail */
+       total_len = 0;
+
+send_ack:
+       /* success */
+       sendACKToHost(NMSG_GET_PROCESS_ADD_INFO, err_code, payload, total_len);
+
+       /* free data */
+       if (payload != NULL) {
+               free(payload);
+               payload = NULL;
+       }
+
+       if (pidarr != NULL) {
+               free(pidarr);
+               pidarr = NULL;
+       }
+
+       if (cmd_line_arr != NULL) {
+               free(cmd_line_arr);
+               cmd_line_arr = NULL;
+       }
+
+       return -(err_code != ERR_NO);
+}
+
+int host_message_handler(struct msg_t *msg)
+{
+       struct target_info_t target_info;
+       struct msg_t *msg_reply = NULL;
+       struct msg_buf_t msg_control;
+       struct conf_t conf;
+       enum ErrorCode error_code = ERR_NO;
+
+       int target_index;
+       struct msg_target_t sendlog;
+
+       LOGI("MY HANDLE %s (%X)\n", msg_ID_str(msg->id), msg->id);
+       init_parse_control(&msg_control, msg);
+
+       switch (msg->id) {
+       case NMSG_KEEP_ALIVE:
+               sendACKToHost(msg->id, ERR_NO, 0, 0);
+               break;
+       case NMSG_START:
+               return process_msg_start(&msg_control);
+       case NMSG_STOP:
+               sendACKToHost(msg->id, ERR_NO, 0, 0);
+               if (stop_all() != ERR_NO) {
+                       LOGE("Stop failed\n");
+                       write_msg_error("Stop failed");
+               }
+               break;
+       case NMSG_CONFIG:
+               error_code = ERR_NO;
+               if (!parse_msg_config(&msg_control, &conf)) {
+                       LOGE("config parsing error\n");
+                       sendACKToHost(msg->id, ERR_WRONG_MESSAGE_FORMAT, 0, 0);
+                       return -1;
+               }
+               if (reconfigure(conf) != 0) {
+                       LOGE("Cannot change configuration\n");
+                       return -1;
+               }
+               //write to device
+
+               // TODO make it normally
+               // Attention!!! convert feature to old format!!!
+               uint64_t feature0 = *((uint64_t *)msg->payload);
+               if (feature0 & FL_SYSTEM_ENERGY) {
+                       feature0 &= ~FL_SYSTEM_ENERGY;
+                       feature0 |= FL_SYSTEM_ENERGY_OLD;
+               } else {
+                       feature0 &= ~FL_SYSTEM_ENERGY;
+                       feature0 &= ~FL_SYSTEM_ENERGY_OLD;
+               }
+               *((uint64_t *)msg->payload) = feature0;
+
+               if (ioctl_send_msg(msg) != 0) {
+                       LOGE("ioctl send error\n");
+                       sendACKToHost(msg->id, ERR_UNKNOWN, 0, 0);
+                       return -1;
+               }
+               //send ack to host
+               sendACKToHost(msg->id, ERR_NO, 0, 0);
+               // send config message to target process
+               sendlog.type = MSG_OPTION;
+               sendlog.length = snprintf(sendlog.data, sizeof(sendlog.data),
+                                         "%llu",
+                                         (unsigned long long)
+                                         prof_session.conf.use_features0) + 1;
+               target_send_msg_to_all(&sendlog);
+               break;
+       case NMSG_BINARY_INFO:
+               return process_msg_binary_info(&msg_control);
+       case NMSG_SWAP_INST_ADD:
+               if (msg_swap_inst_add(&msg_control, &prof_session.user_space_inst,
+                                     &msg_reply, &error_code) != 0) {
+                       LOGE("swap inst add\n");
+                       goto send_ack;
+               }
+               if (msg_reply != NULL)
+                       if (ioctl_send_msg(msg_reply) != 0) {
+                               error_code = ERR_UNKNOWN;
+                               LOGE("ioclt send error\n");
+                       }
+               //send ack to host
+               goto send_ack;
+       case NMSG_SWAP_INST_REMOVE:
+               if (msg_swap_inst_remove(&msg_control, &prof_session.user_space_inst,
+                                        &msg_reply, &error_code) != 0) {
+                       LOGE("swap inst remove\n");
+                       error_code = ERR_UNKNOWN;
+                       goto send_ack;
+               }
+               if (msg_reply != NULL) {
+                       if (ioctl_send_msg(msg_reply) != 0)
+                               error_code = ERR_UNKNOWN;
+               } else {
+                       error_code = ERR_UNKNOWN;
+               }
+               goto send_ack;
+       case NMSG_GET_TARGET_INFO:
+               fill_target_info(&target_info);
+               msg_reply = gen_target_info_reply(&target_info);
+               if (!msg_reply) {
+                       LOGE("cannot generate reply message\n");
+                       sendACKToHost(msg->id, ERR_UNKNOWN, 0, 0);
+                       return -1;
+               }
+               if (send_reply(msg_reply) != 0) {
+                       LOGE("Cannot send reply\n");
+               }
+               free(msg_reply);
+               reset_target_info(&target_info);
+               break;
+       case NMSG_GET_SCREENSHOT:
+               return process_msg_get_screenshot(&msg_control);
+       case NMSG_GET_PROCESS_ADD_INFO:
+               return process_msg_get_process_add_info(&msg_control);
+       default:
+               LOGE("unknown message %d <0x%08X>\n", msg->id, msg->id);
+               error_code = ERR_WRONG_MESSAGE_TYPE;
+               goto send_ack;
+       }
+
+       return 0;
+
+send_ack:
+       sendACKToHost(msg->id, error_code, 0, 0);
+       if (msg_reply != NULL)
+               free(msg_reply);
+       return (error_code == ERR_NO);
+}
+
+// testing
+
+static void print_conf(struct conf_t *conf)
+{
+       char buf[1024];
+       memset(&buf[0], 0, 1024);
+       feature_code_str(conf->use_features0, conf->use_features1, buf, sizeof(buf));
+       LOGI("conf = \n");
+       LOGI("\tuse_features = 0x%016LX : 0x%016LX \n(\t%s)\n",
+            conf->use_features0, conf->use_features1, buf);
+       LOGI(
+                "\tsystem_trace_period = %d ms\n"
+                "\tdata message period = %d ms\n",
+                conf->system_trace_period,
+                conf->data_message_period
+                );
+}
+
+void print_replay_event(struct replay_event_t *ev, uint32_t num, char *tab)
+{
+       LOGW("%s\t#%04d:time=0x%08X %08X, "
+               " id=0x%08X,"
+               " type=0x%08X,"
+               " code=0x%08X,"
+               " value=0x%08X\n",
+               tab,num,
+               (unsigned int)ev->ev.time.tv_sec,//timeval
+               (unsigned int)ev->ev.time.tv_usec,//timeval
+               ev->id,
+               ev->ev.type,//u16
+               ev->ev.code,//u16
+               ev->ev.value//s32
+               );
+}
diff --git a/daemon/da_protocol.h b/daemon/da_protocol.h
new file mode 100644 (file)
index 0000000..24aeefd
--- /dev/null
@@ -0,0 +1,464 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ * Nikita Kalyazin    <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#ifndef _DA_PROTOCOL_
+#define _DA_PROTOCOL_
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <linux/input.h>
+
+enum HostMessageT {
+NMSG_KEEP_ALIVE                        =0x0001,
+NMSG_START                             =0x0002,
+NMSG_STOP                              =0x0003,
+NMSG_CONFIG                            =0x0004,
+NMSG_BINARY_INFO               =0x0005,
+NMSG_GET_TARGET_INFO   =0x0007,
+NMSG_SWAP_INST_ADD             =0x0008,
+NMSG_SWAP_INST_REMOVE          =0x0009,
+NMSG_GET_SCREENSHOT            =0x0010,
+NMSG_GET_PROCESS_ADD_INFO      =0x0011,
+
+NMSG_KEEP_ALIVE_ACK                    =0x1001,
+NMSG_START_ACK                         =0x1002,
+NMSG_STOP_ACK                          =0x1003,
+NMSG_CONFIG_ACK                                =0x1004,
+NMSG_BINARY_INFO_ACK           =0x1005,
+NMSG_SWAP_INST_ACK                     =0x1006,
+NMSG_GET_TARGET_INFO_ACK       =0x1007,
+NMSG_SWAP_INST_ADD_ACK         =0x1008,
+NMSG_SWAP_INST_REMOVE_ACK      =0x1009,
+NMSG_GET_PROCESS_ADD_INFO_ACK  =0x1011,
+
+NMSG_PROCESS_INFO                      =0x0001,        //      target process info
+NMSG_TERMINATE                         =0x0002,        //terminate
+NMSG_ERROR                                     =0x0003,        //error message
+NMSG_SAMPLE                                    =0x0004,        //N     10ms
+NMSG_SYSTEM                                    =0x0005,        //N     10~1000ms       DaData, start sending immediately after start message from host, first system message time is tracing start time
+NMSG_IMAGE                                     =0x0006,        //N     irregular       image
+NMSG_RECORD                                    =0x0007,        //N     irregular       replay event
+NMSG_FUNCTION_ENTRY                    =0x0008,        //N     irregular       swap instrumentation, Instrumented functions by AppInst and LibInst
+NMSG_FUNCTION_EXIT                     =0x0009,        //N     irregular       swap instrumentation, Instrumented functions by AppInst and LibInst
+NMSG_CONTEXT_SWITCH_ENTRY      =0x0010,        //N     irregular       swap instrumentation for kernel
+NMSG_CONTEXT_SWITCH_EXIT       =0x0011,        //N     irregular       swap instrumentation for kernel
+};
+#define MSG_MAX_NUM NMSG_SWAP_INST_REMOVE
+
+enum ErrorCode {
+       ERR_NO                                  = 0,    /* success */
+       ERR_LOCKFILE_CREATE_FAILED              = -101, /* lock file create failed */
+       ERR_ALREADY_RUNNING                     = -102, /* already running */
+       ERR_INITIALIZE_SYSTEM_INFO_FAILED       = -103, /* initialize system info failed */
+       ERR_HOST_SERVER_SOCKET_CREATE_FAILED    = -104, /* host server socket create failed */
+       ERR_TARGET_SERVER_SOCKET_CREATE_FAILED  = -105, /* target server socket create failed */
+
+       ERR_SIGNAL_MASK_SETTING_FAILED          = -106, /* TODO del (old parametr) */
+
+       ERR_WRONG_MESSAGE_FORMAT                = -201, /* wrong message format */
+       ERR_WRONG_MESSAGE_TYPE                  = -202, /* wrong message type */
+       ERR_WRONG_MESSAGE_DATA                  = -203, /* wrong message data */
+       ERR_CANNOT_START_PROFILING              = -204, /* cannot start profiling */
+       ERR_SERV_SOCK_CREATE                    = -900, /* server socket creation failed (written in /tmp/da.port file) */
+       ERR_SERV_SOCK_BIND                      = -901, /* server socket bind failed (written in /tmp/da.port file) */
+       ERR_SERV_SOCK_LISTEN                    = -902, /* server socket listen failed (written in /tmp/da.port file) */
+       ERR_UNKNOWN                             = -999  /* unknown error */
+};
+
+#define FL_SYSTEM_ENERGY_OLD (1<<26)
+
+enum feature_code{
+       FL_RESERVED1                    = 0x000000000003ULL, // reserved 0011
+
+       FL_FUNCTION_PROFILING           = 0x000000000004ULL, // On/Off the UserSpaceInst
+       FL_MEMORY_ALLOC_PROBING         = 0x000000000008ULL, // memory allocation API (glibc)
+       FL_FILE_API_PROBING             = 0x000000000010ULL, // file API (glibc, OSP)
+       FL_THREAD_API_PROBING           = 0x000000000020ULL, // thread API (glibc, OSP)
+       FL_OSP_UI_API_PROBING           = 0x000000000040ULL, // UI API (OSP)
+       FL_SCREENSHOT                   = 0x000000000080ULL, // Screenshot
+       FL_USER_EVENT                   = 0x000000000100ULL, // events of Touch, Gesture, Orientation, Key
+       FL_RECORDING                    = 0x000000000200ULL, // recording the user event
+       FL_SYSTCALL_FILE                = 0x000000000400ULL, // File operation syscalls tracing
+       FL_SYSTCALL_IPC                 = 0x000000000800ULL, // IPC syscall tracing
+       FL_SYSTCALL_PROCESS             = 0x000000001000ULL, // Process syscalls tracing
+       FL_SYSTCALL_SIGNAL              = 0x000000002000ULL, // Signal syscalls tracing
+       FL_SYSTCALL_NETWORK             = 0x000000004000ULL, // Network syscalls tracing
+       FL_SYSTCALL_DESC                = 0x000000008000ULL, // Descriptor syscalls tracing
+       FL_CONTEXT_SWITCH               = 0x000000010000ULL, // Context switch tracing
+       FL_NETWORK_API_PROBING          = 0x000000020000ULL, // network API (glibc, OSP, libsoap, openssl)
+       FL_OPENGL_API_PROBING           = 0x000000040000ULL, // openGL API
+       FL_FUNCTION_SAMPLING            = 0x000000080000ULL, // Function sampling
+
+       FL_RESERVED2                    = 0x00000FF00000ULL, // reserved
+
+       FL_MEMORY_ALLOC_ALWAYS_PROBING  = 0x000010000000ULL, // all (include external) memory allocation API (glibc) always
+       FL_FILE_API_ALWAYS_PROBING      = 0x000020000000ULL, // all (include external) file API (glibc, OSP) always
+       FL_THREAD_API_ALWAYS_PROBING    = 0x000040000000ULL, // all (include external) thread API (glibc, OSP) always
+       FL_OSP_UI_API_ALWAYS_PROBING    = 0x000080000000ULL, // all (include external) UI API (OSP) always
+       FL_NETWORK_API_ALWAYS_PROBING   = 0x000100000000ULL, // all (include external) network API (glibc, OSP, libsoap, openssl) always
+       FL_OPENGL_API_ALWAYS_PROBING    = 0x000200000000ULL, // all (include external) openGL API always
+
+       FL_RESERVED3                    = 0x000c00000000ULL, // reserved
+
+       FL_SYSTEM_CPU                   = 0x001000000000ULL, // CPU core load, frequency
+       FL_SYSTEM_MEMORY                = 0x002000000000ULL, // System memory used
+       FL_SYSTEM_PROCESS               = 0x004000000000ULL, // Info for profilling processes (VSS, PSS, RSS, etc)
+       FL_SYSTEM_THREAD_LOAD           = 0x008000000000ULL, // Thread loading for profiling processes
+       FL_SYSTEM_PROCESSES_LOAD        = 0x010000000000ULL, // Non instrumented process load
+       FL_SYSTEM_DISK                  = 0x020000000000ULL, // /proc/diskstats - reads, sectors read, writes, sectors written
+       FL_SYSTEM_NETWORK               = 0x040000000000ULL, // network send/recv size
+       FL_SYSTEM_DEVICE                = 0x080000000000ULL, //
+       FL_SYSTEM_ENERGY                = 0x100000000000ULL, //
+
+       FL_RESERVED4                    = 0xe00000000000ULL, // reserved 1110
+
+       FL_ALL_FEATURES                 = 0x3FFFFFFFFFFFULL &
+                                         (~FL_RESERVED1) &
+                                         (~FL_RESERVED2) &
+                                         (~FL_RESERVED3) &
+                                         (~FL_RESERVED4)
+
+};
+
+#define IS_OPT_SET_IN(OPT, reg) (reg & (OPT))
+#define IS_OPT_SET(OPT) IS_OPT_SET_IN((OPT), prof_session.conf.use_features0)
+
+enum app_type {
+       AT_TIZEN        =0x01,
+       AT_LAUNCHED     =0x02,
+       AT_COMMON       =0x03
+};
+enum supported_device {
+       DEVICE_FLASH,
+       DEVICE_CPU,
+       DEVICE_LCD
+};
+static const char *supported_devices_strings[] = {
+       "FLASH",
+       "CPU",
+       "LCD"
+};
+#define array_size(x) (sizeof(x)/sizeof((x)[0]))
+enum { supported_devices_count = array_size(supported_devices_strings) };
+
+#define TARGER_MSG_MAX_LEN                     4096
+#define HOST_CTL_MSG_MAX_LEN                   (10 * 1024 * 1024)
+
+struct _msg_target_t {
+       unsigned int type;
+       unsigned int length;
+       char data[0];
+};
+
+struct msg_target_t {
+       unsigned int type;
+       unsigned int length;
+       char data[TARGER_MSG_MAX_LEN];
+};
+
+enum { MSG_HEADER_LEN = offsetof(struct msg_target_t, data) };
+
+
+#define MAX_FILENAME 128
+
+#define MSG_DATA_HDR_LEN 20
+struct msg_data_t {
+       uint32_t id;
+       uint32_t seq_num;
+       uint32_t sec;
+       uint32_t nsec;
+       uint32_t len;
+       char payload[0];
+};
+
+#define MSG_CMD_HDR_LEN 8
+//conf
+struct msg_buf_t {
+       char *payload;
+       char *cur_pos;
+       char *end;
+       uint32_t len;
+};
+
+struct msg_t {
+       uint32_t id;
+       uint32_t len;
+       char payload[0];
+};
+
+
+struct conf_t {
+       uint64_t use_features0;
+       uint64_t use_features1;
+       uint32_t system_trace_period;
+       uint32_t data_message_period;
+};
+
+typedef uint32_t log_interval_t;
+
+//app, libs, probes
+enum app_type_t {
+       APP_TYPE_UNKNOWN = 0,
+       APP_TYPE_TIZEN = 1,
+       APP_TYPE_RUNNING = 2,
+       APP_TYPE_COMMON = 3,
+       APP_TYPE_WEB = 4
+};
+
+struct app_info_t {
+       uint32_t app_type;
+       char *app_id;
+       char *exe_path;
+};
+
+
+
+struct us_func_inst_plane_t {
+       //format
+       //name       | type   | len       | info
+       //------------------------------------------
+       //func_addr  | uint64 | 8         |
+       //args       | string | len(args) |end with '\0'
+       //ret_type   | char   | 1         |
+       uint64_t func_addr;
+       char args[0];
+};
+
+struct us_lib_inst_t {
+       char *bin_path;
+};
+
+struct user_space_inst_t {
+       uint32_t app_num;
+       struct app_list_t *app_inst_list;
+       uint32_t lib_num;
+       struct lib_list_t *lib_inst_list;
+};
+
+//replays
+struct replay_event_t {
+       uint32_t id;
+       struct input_event ev;
+};
+
+struct replay_event_seq_t {
+       uint32_t enabled;
+       struct timeval tv;
+       uint32_t event_num;
+       struct replay_event_t *events;
+};
+
+struct prof_session_t {
+       struct conf_t conf;
+       struct user_space_inst_t user_space_inst;
+       struct replay_event_seq_t replay_event_seq;
+       unsigned running_status:1; // to stop properly (1 - it is running, 0 - no)
+};
+
+int parseHostMessage(struct msg_t *log, char *msg);
+int host_message_handler(struct msg_t *msg);
+
+char *msg_ID_str(enum HostMessageT ID);
+
+// testing
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+//data protocol
+struct thread_info_t {
+       uint32_t pid;
+       float load;
+};
+
+struct other_process_info_t {
+       uint32_t id;
+       float load;
+};
+
+struct inst_process_info_t {
+       uint32_t id;
+       float load;
+       uint64_t virtual_memory;
+       uint64_t resident_memory;
+       uint64_t shared_memory;
+       uint64_t pss_memory;
+       uint64_t total_alloc_size;
+       uint32_t count_of_threads;
+
+};
+
+
+/**
+ * NOTE:
+ *
+ * Adding pointer memebers to struct %system_info_t REQUIRES updating code,
+ * calculating length of bytevector, suitable for serializing it. See
+ * msg_data_payload_length()
+ *
+ */
+struct system_info_t {
+       // system_cpu
+       float *cpu_frequency;
+       float *cpu_load;
+
+       // total thread count to calculate msg size
+       uint32_t count_of_threads;
+
+       // system_memory
+       uint64_t system_memory_used;
+
+       // system_processes
+       uint32_t count_of_inst_processes;
+       uint32_t count_of_other_processes;
+
+       //system fd
+       uint32_t fd_count;
+       uint32_t fd_peration_count;
+
+       // system_disk
+       uint32_t total_used_drive;
+       uint32_t disk_reads;
+       uint32_t disk_bytes_read;
+       uint32_t disk_writes;
+       uint32_t disk_bytes_write;
+
+       // system_network
+       uint32_t network_send_size;
+       uint32_t network_receive_size;
+
+       // system_device
+       uint32_t wifi_status;
+       uint32_t bt_status;
+       uint32_t gps_status;
+       uint32_t brightness_status;
+       uint32_t camera_status;
+       uint32_t sound_status;
+       uint32_t audio_status;
+       uint32_t vibration_status;
+       uint32_t voltage_status;
+       uint32_t rssi_status;
+       uint32_t video_status;
+       uint32_t call_status;
+       uint32_t dnet_status;
+
+       // system_energy
+       uint32_t energy;
+       uint32_t energy_per_device[supported_devices_count];
+       uint32_t app_energy_per_device[supported_devices_count];
+};
+
+struct recorded_event_t {
+       uint32_t id;
+       uint32_t type;
+       uint32_t code;
+       uint32_t value;
+};
+#define static_assert(cond) \
+       char __attribute__((unused)) __static_assert[(cond) ? 1 : -1];
+
+#define pack_int64(to, n) do {                                         \
+               static_assert(sizeof(n) == 8);                          \
+               *(uint64_t *)to = n;                                    \
+               to += sizeof(uint64_t);                                 \
+       } while (0)
+
+#define pack_int32(to, n) do {                                         \
+               static_assert(sizeof(n) == 4);                          \
+               *(uint32_t *)to = n;                                    \
+               to += sizeof(uint32_t);                                 \
+       } while (0)
+
+#define pack_time(to, n)                                               \
+       do {                                                            \
+               pack_int32(to, n.tv_sec);                               \
+               pack_int32(to, n.tv_usec);                              \
+       } while (0)
+
+#define pack_float(to, n)                                      \
+       do {                                                    \
+               *(float *)to = n;                               \
+               to += sizeof(float);                            \
+       } while (0)
+
+#define pack_str(to, n)                                \
+       do {                                    \
+               memcpy(to, n, strlen(n) + 1);   \
+               to += strlen(n) + 1;            \
+       } while (0)
+
+static inline void* pack_str_array(void *buffer, const char **strings,
+                                  size_t count)
+{
+       int index;
+       for (index = 0; index != count; ++index)
+               pack_str(buffer, strings[index]);
+       return buffer;
+}
+
+struct msg_data_t *pack_system_info(struct system_info_t *sys_info);
+int write_to_buf(struct msg_data_t *msg);
+void free_msg_data(struct msg_data_t *msg);
+void free_msg_payload(struct msg_t *msg);
+void free_sys_info(struct system_info_t *sys_info);
+int start_replay(void);
+void stop_replay(void);
+
+enum ErrorCode stop_all(void);
+enum ErrorCode stop_all_no_lock(void);
+int stop_all_in_process(void);
+void stop_all_done(void);
+
+void reset_msg(struct msg_t *msg);
+void reset_replay_event_seq(struct replay_event_seq_t *res);
+void reset_system_info(struct system_info_t *sys);
+int check_running_status(const struct prof_session_t *prof_session);
+
+extern struct prof_session_t prof_session;
+
+int send_msg_to_sock(int sock, struct msg_target_t *msg);
+int recv_msg_from_sock(int sock, struct msg_target_t *msg);
+
+//debugs
+void print_replay_event(struct replay_event_t *ev, uint32_t num, char *tab);
+
+int sendACKToHost(enum HostMessageT resp, enum ErrorCode err_code,
+                       char *payload, int payload_size);
+
+int parse_int8(struct msg_buf_t *msg, uint8_t *val);
+int parse_int32(struct msg_buf_t *msg, uint32_t *val);
+int parse_int64(struct msg_buf_t *msg, uint64_t *val);
+int parse_string(struct msg_buf_t *msg, char **str);
+int parse_string_no_alloc(struct msg_buf_t *msg, char *str);
+int parse_replay_event_seq(struct msg_buf_t *msg, struct replay_event_seq_t *res);
+
+void init_prof_session(struct prof_session_t *prof_session);
+#endif /* _DA_PROTOCOL_ */
diff --git a/daemon/da_protocol_check.c b/daemon/da_protocol_check.c
new file mode 100644 (file)
index 0000000..149c35f
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+#include "debug.h"
+#include "da_protocol.h"
+#include "da_protocol_check.h"
+
+#include <stdint.h>
+#include <string.h>
+
+//application checking functions
+int check_app_type(uint32_t app_type)
+{
+       if ((app_type >= APP_INFO_TYPE_MIN) &&
+               (app_type <= APP_INFO_TYPE_MAX)) {
+               return 1;
+       } else {
+               LOGE("wrong value\n");
+               return 0;
+       }
+}
+
+static int is_pid_string_valid(const char *pid_str)
+{
+       char *tmp;
+       long pid;
+
+       if (pid_str[0] == '\0') /* no pid filtering */
+               return 1;
+
+       /* otherwise this should be a valid number */
+       pid = strtol(pid_str, &tmp, 10);
+
+       /* TODO: get max pid value from /proc/sys/kernel/pid_max */
+       return *tmp == '\0' && pid > 0 && pid <= 32768;
+}
+
+int check_app_id(uint32_t app_type, char *app_id)
+{
+       int res = 0;
+       char *p;
+       switch (app_type){
+               case APP_TYPE_TIZEN:
+                       res = 1;
+                       break;
+               case APP_TYPE_RUNNING:
+                       if (!is_pid_string_valid(app_id))
+                               LOGE("wrong app id for APP_RUNNING\n");
+                       else
+                               res = 1;
+                       break;
+               case APP_TYPE_COMMON:
+                       res = (strlen(app_id) == 0);
+                       if (!res)
+                               LOGE("wrong app id for APP_COMMON\n");
+                       break;
+               case APP_TYPE_WEB:
+                       res = 1;
+                       break;
+               default :
+                       LOGE("wrong app type\n");
+                       return 0;
+                       break;
+       }
+       return res;
+}
+
+int check_exec_path(char *path)
+{
+       int res = 1;
+       struct stat buffer;
+
+       if (!(res = (stat (path, &buffer) == 0)))
+               LOGE("wrong exec path <%s>\n", path);
+
+       return res;
+}
+
+//config checking functions
+int check_conf_features(uint64_t feature0, uint64_t feature1)
+{
+       int res = 1;
+
+       feature0 &= ~(uint64_t)FL_ALL_FEATURES;
+
+       if (feature0 != 0) {
+               LOGE("wrong features0 0x%016llX mask %016llX\n", feature0, (uint64_t)FL_ALL_FEATURES);
+               res = 0;
+       }
+
+       feature1 &= ~(uint64_t)0;
+
+       if (feature1 != 0) {
+               LOGE("wrong features1 0x%016llX mask %016llX\n", feature1, (uint64_t)0);
+               res = 0;
+       }
+
+       return res;
+}
+
+
+int check_conf_systrace_period(uint32_t system_trace_period)
+{
+       int res = 1;
+       if ((system_trace_period < CONF_SYSTRACE_PERIOD_MIN) ||
+               (system_trace_period > CONF_SYSTRACE_PERIOD_MAX))
+       {
+               LOGE("wrong system trace period value %u (0x%08X)\n",
+                    (unsigned int) system_trace_period, system_trace_period);
+               res = 0;
+       }
+
+       return res;
+}
+
+int check_conf_datamsg_period(uint32_t data_message_period)
+{
+       int res = 1;
+       if ((data_message_period < CONF_DATA_MSG_PERIOD_MIN) ||
+               (data_message_period > CONF_DATA_MSG_PERIOD_MAX))
+       {
+               LOGE("wrong data message period value %u (0x%08X)\n",
+                    (unsigned int) data_message_period, data_message_period);
+               res = 0;
+       }
+
+       return res;
+}
+
+//User space check functions
+int check_us_app_count(uint32_t app_count)
+{
+       int res = 1;
+       if (app_count > US_APP_COUNT_MAX) {
+               LOGE("wrong user space app count %u (0x%08X)\n",
+                    (unsigned int)app_count, app_count);
+               res = 0;
+       }
+
+       return res;
+}
+//User space app inst check function
+int check_us_app_inst_func_count(uint32_t func_count)
+{
+       int res = 1;
+       if (func_count > US_APP_INST_FUNC_MAX) {
+               LOGE("wrong US app inst func count %u (0x%08X)\n",
+                    (unsigned int)func_count, func_count);
+               res = 0;
+       }
+
+       return res;
+}
+
+static char *args_avail = US_FUNC_ARGS;
+int check_us_inst_func_args(char *args)
+{
+       char *p;
+       for (p = args; *p != 0; p++)
+               if (strchr(args_avail, (int)*p) == NULL){
+                       LOGE("wrong args <%s> char <%c> <0x%02X>\n", args, (int)*p, (char)*p);
+                       return 0;
+               }
+       return 1;
+}
+
+static char *rets_avail = US_FUNC_RETURN;
+int check_us_inst_func_ret_type(char ret_type)
+{
+       if (strchr(rets_avail, (int)ret_type) == NULL){
+               LOGE("wrong ret type <%c> <0x%02X>\n", (int)ret_type, (char)ret_type);
+               return 0;
+       }
+       return 1;
+}
+
+int check_lib_inst_count(uint32_t lib_count)
+{
+       int res = 1;
+       if (lib_count > US_APP_INST_LIB_MAX) {
+               LOGE("wrong US app inst lib count %u (0x%08X)\n",
+                    (unsigned int)lib_count, lib_count);
+               res = 0;
+       }
+
+       return res;
+}
+
+int check_conf(struct conf_t *conf)
+{
+       //Check features value
+       if (!check_conf_features(conf->use_features0, conf->use_features1)) {
+               LOGE("check features fail\n");
+               return 0;
+       }
+
+       if (!check_conf_systrace_period(conf->system_trace_period)) {
+               LOGE("system trace period error\n");
+               return 0;
+       }
+
+       if (!check_conf_datamsg_period(conf->data_message_period)) {
+               LOGE("data message period error\n");
+               return 0;
+       }
+
+       return 1;
+}
diff --git a/daemon/da_protocol_check.h b/daemon/da_protocol_check.h
new file mode 100644 (file)
index 0000000..5157df7
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+#include <stdint.h>
+
+#include "daemon.h"
+
+// Max values defines
+#define APP_INFO_TYPE_MIN 0x0001
+#define APP_INFO_TYPE_MAX 0x0004
+
+#define CONF_SYSTRACE_PERIOD_MIN 100
+#define CONF_SYSTRACE_PERIOD_MAX 1000
+
+#define CONF_DATA_MSG_PERIOD_MIN 1
+#define CONF_DATA_MSG_PERIOD_MAX 100
+
+#define US_APP_COUNT_MAX MAX_TARGET_COUNT
+
+#define US_APP_INST_FUNC_MAX 100000
+
+#define US_FUNC_ARGS "bcdxpfw"
+#define US_FUNC_RETURN "vnbcdxpfw"
+
+#define US_APP_INST_LIB_MAX 1000
+
+int check_app_type(uint32_t app_type);
+int check_app_id(uint32_t app_type, char *app_id);
+int check_exec_path(char *path);
+int check_conf_features(uint64_t feature0, uint64_t feature1);
+int check_conf_systrace_period(uint32_t system_trace_period);
+int check_conf_datamsg_period(uint32_t data_message_period);
+int check_us_app_count(uint32_t app_count);
+int check_us_app_inst_func_count(uint32_t func_count);
+int check_us_inst_func_args(char *args);
+int check_lib_inst_count(uint32_t lib_count);
+int check_conf(struct conf_t *conf);
+int check_us_inst_func_ret_type(char ret_type);
diff --git a/daemon/da_protocol_inst.c b/daemon/da_protocol_inst.c
new file mode 100644 (file)
index 0000000..26ffb35
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+#include "debug.h"
+#include "da_protocol.h"
+#include "da_protocol_inst.h"
+#include "da_inst.h"
+#include "da_protocol_check.h"
+
+//----------------- hash
+static uint32_t calc_lib_hash(struct us_lib_inst_t *lib)
+{
+       uint32_t hash = 0;
+       char *p = lib->bin_path;
+       while (*p != 0) {
+               hash <<= 1;
+               hash += *p;
+               p++;
+       }
+       return hash;
+}
+
+static uint32_t calc_app_hash(struct app_info_t *app)
+{
+       uint32_t hash = 0;
+       char *p = app->exe_path;
+       while (*p != 0) {
+               hash <<= 1;
+               hash += *p;
+               p++;
+       }
+       return hash;
+}
+
+
+//----------------------------------- parse -----------------------------------
+static int parse_us_inst_func(struct msg_buf_t *msg, struct probe_list_t **dest)
+{
+       //probe format
+       //name       | type   | len       | info
+       //------------------------------------------
+       //func_addr  | uint64 | 8         |
+       //args       | string | len(args) |end with '\0'
+       //ret_type   | char   | 1         |
+
+       uint32_t size = 0;
+       struct us_func_inst_plane_t *func;
+       int par_count = 0;
+       char *ret_type = NULL;
+
+       par_count = strlen(msg->cur_pos + sizeof(func->func_addr));
+       size = sizeof(*func) + par_count + 1 +
+              sizeof(char) /* sizeof(char) for ret_type */;
+       func = malloc(size);
+       if (!parse_int64(msg, &(func->func_addr))) {
+               LOGE("func addr parsing error\n");
+               goto err_ret;
+       }
+
+       if (!parse_string_no_alloc(msg, func->args) ||
+           !check_us_inst_func_args(func->args))
+       {
+               LOGE("args format parsing error\n");
+               goto err_ret;
+       }
+
+       //func->args type is char[0]
+       //and we need put ret_type after func->args
+       ret_type = func->args + par_count + 1;
+       if (!parse_int8(msg, (uint8_t *)ret_type) ||
+           !check_us_inst_func_ret_type(*ret_type))
+       {
+               LOGE("return type parsing error\n");
+               goto err_ret;
+       } else {
+               parse_deb("ret type = <%c>\n", *ret_type);
+       }
+
+       *dest = new_probe();
+       if (*dest == NULL) {
+               LOGE("alloc new_probe error\n");
+               goto err_ret;
+       }
+       (*dest)->size = size;
+       (*dest)->func = func;
+       return 1;
+err_ret:
+       free(func);
+       return 0;
+}
+
+static int parse_func_inst_list(struct msg_buf_t *msg,
+                               struct data_list_t *dest)
+{
+       uint32_t i = 0, num = 0;
+       struct probe_list_t *probe_el;
+
+       if (!parse_int32(msg, &num) ||
+               !check_us_app_inst_func_count(num))
+       {
+               LOGE("func num parsing error\n");
+               return 0;
+       }
+       //parse user space function list
+
+       parse_deb("app_int_num = %d\n", num);
+       for (i = 0; i < num; i++) {
+               parse_deb("app_int #%d\n", i);
+               if (!parse_us_inst_func(msg, &probe_el)) {
+                       // TODO maybe need to free allocated memory up there
+                       LOGE("parse us inst func #%d failed\n", i + 1);
+                       return 0;
+               }
+               probe_list_append(dest, probe_el);
+       }
+       dest->func_num = num;
+       return 1;
+}
+
+static int parse_inst_lib(struct msg_buf_t *msg, struct lib_list_t **dest)
+{
+       int res = 1;
+       *dest = new_lib();
+       if (*dest == NULL) {
+               LOGE("lib alloc error\n");
+               res = 0;
+               goto exit;
+       };
+
+       if (!parse_string(msg, &((*dest)->lib->bin_path)) ||
+           !check_exec_path((*dest)->lib->bin_path))
+       {
+               LOGE("bin path parsing error\n");
+               goto exit_free_err;
+       }
+
+       if (!parse_func_inst_list(msg, (struct data_list_t *) *dest)) {
+               LOGE("funcs parsing error\n");
+               goto exit_free_err;
+       }
+
+       (*dest)->size +=  strlen((*dest)->lib->bin_path) + 1 + sizeof((*dest)->func_num);
+       (*dest)->hash = calc_lib_hash((*dest)->lib);
+
+       goto exit;
+
+exit_free_err:
+       res = 0;
+       free(*dest);
+
+exit:
+       return res;
+
+}
+
+int parse_lib_inst_list(struct msg_buf_t *msg,
+                       uint32_t *num,
+                       struct lib_list_t **lib_list)
+{
+       uint32_t i = 0;
+       struct lib_list_t *lib = NULL;
+       if (!parse_int32(msg, num) ||
+               !check_lib_inst_count(*num))
+       {
+               LOGE("lib num parsing error\n");
+               return 0;
+       }
+
+       for (i = 0; i < *num; i++) {
+               if (!parse_inst_lib(msg, &lib)) {
+                       // TODO maybe need free allocated memory up there
+                       LOGE("parse is inst lib #%d failed\n", i + 1);
+                       return 0;
+               }
+               data_list_append((struct data_list_t **)lib_list,
+                                (struct data_list_t *)lib);
+       }
+
+       return 1;
+}
+
+int parse_inst_app(struct msg_buf_t *msg, struct app_list_t **dest)
+{
+       int res = 1;
+       char *start, *end;
+       struct app_info_t *app_info = NULL;
+       *dest = new_app();
+
+       if (*dest == NULL) {
+               LOGE("lib alloc error\n");
+               res = 0;
+               goto exit;
+       };
+
+       app_info = (*dest)->app;
+       start = msg->cur_pos;
+       if (!parse_int32(msg, &app_info->app_type) ||
+               !check_app_type(app_info->app_type))
+       {
+               LOGE("app type parsing error <0x%X>\n", app_info->app_type);
+               goto exit_free_err;
+       }
+
+       if (!parse_string(msg, &app_info->app_id) ||
+               !check_app_id(app_info->app_type, app_info->app_id))
+       {
+               LOGE("app id parsing error\n");
+               goto exit_free_err;
+       }
+
+       if (!parse_string(msg, &app_info->exe_path) ||
+           ((app_info->app_type != APP_TYPE_WEB) &&
+            ((app_info->app_type != APP_TYPE_RUNNING) ||
+             (app_info->app_id[0] != '\0')) &&
+            !check_exec_path(app_info->exe_path)))
+       {
+               LOGE("exec path parsing error\n");
+               goto exit_free_err;
+       }
+       end = msg->cur_pos;
+
+       if (!parse_func_inst_list(msg, (struct data_list_t *)*dest)) {
+               LOGE("funcs parsing error\n");
+               goto exit_free_err;
+       }
+
+       (*dest)->size += (end - start) + sizeof((*dest)->func_num);
+       (*dest)->hash = calc_app_hash(app_info);
+       goto exit;
+
+exit_free_err:
+       res = 0;
+       free(*dest);
+exit:
+       return res;
+}
+
+int parse_app_inst_list(struct msg_buf_t *msg,
+                       uint32_t *num,
+                       struct app_list_t  **app_list)
+{
+       uint32_t i = 0;
+       struct app_list_t *app = NULL;
+       if (!parse_int32(msg, num) ||
+               !check_lib_inst_count(*num))
+       {
+               LOGE("app num parsing error\n");
+               return 0;
+       }
+
+       parse_deb("app_int_num = %d\n", *num);
+       for (i = 0; i < *num; i++) {
+               parse_deb("app_int #%d\n", i);
+               if (!parse_inst_app(msg, &app)) {
+                       // TODO maybe need free allocated memory up there
+                       LOGE("parse is inst app #%d failed\n", i + 1);
+                       return 0;
+               }
+               data_list_append((struct data_list_t **)app_list,
+                                (struct data_list_t *)app);
+       }
+
+       if (!parse_replay_event_seq(msg, &prof_session.replay_event_seq)) {
+               LOGE("replay parsing error\n");
+               return 0;
+       }
+
+       return 1;
+}
+
diff --git a/daemon/da_protocol_inst.h b/daemon/da_protocol_inst.h
new file mode 100644 (file)
index 0000000..aaebbce
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+#ifndef __DA_PROTOCOL_INST__
+#define __DA_PROTOCOL_INST__
+
+int parse_lib_inst_list(struct msg_buf_t *msg,
+                       uint32_t *num,
+                       struct lib_list_t **lib_list);
+
+int parse_inst_app(struct msg_buf_t *msg, struct app_list_t **dest);
+
+int parse_app_inst_list(struct msg_buf_t *msg,
+                       uint32_t *num,
+                       struct app_list_t **app_list);
+
+#endif /* __DA_PROTOCOL_INST__ */
diff --git a/daemon/daemon.c b/daemon/daemon.c
new file mode 100644 (file)
index 0000000..2bb04c7
--- /dev/null
@@ -0,0 +1,1017 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Jaewon Lim <jaewon81.lim@samsung.com>
+ * Woojin Jung <woojin2.jung@samsung.com>
+ * Juyoung Kim <j0.kim@samsung.com>
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ * Nikita Kalyazin    <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ * - Samsung RnD Institute Russia
+ *
+ */
+#define __STDC_FORMAT_MACROS
+#include <stdio.h>
+#include <stdlib.h>            // for realpath
+#include <string.h>            // for strtok, strcpy, strncpy
+#include <limits.h>            // for realpath
+#include <inttypes.h>
+
+#include <errno.h>             // for errno
+#include <sys/types.h>         // for accept, mkdir, opendir, readdir
+#include <sys/socket.h>                // for accept
+#include <sys/stat.h>          // for mkdir
+#include <sys/eventfd.h>       // for eventfd
+#include <sys/timerfd.h>       // for timerfd
+#include <unistd.h>            // for access, sleep
+#include <stdbool.h>
+
+#include <ctype.h>
+
+#include <fcntl.h>
+
+#include <assert.h>
+
+#include <Ecore.h>
+
+#include "daemon.h"
+#include "sys_stat.h"
+#include "utils.h"
+#include "da_protocol.h"
+#include "da_inst.h"
+#include "da_data.h"
+#include "input_events.h"
+#include "smack.h"
+#include "debug.h"
+
+#define DA_WORK_DIR                    "/home/developer/sdk_tools/da/"
+#define DA_READELF_PATH                        "/home/developer/sdk_tools/da/readelf"
+#define SCREENSHOT_DIR                 "/tmp/da"
+
+#define MAX_APP_LAUNCH_TIME            60
+#define MAX_CONNECT_TIMEOUT_TIME       5*60
+
+
+// =============================================================================
+// start and terminate control functions
+// =============================================================================
+
+static Ecore_Fd_Handler *launch_timer_handler;
+static pthread_mutex_t launch_timer_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static void launch_timer_lock()
+{
+       LOGI("lock launch_timer_mutex\n");
+       pthread_mutex_lock(&launch_timer_mutex);
+       LOGI("locked launch_timer_mutex\n");
+}
+
+static void launch_timer_unlock()
+{
+       pthread_mutex_unlock(&launch_timer_mutex);
+       LOGI("unlock launch_timer_mutex\n");
+}
+
+//stop application launch timer
+static int stop_app_launch_timer()
+{
+       int res = 0;
+       launch_timer_lock();
+
+       if (manager.app_launch_timerfd > 0) {
+               ecore_main_fd_handler_del(launch_timer_handler);
+               if (close(manager.app_launch_timerfd)) {
+                       LOGE("close app_launch_timerfd failed\n");
+                       res = 1;
+               }
+               manager.app_launch_timerfd = -1;
+       } else {
+               LOGW("trying to stop app launch timer when it stoped\n");
+       }
+
+       launch_timer_unlock();
+       return res;
+}
+
+static Eina_Bool launch_timer_cb(void *data, Ecore_Fd_Handler *fd_handler)
+{
+       LOGE("Failed to launch application\n");
+       if (stop_app_launch_timer())
+               LOGE("cannot stop app launch timer\n");
+
+       return ECORE_CALLBACK_CANCEL;
+}
+
+//start application launch timer function
+static int start_app_launch_timer(int apps_count)
+{
+       int res = 0;
+
+       assert(apps_count >= 0 && "negative apps count");
+
+       if (apps_count == 0)
+               return res;
+
+       if (manager.app_launch_timerfd > 0) {
+               LOGI("stop previous app launch timer\n");
+               stop_app_launch_timer();
+       }
+
+       launch_timer_lock();
+
+       manager.app_launch_timerfd =
+           timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC);
+       if (manager.app_launch_timerfd > 0) {
+               struct itimerspec ctime;
+               ctime.it_value.tv_sec = MAX_APP_LAUNCH_TIME * apps_count;
+               ctime.it_value.tv_nsec = 0;
+               ctime.it_interval.tv_sec = 0;
+               ctime.it_interval.tv_nsec = 0;
+               if (timerfd_settime(manager.app_launch_timerfd, 0, &ctime, NULL) < 0) {
+                       LOGE("fail to set app launch timer\n");
+                       res = -1;
+                       goto unlock_and_stop;
+               } else {
+                       launch_timer_handler =
+                               ecore_main_fd_handler_add(manager.app_launch_timerfd,
+                                                         ECORE_FD_READ,
+                                                         launch_timer_cb,
+                                                         NULL,
+                                                         NULL, NULL);
+                       if (!launch_timer_handler) {
+                               LOGE("fail to add app launch timer fd to \n");
+                               res = -2;
+                               goto unlock_and_stop;
+                       } else {
+                               LOGI("application launch time started\n");
+                       }
+               }
+       } else {
+               LOGE("cannot create launch timer\n");
+               res = -3;
+       }
+
+       launch_timer_unlock();
+       return res;
+
+unlock_and_stop:
+       launch_timer_unlock();
+
+       stop_app_launch_timer();
+       return res;
+}
+
+static inline void inc_apps_to_run()
+{
+       manager.apps_to_run++;
+}
+
+static inline void dec_apps_to_run()
+{
+       if (manager.apps_to_run > 0)
+               manager.apps_to_run--;
+}
+
+static inline int get_apps_to_run()
+{
+       return manager.apps_to_run;
+}
+
+static int kill_app_by_info(const struct app_info_t *app_info)
+{
+       int res = 0;
+
+       if (app_info == NULL) {
+               LOGE("Cannot exec app. app_info is NULL");
+               return -1;
+       }
+
+       switch (app_info->app_type) {
+       case APP_TYPE_TIZEN:
+               res = kill_app(app_info->exe_path);
+               break;
+       case APP_TYPE_RUNNING:
+               // TODO: nothing, it's running
+               LOGI("already started\n");
+               break;
+       case APP_TYPE_COMMON:
+               res = kill_app(app_info->exe_path);
+               break;
+       case APP_TYPE_WEB:
+               /* do nothing (it is restarted by itself) */
+               break;
+       default:
+               LOGE("Unknown app type %d\n", app_info->app_type);
+               res = -1;
+               break;
+       }
+
+       return res;
+}
+
+static int exec_app(const struct app_info_t *app_info)
+{
+       int res = 0;
+
+       if (app_info == NULL) {
+               LOGE("Cannot exec app. app_info is NULL");
+               return -1;
+       }
+
+       switch (app_info->app_type) {
+       case APP_TYPE_TIZEN:
+               if (exec_app_tizen(app_info->app_id, app_info->exe_path)) {
+                       LOGE("Cannot exec tizen app %s\n", app_info->app_id);
+                       res = -1;
+               } else {
+                       inc_apps_to_run();
+               }
+               break;
+       case APP_TYPE_RUNNING:
+               // TODO: nothing, it's running
+               LOGI("already started\n");
+               break;
+       case APP_TYPE_COMMON:
+               if (exec_app_common(app_info->exe_path)) {
+                       LOGE("Cannot exec common app %s\n", app_info->exe_path);
+                       res = -1;
+               } else {
+                       inc_apps_to_run();
+               }
+               break;
+       case APP_TYPE_WEB:
+               if (exec_app_web(app_info->app_id)) {
+                       LOGE("Cannot exec web app %s\n", app_info->app_id);
+                       res = -1;
+               }
+               break;
+       default:
+               LOGE("Unknown app type %d\n", app_info->app_type);
+               res = -1;
+               break;
+       }
+
+       LOGI("ret=%d\n", res);
+       return res;
+}
+
+// just send stop message to all target process
+static void terminate_all_target()
+{
+       struct msg_target_t msg = {
+               .type = MSG_STOP,
+               .length = 0
+       };
+
+       target_send_msg_to_all(&msg);
+}
+
+// terminate all target and wait for threads
+void terminate_all()
+{
+       terminate_all_target();
+
+       // wait for all other thread exit
+       target_wait_all();
+}
+
+// terminate all profiling by critical error
+// TODO: don't send data to host
+static void terminate_error(char *errstr, int send_to_host)
+{
+       LOGE("termination all with err '%s'\n", errstr);
+       struct msg_data_t *msg = NULL;
+       if (send_to_host != 0) {
+               msg = gen_message_error(errstr);
+               if (msg) {
+                       if (write_to_buf(msg) != 0)
+                               LOGE("write to buf fail\n");
+                       free_msg_data(msg);
+               } else {
+                       LOGI("cannot generate error message\n");
+               }
+       }
+       terminate_all();
+}
+
+static Ecore_Fd_Handler *connect_timer_handler;
+
+static Eina_Bool connect_timer_cb(void *data, Ecore_Fd_Handler *fd_handler)
+{
+       terminate_error("no incoming connections", 1);
+       close(manager.connect_timeout_timerfd);
+       manager.connect_timeout_timerfd = -1;
+       LOGE("No connection in %d sec. shutdown.\n",
+            MAX_CONNECT_TIMEOUT_TIME);
+       ecore_main_loop_quit();
+
+       return ECORE_CALLBACK_CANCEL;
+}
+
+static int launch_timer_start(void)
+{
+       int res = 0;
+
+       manager.connect_timeout_timerfd =
+           timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC);
+       if (manager.connect_timeout_timerfd > 0) {
+               struct itimerspec ctime;
+               ctime.it_value.tv_sec = MAX_CONNECT_TIMEOUT_TIME;
+               ctime.it_value.tv_nsec = 0;
+               ctime.it_interval.tv_sec = 0;
+               ctime.it_interval.tv_nsec = 0;
+               if (timerfd_settime(manager.connect_timeout_timerfd, 0, &ctime, NULL) < 0) {
+                       LOGE("fail to set connect timeout timer\n");
+                       close(manager.connect_timeout_timerfd);
+                       manager.connect_timeout_timerfd = -1;
+               } else {
+                       connect_timer_handler =
+                               ecore_main_fd_handler_add(manager.connect_timeout_timerfd,
+                                                         ECORE_FD_READ,
+                                                         connect_timer_cb,
+                                                         NULL,
+                                                         NULL, NULL);
+                       if (!connect_timer_handler) {
+                               LOGE("fail to add app connection timeout timer fd\n");
+                               close(manager.connect_timeout_timerfd);
+                               manager.connect_timeout_timerfd = -1;
+                       } else {
+                               LOGI("connection timeout timer started\n");
+                       }
+               }
+       } else {
+               LOGE("cannot create connection timeout timer\n");
+       }
+
+       LOGI("ret=%d\n", res);
+       return res;
+}
+
+int prepare_profiling(void)
+{
+       struct app_list_t *app = NULL;
+       const struct app_info_t *app_info = NULL;
+
+       app_info = app_info_get_first(&app);
+       if (app_info == NULL) {
+               LOGE("No app info found\n");
+               return -1;
+       }
+
+       //all apps
+       while (app_info != NULL) {
+               if (kill_app_by_info(app_info) != 0) {
+                       LOGE("kill app failed\n");
+                       return -1;
+               }
+               app_info = app_info_get_next(&app);
+       }
+       //init rw for systeminfo
+       //init recv send network systeminfo
+       sys_stat_prepare();
+       return 0;
+
+}
+
+int start_profiling(void)
+{
+       struct app_list_t *app = NULL;
+       const struct app_info_t *app_info = NULL;
+       int res = 0;
+
+       app_info = app_info_get_first(&app);
+       if (app_info == NULL) {
+               LOGE("No app info found\n");
+               return -1;
+       }
+       // remove previous screen capture files
+       remove_indir(SCREENSHOT_DIR);
+       if (mkdir(SCREENSHOT_DIR, 0777) == -1 && errno != EEXIST) {
+               GETSTRERROR(errno, buf);
+               LOGW("Failed to create directory for screenshot : %s\n", buf);
+       }
+
+       set_label_for_all(SCREENSHOT_DIR);
+
+       if (samplingStart() < 0) {
+               LOGE("Cannot start sampling\n");
+               res = -1;
+               goto exit;
+       }
+
+       if (IS_OPT_SET(FL_RECORDING))
+               add_input_events();
+
+       while (app_info != NULL) {
+               if (exec_app(app_info)) {
+                       LOGE("Cannot exec app\n");
+                       res = -1;
+                       goto recording_stop;
+               }
+               app_info = app_info_get_next(&app);
+       }
+
+       if (start_app_launch_timer(get_apps_to_run()) < 0) {
+               res = -1;
+               goto recording_stop;
+       }
+
+       goto exit;
+
+ recording_stop:
+       if (IS_OPT_SET(FL_RECORDING))
+               del_input_events();
+       samplingStop();
+
+ exit:
+       LOGI("return %d\n", res);
+       return res;
+}
+
+void stop_profiling(void)
+{
+       if (IS_OPT_SET(FL_RECORDING))
+               del_input_events();
+       samplingStop();
+}
+
+static void reconfigure_recording(struct conf_t conf)
+{
+       uint64_t old_features = prof_session.conf.use_features0;
+       uint64_t new_features = conf.use_features0;
+       uint64_t to_enable = (new_features ^ old_features) & new_features;
+       uint64_t to_disable = (new_features ^ old_features) & old_features;
+
+       if (IS_OPT_SET_IN(FL_RECORDING, to_disable)) {
+               del_input_events();
+               prof_session.conf.use_features0 &= ~FL_RECORDING;
+       }
+
+       if (IS_OPT_SET_IN(FL_RECORDING, to_enable)) {
+               add_input_events();
+               prof_session.conf.use_features0 |= FL_RECORDING;
+       }
+
+}
+
+int reconfigure(struct conf_t conf)
+{
+       reconfigure_recording(conf);
+
+       samplingStop();
+       memcpy(&prof_session.conf, &conf, sizeof(conf));
+       if (samplingStart() < 0) {
+               LOGE("Cannot start sampling\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+
+static int file2str(const char *filename, char *buf, int len)
+{
+       int fd, num_read;
+
+       fd = open(filename, O_RDONLY, 0);
+       if (fd == -1)
+               return -1;
+
+       num_read = read(fd, buf, len - 1);
+
+       close(fd);
+
+       if (num_read <= 0)
+               return -1;
+
+       buf[num_read] = '\0';
+
+       return num_read;
+}
+
+static pid_t get_lpad_pid(pid_t pid)
+{
+       static pid_t lpad_pid = UNKNOWN_PID;
+       static const char lpad_path[] = DEBUG_LAUNCH_PRELOAD_PATH;
+       enum { lpad_path_len = sizeof(lpad_path) };
+
+       if (lpad_pid == UNKNOWN_PID) {
+               char fname[64];
+               char buf[lpad_path_len];
+
+               snprintf(fname, sizeof(fname), "/proc/%d/cmdline", pid);
+               if (-1 == file2str(fname, buf, lpad_path_len))
+                       return lpad_pid;
+
+               buf[lpad_path_len - 1] = '\0';
+
+               if (strncmp(buf, lpad_path, lpad_path_len - 1) == 0)
+                       lpad_pid = pid;
+       }
+
+       return lpad_pid;
+}
+
+static pid_t get_current_pid(void)
+{
+       static pid_t pid = UNKNOWN_PID;
+
+       if (pid == UNKNOWN_PID)
+               pid = getpid();
+
+       return pid;
+}
+
+static void target_set_type(struct target *t)
+{
+       pid_t ppid = target_get_ppid(t);
+       enum app_type_t app_type = APP_TYPE_UNKNOWN;
+
+       if (get_current_pid() == ppid) {
+               app_type = APP_TYPE_COMMON;
+       } else if (get_lpad_pid(ppid) == ppid) {
+               app_type = APP_TYPE_TIZEN;
+       }
+
+       t->app_type = app_type;
+}
+
+
+static int target_event_pid_handler(struct target *target)
+{
+       struct app_list_t *app = NULL;
+       struct app_info_t *app_info = NULL;
+
+       target_set_type(target);
+
+       /* posible need some process check right there before start_replay >> */
+       app_info = app_info_get_first(&app);
+       if (app_info == NULL) {
+               LOGE("No app info found\n");
+               return -1;
+       }
+
+       while (app_info != NULL) {
+               if (is_same_app_process(app_info->exe_path,
+                                       target_get_pid(target)))
+                       break;
+               app_info = app_info_get_next(&app);
+       }
+
+       if (app_info == NULL) {
+               LOGE("pid %d not found in app list\n",
+                    target_get_pid(target));
+               return -1;
+       }
+
+       if (start_replay() != 0) {
+               LOGE("Cannot start replay thread\n");
+               return -1;
+       }
+       /* posible need some process check right there before start_replay << */
+
+       target->initial_log = 1;
+
+       return 0;
+}
+
+static int target_event_stop_handler(struct target *target)
+{
+       int cnt;
+       enum app_type_t app_type = target->app_type;
+
+       LOGI("target[%p] close, pid(%d) : (remaining %d target)\n",
+            target, target_get_pid(target), target_cnt_get() - 1);
+
+       ecore_main_fd_handler_del(target->handler);
+
+       target_wait(target);
+       target_dtor(target);
+       // all target client are closed
+       cnt = target_cnt_sub_and_fetch();
+       if (0 == cnt) {
+               switch (app_type) {
+               case APP_TYPE_TIZEN:
+               case APP_TYPE_COMMON:
+                       LOGI("all targets are stopped\n");
+                       if (stop_all() != ERR_NO)
+                               LOGE("Stop failed\n");
+                       return -11;
+               }
+       }
+
+       return 0;
+}
+
+// return 0 if normal case
+// return plus value if non critical error occur
+// return minus value if critical error occur
+// return -11 if all target process closed
+static int target_event_handler(struct target *t, uint64_t msg)
+{
+       int err = 0;
+       if (msg & EVENT_PID)
+               err = target_event_pid_handler(t);
+       if (err)
+               return err;
+
+       if (msg & EVENT_STOP || msg & EVENT_ERROR)
+               err = target_event_stop_handler(t);
+
+       return err;
+}
+
+static Eina_Bool target_event_cb(void *data, Ecore_Fd_Handler *fd_handler)
+{
+       uint64_t u;
+       ssize_t recvLen;
+       struct target *target = (struct target *)data;
+
+       recvLen = read(target->event_fd, &u, sizeof(uint64_t));
+       if (recvLen != sizeof(uint64_t)) {
+               // maybe closed, but ignoring is more safe then
+               // removing fd from event loop
+       } else {
+               if (-11 == target_event_handler(target, u)) {
+                       LOGI("all target process is closed\n");
+               }
+       }
+
+       return ECORE_CALLBACK_RENEW;
+}
+
+/**
+ * return 0 if normal case
+ * return plus value if non critical error occur
+ * return minus value if critical error occur
+ */
+static int targetServerHandler(void)
+{
+       int err;
+       struct msg_target_t log;
+       struct target *target;
+
+       target = target_ctor();
+       if (target == NULL) {
+               LOGW("(target == NULL) no more target can connected\n");
+               return 1;
+       }
+
+       err = target_accept(target, manager.target_server_socket);
+       if (err == 0) {
+               /* send config message to target process */
+               log.type = MSG_OPTION;
+               log.length = snprintf(log.data, sizeof(log.data), "%llu",
+                                     prof_session.conf.use_features0) + 1;
+               if (target_send_msg(target, &log) != 0)
+                       LOGE("fail to send data to target %p\n", target);
+
+               /* send current instrument maps */
+               send_maps_inst_msg_to(target);
+
+               // make event fd
+               target->event_fd = eventfd(EFD_CLOEXEC, EFD_NONBLOCK);
+               if (target->event_fd == -1) {
+                       // fail to make event fd
+                       LOGE("fail to make event fd for target[%p]\n", target);
+                       goto TARGET_CONNECT_FAIL;
+               }
+
+               target->handler =
+                       ecore_main_fd_handler_add(target->event_fd,
+                                                 ECORE_FD_READ,
+                                                 target_event_cb,
+                                                 (void *)target,
+                                                 NULL, NULL);
+               if (!target->handler) {
+                       LOGE("fail to add event fd for target[%p]\n", target);
+                       goto TARGET_CONNECT_FAIL;
+               }
+
+               // make recv thread for target
+               if (makeRecvThread(target) != 0) {
+                       // fail to make recv thread
+                       LOGE("fail to make recv thread for target[%p]\n",
+                            target);
+                       ecore_main_fd_handler_del(target->handler);
+                       goto TARGET_CONNECT_FAIL;
+               }
+
+               dec_apps_to_run();
+
+               if ((manager.app_launch_timerfd > 0) && (get_apps_to_run() == 0)) {
+                       if (stop_app_launch_timer())
+                               LOGE("cannot stop app launch timer\n");
+               }
+
+               LOGI("target connected target[%p](running %d target)\n",
+                    target, target_cnt_get() + 1);
+
+               target_cnt_set(target_cnt_get() + 1);
+               return 0;
+       } else {
+               // accept error
+               LOGE("Failed to accept at target server socket\n");
+       }
+
+ TARGET_CONNECT_FAIL:
+       if (target_cnt_get() == 0) {
+               // if this connection is main connection
+               return -1;
+       } else {
+               // if this connection is not main connection then ignore process by error
+               target_dtor(target);
+               return 1;
+       }
+}
+
+static void recv_msg_tail(int fd, uint32_t len)
+{
+       char buf[512];
+       uint32_t blocks;
+       int recv_len;
+
+       for (blocks = len / sizeof(buf); blocks != 0; blocks--) {
+               recv_len = recv(fd, buf, sizeof(buf), MSG_WAITALL);
+               if (recv_len != sizeof(buf))
+                       goto error_ret;
+       }
+
+       len = len % sizeof(buf);
+       if (len != 0) {
+               recv_len = recv(fd, buf, len, MSG_WAITALL);
+               if (recv_len == -1)
+                       goto error_ret;
+       }
+
+       return;
+
+error_ret:
+       LOGE("error or close request from host. recv_len = %d\n",
+            recv_len);
+       return;
+}
+
+static Ecore_Fd_Handler *host_ctrl_handler;
+static Ecore_Fd_Handler *host_data_handler;
+
+// return plus value if non critical error occur
+// return minus value if critical error occur
+// return -11 if socket closed
+static int controlSocketHandler(int efd)
+{
+       ssize_t recv_len;
+       struct msg_t msg_head;
+       struct msg_t *msg;
+       int res = 0;
+
+       if (manager.connect_timeout_timerfd >= 0) {
+               LOGI("release connect timeout timer\n");
+               close(manager.connect_timeout_timerfd);
+               manager.connect_timeout_timerfd = -1;
+       }
+       // Receive header
+       recv_len = recv(manager.host.control_socket,
+                       &msg_head, MSG_CMD_HDR_LEN, 0);
+
+       // error or close request from host
+       if (recv_len == -1 || recv_len == 0) {
+               LOGW("error or close request from host. "
+                    "MSG_ID = 0x%08X; recv_len = %d\n",
+                    msg_head.id, recv_len);
+               return -11;
+       } else {
+               if (msg_head.len > HOST_CTL_MSG_MAX_LEN) {
+                       LOGE("Too long message. size = %u\n", msg_head.len);
+                       recv_msg_tail(manager.host.control_socket, msg_head.len);
+                       sendACKToHost(msg_head.id, ERR_WRONG_MESSAGE_FORMAT, 0, 0);
+                       return -1;
+               }
+               msg = malloc(MSG_CMD_HDR_LEN + msg_head.len);
+               if (!msg) {
+                       LOGE("Cannot alloc msg\n");
+                       recv_msg_tail(manager.host.control_socket, msg_head.len);
+                       sendACKToHost(msg_head.id, ERR_WRONG_MESSAGE_FORMAT, 0, 0);
+                       return -1;
+               }
+               msg->id = msg_head.id;
+               msg->len = msg_head.len;
+               if (msg->len > 0) {
+                       // Receive payload (if exists)
+                       recv_len = recv(manager.host.control_socket,
+                                       msg->payload, msg->len, MSG_WAITALL);
+                       if (recv_len == -1) {
+                               LOGE("error or close request from host. recv_len = %d\n",
+                                    recv_len);
+                               free(msg);
+                               return -11;
+                       }
+               }
+               printBuf((char *)msg, MSG_CMD_HDR_LEN + msg->len);
+               res = host_message_handler(msg);
+               free(msg);
+       }
+
+       return res;
+}
+
+static Eina_Bool host_ctrl_cb(void *data, Ecore_Fd_Handler *fd_handler)
+{
+       int result = controlSocketHandler(manager.efd);
+       if (result == -11) {
+               // socket close
+               //if the host disconnected.
+               //In all other cases daemon must report an error and continue the loop
+               //close connect_timeoutt and host socket and quit
+               LOGI("Connection closed. Termination. (%d)\n",
+                    manager.host.control_socket);
+               manager.host.data_socket = -1; //splice will fail without that
+               ecore_main_loop_quit();
+       } else if (result < 0) {
+               LOGE("Control socket handler. err #%d\n", result);
+       }
+
+       return ECORE_CALLBACK_RENEW;
+}
+
+static Eina_Bool host_data_cb(void *data, Ecore_Fd_Handler *fd_handler)
+{
+       ssize_t recvLen;
+       char recvBuf[32];
+
+       recvLen = recv(manager.host.data_socket, recvBuf, 32, MSG_DONTWAIT);
+       if (recvLen == 0) {
+               // close data socket
+               ecore_main_fd_handler_del(host_data_handler);
+               close(manager.host.data_socket);
+               manager.host.data_socket = -1;
+               // TODO: finish transfer thread
+       }
+
+       LOGI("host message from data socket %d\n", recvLen);
+
+       return ECORE_CALLBACK_RENEW;
+}
+
+// return 0 if normal case
+// return plus value if non critical error occur
+// return minus value if critical error occur
+static int hostServerHandler(void)
+{
+       static int hostserverorder = 0;
+       int csocket;
+
+       if (hostserverorder > 1)        // control and data socket connected already
+               return 1;               // ignore
+
+       csocket = accept4(manager.host_server_socket, NULL, NULL, SOCK_CLOEXEC);
+
+       if (csocket >= 0) {
+               // accept succeed
+
+               if (hostserverorder == 0) {
+                       manager.host.control_socket = csocket;
+                       unlink_portfile();
+                       LOGI("host control socket connected = %d\n", csocket);
+                       host_ctrl_handler =
+                               ecore_main_fd_handler_add(manager.host.control_socket,
+                                                         ECORE_FD_READ,
+                                                         host_ctrl_cb,
+                                                         NULL,
+                                                         NULL, NULL);
+                       if (!host_ctrl_handler) {
+                               LOGE("Failed to add host control socket fd\n");
+                               close(csocket);
+                               return -1;
+                       }
+               } else {
+                       manager.host.data_socket = csocket;
+                       LOGI("host data socket connected = %d\n", csocket);
+
+                       host_data_handler =
+                               ecore_main_fd_handler_add(manager.host.data_socket,
+                                                         ECORE_FD_READ,
+                                                         host_data_cb,
+                                                         NULL,
+                                                         NULL, NULL);
+                       if (!host_data_handler) {
+                               LOGE("Failed to add host data socket fd\n");
+                               close(csocket);
+                               return -1;
+                       }
+               }
+
+               hostserverorder++;
+               return 0;
+       } else {
+               // accept error
+               LOGE("Failed to accept from host server socket\n");
+               return -1;
+       }
+}
+
+static Ecore_Fd_Handler *host_connect_handler;
+static Ecore_Fd_Handler *target_connect_handler;
+
+static Eina_Bool host_connect_cb(void *data, Ecore_Fd_Handler *fd_handler)
+{
+       // connect request from host
+       int result = hostServerHandler();
+       if (result < 0) {
+               LOGE("Internal DA framework error (hostServerHandler)\n");
+       }
+
+       return ECORE_CALLBACK_RENEW;
+}
+
+static Eina_Bool target_connect_cb(void *data, Ecore_Fd_Handler *fd_handler)
+{
+       if (targetServerHandler() < 0) {
+               // critical error
+               terminate_error("Internal DA framework error, "
+                               "Please re-run the profiling "
+                               "(targetServerHandler)\n", 1);
+       }
+
+       return ECORE_CALLBACK_RENEW;
+}
+
+static bool initialize_events(void)
+{
+       host_connect_handler =
+               ecore_main_fd_handler_add(manager.host_server_socket,
+                                         ECORE_FD_READ,
+                                         host_connect_cb,
+                                         NULL,
+                                         NULL, NULL);
+       if (!host_connect_handler) {
+               LOGE("Host server socket add error\n");
+               return false;
+       }
+
+       target_connect_handler =
+               ecore_main_fd_handler_add(manager.target_server_socket,
+                                         ECORE_FD_READ,
+                                         target_connect_cb,
+                                         NULL,
+                                         NULL, NULL);
+       if (!target_connect_handler) {
+               LOGE("Target server socket add error\n");
+               return false;
+       }
+
+       return true;
+}
+
+// return 0 for normal case
+int daemonLoop(void)
+{
+       int return_value = 0;
+
+       ecore_init();
+
+       if (init_input_events() == -1) {
+               LOGE("Init input event failed. "
+                    "Record and replay events failed.\n");
+       }
+
+       if (!initialize_events()) {
+               return_value = -1;
+               goto END_EFD;
+       }
+
+       if (launch_timer_start() < 0) {
+               LOGE("Launch timer start failed\n");
+               return_value = -1;
+               goto END_EFD;
+       }
+
+       init_prof_session(&prof_session);
+
+       ecore_main_loop_begin();
+       ecore_shutdown();
+
+ END_EFD:
+       LOGI("close efd\n");
+       close(manager.efd);
+ END_EVENT:
+       return return_value;
+}
diff --git a/daemon/daemon.h b/daemon/daemon.h
new file mode 100644 (file)
index 0000000..fc465d5
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Jaewon Lim <jaewon81.lim@samsung.com>
+ * Woojin Jung <woojin2.jung@samsung.com>
+ * Juyoung Kim <j0.kim@samsung.com>
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ * Nikita Kalyazin    <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#ifndef _DAEMON_H_
+#define _DAEMON_H_
+
+#include <stdint.h>            // for uint64_t, int64_t
+#include <pthread.h>   // for pthread_mutex_t
+#include "da_protocol.h"
+#include "target.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define PROTOCOL_VERSION                       "2.1"
+
+#define RUN_APP_LOADER
+
+#define MAX_TARGET_COUNT                       8
+
+#define MAX_DEVICE                             10
+#define MAX_FILENAME                   128
+/*
+enum ErrorCode
+{
+       ERR_LOCKFILE_CREATE_FAILED = -101,
+       ERR_ALREADY_RUNNING = -102,
+       ERR_INITIALIZE_SYSTEM_INFO_FAILED = -103,
+       ERR_HOST_SERVER_SOCKET_CREATE_FAILED = -104,
+       ERR_TARGET_SERVER_SOCKET_CREATE_FAILED = -105,
+       ERR_SIGNAL_MASK_SETTING_FAILED = -106,
+       ERR_WRONG_MESSAGE_FORMAT = -201,
+       ERR_WRONG_MESSAGE_TYPE = -202,
+       ERR_WRONG_MESSAGE_DATA = -203,
+       ERR_CANNOT_START_PROFILING = -204,
+       ERR_WRONG_PROTOCOL_VERSION = -205
+};*/
+
+enum TargetMessageType
+{
+       MSG_DEVICE = 1,
+       MSG_TIME = 2,
+       MSG_SAMPLE = 3,
+       MSG_RESOURCE = 4,
+       MSG_LOG = 5,
+       MSG_IMAGE = 6,
+       MSG_TERMINATE = 7,
+       MSG_PID = 8,
+       MSG_MSG = 9,
+       MSG_ALLOC = 10,
+       MSG_ERROR = 11,
+       MSG_WARNING = 12
+};
+#define IS_PROBE_MSG(type) (((type) & 0x0100) == 0x0100)
+
+enum HostMessageType
+{
+       MSG_HOST_BEGIN = 100,
+       MSG_START = 100,
+       MSG_STOP = 101,
+       MSG_PAUSE = 102,
+       MSG_OPTION = 103,
+       MSG_ISALIVE = 104,
+       MSG_ALIVE = 105,
+       MSG_BATT_START = 106,
+       MSG_BATT_STOP = 107,
+       MSG_CAPTURE_SCREEN = 108,
+       MSG_MAPS_INST_LIST = 109,
+       MSG_RECORD = 801,
+       MSG_REPLAY = 802,
+       MSG_OK = 901,
+       MSG_NOTOK = 902,
+       MSG_VERSION = 999,
+       MSG_HOST_END = 999
+};
+
+enum DAState
+{
+       DAS_NONE = 0,
+       DAS_START_BEGIN = 1,
+       DAS_TARGET_ARM_START = 1,
+       DAS_TARGET_X86_START = 2,
+       DAS_EMUL_ARM_START = 3,
+       DAS_EMUL_X86_START = 4,
+       DAS_TARGET_ARM_BATT_START = 5,
+       DAS_TARGET_X86_BATT_START = 6,
+       DAS_EMUL_ARM_BATT_START = 7,
+       DAS_EMUL_X86_BATT_START = 8,
+       DAS_START_END = 8,
+       DAS_STOP = 9,
+       DAS_TERMINATE = 10
+};
+
+
+#ifndef likely
+#define likely(x)      __builtin_expect((x), 1)
+#define unlikely(x)    __builtin_expect((x), 0)
+#endif
+
+#define EVENT_STOP             0x00000001
+#define EVENT_PID              0x00000002
+#define EVENT_ERROR            0x00000004
+
+
+
+typedef struct
+{
+       int                                     control_socket;
+       int                                     data_socket;
+       pthread_mutex_t         data_socket_mutex;
+} __da_host_info;
+
+typedef struct
+{
+       int brightness;
+       int voltage;
+       int procmeminfo;
+       FILE *video;
+       FILE *procstat;
+       FILE *networkstat;
+       FILE *diskstats;
+       FILE *inst_tasks;
+} __file_descriptors;
+
+typedef struct
+{
+       int host_server_socket;
+       int target_server_socket;
+       int apps_to_run;
+       unsigned int config_flag;
+       int app_launch_timerfd;
+       int connect_timeout_timerfd;
+       pthread_t sampling_thread;
+       pthread_t replay_thread;
+       pthread_t transfer_thread;
+       int buf_fd;
+       int user_ev_fd;
+       int efd;
+       int lockfd;
+       __da_host_info host;
+       __file_descriptors fd;
+       char appPath[128]; // application executable path
+} __da_manager;
+
+extern __da_manager manager;
+
+
+uint64_t get_total_alloc_size(void);
+int initialize_log(void);
+int daemonLoop(void);
+void unlink_portfile(void);
+
+int samplingStart(void);
+int samplingStop(void);
+
+
+
+
+// TODO maybe need move to other file
+int prepare_profiling(void);
+int start_profiling(void);
+void stop_profiling(void);
+int reconfigure(struct conf_t conf);
+int sendACKCodeToHost(enum HostMessageType resp, int msgcode);
+void terminate_all(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _DAEMON_H_
diff --git a/daemon/debug.c b/daemon/debug.c
new file mode 100644 (file)
index 0000000..00e584e
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ * Nikita Kalyazin    <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#include <ctype.h>
+
+#include "debug.h"
+
+#ifdef DEB_PRINTBUF
+//TODO del it or move to debug section
+void print_buf(char * buf, int len, const char *info)
+{
+       int i,j;
+       char local_buf[3*17 + 2*16 + 1 + 8];
+       char * p1, * p2;
+
+       LOGI("BUFFER [%d] <%s>:\n", len, info);
+       for ( i = 0; i < len/16 + 1; i++)
+       {
+               memset(local_buf, ' ', 5*16 + 8);
+
+               sprintf(local_buf, "0x%04X: ", i);
+               p1 = local_buf + 8;
+               p2 = local_buf + 8 + 3*17;
+               for ( j = 0; j < 16; j++)
+                       if (i*16+j < len )
+                       {
+                               sprintf(p1, "%02X ",(unsigned char) *buf);
+                               p1+=3;
+                               if (isprint( *buf)){
+                                       sprintf(p2, "%c ",(int)*buf);
+                               }else{
+                                       sprintf(p2,". ");
+                               }
+                               p2+=2;
+                               buf++;
+                       }
+               *p1 = ' ';
+               *p2 = '\0';
+               LOGI("%s\n",local_buf);
+       }
+}
+#else
+inline void print_buf(char * buf, int len, const char *info) {
+       return;
+}
+#endif
diff --git a/daemon/debug.h b/daemon/debug.h
new file mode 100644 (file)
index 0000000..49de7b5
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ * Nikita Kalyazin    <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#ifndef _DAEMON_DEBUG_H_
+#define _DAEMON_DEBUG_H_
+
+#include <stdint.h>            // for uint64_t, int64_t
+#include <pthread.h>   // for pthread_mutex_t
+#include <stdarg.h>
+
+#include "da_protocol.h"
+#include "malloc_debug.h"
+#include "utils.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define printBuf(buf, len) print_buf(buf, len, __func__)
+void print_buf(char *buf, int len, const char *info);
+
+#ifdef PARSE_DEBUG_ON
+       #define parse_deb LOGI
+#else
+       #define parse_deb(...)
+#endif
+
+#ifdef THREAD_SAMPLING_DEBUG
+       #define LOGI_th_samp LOGI
+#else
+       #define LOGI_th_samp(...)
+#endif
+
+#ifdef THREAD_REPLAY_DEBUG
+       #define LOGI_th_rep LOGI
+#else
+       #define LOGI_th_rep(...)
+#endif
+
+#ifdef DEBUG
+#define GETSTRERROR(err_code, buf)                             \
+       char buf[256];                                          \
+       strerror_r(err_code, buf, sizeof(buf))
+
+#define LOGE(...) do_log("ERR", __func__, __LINE__, __VA_ARGS__)
+#define LOGW(...) do_log("WRN", __func__, __LINE__, __VA_ARGS__)
+
+#ifdef USE_LOG_ONCE
+       #define TOKENPASTE(x, y) x ## y
+       #define TOKENPASTE2(x, y) TOKENPASTE(x, y)
+       #define LOG_ONCE_VAR TOKENPASTE2(log_once_var_, __LINE__)
+       #define INIT_LOG_ONCE static char LOG_ONCE_VAR = 0
+
+       #define LOG_ONCE(W_E,...)                               \
+               INIT_LOG_ONCE;                                  \
+               if (LOG_ONCE_VAR == 0) {                        \
+                       TOKENPASTE2(LOG, W_E)(__VA_ARGS__);     \
+                       LOG_ONCE_VAR = 1;                       \
+               }
+       #define LOG_ONCE_E(...) LOG_ONCE(E, __VA_ARGS__)
+       #define LOG_ONCE_W(...) LOG_ONCE(W, __VA_ARGS__)
+#else
+       #define LOG_ONCE_W(...)
+       #define LOG_ONCE_E(...)
+#endif
+
+static inline void do_log(const char *prefix, const char *funcname, int line, ...)
+{
+       va_list ap;
+       const char *fmt;
+       fprintf(stderr, "[%s][%f] (%s:%d):", prefix, get_uptime(), funcname, line);
+
+       va_start(ap, line);
+       fmt = va_arg(ap, const char *);
+       vfprintf(stderr, fmt, ap);
+       va_end(ap);
+}
+
+       #ifdef NOLOGI
+               #define LOGI(...)
+               #define LOGI_(...)
+       #else
+               #define LOGI(...) do_log("INF", __func__, __LINE__, __VA_ARGS__)
+               #define LOGI_(...)      do {            \
+                       fprintf(stderr, __VA_ARGS__);   \
+                       fflush(stderr);                 \
+               } while (0)
+
+       #endif
+#else
+       #define GETSTRERROR(...)
+       #define LOGI(...)
+       #define LOGI_(...)
+       #define LOGE(...)
+       #define LOGW(...)
+       #define LOG_ONCE_W(...)
+       #define LOG_ONCE_E(...)
+
+#endif
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _DAEMON_DEBUG_H_
diff --git a/daemon/device_camera.c b/daemon/device_camera.c
new file mode 100644 (file)
index 0000000..b2ed596
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Jaewon Lim          <jaewon81.lim@samsung.com>
+ * Woojin Jung         <woojin2.jung@samsung.com>
+ * Juyoung Kim         <j0.kim@samsung.com>
+ * Nikita Kalyazin     <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#include <stdio.h>
+#include <string.h>
+#include "device_camera.h"
+
+#define CAMCORDER_FILE "/usr/etc/mmfw_camcorder.ini"
+#define CAMERA_COUNT_STR "DeviceCount"
+#define BUFFER_MAX 1024
+
+int get_camera_count(void)
+{
+       FILE* fp;
+       int count = 0;
+       int size;
+       char buf[BUFFER_MAX];
+
+       fp = fopen(CAMCORDER_FILE, "r");
+       if (fp == NULL)
+               return 0;
+
+       size = strlen(CAMERA_COUNT_STR);
+       while (fgets(buf, BUFFER_MAX, fp) != NULL) {
+               if (strncmp(buf, CAMERA_COUNT_STR, size) == 0) {
+                       sscanf(buf, CAMERA_COUNT_STR " = %d", &count);
+                       break;
+               }
+       }
+
+       fclose(fp);
+
+       return count;
+}
diff --git a/daemon/device_camera.h b/daemon/device_camera.h
new file mode 100644 (file)
index 0000000..e04d4c6
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Jaewon Lim          <jaewon81.lim@samsung.com>
+ * Woojin Jung         <woojin2.jung@samsung.com>
+ * Juyoung Kim         <j0.kim@samsung.com>
+ * Nikita Kalyazin     <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+#ifndef _DEVICE_CAMERA_H_
+#define _DEVICE_CAMERA_H_
+
+int get_camera_count(void);
+
+#endif /* _DEVICE_CAMERA_H_ */
diff --git a/daemon/device_system_info.c b/daemon/device_system_info.c
new file mode 100644 (file)
index 0000000..94048e6
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Jaewon Lim          <jaewon81.lim@samsung.com>
+ * Woojin Jung         <woojin2.jung@samsung.com>
+ * Juyoung Kim         <j0.kim@samsung.com>
+ * Nikita Kalyazin     <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+#include <system_info.h>
+#include <runtime_info.h>
+#include "device_system_info.h"
+#include "debug.h"
+
+static int is_available(const char *path)
+{
+       bool res = 0;
+
+       if (system_info_get_platform_bool(path, &res) != SYSTEM_INFO_ERROR_NONE) {
+               /* TODO do something */
+               LOGE("get bool value fail\n");
+       }
+
+       return res;
+}
+
+int is_cdma_available(void)
+{
+       return is_available("tizen.org/feature/network.telephony.service.cdma");
+}
+
+int is_edge_available(void)
+{
+       return is_available("tizen.org/feature/network.telephony.service.edge");
+}
+
+int is_gprs_available(void)
+{
+       return is_available("tizen.org/feature/network.telephony.service.gprs");
+}
+
+int is_gsm_available(void)
+{
+       return is_available("tizen.org/feature/network.telephony.service.gsm");
+}
+
+int is_hsdpa_available(void)
+{
+       return is_available("tizen.org/feature/network.telephony.service.hsdpa");
+}
+
+int is_hspa_available(void)
+{
+       return is_available("tizen.org/feature/network.telephony.service.hspa");
+}
+
+int is_hsupa_available(void)
+{
+       return is_available("tizen.org/feature/network.telephony.service.hsupa");
+}
+
+int is_umts_available(void)
+{
+       return is_available("tizen.org/feature/network.telephony.service.umts");
+}
+
+int is_lte_available(void)
+{
+       return is_available("tizen.org/feature/network.telephony.service.lte");
+}
+
+int is_bluetooth_available(void)
+{
+       return is_available("tizen.org/feature/network.bluetooth");
+}
+
+int is_gps_available(void)
+{
+       return is_available("tizen.org/feature/location.gps");
+}
+
+int is_wifi_available(void)
+{
+       return is_available("tizen.org/feature/network.wifi");
+}
diff --git a/daemon/device_system_info.h b/daemon/device_system_info.h
new file mode 100644 (file)
index 0000000..dce5ca7
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Jaewon Lim          <jaewon81.lim@samsung.com>
+ * Woojin Jung         <woojin2.jung@samsung.com>
+ * Juyoung Kim         <j0.kim@samsung.com>
+ * Nikita Kalyazin     <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+#ifndef _DEVICE_SYSTEM_INFO_H_
+#define _DEVICE_SYSTEM_INFO_H_
+
+int is_cdma_available(void);
+int is_edge_available(void);
+int is_gprs_available(void);
+int is_gsm_available(void);
+int is_hsdpa_available(void);
+int is_hsupa_available(void);
+int is_hspa_available(void);
+int is_umts_available(void);
+int is_lte_available(void);
+
+int is_bluetooth_available(void);
+int is_gps_available(void);
+int is_wifi_available(void);
+
+#endif /* _DEVICE_SYSTEM_INFO_H_ */
diff --git a/daemon/device_vconf.c b/daemon/device_vconf.c
new file mode 100644 (file)
index 0000000..4d18eca
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Jaewon Lim          <jaewon81.lim@samsung.com>
+ * Woojin Jung         <woojin2.jung@samsung.com>
+ * Juyoung Kim         <j0.kim@samsung.com>
+ * Nikita Kalyazin     <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#include <vconf.h>
+#include "debug.h"
+#include "device_vconf.h"
+
+int get_wifi_status(void)
+{
+       int wifi_status = 0;
+       int res = 0;
+
+       res = vconf_get_int(VCONFKEY_WIFI_STATE, &wifi_status);
+       if (res < 0) {
+               LOG_ONCE_W("get error #%d\n", res);
+               wifi_status = VCONFKEY_WIFI_OFF;
+       }
+
+       return wifi_status;
+}
+
+int get_bt_status(void)
+{
+       int bt_status = 0;
+       int res = 0;
+
+       res = vconf_get_int(VCONFKEY_BT_STATUS, &bt_status);
+       if (res < 0) {
+               LOG_ONCE_W("get error #%d\n", res);
+               bt_status = VCONFKEY_BT_STATUS_OFF;
+       }
+
+       return bt_status;
+}
+
+int get_gps_status(void)
+{
+       int gps_status = 0;
+       int res = 0;
+
+       res = vconf_get_int(VCONFKEY_LOCATION_ENABLED, &gps_status);
+       if (res < 0) {
+               LOG_ONCE_W("get error #%d\n", res);
+               gps_status = VCONFKEY_LOCATION_GPS_OFF;
+       } else if (gps_status != 0) {
+               res = vconf_get_int(VCONFKEY_LOCATION_GPS_STATE, &gps_status);
+               if (res < 0) {
+                       LOG_ONCE_W("get error #%d\n", res);
+                       gps_status = VCONFKEY_LOCATION_GPS_OFF;
+               }
+       }
+
+       return gps_status;
+}
+
+int get_rssi_status(void)
+{
+
+       int flightmode_status;
+       int res = 0;
+
+       int rssi_status;
+       res = vconf_get_bool(VCONFKEY_TELEPHONY_FLIGHT_MODE,
+                                       &flightmode_status);
+       if (res < 0) {
+               LOG_ONCE_W("get err #%d <%s>\n", res,
+                        VCONFKEY_TELEPHONY_FLIGHT_MODE);
+               flightmode_status = 0;
+       }
+
+       if (!flightmode_status) {
+               res = vconf_get_int(VCONFKEY_TELEPHONY_RSSI, &rssi_status);
+               if (res < 0) {
+                       LOG_ONCE_W("rssi get err #%d\n", res);
+                       rssi_status = VCONFKEY_TELEPHONY_RSSI_0;
+               }
+       } else {
+               rssi_status = VCONFKEY_TELEPHONY_RSSI_0;
+       }
+
+       return rssi_status;
+
+       return 0;
+}
+
+int get_call_status(void)
+{
+       int call_status = 0;
+       int res = 0;
+
+       res = vconf_get_int(VCONFKEY_CALL_STATE, &call_status);
+       if (res < 0) {
+               LOG_ONCE_W("get err #%d\n", res);
+               call_status = VCONFKEY_CALL_OFF;
+       }
+
+       return call_status;
+}
+
+int get_dnet_status(void)
+{
+       int dnet_status = 0;
+       int res = 0;
+
+       res = vconf_get_int(VCONFKEY_DNET_STATE, &dnet_status);
+       if (res < 0) {
+               LOG_ONCE_W("get err #%d <%s>\n", res, VCONFKEY_DNET_STATE);
+               dnet_status = VCONFKEY_DNET_OFF;
+       }
+
+       return dnet_status;
+}
+
+int get_camera_status(void)
+{
+       int camera_status = 0;
+
+       if (vconf_get_int(VCONFKEY_CAMERA_STATE, &camera_status) < 0) {
+               camera_status = VCONFKEY_CAMERA_STATE_NULL;
+       }
+
+       return camera_status;
+}
+
+int get_sound_status(void)
+{
+       int sound_status = 0;
+       int res = 0;
+
+       res = vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL,
+                            &sound_status);
+       if (res < 0) {
+               LOG_ONCE_W("get err #%d\n", res);
+               sound_status = 0;
+       }
+
+       return sound_status;
+}
+
+int get_audio_status(void)
+{
+       int audio_state = 0;
+       int res = 0;
+
+       res = vconf_get_int(VCONFKEY_SOUND_STATUS,
+                           &audio_state);
+       if (res < 0) {
+               LOG_ONCE_W("get err #%d\n", res);
+               audio_state = 0;
+       }
+
+       return !!audio_state;
+}
+
+int get_vibration_status(void)
+{
+       int vibration_status = 0;
+       int res = 0;
+
+       res = vconf_get_bool(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL,
+                                       &vibration_status);
+       if (res < 0) {
+               LOG_ONCE_W("get err #%d\n", res);
+               vibration_status = 0;
+       }
+
+       return vibration_status;
+}
diff --git a/daemon/device_vconf.h b/daemon/device_vconf.h
new file mode 100644 (file)
index 0000000..0bb965a
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Jaewon Lim          <jaewon81.lim@samsung.com>
+ * Woojin Jung         <woojin2.jung@samsung.com>
+ * Juyoung Kim         <j0.kim@samsung.com>
+ * Nikita Kalyazin     <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+#ifndef _DEVICE_VCONF_H_
+#define _DEVICE_VCONF_H_
+
+int get_wifi_status(void);
+int get_bt_status(void);
+int get_gps_status(void);
+int get_rssi_status(void);
+int get_call_status(void);
+int get_dnet_status(void);
+int get_camera_status(void);
+int get_sound_status(void);
+int get_audio_status(void);
+int get_vibration_status(void);
+
+#endif /* _DEVICE_VCONF_H_ */
diff --git a/daemon/elf.c b/daemon/elf.c
new file mode 100644 (file)
index 0000000..2a624cb
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ * Dmitry Bogatov     <d.bogatov@samsung.com>
+ * Nikita Kalyazin    <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <elf.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include "elf.h"
+#include "debug.h"
+
+#define SIZEOF_VOID_P 4
+#if SIZEOF_VOID_P == 8
+typedef Elf64_Ehdr Elf_Ehdr;
+typedef Elf64_Shdr Elf_Shdr;
+#elif SIZEOF_VOID_P == 4
+typedef Elf32_Ehdr Elf_Ehdr;
+typedef Elf32_Shdr Elf_Shdr;
+#else
+#error "Unknown void* size"
+#endif
+
+static size_t fsize(int fd)
+{
+       struct stat buf;
+       if (fstat(fd, &buf) != 0) {
+               LOGE("cannot get file size\n");
+               return 0;
+       }
+       return buf.st_size;
+}
+
+static void *mmap_file(const char *filepath, size_t * len)
+{
+       int fd = open(filepath, O_RDONLY);
+       if (fd < 0)
+               return NULL;
+       *len = fsize(fd);
+       void *mem = mmap(NULL, *len, PROT_READ, MAP_PRIVATE, fd, 0);
+       close(fd);
+       return mem == MAP_FAILED ? NULL : mem;
+}
+
+static const Elf_Shdr *elf_find_debug_header(const void *obj)
+{
+       const Elf_Ehdr *elf_header = obj;
+       const Elf_Shdr *section_table = obj + elf_header->e_shoff;
+       const Elf_Shdr *string_entry = section_table + elf_header->e_shstrndx;
+       const char *string_section = obj + string_entry->sh_offset;
+       int index;
+
+       for (index = 0; index != elf_header->e_shnum; ++index) {
+               const Elf_Shdr *entry = section_table + index;
+               if (!strcmp(".debug_str", string_section + entry->sh_name))
+                       return entry;
+       }
+       return NULL;
+}
+
+static int read_elf_header(Elf_Ehdr * header, const char *filepath)
+{
+       int fd = open(filepath, O_RDONLY);
+       if (fd < 0)
+               return -ENOENT;
+       bool read_failed = read(fd, header, sizeof(*header)) != sizeof(*header);
+       close(fd);
+       return read_failed ? -EIO : 0;
+}
+
+static int elf_type(const char *filepath)
+{
+       Elf_Ehdr header;
+       int err = read_elf_header(&header, filepath);
+       return err ? err : header.e_type;
+}
+
+uint32_t get_binary_type(const char *path)
+{
+       int type = elf_type(path);
+
+       switch (type) {
+       case ET_DYN:
+               return BINARY_TYPE_PIE;
+       case ET_EXEC:
+               return BINARY_TYPE_NO_PIE;
+       default:
+               return BINARY_TYPE_UNKNOWN;
+       }
+}
+
+static int is_like_absolute_path(const char *str)
+{
+       if (*str == '/')
+               return 1;
+       if (isupper(*str) && str[1] == ':' && str[2] == '\\')
+               return 1;
+       return 0;
+}
+
+static bool exist(const char *filename)
+{
+       struct stat decoy;
+       return stat(filename, &decoy) == 0;
+}
+
+static void suffix_filename(char buf[PATH_MAX], const char *filename)
+{
+       char adj_filename[PATH_MAX];
+       snprintf(adj_filename, sizeof(adj_filename), "%s.exe", filename);
+       const char *use_filename = exist(adj_filename) ? adj_filename
+                                                      : filename;
+       size_t len = strlen(use_filename) + 1;
+       strncpy(buf, use_filename, len);
+       if (len > strlen(buf) + 1)
+               LOGE("too small buf <%s>\n", buf);
+}
+
+void get_build_dir(char builddir[PATH_MAX], const char *filename)
+{
+       size_t len;
+       void *filemem;
+       char adj_filename[PATH_MAX];
+
+       suffix_filename(adj_filename, filename);
+
+       filemem = mmap_file(adj_filename, &len);
+       if (filemem) {
+               const Elf_Shdr *debug_header = elf_find_debug_header(filemem);
+               if (debug_header) {
+                       const char *debug_section, *debug_section_end, *p;
+
+                       debug_section = filemem + debug_header->sh_offset;
+                       debug_section_end = debug_section + debug_header->sh_size;
+                       p = debug_section;
+
+                       /* `is_like_absolute_path' checks three chars forward. */
+                       while (p < debug_section_end - 3) {
+                               if (is_like_absolute_path(p)) {
+                                       snprintf(builddir, PATH_MAX, "%s", p);
+                                       munmap(filemem, len);
+                                       return;
+                               }
+                               p = 1 + memchr(p, '\0', debug_section_end - p);
+                       }
+               } else {
+                       LOGW("cannot debug_header <%s>\n", adj_filename);
+               }
+               munmap(filemem, len);
+       } else {
+               LOGW("cannot mmap file <%s>\n", adj_filename);
+       }
+       *builddir = '\0';
+}
diff --git a/daemon/elf.h b/daemon/elf.h
new file mode 100644 (file)
index 0000000..5f849b5
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ * Dmitry Bogatov     <d.bogatov@samsung.com>
+ * Nikita Kalyazin    <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#ifndef _ELF_
+#define _ELF_
+#include <limits.h>
+enum binary_type_t {
+       BINARY_TYPE_NO_PIE = 0,
+       BINARY_TYPE_PIE = 1,
+       BINARY_TYPE_UNKNOWN = -2,
+       BINARY_TYPE_FILE_NOT_EXIST = -1
+};
+
+uint32_t get_binary_type(const char *path);
+void get_build_dir(char builddir[PATH_MAX], const char *path);
+#endif                         /* _ELF_ */
diff --git a/daemon/input_events.c b/daemon/input_events.c
new file mode 100644 (file)
index 0000000..e9408e0
--- /dev/null
@@ -0,0 +1,336 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Jaewon Lim          <jaewon81.lim@samsung.com>
+ * Woojin Jung         <woojin2.jung@samsung.com>
+ * Juyoung Kim         <j0.kim@samsung.com>
+ * Cherepanov Vitaliy  <v.cherepanov@samsung.com>
+ * Nikita Kalyazin     <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#include <dirent.h>
+#include <Ecore.h>
+
+#include "debug.h"
+#include "da_data.h"
+#include "input_events.h"
+
+#define MAX_DEVICE             10
+#define ARRAY_END              (-11)
+#define BUF_SIZE               1024
+#define MAX_FILENAME 128
+
+#define INPUT_ID_TOUCH         0
+#define INPUT_ID_KEY           1
+#define STR_TOUCH              "TOUCH"
+#define STR_KEY                        "KEY"
+#define INPUT_ID_STR_KEY       "ID_INPUT_KEY=1"
+#define INPUT_ID_STR_TOUCH     "ID_INPUT_TOUCHSCREEN=1"
+#define INPUT_ID_STR_KEYBOARD  "ID_INPUT_KEYBOARD=1"
+#define INPUT_ID_STR_TABLET    "ID_INPUT_TABLET=1"
+
+typedef struct _input_dev
+{
+       int fd;
+       char fileName[MAX_FILENAME];
+} input_dev;
+
+static input_dev g_key_dev[MAX_DEVICE];
+static input_dev g_touch_dev[MAX_DEVICE];
+
+static Ecore_Fd_Handler *key_handlers[MAX_DEVICE];
+static Ecore_Fd_Handler *touch_handlers[MAX_DEVICE];
+
+enum status_t { s_stopped, s_running };
+static enum status_t status = s_stopped;
+
+static const char *input_key_devices[] = {
+       /* target: Emulator, kernel: 3.4, all buttons */
+       "Maru Virtio Hwkey",
+       /* target: M0, kernel: 3.0, buttons: volume +/-, home, power */
+       "gpio-keys",
+       /* target: M0, kernel: 3.0, buttons: menu, back */
+       "melfas-touchkey",
+       /* target: M0, kernel: 3.10, buttons: menu, back */
+       "MELFAS MCS Touchkey",
+       /* target: M0, kernel: 3.10, buttons: volume +/-, home, power */
+       "gpio-keys.5",
+       /* target: Kiran, kernel: 3.10.17, buttons: volume +/-, home, power*/
+       "sci-keypad",
+       /* target: Kiran, kernel: 3.10.17, buttons: menu, back */
+       "ist30xx_ts_tinput",
+       NULL
+};
+
+static const char *input_touch_devices[] = {
+       /* target: Emulator, kernel: 3.0 */
+       "Maru Virtio Touchscreen",
+       /* target: M0, kernel: 3.0 */
+       "sec_touchscreen",
+       /* target: M0, kernel: 3.10 */
+       "MELPAS MMS114 Touchscreen",
+       /* target: Kiran, kernel: 3.10.17 */
+       "ist30xx_ts_input",
+       /* target: tv emulator, kernel: 3.12.18 */
+       "ImExPS/2 Generic Explorer Mouse",
+       NULL
+};
+
+static int check_input(char *inputname, int input_id)
+{
+       int ret = -1;
+       FILE *cmd_fp = NULL;
+       char buffer[BUF_SIZE];
+       char command[MAX_FILENAME];
+       char **name_arr;
+       size_t bytes_count;
+
+       if (snprintf(command, sizeof(command), "/sys/class/input/%s/device/name",
+                    inputname) >= sizeof(command))
+               LOGE("too small buffer\n");
+       // run command
+       cmd_fp = fopen(command, "r");
+       if (cmd_fp == NULL)
+               goto exit;
+
+       buffer[0] = '\0';
+       bytes_count = fread(buffer, 1, BUF_SIZE, cmd_fp);
+       if (bytes_count <= 1) {
+               LOGE("Failed to read input_id\n");
+               goto exit;
+       } else {
+               buffer[bytes_count - 1] = '\0';
+       }
+
+       if (input_id == INPUT_ID_KEY)
+               name_arr = input_key_devices;
+       else if (input_id == INPUT_ID_TOUCH)
+               name_arr = input_touch_devices;
+       else
+               goto exit;
+
+       while (*name_arr != NULL) {
+               if (strcmp(buffer, *name_arr) == 0) {
+                       ret = 0;
+                       goto exit;
+               }
+               name_arr++;
+       }
+
+exit:
+       if (cmd_fp != NULL)
+               fclose(cmd_fp);
+       return ret;
+}
+
+// get filename and fd of given input type devices
+static void _get_fds(input_dev *dev, int input_id)
+{
+       DIR *dp;
+       struct dirent *d;
+       int count = 0;
+       static char dirent_buffer[ sizeof(struct dirent) + PATH_MAX + 1 ] = {0,};
+       static struct dirent *dirent_r = (struct dirent *)dirent_buffer;
+
+
+       dp = opendir("/sys/class/input");
+
+       if (dp == NULL)
+               goto exit;
+
+       while ((readdir_r(dp, dirent_r, &d) == 0) && d) {
+               if (!strncmp(d->d_name, "event", 5)) {
+                       // start with "event"
+                       // event file
+                       if (!check_input(d->d_name, input_id)) {
+                               snprintf(dev[count].fileName, MAX_FILENAME,
+                                        "/dev/input/%s", d->d_name);
+                               dev[count].fd = open(dev[count].fileName,
+                                                    O_RDWR | O_NONBLOCK);
+                               count++;
+                       }
+               }
+       }
+
+       closedir(dp);
+
+exit:
+       dev[count].fd = ARRAY_END;      // end of input_dev array
+}
+
+#define MAX_EVENTS_NUM 10
+static int deviceEventHandler(input_dev *dev, int input_type)
+{
+       int ret = 0;
+       ssize_t size = 0;
+       int count = 0;
+       struct input_event in_ev[MAX_EVENTS_NUM];
+       struct msg_data_t *log;
+
+       if (input_type == INPUT_ID_TOUCH || input_type == INPUT_ID_KEY) {
+               do {
+                       size = read(dev->fd, &in_ev[count], sizeof(*in_ev));
+                       if (size > 0)
+                               count++;
+               } while (count < MAX_EVENTS_NUM && size > 0);
+
+               if (count) {
+                       LOGI("read %d %s events\n",
+                            count,
+                            input_type == INPUT_ID_KEY ? STR_KEY : STR_TOUCH);
+                       log = gen_message_event(in_ev, count, input_type);
+                       printBuf((char *)log, MSG_DATA_HDR_LEN + log->len);
+                       if (write_to_buf(log) != 0)
+                               LOGE("write to buf fail\n");
+                       free_msg_data(log);
+               }
+       } else {
+               LOGW("unknown input_type\n");
+               ret = 1;        // it is not error
+       }
+       return ret;
+}
+
+static Eina_Bool touch_event_cb(void *data, Ecore_Fd_Handler *fd_handler)
+{
+       input_dev *touch_dev = (input_dev *)data;
+
+       if (deviceEventHandler(touch_dev, INPUT_ID_TOUCH) < 0) {
+               LOGE("Internal DA framework error, "
+                    "Please re-run the profiling (touch dev)\n");
+               /* TODO: ??? */
+       }
+
+       return ECORE_CALLBACK_RENEW;
+}
+
+static Eina_Bool key_event_cb(void *data, Ecore_Fd_Handler *fd_handler)
+{
+       input_dev *key_dev = (input_dev *)data;
+
+       if (deviceEventHandler(key_dev, INPUT_ID_KEY) < 0) {
+               LOGE("Internal DA framework error, "
+                    "Please re-run the profiling (key dev)\n");
+               /* TODO: ??? */
+       }
+
+       return ECORE_CALLBACK_RENEW;
+}
+
+void add_input_events(void)
+{
+       int i;
+
+       if (status == s_running)
+               return;
+
+       for (i = 0; g_key_dev[i].fd != ARRAY_END; i++) {
+               if (g_key_dev[i].fd > 0) {
+                       key_handlers[i] =
+                               ecore_main_fd_handler_add(g_key_dev[i].fd,
+                                                         ECORE_FD_READ,
+                                                         key_event_cb,
+                                                         &g_key_dev[i],
+                                                         NULL, NULL);
+                       if (!key_handlers[i])
+                               LOGE("keyboard device file handler add error\n");
+               }
+       }
+
+       for (i = 0; g_touch_dev[i].fd != ARRAY_END; i++) {
+               if (g_touch_dev[i].fd > 0) {
+                       touch_handlers[i] =
+                               ecore_main_fd_handler_add(g_touch_dev[i].fd,
+                                                         ECORE_FD_READ,
+                                                         touch_event_cb,
+                                                         &g_touch_dev[i],
+                                                         NULL, NULL);
+                       if (!touch_handlers[i])
+                               LOGE("touch device file handler add error\n");
+               }
+       }
+
+       status = s_running;
+}
+
+void del_input_events(void)
+{
+       int i;
+
+       if (status == s_stopped)
+               return;
+
+       for (i = 0; g_key_dev[i].fd != ARRAY_END; i++)
+               if (g_key_dev[i].fd > 0)
+                       ecore_main_fd_handler_del(key_handlers[i]);
+
+       for (i = 0; g_touch_dev[i].fd != ARRAY_END; i++)
+               if (g_touch_dev[i].fd > 0)
+                       ecore_main_fd_handler_del(touch_handlers[i]);
+
+       status = s_stopped;
+}
+
+static void _device_write(input_dev dev[], struct input_event *in_ev)
+{
+       int i;
+       for (i = 0; dev[i].fd != ARRAY_END; i++) {
+               if (dev[i].fd >= 0) {
+                       write(dev[i].fd, in_ev, sizeof(struct input_event));
+                       LOGI("write(%d, %d, %d)\n",
+                            dev[i].fd, (int)in_ev, sizeof(struct input_event));
+               }
+       }
+}
+
+void write_input_event(int id, struct input_event *ev)
+{
+       switch (id) {
+       case INPUT_ID_TOUCH:
+               _device_write(g_touch_dev, ev);
+               break;
+       case INPUT_ID_KEY:
+               _device_write(g_key_dev, ev);
+               break;
+       default:
+               LOGE("unknown input id (%d)\n", id);
+       }
+}
+
+int init_input_events(void)
+{
+       _get_fds(g_key_dev, INPUT_ID_KEY);
+       if (g_key_dev[0].fd == ARRAY_END) {
+               LOGE("No key devices found.\n");
+               return -1;
+       }
+       _get_fds(g_touch_dev, INPUT_ID_TOUCH);
+       if (g_touch_dev[0].fd == ARRAY_END) {
+               LOGE("No touch devices found.\n");
+               return -1;
+       }
+
+       return 0;
+}
diff --git a/daemon/input_events.h b/daemon/input_events.h
new file mode 100644 (file)
index 0000000..8064cd5
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Jaewon Lim          <jaewon81.lim@samsung.com>
+ * Woojin Jung         <woojin2.jung@samsung.com>
+ * Juyoung Kim         <j0.kim@samsung.com>
+ * Nikita Kalyazin     <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+int init_input_events(void);
+void add_input_events(void);
+void del_input_events(void);
+void write_input_event(int id, struct input_event *ev);
diff --git a/daemon/ioctl_commands.c b/daemon/ioctl_commands.c
new file mode 100644 (file)
index 0000000..f617170
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ * Nikita Kalyazin    <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+/* SWAP Device ioctl commands */
+
+#include "ioctl_commands.h"
+#include "debug.h"
+#include "da_protocol.h"
+#include "daemon.h"
+
+#include <errno.h>
+
+//send message to device
+int ioctl_send_msg(struct msg_t *msg)
+{
+       LOGI("write to device\n");
+       if (ioctl(manager.buf_fd, SWAP_DRIVER_MSG, msg) == -1) {
+               GETSTRERROR(errno, buf);
+               LOGE("write to device: %s\n", buf);
+               return 1;
+       }
+       return 0;
+}
diff --git a/daemon/ioctl_commands.h b/daemon/ioctl_commands.h
new file mode 100644 (file)
index 0000000..7230563
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ * Nikita Kalyazin    <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+/* SWAP Device ioctl commands */
+
+#include "da_protocol.h"
+
+#include <linux/ioctl.h>
+
+#ifndef __SWAP_IOCTL_COMMANDS_H__
+#define __SWAP_IOCTL_COMMANDS_H__
+
+#define SWAP_DRIVER_IOC_MAGIC 0xAF
+
+struct buffer_initialize {
+    size_t size;
+    unsigned int count;
+};
+#define SWAP_DRIVER_BUFFER_INITIALIZE          _IOW(SWAP_DRIVER_IOC_MAGIC, 1, \
+                                                                                    struct buffer_initialize *)
+#define SWAP_DRIVER_BUFFER_UNINITIALIZE                _IO(SWAP_DRIVER_IOC_MAGIC, 2)
+#define SWAP_DRIVER_NEXT_BUFFER_TO_READ                _IO(SWAP_DRIVER_IOC_MAGIC, 3)
+#define SWAP_DRIVER_FLUSH_BUFFER                       _IO(SWAP_DRIVER_IOC_MAGIC, 4)
+#define SWAP_DRIVER_MSG                                                _IOW(SWAP_DRIVER_IOC_MAGIC, 5, \
+                                                                                    void *)
+#define SWAP_DRIVER_WAKE_UP                             _IO(SWAP_DRIVER_IOC_MAGIC, 6)
+
+
+int ioctl_send_msg(struct msg_t *msg);
+
+
+#endif /* __SWAP_IOCTL_H__ */
diff --git a/daemon/main.c b/daemon/main.c
new file mode 100644 (file)
index 0000000..0e4c5fe
--- /dev/null
@@ -0,0 +1,464 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Jaewon Lim <jaewon81.lim@samsung.com>
+ * Woojin Jung <woojin2.jung@samsung.com>
+ * Juyoung Kim <j0.kim@samsung.com>
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ * Nikita Kalyazin    <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+#include <stdio.h>                     // for fopen, fprintf
+#include <stdlib.h>                    // for atexit
+#include <sys/types.h>         // for open
+#include <sys/file.h>
+#include <sys/stat.h>          // for open
+#include <sys/socket.h>                // for socket
+#include <sys/un.h>                    // for sockaddr_un
+#include <arpa/inet.h>         // for sockaddr_in, socklen_t
+
+#include <signal.h>                    // for signal
+#include <unistd.h>                    // for unlink
+#include <fcntl.h>                     // for open, fcntl
+#include <errno.h>
+#include <stdbool.h>
+#include "daemon.h"
+#include "da_protocol.h"
+#include "sys_stat.h"
+#include "buffer.h"
+#include "debug.h"
+#include "utils.h"
+#include "smack.h"
+
+#define SINGLETON_LOCKFILE                     "/tmp/da_manager.lock"
+#define PORTFILE                                       "/tmp/port.da"
+#define UDS_NAME                                       "/tmp/da.socket"
+
+#define INIT_PORT                              8001
+#define LIMIT_PORT                             8100
+
+
+// initialize global variable
+__da_manager manager =
+{
+       .host_server_socket = -1,
+       .target_server_socket = -1,
+       .apps_to_run = 0,
+       .config_flag = 0,
+       .app_launch_timerfd = -1,
+       .connect_timeout_timerfd = -1,
+       .sampling_thread = -1,
+       .replay_thread = -1,
+       .transfer_thread = -1,
+       .buf_fd = -1,
+       .user_ev_fd = -1,
+       .efd = -1,
+       .lockfd = -1,
+
+       .host = {
+               .control_socket = -1,
+               .data_socket = -1,
+               .data_socket_mutex = PTHREAD_MUTEX_INITIALIZER
+       },
+
+       .fd = {
+               .brightness = -1,
+               .voltage = -1,
+               .procmeminfo = -1,
+               .video = NULL,
+               .procstat = NULL,
+               .networkstat = NULL,
+               .diskstats = NULL
+       },
+       .appPath = {0, }
+
+       };
+// =============================================================================
+// util functions
+// =============================================================================
+
+static void write_int(FILE *fp, int code)
+{
+       fprintf(fp, "%d", code);
+}
+
+// =============================================================================
+// atexit functions
+// =============================================================================
+
+static void _close_server_socket(void)
+{
+       LOGI("close_server_socket\n");
+       // close server socket
+       if(manager.host_server_socket != -1)
+               close(manager.host_server_socket);
+       if(manager.target_server_socket != -1)
+               close(manager.target_server_socket);
+}
+
+static void _unlink_files(void)
+{
+       LOGI("unlink files start\n");
+       unlink(PORTFILE);
+       unlink(SINGLETON_LOCKFILE);
+       LOGI("unlink files done\n");
+}
+
+void unlink_portfile(void)
+{
+       unlink(PORTFILE);
+}
+
+// =============================================================================
+// making sockets
+// =============================================================================
+
+// return 0 for normal case
+static int makeTargetServerSocket()
+{
+       struct sockaddr_un serverAddrUn;
+
+       if(manager.target_server_socket != -1)
+               return -1;      // should be never happend
+
+       // remove existed unix domain socket file
+       unlink(UDS_NAME);
+
+       manager.target_server_socket = socket(AF_UNIX,
+                                             SOCK_STREAM | SOCK_CLOEXEC, 0);
+       if (manager.target_server_socket < 0)
+       {
+               LOGE("Target server socket creation failed\n");
+               return -1;
+       }
+
+       fd_setup_attributes(manager.target_server_socket);
+
+       memset(&serverAddrUn, '\0', sizeof(serverAddrUn));
+       serverAddrUn.sun_family = AF_UNIX;
+       snprintf(serverAddrUn.sun_path, sizeof(serverAddrUn.sun_path), "%s", UDS_NAME);
+
+       if (-1 == bind(manager.target_server_socket, (struct sockaddr*) &serverAddrUn,
+                                       sizeof(serverAddrUn)))
+       {
+               LOGE("Target server socket binding failed\n");
+               return -1;
+       }
+
+       if(chmod(serverAddrUn.sun_path, 0777) < 0)
+       {
+               LOGE("Failed to change mode for socket file : errno(%d)\n", errno);
+       }
+
+
+       if (-1 == listen(manager.target_server_socket, 5))
+       {
+               LOGE("Target server socket listening failed\n");
+               return -1;
+       }
+
+       LOGI("Created TargetSock %d\n", manager.target_server_socket);
+       return 0;
+}
+
+// return port number for normal case
+// return negative value for error case
+static int makeHostServerSocket()
+{
+       struct sockaddr_in serverAddrIn;
+       int opt = 1;
+       int port;
+
+       if(manager.host_server_socket != -1)
+               return -1;      // should be never happened
+
+       manager.host_server_socket = socket(PF_INET,
+                                           SOCK_STREAM | SOCK_CLOEXEC,
+                                           IPPROTO_TCP);
+       if (manager.host_server_socket < 0)
+       {
+               LOGE("Host server socket creation failed\n");
+               return -1;
+       }
+
+       if(setsockopt(manager.host_server_socket,
+          SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
+       {
+               LOGE("Failed to set socket option : errno(%d)\n", errno);
+       }
+
+       memset(&serverAddrIn, 0, sizeof(serverAddrIn));
+       serverAddrIn.sin_family = AF_INET;
+       serverAddrIn.sin_addr.s_addr = htonl(INADDR_ANY);
+
+       // bind address to server socket
+       for(port = INIT_PORT; port < LIMIT_PORT; port++)
+       {
+               serverAddrIn.sin_port = htons(port);
+               if (0 == bind(manager.host_server_socket,
+                                       (struct sockaddr*) &serverAddrIn, sizeof(serverAddrIn)))
+                       break;
+       }
+
+       if(port == LIMIT_PORT)
+       {
+               LOGE("Host server socket binding failed\n");
+               return -1;
+       }
+
+       // enter listen state from client
+       if (-1 == listen(manager.host_server_socket, 5))
+       {
+               LOGE("Host server socket listening failed\n");
+               return -1;
+       }
+
+       LOGI("Created HostSock %d\n", manager.host_server_socket);
+       return port;
+}
+
+// =============================================================================
+// initializing / finalizing functions
+// =============================================================================
+
+static int ensure_singleton(const char *lockfile)
+{
+       int locked;
+
+       /* DO NOT CLOSE lockfile!!! */
+       manager.lockfd = open(lockfile, O_RDWR | O_CREAT, 0600);
+       if (manager.lockfd < 0)
+               LOGI("singleton lock file creation failed\n");
+
+       /* To prevent race condition, also check for lock availiability. */
+       locked = (!(flock(manager.lockfd, LOCK_EX | LOCK_NB) < 0));
+
+       if (!locked)
+               LOGE("another instance of daemon is already running\n");
+
+       /* DO NOT CLOSE lockfile!!! */
+       return locked;
+}
+
+static void release_singleton()
+{
+       close(manager.lockfd);
+       manager.lockfd = -1;
+}
+
+static void inititialize_manager_targets(void)
+{
+       target_cnt_set(0);
+}
+
+static bool initialize_pthread_sigmask()
+{
+       sigset_t newsigmask;
+
+       sigemptyset(&newsigmask);
+       sigaddset(&newsigmask, SIGALRM);
+       sigaddset(&newsigmask, SIGUSR1);
+       return pthread_sigmask(SIG_BLOCK, &newsigmask, NULL) == 0;
+}
+
+// return 0 for normal case
+static int initializeManager(FILE *portfile)
+{
+       if (init_buf() != 0) {
+               LOGE("Cannot init buffer\n");
+               return -1;
+       }
+
+       if (initialize_system_info() < 0) {
+               write_int(portfile, ERR_INITIALIZE_SYSTEM_INFO_FAILED);
+               return -1;
+       }
+       // make server socket
+       if (makeTargetServerSocket() != 0) {
+               write_int(portfile, ERR_TARGET_SERVER_SOCKET_CREATE_FAILED);
+               return -1;
+       }
+       if (!initialize_pthread_sigmask()) {
+               write_int(portfile, ERR_SIGNAL_MASK_SETTING_FAILED);
+               return -1;
+       }
+
+       int port = makeHostServerSocket();
+       if (port < 0) {
+               write_int(portfile, ERR_HOST_SERVER_SOCKET_CREATE_FAILED);
+               return -1;
+       } else {
+               write_int(portfile, port);
+       }
+
+       LOGI("SUCCESS to write port\n");
+
+       inititialize_manager_targets();
+
+       // initialize sendMutex
+       pthread_mutex_init(&(manager.host.data_socket_mutex), NULL);
+
+       return 0;
+}
+
+
+static int finalizeManager()
+{
+       LOGI("Finalize daemon\n");
+       LOGI("finalize system info\n");
+       finalize_system_info();
+
+       // close host client socket
+       if(manager.host.control_socket != -1){
+               LOGI("close host control socket (%d)\n", manager.host.control_socket);
+               close(manager.host.control_socket);
+       }
+       if(manager.host.data_socket != -1){
+               LOGI("close host data socket (%d)\n", manager.host.data_socket);
+               close(manager.host.data_socket);
+       }
+
+       LOGI("return\n");
+       return 0;
+}
+
+static void remove_buf_modules(void)
+{
+       LOGI("rmmod buffer start\n");
+       if (system("cd /opt/swap/sdk && ./stop.sh")) {
+               LOGW("Cannot remove swap modules\n");
+       }
+       LOGI("rmmod buffer done\n");
+}
+
+static void terminate(int sig)
+{
+       LOGI("terminate! sig = %d\n", sig);
+       if (!stop_all_in_process()) {
+               // we are up there if signal accept and stop_all func was not
+               // called yet.
+
+               // so we need stop_all firstly (if profiling was
+               // not started it will be dummy call) and release other sources
+               stop_all_no_lock();
+               _unlink_files();
+               _close_server_socket();
+               exit_buf();
+               remove_buf_modules();
+               if (sig != 0) {
+                       LOGW("Terminating due signal %s\n", strsignal(sig));
+                       signal(sig, SIG_DFL);
+                       raise(sig);
+               }
+               stop_all_done();
+       } else {
+               // we are there if stop_all function was called by some reasons
+
+               // if stop_all called we cannot call remove_buf_modules and
+               // other funcs because of threads are not stopped yet
+               LOGW("Stop in progress\n");
+               if (sig != 0) {
+                       LOGW("ignore signal %s\n", strsignal(sig));
+                       signal(sig, SIG_IGN);
+               }
+       }
+}
+
+static void terminate0()
+{
+       terminate(0);
+}
+
+
+static void setup_signals()
+{
+       struct sigaction sigact = {
+               .sa_handler = terminate,
+               .sa_flags = 0
+       };
+       sigemptyset(&sigact.sa_mask);
+       sigaction(SIGTERM, &sigact, 0);
+       sigaction(SIGINT, &sigact, 0);
+
+       signal(SIGHUP, SIG_IGN);
+       signal(SIGPIPE,SIG_IGN);
+}
+
+// main function
+int main()
+{
+
+       if (!ensure_singleton(SINGLETON_LOCKFILE)) {
+               LOGE("Daemon cannot be launched\n");
+               return 1;
+       }
+
+       if (initialize_log() != 0) {
+               LOGE("Init log failed. uninit\n");
+               terminate0();
+               LOGE("Daemon terminated\n");
+               exit(0);
+       }
+
+       LOGI("da_started\n");
+       atexit(terminate0);
+
+
+       //for terminal exit
+       setup_signals();
+       daemon(0, 1);
+       LOGI("--- daemonized (pid %d) ---\n", getpid());
+
+       FILE *portfile = fopen(PORTFILE, "w");
+       if (!portfile) {
+               LOGE("cannot create portfile");
+               return 1;
+       }
+
+       int err = initializeManager(portfile);
+       fclose(portfile);
+       if (err)
+               return 1;
+
+       //init all file descriptors
+       init_system_file_descriptors();
+       //daemon work
+       //FIX ME remove samplingThread it is only for debug
+       //samplingThread(NULL);
+       daemonLoop();
+       LOGI("daemon loop finished\n");
+       stop_all();
+       finalizeManager();
+
+       close_system_file_descriptors();
+
+       //DO NOT USE THIS FUNCTION FOR RELEASE IT IS TOO SLOW
+#ifdef MALLOC_DEBUG_LEVEL
+       msg_swap_free_all_data(&prof_session.user_space_inst);
+#endif
+       release_singleton();
+       LOGI("main finished\n");
+       print_malloc_list(NULL, 0);
+       return 0;
+}
diff --git a/daemon/malloc_debug.c b/daemon/malloc_debug.c
new file mode 100644 (file)
index 0000000..ec00c13
--- /dev/null
@@ -0,0 +1,220 @@
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "debug.h"
+#include "malloc_debug.h"
+
+#ifdef MALLOC_DEBUG_LEVEL
+
+#undef calloc
+#undef malloc
+#undef free
+
+#if MALLOC_DEBUG_LEVEL == 2
+#define logi LOGI
+#define loge LOGE
+#else
+#define logi(...)
+#define loge(...)
+#endif
+
+struct mlist_t *files_list;
+
+int list_append(struct mlist_t **to, struct mlist_t *from)
+{
+       struct mlist_t *p = NULL;
+
+       if (*to == NULL) {
+               //empty list
+               *to = from;
+       } else {
+               p = *to;
+               *to = from;
+               from->next = (void *)p;
+               p->prev = (void *)from;
+       }
+
+       return 0;
+}
+
+void list_rm_el(struct mlist_t **list, struct mlist_t *element)
+{
+       struct mlist_t *prev = element->prev;
+       struct mlist_t *next = element->next;
+
+       if (element != NULL) {
+               if (prev != NULL)
+                       //prev != null, next == null
+                       //prev != null, next != null
+                       prev->next = next;
+               else
+                       //prev == null, next == null
+                       //prev == null, next != null
+                       *list = next;
+
+               if (next != NULL)
+                       next->prev = prev;
+       }
+
+       free(element);
+}
+
+struct mlist_t *find_malloc(struct mlist_t *file_list, void *addr)
+{
+       struct mlist_t *el = file_list->addr;
+
+       while (el != NULL) {
+               if (el->addr == addr)
+                       return el;
+               el = el->next;
+       }
+
+       return NULL;
+}
+
+struct mlist_t *find_list(const char *name)
+{
+       struct mlist_t *el = files_list;
+
+       while (el != NULL) {
+               if (strcmp(el->info, name) == 0)
+                       return el;
+               el = el->next;
+       }
+       el = malloc(sizeof(struct mlist_t));
+       memset(el, 0, sizeof(struct mlist_t));
+       el->info = name;
+       list_append(&files_list, el);
+
+       return el;
+}
+
+void print_file_malloc_list(struct mlist_t *file, int only_count)
+{
+       struct mlist_t *el = NULL;
+       int count = 0;
+
+       LOGI(" -> malloc list for file (%s)\n", file->info);
+       el = file->addr;
+       if (el == NULL)
+               LOGI("list is empty\n");
+       while (el != NULL) {
+               count++;
+               if (only_count == 0)
+                       LOGI("  %04d) 0x%lX <%s>\n", el->line, el->addr,
+                            el->info);
+               el = el->next;
+       }
+
+       if (only_count == 1)
+               LOGI("  malloc count = %d\n", count);
+}
+
+void print_malloc_list(char *file_name, int only_count)
+{
+       struct mlist_t *file = NULL;
+       LOGI("BEGIN--------------------------------------------------------\n");
+       if (file_name == NULL) {
+               file = files_list;
+               while (file != NULL) {
+                       print_file_malloc_list(file, only_count);
+                       file = file->next;
+               }
+       } else {
+               struct mlist_t *file = find_list(file_name);
+               print_file_malloc_list(file, only_count);
+       }
+       LOGI("END----------------------------------------------------------\n");
+}
+
+int rm_malloc(struct mlist_t *file_list, void *addr)
+{
+       struct mlist_t *el = find_malloc(file_list, addr);
+
+       if (el != NULL) {
+               list_rm_el(&(file_list->addr), el);
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+void add_malloc(struct mlist_t **list, void *addr, int line,
+               const char *file_name, const char *func_name, size_t size)
+{
+       struct mlist_t *el = malloc(sizeof(*el));
+
+       el->addr = addr;
+       el->line = line;
+       el->info = func_name;
+       el->size = size;
+       el->next = NULL;
+       el->prev = NULL;
+
+       list_append(list, el);
+
+}
+
+void *malloc_call_d(int line, const char *file_name, const char *func_name,
+                   size_t size)
+{
+       logi("malloc>\n");
+       void *addr = malloc(size);
+       logi("malloc> 0x%0lX (%d:%s '%s')\n", addr, line, func_name, file_name);
+       struct mlist_t *file_el = find_list(file_name);
+
+       add_malloc(&(file_el->addr), addr, line, file_name, func_name, size);
+
+       return addr;
+}
+
+void *calloc_call_d(int line, const char *file_name, const char *func_name,
+                   size_t n, size_t size)
+{
+
+       logi("calloc>\n");
+       void *addr = calloc(n, size);
+       logi("calloc> 0x%0lX (%d:%s '%s')\n", addr, line, func_name, file_name);
+       struct mlist_t *file_el = find_list(file_name);
+
+       add_malloc(&(file_el->addr), addr, line, file_name, func_name,
+                  size * n);
+
+       return addr;
+}
+
+void free_call_d(int line, const char *file_name, const char *function,
+                void *addr)
+{
+
+       struct mlist_t *list = find_list(file_name);
+       if (!rm_malloc(list, addr)) {
+               list = files_list;
+               while (list != NULL) {
+                       if (rm_malloc(list, addr)) {
+                               free(addr);
+                               return;
+                       }
+                       list = list->next;
+               }
+
+       } else {
+               logi("free addr 0x%08lX (%d:%s '%s')\n",
+                    addr, line, function, file_name);
+               free(addr);
+               return;
+       }
+       LOGW("cannot free element!!! 0x%08lX (%d:%s '%s')\n",
+            addr, line, function, file_name);
+
+}
+
+//redefine functions
+#define malloc(size) malloc_call_d( __LINE__ , __FILE__, __FUNCTION__, size)
+#define calloc(num, size) calloc_call_d( __LINE__ , __FILE__, __FUNCTION__, num, size)
+#define free(addr) free_call_d(__LINE__, __FILE__, __func__, addr)
+
+#else
+
+#endif /* MALLOC_DEBUG_LEVEL */
diff --git a/daemon/malloc_debug.h b/daemon/malloc_debug.h
new file mode 100644 (file)
index 0000000..5b1be17
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef __MALLOC_DEBUG__
+#define __MALLOC_DEBUG__
+
+#include <stdint.h>
+
+#ifdef MALLOC_DEBUG_LEVEL
+struct mlist_t {
+       void *next;
+       void *prev;
+       void *addr;
+       int line;
+       char *info;
+       uint32_t size;
+};
+
+void print_malloc_list(char *file_name, int only_count);
+
+#define malloc(size) malloc_call_d( __LINE__ , __FILE__, __FUNCTION__, size)
+#define calloc(num, size) calloc_call_d( __LINE__ , __FILE__, __FUNCTION__, num, size)
+#define free(addr) free_call_d(__LINE__, __FILE__, __func__, addr)
+
+#else /* MALLOC_DEBUG_LEVEL */
+
+#define print_malloc_list(...) do{}while(0)
+
+#endif /* MALLOC_DEBUG_LEVEL */
+
+#endif /* __MALLOC_DEBUG__ */
diff --git a/daemon/md5.c b/daemon/md5.c
new file mode 100644 (file)
index 0000000..c35d96c
--- /dev/null
@@ -0,0 +1,381 @@
+/*
+  Copyright (C) 1999, 2000, 2002 Aladdin Enterprises.  All rights reserved.
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  L. Peter Deutsch
+  ghost@aladdin.com
+
+ */
+/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
+/*
+  Independent implementation of MD5 (RFC 1321).
+
+  This code implements the MD5 Algorithm defined in RFC 1321, whose
+  text is available at
+       http://www.ietf.org/rfc/rfc1321.txt
+  The code is derived from the text of the RFC, including the test suite
+  (section A.5) but excluding the rest of Appendix A.  It does not include
+  any code or documentation that is identified in the RFC as being
+  copyrighted.
+
+  The original and principal author of md5.c is L. Peter Deutsch
+  <ghost@aladdin.com>.  Other authors are noted in the change history
+  that follows (in reverse chronological order):
+
+  2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
+       either statically or dynamically; added missing #include <string.h>
+       in library.
+  2002-03-11 lpd Corrected argument list for main(), and added int return
+       type, in test program and T value program.
+  2002-02-21 lpd Added missing #include <stdio.h> in test program.
+  2000-07-03 lpd Patched to eliminate warnings about "constant is
+       unsigned in ANSI C, signed in traditional"; made test program
+       self-checking.
+  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
+  1999-05-03 lpd Original version.
+ */
+
+#include "md5.h"
+#include <string.h>
+
+#undef BYTE_ORDER      /* 1 = big-endian, -1 = little-endian, 0 = unknown */
+#ifdef ARCH_IS_BIG_ENDIAN
+#  define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
+#else
+#  define BYTE_ORDER 0
+#endif
+
+#define T_MASK ((md5_word_t)~0)
+#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
+#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
+#define T3    0x242070db
+#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
+#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
+#define T6    0x4787c62a
+#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
+#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
+#define T9    0x698098d8
+#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
+#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
+#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
+#define T13    0x6b901122
+#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
+#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
+#define T16    0x49b40821
+#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
+#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
+#define T19    0x265e5a51
+#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
+#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
+#define T22    0x02441453
+#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
+#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
+#define T25    0x21e1cde6
+#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
+#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
+#define T28    0x455a14ed
+#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
+#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
+#define T31    0x676f02d9
+#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
+#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
+#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
+#define T35    0x6d9d6122
+#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
+#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
+#define T38    0x4bdecfa9
+#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
+#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
+#define T41    0x289b7ec6
+#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
+#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
+#define T44    0x04881d05
+#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
+#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
+#define T47    0x1fa27cf8
+#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
+#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
+#define T50    0x432aff97
+#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
+#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
+#define T53    0x655b59c3
+#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
+#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
+#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
+#define T57    0x6fa87e4f
+#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
+#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
+#define T60    0x4e0811a1
+#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
+#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
+#define T63    0x2ad7d2bb
+#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
+
+
+static void
+md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
+{
+    md5_word_t
+       a = pms->abcd[0], b = pms->abcd[1],
+       c = pms->abcd[2], d = pms->abcd[3];
+    md5_word_t t;
+#if BYTE_ORDER > 0
+    /* Define storage only for big-endian CPUs. */
+    md5_word_t X[16];
+#else
+    /* Define storage for little-endian or both types of CPUs. */
+    md5_word_t xbuf[16];
+    const md5_word_t *X;
+#endif
+
+    {
+#if BYTE_ORDER == 0
+       /*
+        * Determine dynamically whether this is a big-endian or
+        * little-endian machine, since we can use a more efficient
+        * algorithm on the latter.
+        */
+       static const int w = 1;
+
+       if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
+#endif
+#if BYTE_ORDER <= 0            /* little-endian */
+       {
+           /*
+            * On little-endian machines, we can process properly aligned
+            * data without copying it.
+            */
+           if (!((data - (const md5_byte_t *)0) & 3)) {
+               /* data are properly aligned */
+               X = (const md5_word_t *)data;
+           } else {
+               /* not aligned */
+               memcpy(xbuf, data, 64);
+               X = xbuf;
+           }
+       }
+#endif
+#if BYTE_ORDER == 0
+       else                    /* dynamic big-endian */
+#endif
+#if BYTE_ORDER >= 0            /* big-endian */
+       {
+           /*
+            * On big-endian machines, we must arrange the bytes in the
+            * right order.
+            */
+           const md5_byte_t *xp = data;
+           int i;
+
+#  if BYTE_ORDER == 0
+           X = xbuf;           /* (dynamic only) */
+#  else
+#    define xbuf X             /* (static only) */
+#  endif
+           for (i = 0; i < 16; ++i, xp += 4)
+               xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
+       }
+#endif
+    }
+
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+    /* Round 1. */
+    /* Let [abcd k s i] denote the operation
+       a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
+#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + F(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+    /* Do the following 16 operations. */
+    SET(a, b, c, d,  0,  7,  T1);
+    SET(d, a, b, c,  1, 12,  T2);
+    SET(c, d, a, b,  2, 17,  T3);
+    SET(b, c, d, a,  3, 22,  T4);
+    SET(a, b, c, d,  4,  7,  T5);
+    SET(d, a, b, c,  5, 12,  T6);
+    SET(c, d, a, b,  6, 17,  T7);
+    SET(b, c, d, a,  7, 22,  T8);
+    SET(a, b, c, d,  8,  7,  T9);
+    SET(d, a, b, c,  9, 12, T10);
+    SET(c, d, a, b, 10, 17, T11);
+    SET(b, c, d, a, 11, 22, T12);
+    SET(a, b, c, d, 12,  7, T13);
+    SET(d, a, b, c, 13, 12, T14);
+    SET(c, d, a, b, 14, 17, T15);
+    SET(b, c, d, a, 15, 22, T16);
+#undef SET
+
+     /* Round 2. */
+     /* Let [abcd k s i] denote the operation
+          a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
+#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + G(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+     /* Do the following 16 operations. */
+    SET(a, b, c, d,  1,  5, T17);
+    SET(d, a, b, c,  6,  9, T18);
+    SET(c, d, a, b, 11, 14, T19);
+    SET(b, c, d, a,  0, 20, T20);
+    SET(a, b, c, d,  5,  5, T21);
+    SET(d, a, b, c, 10,  9, T22);
+    SET(c, d, a, b, 15, 14, T23);
+    SET(b, c, d, a,  4, 20, T24);
+    SET(a, b, c, d,  9,  5, T25);
+    SET(d, a, b, c, 14,  9, T26);
+    SET(c, d, a, b,  3, 14, T27);
+    SET(b, c, d, a,  8, 20, T28);
+    SET(a, b, c, d, 13,  5, T29);
+    SET(d, a, b, c,  2,  9, T30);
+    SET(c, d, a, b,  7, 14, T31);
+    SET(b, c, d, a, 12, 20, T32);
+#undef SET
+
+     /* Round 3. */
+     /* Let [abcd k s t] denote the operation
+          a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + H(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+     /* Do the following 16 operations. */
+    SET(a, b, c, d,  5,  4, T33);
+    SET(d, a, b, c,  8, 11, T34);
+    SET(c, d, a, b, 11, 16, T35);
+    SET(b, c, d, a, 14, 23, T36);
+    SET(a, b, c, d,  1,  4, T37);
+    SET(d, a, b, c,  4, 11, T38);
+    SET(c, d, a, b,  7, 16, T39);
+    SET(b, c, d, a, 10, 23, T40);
+    SET(a, b, c, d, 13,  4, T41);
+    SET(d, a, b, c,  0, 11, T42);
+    SET(c, d, a, b,  3, 16, T43);
+    SET(b, c, d, a,  6, 23, T44);
+    SET(a, b, c, d,  9,  4, T45);
+    SET(d, a, b, c, 12, 11, T46);
+    SET(c, d, a, b, 15, 16, T47);
+    SET(b, c, d, a,  2, 23, T48);
+#undef SET
+
+     /* Round 4. */
+     /* Let [abcd k s t] denote the operation
+          a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + I(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+     /* Do the following 16 operations. */
+    SET(a, b, c, d,  0,  6, T49);
+    SET(d, a, b, c,  7, 10, T50);
+    SET(c, d, a, b, 14, 15, T51);
+    SET(b, c, d, a,  5, 21, T52);
+    SET(a, b, c, d, 12,  6, T53);
+    SET(d, a, b, c,  3, 10, T54);
+    SET(c, d, a, b, 10, 15, T55);
+    SET(b, c, d, a,  1, 21, T56);
+    SET(a, b, c, d,  8,  6, T57);
+    SET(d, a, b, c, 15, 10, T58);
+    SET(c, d, a, b,  6, 15, T59);
+    SET(b, c, d, a, 13, 21, T60);
+    SET(a, b, c, d,  4,  6, T61);
+    SET(d, a, b, c, 11, 10, T62);
+    SET(c, d, a, b,  2, 15, T63);
+    SET(b, c, d, a,  9, 21, T64);
+#undef SET
+
+     /* Then perform the following additions. (That is increment each
+        of the four registers by the value it had before this block
+        was started.) */
+    pms->abcd[0] += a;
+    pms->abcd[1] += b;
+    pms->abcd[2] += c;
+    pms->abcd[3] += d;
+}
+
+void
+md5_init(md5_state_t *pms)
+{
+    pms->count[0] = pms->count[1] = 0;
+    pms->abcd[0] = 0x67452301;
+    pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
+    pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
+    pms->abcd[3] = 0x10325476;
+}
+
+void
+md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
+{
+    const md5_byte_t *p = data;
+    int left = nbytes;
+    int offset = (pms->count[0] >> 3) & 63;
+    md5_word_t nbits = (md5_word_t)(nbytes << 3);
+
+    if (nbytes <= 0)
+       return;
+
+    /* Update the message length. */
+    pms->count[1] += nbytes >> 29;
+    pms->count[0] += nbits;
+    if (pms->count[0] < nbits)
+       pms->count[1]++;
+
+    /* Process an initial partial block. */
+    if (offset) {
+       int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+
+       memcpy(pms->buf + offset, p, copy);
+       if (offset + copy < 64)
+           return;
+       p += copy;
+       left -= copy;
+       md5_process(pms, pms->buf);
+    }
+
+    /* Process full blocks. */
+    for (; left >= 64; p += 64, left -= 64)
+       md5_process(pms, p);
+
+    /* Process a final partial block. */
+    if (left)
+       memcpy(pms->buf, p, left);
+}
+
+void
+md5_finish(md5_state_t *pms, md5_byte_t digest[16])
+{
+    static const md5_byte_t pad[64] = {
+       0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+    };
+    md5_byte_t data[8];
+    int i;
+
+    /* Save the length before padding. */
+    for (i = 0; i < 8; ++i)
+       data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
+    /* Pad to 56 bytes mod 64. */
+    md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
+    /* Append the length. */
+    md5_append(pms, data, 8);
+    for (i = 0; i < 16; ++i)
+       digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
+}
diff --git a/daemon/md5.h b/daemon/md5.h
new file mode 100644 (file)
index 0000000..698c995
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+  Copyright (C) 1999, 2002 Aladdin Enterprises.  All rights reserved.
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  L. Peter Deutsch
+  ghost@aladdin.com
+
+ */
+/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */
+/*
+  Independent implementation of MD5 (RFC 1321).
+
+  This code implements the MD5 Algorithm defined in RFC 1321, whose
+  text is available at
+       http://www.ietf.org/rfc/rfc1321.txt
+  The code is derived from the text of the RFC, including the test suite
+  (section A.5) but excluding the rest of Appendix A.  It does not include
+  any code or documentation that is identified in the RFC as being
+  copyrighted.
+
+  The original and principal author of md5.h is L. Peter Deutsch
+  <ghost@aladdin.com>.  Other authors are noted in the change history
+  that follows (in reverse chronological order):
+
+  2002-04-13 lpd Removed support for non-ANSI compilers; removed
+       references to Ghostscript; clarified derivation from RFC 1321;
+       now handles byte order either statically or dynamically.
+  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
+       added conditionalization for C++ compilation from Martin
+       Purschke <purschke@bnl.gov>.
+  1999-05-03 lpd Original version.
+ */
+
+#ifndef md5_INCLUDED
+#  define md5_INCLUDED
+
+/*
+ * This package supports both compile-time and run-time determination of CPU
+ * byte order.  If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
+ * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
+ * defined as non-zero, the code will be compiled to run only on big-endian
+ * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
+ * run on either big- or little-endian CPUs, but will run slightly less
+ * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
+ */
+
+typedef unsigned char md5_byte_t; /* 8-bit byte */
+typedef unsigned int md5_word_t; /* 32-bit word */
+
+/* Define the state of the MD5 Algorithm. */
+typedef struct md5_state_s {
+    md5_word_t count[2];       /* message length in bits, lsw first */
+    md5_word_t abcd[4];                /* digest buffer */
+    md5_byte_t buf[64];                /* accumulate block */
+} md5_state_t;
+
+#ifdef __cplusplus
+extern "C" 
+{
+#endif
+
+/* Initialize the algorithm. */
+void md5_init(md5_state_t *pms);
+
+/* Append a string to the message. */
+void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
+
+/* Finish the message and return the digest. */
+void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
+
+#ifdef __cplusplus
+}  /* end extern "C" */
+#endif
+
+#endif /* md5_INCLUDED */
diff --git a/daemon/smack.c b/daemon/smack.c
new file mode 100644 (file)
index 0000000..9e285e6
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Jaewon Lim          <jaewon81.lim@samsung.com>
+ * Woojin Jung         <woojin2.jung@samsung.com>
+ * Juyoung Kim         <j0.kim@samsung.com>
+ * Nikita Kalyazin     <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#include <sys/smack.h>
+#include <attr/xattr.h>
+#include "smack.h"
+
+#define SELF_LABEL_FILE "/proc/self/attr/current"
+#define SMACK_LABEL_LEN 255
+
+void fd_setup_attributes(int fd)
+{
+       fsetxattr(fd, "security.SMACK64IPIN", "*", 1, 0);
+       fsetxattr(fd, "security.SMACK64IPOUT", "@", 1, 0);
+}
+
+void set_label_for_all(const char *path)
+{
+       smack_lsetlabel(path, "*", SMACK_LABEL_ACCESS);
+}
diff --git a/daemon/smack.h b/daemon/smack.h
new file mode 100644 (file)
index 0000000..ddfbd5a
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Jaewon Lim          <jaewon81.lim@samsung.com>
+ * Woojin Jung         <woojin2.jung@samsung.com>
+ * Juyoung Kim         <j0.kim@samsung.com>
+ * Nikita Kalyazin     <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#ifndef _SMACK_H_
+#define _SMACK_H_
+
+void fd_setup_attributes(int fd);
+void set_label_for_all(const char *path);
+
+#endif /* _SMACK_H_ */
diff --git a/daemon/start.sh b/daemon/start.sh
new file mode 100755 (executable)
index 0000000..70830b7
--- /dev/null
@@ -0,0 +1,61 @@
+#!/bin/sh
+
+if [ ! -e /sys/kernel/debug/swap/writer/raw ]; then
+
+    insmod swap_buffer.ko || exit 1  # buffer is loaded
+    insmod swap_ksyms.ko || exit 1
+    insmod swap_driver.ko || exit 1  # driver is loaded
+    insmod swap_writer.ko || exit 1
+    insmod swap_kprobe.ko || exit 1  # kprobe is loaded
+    insmod swap_uprobe.ko || exit 1  # uprobe is loaded
+    insmod swap_us_manager.ko || exit 1  # us_manager is loaded
+    insmod swap_ks_features.ko || exit 1  # ks_features is loaded
+    insmod swap_sampler.ko || exit 1
+    insmod swap_energy.ko || exit 1
+    insmod swap_message_parser.ko || exit 1  # parser is loaded
+
+fi
+
+# Energy coefficients
+# CPU coefficients are divided by 10^6 because
+#  - they were calculated for mAs
+#  - SWAP modules count nanoseconds
+#  - result should be exposed in uAs
+# Flash coefficients are multiplied by 10^3 because
+#  - they were calculated for mAs
+#  - result should be exposed in uAs
+# LCD coefficients are divided by 10^6 because
+#  - they were calculated for mAs
+#  - result should be exposed in uAs
+
+# cpu idle: 62.27 / 1
+echo 62270 > /sys/kernel/debug/swap/energy/cpu_idle/numerator &&
+echo 1000000000 > /sys/kernel/debug/swap/energy/cpu_idle/denominator &&
+
+# cpu0 running: 213.21 / 1
+echo 213210 > /sys/kernel/debug/swap/energy/cpu_running/numerator &&
+echo 1000000000 > /sys/kernel/debug/swap/energy/cpu_running/denominator &&
+
+# cpuN running: 97.29 / 1
+echo 97290 > /sys/kernel/debug/swap/energy/cpuN_running/numerator &&
+echo 1000000000 > /sys/kernel/debug/swap/energy/cpuN_running/denominator &&
+
+# flash read:  74.32 / 33154239
+echo 74320 > /sys/kernel/debug/swap/energy/flash_read/numerator &&
+echo 33154239 > /sys/kernel/debug/swap/energy/flash_read/denominator &&
+
+# flash write: 141.54 / 27920983
+echo 141540 > /sys/kernel/debug/swap/energy/flash_write/numerator &&
+echo 27920983 > /sys/kernel/debug/swap/energy/flash_write/denominator &&
+
+# LCD:
+if [ -d /sys/kernel/debug/swap/energy/lcd/ ]
+then
+       # lcd max (white max - black max) / 2: 255 / 1
+       echo 255 > `ls /sys/kernel/debug/swap/energy/lcd/*/max_num` &&
+       echo 1000000 > `ls /sys/kernel/debug/swap/energy/lcd/*/max_denom` &&
+
+       # lcd min (white min - black min) / 2: 179 / 1
+       echo 179 > `ls /sys/kernel/debug/swap/energy/lcd/*/min_num` &&
+       echo 1000000 > `ls /sys/kernel/debug/swap/energy/lcd/*/min_denom`
+fi
diff --git a/daemon/stop.sh b/daemon/stop.sh
new file mode 100755 (executable)
index 0000000..2589269
--- /dev/null
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+rmmod swap_message_parser
+rmmod swap_energy
+rmmod swap_sampler
+rmmod swap_ks_features
+rmmod swap_us_manager
+rmmod swap_uprobe
+rmmod swap_kprobe
+rmmod swap_writer
+rmmod swap_driver
+rmmod swap_ksyms
+rmmod swap_buffer
+
+
+
+
+
+
+
+
+
diff --git a/daemon/sys_stat.c b/daemon/sys_stat.c
new file mode 100644 (file)
index 0000000..54484e7
--- /dev/null
@@ -0,0 +1,2371 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Jaewon Lim <jaewon81.lim@samsung.com>
+ * Woojin Jung <woojin2.jung@samsung.com>
+ * Juyoung Kim <j0.kim@samsung.com>
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ * Nikita Kalyazin    <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+#include <glob.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/vfs.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <stdint.h>
+
+#include "da_protocol.h"
+#include "da_data.h"
+#include "sys_stat.h"
+#include "daemon.h"
+#include "device_system_info.h"
+#include "device_vconf.h"
+#include "device_camera.h"
+#include "debug.h"
+
+// defines for runtime environment
+#define FOR_EACH_CPU
+
+#define BUFFER_MAX                     1024
+#define LARGE_BUFFER           512
+#define MIDDLE_BUFFER          256
+#define SMALL_BUFFER           64
+#define PROCPATH_MAX           32
+#define STATUS_STRING_MAX      16
+#define MAX_NUM_OF_FREQ                16
+
+#define MEM_SLOT_TOTAL         0
+#define MEM_SLOT_FREE          1
+#define MEM_SLOT_BUFFER                2
+#define MEM_SLOT_CACHED                3
+#define MEM_SLOT_MAX           4
+
+#define MIN_TICKS_FOR_LOAD     8
+#define MIN_TOTAL_TICK         1
+#define SYS_INFO_TICK          100     // TODO : change to (Hertz * profiling period)
+
+#define CPUMHZ         "cpu MHz"
+#define DA_PROBE_TIZEN_SONAME          "da_probe_tizen.so"
+#define DA_PROBE_OSP_SONAME                    "da_probe_osp.so"
+
+// define for correct difference of system feature vars
+#define val_diff(v_new, v_old) ((v_new < v_old) ? v_new : v_new - v_old)
+
+enum PROCESS_DATA
+{
+       PROCDATA_STAT,
+       PROCDATA_SMAPS
+};
+
+typedef unsigned long long tic_t;
+
+typedef struct {
+       unsigned long freq;
+       tic_t tick;
+       tic_t tick_sav;
+} cpufreq_t;
+
+typedef struct {
+       tic_t u, n, s, i, w, x, y, z;
+       tic_t u_sav, n_sav, s_sav, i_sav, w_sav, x_sav, y_sav, z_sav;
+       unsigned int id;                // cpu id
+       float cpu_usage;                // cpu load for this core
+       int sav_load_index;             // saved cpu load sampling index
+       int cur_load_index;             // current cpu load sampling index
+       cpufreq_t* pfreq;               // frequency information of cpu
+       int sav_freq_index;             // sav cpu frequency sampling index
+       int cur_freq_index;             // current cpu frequency sampling index
+       long long idle_ticks;
+       long long total_ticks;
+} CPU_t;       // for each cpu core
+
+// declared by greatim
+static int Hertz = 0;
+static int num_of_cpu = 0;
+static int num_of_freq = 0;
+static uint64_t mem_slot_array[MEM_SLOT_MAX];
+static CPU_t* cpus = NULL;
+static unsigned long probe_so_size = 0;
+
+
+static int get_file_status_no_open(int pfd, const char *filename)
+{
+       int status = 0;
+       char buf[STATUS_STRING_MAX];
+
+       if (unlikely(pfd < 0)) {
+               // file is not open
+               return 0;
+       }
+
+       lseek(pfd, 0, SEEK_SET);        // rewind to start of file
+
+       // read from file
+       if (unlikely(read(pfd, buf, STATUS_STRING_MAX) == -1))
+               status =  -(errno);
+       else
+               status = atoi(buf);
+
+       return status;
+}
+// daemon api : get status from file
+// pfd must not be null
+static int get_file_status(int *pfd, const char *filename)
+{
+       int status = 0;
+
+       if (likely(pfd != NULL)) {
+               //open if is not open
+               if (unlikely(*pfd < 0)) {
+                       // open file first
+                       *pfd = open(filename, O_RDONLY);
+                       if (unlikely(*pfd == -1)) {
+                               /* This file may absent in the system */
+                               return 0;
+                       }
+               }
+
+               if (unlikely(*pfd < 0)) {
+                       //file is open. lets read
+                       status = get_file_status_no_open(*pfd, filename);
+               }
+
+       }
+
+       return status;
+}
+
+// =============================================================================
+// device status information getter functions
+// =============================================================================
+
+static void init_brightness_status()
+{
+#ifdef DEVICE_ONLY
+       DIR *dir_info;
+       struct dirent *dir_entry;
+       char fullpath[PATH_MAX];
+       static char dirent_buffer[ sizeof(struct dirent) + PATH_MAX + 1 ] = {0,};
+       static struct dirent *dirent_r = (struct dirent *)dirent_buffer;
+
+
+       dir_info = opendir(BRIGHTNESS_PARENT_DIR);
+       if (dir_info != NULL) {
+               while ((readdir_r(dir_info, dirent_r, &dir_entry) == 0) && dir_entry) {
+                       if (strcmp(dir_entry->d_name, ".") == 0 ||
+                           strcmp(dir_entry->d_name, "..") == 0)
+                               continue;
+                       else { /* first directory */
+                               snprintf(fullpath, sizeof(fullpath),
+                                        BRIGHTNESS_PARENT_DIR "/%s/"
+                                        BRIGHTNESS_FILENAME,
+                                        dir_entry->d_name);
+                               get_file_status(&manager.fd.brightness,
+                                               fullpath);
+                       }
+               }
+               closedir(dir_info);
+       } else {
+               /* do nothing */
+       }
+#else
+       get_file_status(&manager.fd.brightness, EMUL_BRIGHTNESSFD);
+#endif
+}
+
+static int get_brightness_status()
+{
+       return get_file_status_no_open(manager.fd.brightness, EMUL_BRIGHTNESSFD);
+}
+
+static int get_max_brightness()
+{
+       int maxbrightnessfd = -1;
+       static int max_brightness = -1;
+       static char dirent_buffer[ sizeof(struct dirent) + PATH_MAX + 1 ] = {0,};
+       static struct dirent *dirent_r = (struct dirent *)dirent_buffer;
+
+       if (__builtin_expect(max_brightness < 0, 0)) {
+#ifdef DEVICE_ONLY
+               DIR* dir_info;
+               struct dirent* dir_entry;
+               char fullpath[PATH_MAX];
+
+               dir_info = opendir(BRIGHTNESS_PARENT_DIR);
+               if (dir_info != NULL) {
+                       while ((readdir_r(dir_info, dirent_r, &dir_entry) == 0) && dir_entry) {
+                               if (strcmp(dir_entry->d_name, ".") == 0 ||
+                                   strcmp(dir_entry->d_name, "..") == 0)
+                                       continue;
+                               else { /* first */
+                                       snprintf(fullpath, sizeof(fullpath),
+                                                BRIGHTNESS_PARENT_DIR "/%s/" MAX_BRIGHTNESS_FILENAME,
+                                                dir_entry->d_name);
+                                       max_brightness = get_file_status(&maxbrightnessfd, fullpath);
+                               }
+                       }
+                       closedir(dir_info);
+               } else {
+                       // do nothing
+               }
+#else /* DEVICE_ONLY */
+               max_brightness = get_file_status(&maxbrightnessfd, EMUL_MAX_BRIGHTNESSFD);
+#endif /* DEVICE_ONLY */
+       }
+
+       if (maxbrightnessfd != -1)
+               close(maxbrightnessfd);
+
+       return max_brightness;
+}
+
+static void init_video_status()
+{
+       manager.fd.video = fopen(MFCFD, "r");
+}
+
+static int get_video_status()
+{
+       int video_status = 0;
+       int ret;
+       FILE *video_fp = manager.fd.video;
+       char stat[256];
+
+       if (video_fp == NULL) // file is not open
+               return 0;
+
+       rewind(video_fp);
+       fflush(video_fp);
+
+       ret = fscanf(video_fp, "%s", stat);
+
+       if (ret != EOF)
+               if(strncmp(stat,"active",6) == 0)
+                       video_status = 1;
+
+       return video_status;
+}
+
+static void init_voltage_status()
+{
+       get_file_status(&manager.fd.voltage, VOLTAGEFD);
+}
+
+static int get_voltage_status()
+{
+       return get_file_status_no_open(manager.fd.voltage, VOLTAGEFD);
+}
+
+// =====================================================================
+// cpu information getter functions
+// =====================================================================
+static void get_cpu_frequency(float *freqs)
+{
+       char filename[MIDDLE_BUFFER];
+       char freq_str[SMALL_BUFFER];
+       FILE *f;
+       int cpu_n = 0;
+
+       /* clean data array */
+       for (cpu_n = 0; cpu_n < num_of_cpu; cpu_n++)
+               freqs[cpu_n] = 0.0;
+
+       cpu_n = 0;
+       while (1) {
+               /* TODO for targets with 1 cpu core
+                * file "/sys/devices/system/cpu/cpu0/online" can be absent
+                * so need lookup file /sys/devices/system/cpu/online
+                * and parse it
+                */
+
+               /* is CPU present */
+               snprintf(filename, MIDDLE_BUFFER,
+                        "/sys/devices/system/cpu/cpu%d/online", cpu_n);
+
+               f = fopen(filename, "r");
+               if (!f){
+                       LOGI_th_samp("file not found <%s\n>", filename);
+                       break;
+               }
+               fclose(f);
+
+               /* get CPU freq */
+               snprintf(filename, MIDDLE_BUFFER,
+                        "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_cur_freq", cpu_n);
+               f = fopen(filename, "r");
+               if (!f)
+               {
+                       /* core is disabled */
+                       LOGI_th_samp("core #%d diasabled\n", cpu_n);
+                       freqs[cpu_n] = 0.0;
+               } else {
+                       /* core enabled, get frequency /*/
+                       if (fscanf(f, "%s", freq_str) != 1) {
+                               /* TODO return error code */
+                               freqs[cpu_n] = 0.0f;
+                               LOGE("scan cpu #%d freq fail\n", cpu_n);
+                       } else {
+                               freqs[cpu_n] = atof(freq_str);
+                               LOGI_th_samp("core #%d freq = %.0f\n", cpu_n,
+                                            freqs[cpu_n]);
+                       }
+                       fclose(f);
+               }
+
+               //next core
+               cpu_n++;
+
+       }
+}
+
+// ========================================================================
+// get cpu and memory info for each process and whole system
+// ========================================================================
+typedef struct {
+       unsigned int pid;
+       char command[MAXNAMESIZE];
+       char state;
+       int ppid;
+       int pgrp;
+       int sid;
+       int tty_nr;
+       int tty_pgrp;
+       unsigned long flags;
+       unsigned long minor_fault;
+       unsigned long cminor_fault;
+       unsigned long major_fault;
+       unsigned long cmajor_fault;
+       unsigned long long utime;
+       unsigned long long stime;
+       unsigned long long cutime;
+       unsigned long long cstime;
+       long priority;
+       long nice;
+       int numofthread;
+       long dummy;
+       unsigned long long start_time;
+       unsigned long vir_mem;
+       unsigned long sh_mem;
+       long res_memblock;
+       unsigned long pss;
+       float cpu_load;
+} proc_t;
+
+typedef struct _proc_node {
+       proc_t proc_data;
+       void *thread_prochead;
+       unsigned long long saved_utime;
+       unsigned long long saved_stime;
+       int found;
+       struct _proc_node *next;
+} procNode;
+
+static procNode *inst_prochead = NULL;
+static procNode *other_prochead = NULL;
+
+static procNode* find_node(procNode *head, pid_t pid)
+{
+       procNode *t = head;
+
+       while (t != NULL) {
+               if (t->proc_data.pid == pid)
+               {
+                       t->found = 1;
+                       break;
+               }
+               t = t->next;
+       }
+       return t;
+}
+
+static procNode* add_node(procNode **head, pid_t pid)
+{
+       procNode *n;
+
+       n = (procNode *) malloc(sizeof(procNode));
+       if (n == NULL) {
+               LOGE("Not enough memory, add cpu info node failied");
+               return NULL;
+       }
+
+       n->thread_prochead = NULL;
+       n->proc_data.pid = pid;
+       n->found = 1;
+       n->next = *head;
+       *head = n;
+
+       return n;
+}
+
+static int del_node(procNode **head, pid_t pid)
+{
+       procNode *t;
+       procNode *prev;
+
+       t = *head;
+       prev = NULL;
+/*     LOGI("dell t=%d\n",t); */
+       while (t != NULL) {
+               if (t->proc_data.pid == pid) {
+                       if (prev != NULL)
+                               prev->next = t->next;
+                       else
+                               *head = (*head)->next;
+                       free(t);
+                       break;
+               }
+               prev = t;
+               t = t->next;
+       }
+
+/*     LOGI("ret 0\n"); */
+       return 0;
+}
+
+static int del_notfound_node(procNode **head)
+{
+       procNode *proc, *prev;
+       prev = NULL;
+       for(proc = *head; proc != NULL; )
+       {
+               if(proc->found == 0)
+               {
+                       if(prev != NULL)
+                       {
+                               prev->next = proc->next;
+                               free(proc);
+                               proc = prev->next;
+                       }
+                       else
+                       {
+                               *head = (*head)->next;
+                               free(proc);
+                               proc = *head;
+                       }
+               }
+               else
+               {
+                       prev = proc;
+                       proc = proc->next;
+               }
+       }
+       return 0;
+}
+
+static int reset_found_node(procNode *head)
+{
+       procNode* proc;
+       for(proc = head; proc != NULL; proc = proc->next)
+       {
+               proc->found = 0;
+       }
+       return 0;
+}
+
+// return 0 for normal case
+// return negative value for error case
+static int parse_proc_stat_file_bypid(char *path, proc_t* P, int is_inst_process)
+{
+       char filename[PROCPATH_MAX];
+       char buf[BUFFER_MAX];
+       int fd, num;
+       char *abuf, *bbuf;
+
+       // read from stat file
+       snprintf(filename, sizeof(filename), "%s/stat", path);
+       fd = open(filename, O_RDONLY, 0);
+
+       if(unlikely(fd == -1)){
+               return -1;
+       }
+
+       num = read(fd, buf, BUFFER_MAX);
+       close(fd);
+
+       if(unlikely(num <= 0)){
+               LOGE("nothing read from '%s'\n", filename);
+               return -1;
+       } else if(num == BUFFER_MAX)
+               num -= 1;
+
+
+       buf[num] = '\0';
+
+       // scan from buffer
+       // copy command name
+       abuf = strchr(buf, '(') + 1;
+       bbuf = strrchr(buf, ')');
+       num = bbuf - abuf;
+       if(unlikely(num >= sizeof(P->command)))
+               num = sizeof(P->command) - 1;
+       memcpy(P->command, abuf, num);
+       P->command[num] = '\0';
+       abuf = bbuf + 2;
+
+       // scan data
+       if (is_inst_process == 1) {
+               // TODO do not scan unnecessary params
+               sscanf(abuf,
+                       "%c "
+                       "%d %d %d %d %d "
+                       "%lu %lu %lu %lu %lu "
+                       "%Lu %Lu %Lu %Lu "  // utime stime cutime cstime
+                       "%ld %ld "
+                       "%d "
+                       "%ld "
+                       "%Lu "  // start_time
+                       "%lu "
+                       "%ld",
+                       &P->state,
+                       &P->ppid, &P->pgrp, &P->sid, &P->tty_nr, &P->tty_pgrp,
+                       &P->flags, &P->minor_fault, &P->cminor_fault, &P->major_fault, &P->cmajor_fault,
+                       &P->utime, &P->stime, &P->cutime, &P->cstime,
+                       &P->priority, &P->nice,
+                       &P->numofthread,
+                       &P->dummy,
+                       &P->start_time,
+                       &P->vir_mem,
+                       &P->res_memblock
+                       );
+       } else {
+               // TODO do not scan unnecessary params
+               P->numofthread = 0;
+               sscanf(abuf,
+                       "%c "
+                       "%d %d %d %d %d "
+                       "%lu %lu %lu %lu %lu "
+                       "%Lu %Lu ",  // utime stime cutime cstime
+                       &P->state,
+                       &P->ppid, &P->pgrp, &P->sid, &P->tty_nr, &P->tty_pgrp,
+                       &P->flags, &P->minor_fault, &P->cminor_fault, &P->major_fault, &P->cmajor_fault,
+                       &P->utime, &P->stime
+                       );
+       }
+
+       if(P->numofthread == 0)
+               P->numofthread = 1;
+
+       //convert to bytes
+       P->res_memblock = P->res_memblock * getpagesize();
+
+       return 0;
+}
+
+// return 0 for normal case
+// return negative value for error case
+static int parse_proc_smaps_file_bypid(char *path, proc_t* P)
+{
+#define MIN_SMAP_BLOCKLINE     50
+
+       char filename[PROCPATH_MAX];
+       char buf[MIDDLE_BUFFER];
+       char numbuf[SMALL_BUFFER];
+       FILE* fp;
+
+       // reset pss size of proc_t
+       P->pss = 0;
+       P->sh_mem = 0;
+
+       // read from smaps file
+       snprintf(filename, sizeof(filename), "%s/smaps", path);
+       fp = fopen(filename, "r");
+
+       if(fp == NULL){
+               return -1;
+       }
+
+       if(unlikely(probe_so_size == 0))        // probe so size is not abtained
+       {
+               int is_probe_so = 0;
+               while(fgets(buf, MIDDLE_BUFFER, fp) != NULL)
+               {
+                       if(strncmp(buf, "Pss:", 4) == 0)        // line is started with "Pss:"
+                       {
+                               sscanf(buf, "Pss:%s kB", numbuf);
+                               P->pss += atoi(numbuf);
+                               if(is_probe_so == 1)
+                               {
+                                       probe_so_size += atoi(numbuf);
+                                       is_probe_so = 0;        // reset search flag
+                               }
+                       }
+                       else if(strncmp(buf, "Shared", 6) == 0) // line is started with "Shared"
+                       {
+                               char *p = strstr(buf, ":");
+                               if (p != 0) {
+                                       sscanf(p, ":%s kB", numbuf);
+                                       P->sh_mem += atoi(numbuf);
+                               }
+
+                       }
+                       else    // not Pss line
+                       {
+                               if (is_probe_so == 0 && strlen(buf) > MIN_SMAP_BLOCKLINE)
+                               {
+                                       // first we find probe so section
+                                       if(strstr(buf, DA_PROBE_TIZEN_SONAME) != NULL ||
+                                                       strstr(buf, DA_PROBE_OSP_SONAME) != NULL)
+                                       {
+                                               // found probe.so
+                                               is_probe_so = 1;
+                                       }
+                                       else
+                                       {
+                                               // do nothing
+                                       }
+                               }
+                               else
+                               {
+                                       // do nothing
+                               }
+                       }
+               }
+       }
+       else    // we know about probe.so size already
+       {
+               while(fgets(buf, MIDDLE_BUFFER, fp) != NULL)
+               {
+                       if(strncmp(buf, "Pss:", 4) == 0)
+                       {
+                               sscanf(buf, "Pss:%s kB", numbuf);
+                               P->pss += atoi(numbuf);
+                       }
+                       else if(strncmp(buf, "Shared", 6) == 0) // line is started with "Shared"
+                       {
+                               char *p = strstr(buf, ":");
+                               if (p != 0) {
+                                       sscanf(p, ":%s kB", numbuf);
+                                       P->sh_mem += atoi(numbuf);
+                               }
+                       }
+               }
+       }
+       // TODO that probe_so_size calculation maybe wrong. check it. fix it
+       P->pss -= probe_so_size;
+
+       // convert to bytes
+       P->pss *= 1024;
+       P->sh_mem *= 1024;
+
+       fclose(fp);
+
+       return 0;
+}
+
+// return 0 for normal case
+// return positive value for non critical case
+// return negative value for critical case
+static int update_process_data(procNode **prochead, pid_t* pidarray, int pidcount, enum PROCESS_DATA datatype, int is_inst_process)
+{
+       static struct stat sb;
+       int i, ret = 0, is_new_node = 0;
+       char buf[PROCPATH_MAX];
+       procNode* procnode;
+
+       for(i = 0; i < pidcount; i++)
+       {
+               if (pidarray[i] == 0)   // pid is invalid
+               {
+                       ret = 1;
+                       continue;
+               }
+
+               snprintf(buf, sizeof(buf), "/proc/%d", pidarray[i]);
+               if (unlikely(stat(buf, &sb) == -1))     // cannot access anymore
+               {
+                       del_node(prochead, pidarray[i]);
+                       ret = errno;
+                       continue;
+               }
+
+               if ((procnode = find_node(*prochead, pidarray[i])) == NULL) {
+                       // new process
+                       procnode = add_node(prochead, pidarray[i]);
+                       is_new_node = 1;
+               }
+
+               if (datatype == PROCDATA_STAT) {
+                       ret = parse_proc_stat_file_bypid(buf,
+                                                        &(procnode->proc_data),
+                                                        is_inst_process);
+                       if (unlikely(ret < 0)) {
+                               //parse fail. log it
+                               LOGE("Failed to get proc stat file by pid(%d)\n", pidarray[i]);
+                       } else if (is_new_node == 1) {
+                               //update data for new node
+                               procnode->saved_utime = procnode->proc_data.utime;
+                               procnode->saved_stime = procnode->proc_data.stime;
+                       }
+
+               } else if (datatype == PROCDATA_SMAPS) {
+                       //parse smaps
+                       ret = parse_proc_smaps_file_bypid(buf,
+                                                         &(procnode->proc_data));
+
+                       if (unlikely( ret < 0))
+                               LOGE("Failed to get proc smaps file by pid(%d)\n", pidarray[i]);
+
+               } else {
+                       // impossible
+               }
+
+       }
+       del_notfound_node(prochead);
+       reset_found_node(*prochead);
+
+       return ret;
+}
+
+static int update_system_cpu_frequency(int cur_index)
+{
+       char buf[SMALL_BUFFER];
+       char filename[SMALL_BUFFER];
+       int i, j;
+       FILE* fp;
+
+       // execute this block only once
+       if(unlikely(num_of_freq <= 0))
+       {
+               FILE* fp;
+               num_of_freq = 0;
+               if((fp = fopen(CPUNUM_OF_FREQ, "r")) != NULL)
+               {
+                       while(fgets(buf, SMALL_BUFFER, fp) != NULL)
+                       {
+                               num_of_freq++;
+                       }
+                       fclose(fp);
+               }
+               else
+               {
+                       /* This file may absent in the system */
+               }
+
+               for(i = 0; i < num_of_cpu; i++)
+               {
+                       if(cpus[i].pfreq == NULL && num_of_freq)
+                       {
+                               cpus[i].pfreq = (cpufreq_t*) calloc(num_of_freq, sizeof(cpufreq_t));
+                       }
+               }
+       }
+
+       snprintf(filename, sizeof(filename), CPUNUM_OF_FREQ);
+       // update cpu frequency information
+       for(i = 0; i < num_of_cpu; i++)
+       {
+               filename[27] = (char)('0' + i);
+               fp = fopen(filename, "r");
+               if(fp != NULL)
+               {
+                       for(j = 0; j < num_of_freq; j++)
+                       {
+                               if(fgets(buf, SMALL_BUFFER, fp) != NULL)
+                               {
+                                       sscanf(buf, "%lu %Lu", &(cpus[i].pfreq[j].freq),
+                                                       &(cpus[i].pfreq[j].tick));
+                               }
+                               else    // cannot read anymore from frequency info file
+                                       break;
+                       }
+
+                       fclose(fp);
+                       cpus[i].cur_freq_index = cur_index;
+               }
+               else    // cannot load cpu frequency information
+               {       // do nothing
+               }
+       }
+
+       return 0;
+}
+
+// return 0 for normal case
+// return negative value for error
+static void init_system_cpu_data()
+{
+       manager.fd.procstat = fopen(PROCSTAT, "r");
+}
+
+static int update_system_cpu_data(int cur_index)
+{
+/*     LOGI(">\n"); */
+
+       FILE* fp = manager.fd.procstat;
+       int num;
+       char buf[BUFFER_MAX];
+
+       if(fp == NULL)
+               return -1;
+
+       rewind(fp);
+       fflush(fp);
+
+       if(fgets(buf, sizeof(buf), fp) == NULL)
+       {
+               LOGE("Failed to read first line of " PROCSTAT "\n");
+               return -1;
+       }
+
+/* LOGI("scan; cpus = %d\n", cpus); */
+
+       cpus[num_of_cpu].x = 0;
+       cpus[num_of_cpu].y = 0;
+       cpus[num_of_cpu].z = 0;
+       num = sscanf(buf, "cpu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu",
+                       &cpus[num_of_cpu].u,
+                       &cpus[num_of_cpu].n,
+                       &cpus[num_of_cpu].s,
+                       &cpus[num_of_cpu].i,
+                       &cpus[num_of_cpu].w,
+                       &cpus[num_of_cpu].x,
+                       &cpus[num_of_cpu].y,
+                       &cpus[num_of_cpu].z
+                       );
+       cpus[num_of_cpu].cur_load_index = cur_index;
+       if(num < 4)
+       {
+               LOGE("Failed to read from " PROCSTAT "\n");
+               return -1;
+       }
+
+#ifdef FOR_EACH_CPU
+
+/*     LOGI("cpu num = %d\n", num_of_cpu); */
+       // and just in case we're 2.2.xx compiled without SMP support...
+       if(num_of_cpu == 1)
+       {
+               cpus[0].id = cpus[1].id = 0;
+               memcpy(cpus, &cpus[1], sizeof(tic_t) * 8);
+               cpus[0].cur_load_index = cur_index;
+       }
+       else if(num_of_cpu > 1)
+       {
+               int i;
+               // now value each separate cpu's tics
+               for(i = 0; i < num_of_cpu; i++)
+               {
+                       if(fgets(buf, sizeof(buf), fp) != NULL)
+                       {
+                               cpus[i].x = 0;
+                               cpus[i].y = 0;
+                               cpus[i].z = 0;
+                               num = sscanf(buf, "cpu%u %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu",
+                                               &cpus[i].id,
+                                               &cpus[i].u, &cpus[i].n, &cpus[i].s, &cpus[i].i,
+                                               &cpus[i].w, &cpus[i].x, &cpus[i].y, &cpus[i].z);
+                               if(num > 4)
+                               {
+                                       LOGI_th_samp("Readed %d stats of %dth cpu\n", num, i);
+                                       cpus[i].cur_load_index = cur_index;
+                               }
+                               else    // buf is not cpu core tick information
+                               {       // do nothing
+                               }
+                       }
+                       else    // cannot read anymore from /proc/stat file
+                       {       // do nothing
+                       }
+               }
+       }
+       else
+       {
+               // not possible
+               return -1;
+       }
+#endif
+       return 0;
+}
+
+// return 0 for normal case
+// return negative value for error
+static void init_update_system_memory_data()
+{
+       manager.fd.procmeminfo = open(PROCMEMINFO, O_RDONLY);
+}
+
+static int update_system_memory_data(uint64_t *memtotal, uint64_t *memused)
+{
+       typedef struct _mem_t {
+               const char* name;       // memory slot name
+               unsigned long* slot;    // memory value slot
+       } mem_t;
+
+       int meminfo_fd = manager.fd.procmeminfo;
+       char *head, *tail;
+       int i, num;
+       char buf[BUFFER_MAX];
+       static const mem_t mem_table[] = {
+               {"Buffers",             (unsigned long *)&mem_slot_array[MEM_SLOT_BUFFER]},
+               {"Cached",              (unsigned long *)&mem_slot_array[MEM_SLOT_CACHED]},
+               {"MemFree",             (unsigned long *)&mem_slot_array[MEM_SLOT_FREE]},
+               {"MemTotal",    (unsigned long *)&mem_slot_array[MEM_SLOT_TOTAL]},
+       };
+       const int mem_table_size = sizeof(mem_table) / sizeof(mem_t);
+
+       if (meminfo_fd == -1)
+               return -1;
+
+       lseek(meminfo_fd, 0L, SEEK_SET);
+       if((num = read(meminfo_fd, buf, BUFFER_MAX)) < 0)
+       {
+               LOGE("Failed to read from " PROCMEMINFO "\n");
+               return -1;
+       }
+
+       if(num == BUFFER_MAX)
+               num -= 1;
+
+       buf[num] = '\0';
+//     LOGI("buffer=<%s>\n", buf);
+
+       num = 0;        // number of found element
+       head = buf;
+       for( ;num < mem_table_size ; )
+       {
+               tail = strchr(head, ':');
+               if(!tail)
+                       break;
+               *tail = '\0';
+               for(i = 0; i < mem_table_size; i++)
+               {
+                       if(strcmp(head, mem_table[i].name) == 0)        // found
+                       {
+                               head = tail + 1;
+                               *(mem_table[i].slot) = strtoul(head, &tail, 10);
+                               num++;
+                               break;
+                       }
+               }
+               if(i == mem_table_size) // cannot find entry
+               {
+                       head = tail + 1;
+               }
+               tail = strchr(head, '\n');
+               if(tail == NULL)
+                       break;
+               head = tail + 1;
+       }
+/*             LOGI("Buffers = %016LX\n", mem_slot_array[MEM_SLOT_BUFFER]); */
+/*             LOGI("Cached  = %016LX\n", mem_slot_array[MEM_SLOT_CACHED]); */
+/*             LOGI("MemFree = %016LX\n", mem_slot_array[MEM_SLOT_FREE]); */
+/*             LOGI("MemTotal= %016LX\n", mem_slot_array[MEM_SLOT_TOTAL]); */
+       if(num == mem_table_size)       // find all element
+       {
+               *memtotal = mem_slot_array[MEM_SLOT_TOTAL];
+               *memused = mem_slot_array[MEM_SLOT_TOTAL] - mem_slot_array[MEM_SLOT_FREE] -
+                       mem_slot_array[MEM_SLOT_BUFFER] - mem_slot_array[MEM_SLOT_CACHED];
+
+
+               *memtotal *= 1024;      // change to Byte
+               *memused *= 1024;       // change to Byte
+               return 0;
+       }
+       else
+       {
+               LOGE("Cannot find all neccessary element in meminfo\n");
+               return -1;
+       }
+}
+
+
+// return 0 for error case
+// return system total memory in MB
+//static
+static unsigned long get_system_total_memory(void)
+{
+       int meminfo_fd = manager.fd.procmeminfo;
+       char *head, *tail;
+       int num;
+       char buf[BUFFER_MAX];
+       static const char* memtotalstr = "MemTotal";
+       unsigned long totalmem = 0;
+
+       if (meminfo_fd == -1)
+               return 0;
+
+       lseek(meminfo_fd, 0L, SEEK_SET);
+
+       if((num = read(meminfo_fd, buf, BUFFER_MAX)) < 0)
+       {
+               LOGE("Failed to read from " PROCMEMINFO "\n");
+               return 0;
+       }
+
+       if(num == BUFFER_MAX)
+               num -= 1;
+       buf[num] = '\0';
+
+       head = buf;
+       for( ; ; )
+       {
+               tail = strchr(head, ':');
+               if(!tail)
+                       break;
+               *tail = '\0';
+               if(strcmp(head, memtotalstr) == 0)      // found
+               {
+                       head = tail + 1;
+                       totalmem = strtoul(head, &tail, 10);
+                       break;
+               }
+
+               head = tail + 1;
+               tail = strchr(head, '\n');
+               if(tail == NULL)
+                       break;
+               head = tail + 1;
+       }
+
+       return (totalmem * 1024);
+}
+
+// ===============================================================
+// disk information getter functions
+// ===============================================================
+static int get_fsinfo(const char* path, int type)
+{
+       struct statfs buf;
+       int total;
+       int free;
+
+       if (statfs(path, &buf) < 0)
+       {
+               return -errno;
+       }
+
+       total = (int)((long long)(buf.f_bsize / 1024LL * buf.f_blocks) / 1024LL);
+       free = (int)((long long)(buf.f_bsize / 1024LL * buf.f_bavail) / 1024LL);
+
+/*     LOGI("File storage total(%d), free(%d)\n", total, free); */
+       if (type == FSINFO_TYPE_TOTAL)
+       {
+               return total;
+       }
+       else if (type == FSINFO_TYPE_FREE)
+       {
+               return free;
+       }
+
+       return -1;
+}
+
+static int stat_get_storageinfo(int type)
+{
+       return get_fsinfo(UMSFD, type);
+}
+
+static int stat_get_cardinfo(int type)
+{
+       if (access(MMCBLKFD, F_OK) < 0)
+       {
+               return -1;
+       }
+
+       return get_fsinfo(MMCFD, type);
+}
+
+
+static int get_total_drive()
+{
+       int total = 0;
+       int storage = stat_get_storageinfo(FSINFO_TYPE_TOTAL);
+       int card = stat_get_cardinfo(FSINFO_TYPE_TOTAL);
+
+       if (storage < 0 && card < 0)
+       {
+               return -1;
+       }
+
+       total = storage + card;
+
+       return total;
+}
+
+static int get_total_used_drive()
+{
+       int total = 0;
+       int free = 0;
+       int storage = stat_get_storageinfo(FSINFO_TYPE_FREE);
+       int card = stat_get_cardinfo(FSINFO_TYPE_FREE);
+
+       if (storage < 0 && card < 0)
+       {
+               LOGI_th_samp("total_used_drive = -1\n");
+               return -1;
+       }
+
+       free = storage + card;
+       total = get_total_drive() - free;
+
+       LOGI_th_samp("total_used_drive = %d\n", total);
+
+       return total;
+}
+
+static int update_thread_data(int pid)
+{
+       static struct stat sb;
+       int ret = 0;
+       char path[PROCPATH_MAX];
+       char buf[PROCPATH_MAX];
+       procNode* procnode;
+       DIR *taskdir = NULL;
+       struct dirent *entry = NULL;
+       unsigned int tid;
+       procNode *node = NULL;
+       procNode **thread_prochead = NULL;
+       static char dirent_buffer[ sizeof(struct dirent) + PATH_MAX + 1 ] = {0,};
+       static struct dirent *dirent_r = (struct dirent *)dirent_buffer;
+
+       snprintf(path, sizeof(path), "/proc/%d/task", pid);
+
+       if(!(taskdir = opendir(path)))
+       {
+               LOGE("task not found '%s'\n", path);
+               ret = -1;
+               goto exit;
+       }
+
+       node = find_node(inst_prochead, pid);
+       if (node == NULL) {
+               LOGE("inst node task not found '%s' pid = %d\n", path, pid);
+               ret = -1;
+               goto exit_close_dir;
+       }
+       thread_prochead = (procNode **)&(node->thread_prochead);
+
+       while ((readdir_r(taskdir, dirent_r, &entry) == 0) && entry) {
+               if(*entry->d_name > '0' &&      *entry->d_name <= '9')
+               {
+                       tid = atoi(entry->d_name);
+                       snprintf(buf, sizeof(buf), "/proc/%d/task/%d", pid, tid);
+
+                       if(unlikely(stat(buf, &sb) == -1))
+                       {
+                               del_node(thread_prochead, tid);
+                               ret = errno;
+                               continue;
+                       }
+
+                       if((procnode = find_node(*thread_prochead, tid)) == NULL)
+                       {
+                               procnode = add_node(thread_prochead, tid);
+                               if (unlikely((ret = parse_proc_stat_file_bypid(buf, &(procnode->proc_data), 0)) < 0))
+                               {
+                                       LOGE("Failed to get proc stat file by tid(%d). add node\n", tid);
+                               }
+                               else
+                               {
+                                       procnode->saved_utime = procnode->proc_data.utime;
+                                       procnode->saved_stime = procnode->proc_data.stime;
+                                       LOGI_th_samp("data created %s\n", buf);
+                               }
+                       }
+                       else
+                       {
+                               if (unlikely((ret = parse_proc_stat_file_bypid(buf, &(procnode->proc_data), 0)) < 0))
+                                       LOGE("Failed to get proc stat file by tid(%d). node exist\n", tid);
+                               else
+                                       LOGI_th_samp("data updated %s\n", buf);
+                       }
+               }
+       }
+
+       del_notfound_node(thread_prochead);
+       reset_found_node(*thread_prochead);
+
+exit_close_dir:
+       closedir(taskdir);
+exit:
+       return ret;
+}
+
+// ========================================================================
+// overall information getter functions
+// ========================================================================
+
+#define print_to_buf(buf, buflen, str)                         \
+do {                                                           \
+       if (strlen(str) <= buflen) {                            \
+               lenin = snprintf(buf + len, buflen, "CDMA,");   \
+               if (lenin <= 0) {                               \
+                       LOGE("can not pack <%s>\n", str);       \
+                       goto exit;                              \
+               }                                               \
+               lenin -= 1;                                     \
+               len += lenin;                                   \
+               buflen -= lenin;                                \
+       } else {                                                \
+               LOGE("can not pack <%s>\n", str);               \
+               goto exit;                                      \
+       }                                                       \
+} while(1)
+
+static int get_device_network_type(char* buf, size_t buflen)
+{
+       int len = 0, lenin = 0;
+
+       buf[0] = '\0';
+
+       if (is_cdma_available())
+               print_to_buf(buf, buflen, "CDMA,");
+
+       if (is_edge_available())
+               print_to_buf(buf, buflen, "EDGE,");
+
+       if (is_gprs_available())
+               print_to_buf(buf, buflen, "GPRS,");
+
+       if (is_gsm_available())
+               print_to_buf(buf, buflen, "GSM,");
+
+       if (is_hsdpa_available())
+               print_to_buf(buf, buflen, "HSDPA,");
+
+       if (is_hspa_available())
+               print_to_buf(buf, buflen, "HSPA,");
+
+       if (is_hsupa_available())
+               print_to_buf(buf, buflen, "HSUPA,");
+
+       if (is_umts_available())
+               print_to_buf(buf, buflen, "UMTS,");
+
+       if (is_lte_available())
+               print_to_buf(buf, buflen, "LTE,");
+
+exit:
+       return len;
+}
+
+static int update_cpus_info(int event_num, float elapsed)
+{
+       int i = 0;
+       CPU_t* cpuptr;
+       // calculate for system cpu load
+#ifdef FOR_EACH_CPU
+       for(i = 0; i < num_of_cpu; i++)
+#else
+       for(i = num_of_cpu; i <= num_of_cpu; i++)
+#endif
+       {
+       LOGI_th_samp("CPU #%d\n", i);
+               cpuptr = &(cpus[i]);
+
+               if(cpuptr->cur_load_index == event_num)
+               {
+                       if(cpuptr->sav_load_index == event_num - 1)             // previous sampling is just before 1 period
+                       {
+                               cpuptr->idle_ticks = cpuptr->i - cpuptr->i_sav;
+                               if(unlikely(cpuptr->idle_ticks < 0))
+                               {
+                                       cpuptr->idle_ticks = 0;
+                               }
+                               cpuptr->total_ticks = (cpuptr->u - cpuptr->u_sav) +
+                                       (cpuptr->s - cpuptr->s_sav) +
+                                       (cpuptr->n - cpuptr->n_sav) +
+                                       cpuptr->idle_ticks +
+                                       (cpuptr->w - cpuptr->w_sav) +
+                                       (cpuptr->x - cpuptr->x_sav) +
+                                       (cpuptr->y - cpuptr->y_sav) +
+                                       (cpuptr->z - cpuptr->z_sav);
+                               if(cpuptr->total_ticks < MIN_TOTAL_TICK)
+                               {
+                                       cpuptr->cpu_usage = 0.0f;
+                               }
+                               else
+                               {
+                                       cpuptr->cpu_usage = (1.0f - ((float)cpuptr->idle_ticks /
+                                                               (float)cpuptr->total_ticks)) * 100.0f;
+                               }
+
+                               LOGI_th_samp("System cpu usage log : %d, %Ld, %Ld\n",
+                                               i, cpuptr->idle_ticks, cpuptr->total_ticks);
+                               if(unlikely(cpuptr->cpu_usage < 0))
+                               {
+                                       cpuptr->cpu_usage = 0.0f;
+                               }
+                       }
+                       else    // previous sampling is not just before 1 period
+                       {
+                               // assume non idle ticks happen in 1 profiling period
+                               // because sampling is not available just before 1 profiling period
+                               cpuptr->idle_ticks = (cpuptr->u - cpuptr->u_sav) +
+                                       (cpuptr->s - cpuptr->s_sav) +
+                                       (cpuptr->n - cpuptr->n_sav) +
+                                       (cpuptr->w - cpuptr->w_sav) +
+                                       (cpuptr->x - cpuptr->x_sav) +
+                                       (cpuptr->y - cpuptr->y_sav) +
+                                       (cpuptr->z - cpuptr->z_sav);
+                               cpuptr->total_ticks = (long long)(Hertz * elapsed);
+                               if(unlikely(cpuptr->total_ticks < 1))
+                                       cpuptr->total_ticks = 1;
+                               cpuptr->cpu_usage = ((float)cpuptr->idle_ticks /
+                                               (float)cpuptr->total_ticks) * 100.0f;
+                               if(unlikely(cpuptr->cpu_usage > 100.0f))
+                               {
+                                       cpuptr->cpu_usage = 100.0f;
+                               }
+                       }
+
+                       // save new value
+                       cpuptr->u_sav = cpuptr->u;
+                       cpuptr->s_sav = cpuptr->s;
+                       cpuptr->n_sav = cpuptr->n;
+                       cpuptr->i_sav = cpuptr->i;
+                       cpuptr->w_sav = cpuptr->w;
+                       cpuptr->x_sav = cpuptr->x;
+                       cpuptr->y_sav = cpuptr->y;
+                       cpuptr->z_sav = cpuptr->z;
+                       cpuptr->sav_load_index = cpuptr->cur_load_index;
+               }
+               else
+               {
+                       cpuptr->cpu_usage = 0.0f;
+               }
+       }
+
+       return 0;
+}
+
+static int fill_system_processes_info(procNode *prochead, float factor,
+                                     struct system_info_t *sys_info,
+                                     uint32_t *count)
+{
+       procNode* proc;
+       float thread_load;
+       uint32_t app_count = 0;
+
+       LOGI_th_samp("prochead = %X\n", (unsigned int)prochead);
+
+       for(proc = prochead; proc != NULL; proc = proc->next) {
+               LOGI_th_samp("proc#%d (%d %d),(%d %d) (%d) %f\n",
+                               app_count,
+                               (unsigned int)proc->proc_data.utime, (unsigned int)proc->proc_data.stime ,
+                               (unsigned int)proc->saved_utime, (unsigned int)proc->saved_stime,
+                               (int)(proc->proc_data.utime + proc->proc_data.stime - proc->saved_utime - proc->saved_stime),
+                               (float)(
+                                       proc->saved_utime + proc->saved_stime -
+                                       proc->proc_data.utime - proc->proc_data.stime
+                                       ) * factor);
+               thread_load = (float)(proc->proc_data.utime + proc->proc_data.stime -
+                                                               proc->saved_utime - proc->saved_stime) * factor;
+
+               if(thread_load > 100.0f)
+                       thread_load = 100.0f;
+
+               proc->saved_utime = proc->proc_data.utime;
+               proc->saved_stime = proc->proc_data.stime;
+
+               proc->proc_data.cpu_load = thread_load;
+
+               //increment process count
+               app_count++;
+       }
+
+       *count = app_count;
+       return 0;
+
+}
+
+// fill threads information
+static int fill_system_threads_info(float factor, struct system_info_t * sys_info)
+{
+       procNode* inst_proc;
+       procNode* proc;
+       float thread_load;
+
+       for (inst_proc = inst_prochead; inst_proc != NULL; inst_proc = inst_proc->next)
+               for (proc = inst_proc->thread_prochead; proc != NULL; proc = proc->next) {
+                       sys_info->count_of_threads++; //maybe wrong
+
+                       thread_load = (float)(proc->proc_data.utime +
+                                             proc->proc_data.stime -
+                                             proc->saved_utime -
+                                             proc->saved_stime) * factor;
+                       if(thread_load > 100.0f)
+                               thread_load = 100.0f;
+
+                       proc->proc_data.cpu_load = thread_load;
+
+                       proc->saved_utime = proc->proc_data.utime;
+                       proc->saved_stime = proc->proc_data.stime;
+               }
+
+       return 0;
+}
+
+//fill system cpu information
+static int fill_system_cpu_info(struct system_info_t *sys_info)
+{
+       float sys_usage = 0.0f;
+       int i = 0;
+
+       // calculate for whole cpu load by average all core load
+       LOGI_th_samp("calculate for whole cpu load num_of_cpu=%d\n", num_of_cpu);
+       for(i = 0 ; i < num_of_cpu; i++)
+               sys_usage += cpus[i].cpu_usage;
+
+       // fill cpu load
+       float *pcpu_usage;
+       if (num_of_cpu != 0)
+       {
+               sys_info->cpu_load = malloc( num_of_cpu * sizeof(*sys_info->cpu_load) );
+               pcpu_usage = sys_info->cpu_load;
+               for(i = 0; i < num_of_cpu; i++)
+               {
+                       LOGI_th_samp("cpu#%d : %.1f\n" , i,  cpus[i].cpu_usage);
+                       *pcpu_usage = cpus[i].cpu_usage;
+                       pcpu_usage++;
+               }
+       }
+
+       //fill CPU frequency
+       sys_info->cpu_frequency = malloc(num_of_cpu * sizeof(float));
+       if (!sys_info->cpu_frequency) {
+               LOGE("Cannot alloc cpu freq\n");
+               return 1;
+       }
+       get_cpu_frequency(sys_info->cpu_frequency);
+
+       return 0;
+}
+
+/* TODO add return value to skip_lines */
+static void skip_lines(FILE * fp, unsigned int count)
+{
+       char *buffer = NULL;
+       size_t buflen;
+       unsigned int index;
+       for (index = 0; index != count; ++index) {
+               if (getline(&buffer, &buflen, fp) < 0)
+                       LOGE("file scan fail\n");
+       }
+       free(buffer);
+}
+
+static int skip_tokens(FILE * fp, unsigned int count)
+{
+       int res;
+       unsigned int index;
+
+       for (index = 0; index != count; ++index) {
+               res = fscanf(fp, "%*s");
+               if (res == EOF && index != count - 1)
+                       return -1;
+       }
+
+       return 0;
+}
+
+static void init_network_stat()
+{
+       manager.fd.networkstat = fopen("/proc/net/dev", "r");
+}
+
+static void get_network_stat(uint32_t *recv, uint32_t *send)
+{
+       FILE *fp = manager.fd.networkstat;
+       uintmax_t irecv, isend;
+       char ifname[64];
+       if (fp == NULL)
+               return;
+
+       rewind(fp);
+       fflush(fp);
+
+       *recv = *send = 0;
+       skip_lines(fp, 2);      /* strip header */
+
+       while (fscanf(fp, "%s", ifname) != EOF)
+               if (strcmp("lo:", ifname)) {
+                       if (fscanf(fp, "%" SCNuMAX, &irecv) <= 0)
+                               goto scan_error;
+                       skip_tokens(fp, 7);
+
+                       if (fscanf(fp, "%" SCNuMAX, &isend) <= 0)
+                               goto scan_error;
+                       skip_tokens(fp, 7);
+
+                       *recv += irecv;
+                       *send += isend;
+               } else
+                       skip_tokens(fp, 16);
+
+       goto exit;
+scan_error:
+       LOGE("scan fail\n");
+exit:
+       return;
+}
+
+static void peek_network_stat_diff(uint32_t *recv, uint32_t *send)
+{
+       static uint32_t irecv_old, isend_old;
+       uint32_t tmp;
+
+       get_network_stat(recv, send);
+
+       tmp = *recv;
+       *recv = val_diff(tmp, irecv_old);
+       irecv_old = tmp;
+
+       tmp = *send;
+       *send = val_diff(tmp, isend_old);
+       isend_old = tmp;
+
+}
+
+/* function
+ * info: get sector size by partition name
+ * params:
+ *     char *partition_name - partition name to get sector size
+ * return
+ *     uint32_t - partition sector size
+ * */
+static uint32_t get_partition_sector_size(char *partition_name)
+{
+       char buf[MAX_FILENAME];
+       FILE *f = NULL;
+       uint32_t res = 0;
+
+       /* prepare partition sector size file name */
+       snprintf(buf, MAX_FILENAME, "/sys/block/%s/queue/hw_sector_size", partition_name);
+       f = fopen(buf, "r");
+
+       /* check file */
+       if (f != NULL) {
+               /* reset error code */
+               errno = 0;
+               /* scan partition sector size */
+               if (fscanf(f, "%d", &res) != 1) {
+                       /* check errors */
+                       int errsv = errno;
+                       if (errsv) {
+                               GETSTRERROR(errsv, errno_buf);
+                               LOGE("scan file <%s> error: %s\n", buf, errno_buf);
+                               res = 0;
+                       }
+               }
+               /* close source file */
+               fclose(f);
+       } else
+               LOGE("cannot get size for partition <%s> from file <%s>\n",
+                    partition_name, buf);
+
+       /* return result value */
+       return res;
+}
+
+static void init_disk_stat(void)
+{
+       manager.fd.diskstats = fopen("/proc/diskstats", "r");
+}
+
+static void get_disk_stat(uint32_t *reads, uint32_t *bytes_reads,
+                         uint32_t *writes, uint32_t *bytes_writes)
+{
+       enum { partition_name_maxlength = 128 };
+       FILE *fp = manager.fd.diskstats;
+       char master_partition[partition_name_maxlength] = { 0 };
+       uint32_t sector_size = 0;
+
+       *reads = *writes = 0;
+       *bytes_reads = *bytes_writes = 0;
+
+       if (fp == NULL)
+               return;
+
+
+       rewind(fp);
+       fflush(fp);
+
+       while (!feof(fp)) {
+               char partition[partition_name_maxlength];
+               uintmax_t preads, pwrites;
+               uintmax_t psec_read, psec_write;
+               if (skip_tokens(fp, 2) < 0)
+                       goto exit;
+
+               if (fscanf(fp, "%s", partition) != 1)
+                       goto scan_error;
+               if (*master_partition
+                   && !strncmp(master_partition, partition,
+                              strlen(master_partition))) {
+                       /* subpartition */
+                       skip_tokens(fp, 11);
+               } else {
+                       /* TODO add check err in skip_token func */
+                       //1
+                       if (fscanf(fp, "%" SCNuMAX, &preads) == EOF)
+                               goto scan_error;
+                       skip_tokens(fp, 1);
+                       //3
+                       if (fscanf(fp, "%" SCNuMAX, &psec_read) == EOF)
+                               goto scan_error;
+                       skip_tokens(fp, 1);
+                       //5
+                       if (fscanf(fp, "%" SCNuMAX, &pwrites) == EOF)
+                               goto scan_error;
+                       skip_tokens(fp, 1);
+                       //7
+                       if (fscanf(fp, "%" SCNuMAX, &psec_write) == EOF)
+                               goto scan_error;
+                       skip_tokens(fp, 4);
+
+                       memcpy(master_partition, partition,
+                              partition_name_maxlength);
+
+                       /* get sector size */
+                       sector_size = get_partition_sector_size(partition);
+
+                       *reads += (uint32_t)preads;
+                       *writes += (uint32_t)pwrites;
+
+                       /* calculate read and write bytes data */
+                       *bytes_reads += (uint32_t)psec_read * sector_size;
+                       *bytes_writes += (uint32_t)psec_write * sector_size;
+               }
+       }
+
+       goto exit;
+scan_error:
+       LOGE("scan fail\n");
+exit:
+       return;
+}
+
+static void peek_disk_stat_diff(uint32_t *reads, uint32_t *bytes_reads,
+                               uint32_t *writes, uint32_t *bytes_writes)
+{
+       static uint32_t reads_old;
+       static uint32_t bytes_reads_old;
+       static uint32_t writes_old;
+       static uint32_t bytes_writes_old;
+
+       uint32_t tmp;
+
+       //get cur values
+       get_disk_stat(reads, bytes_reads, writes, bytes_writes);
+
+       tmp = *reads;
+       *reads = val_diff(tmp, reads_old);
+       reads_old = tmp;
+
+       tmp = *writes;
+       *writes = val_diff(tmp, writes_old);
+       writes_old = tmp;
+
+       tmp = *bytes_reads;
+       *bytes_reads = val_diff(tmp, bytes_reads_old);
+       bytes_reads_old = tmp;
+
+       tmp = *bytes_writes;
+       *bytes_writes = val_diff(tmp, bytes_writes_old);
+       bytes_writes_old = tmp;
+
+}
+
+static float get_elapsed(void)
+{
+       static struct timeval old_time = {0, 0};
+       struct timeval current_time;
+       float elapsed;
+
+       gettimeofday(&current_time, NULL);
+       elapsed = (current_time.tv_sec - old_time.tv_sec) +
+               ((float)(current_time.tv_usec - old_time.tv_usec) / 1000000.0f);
+       old_time.tv_sec = current_time.tv_sec;
+       old_time.tv_usec = current_time.tv_usec;
+
+       return elapsed;
+}
+
+static float get_factor(float elapsed)
+{
+       return 100.0f / ((float)Hertz * elapsed * num_of_cpu);
+}
+
+static uint64_t read_int64_from_file(const char *fname)
+{
+       FILE *fp = fopen(fname, "r");
+       uint64_t value;
+       if (!fp)
+               return 0;
+       if (fscanf(fp, "%lld", &value) != 1)
+               value = 0;
+       fclose(fp);
+       return value;
+}
+
+#define swap_sysfs_relpath(x) ("/sys/kernel/debug/swap/energy/" #x)
+#define swap_read_int64(x) (read_int64_from_file(swap_sysfs_relpath(x)))
+static uint64_t get_system_lcd_energy()
+{
+       static const char *PROC_LCD_ENERGY_FILES_GLOBPATTERN =
+               "/sys/kernel/debug/swap/energy/lcd/*/system";
+       uint64_t sum_energy = 0;
+       glob_t glob_buf;
+       size_t i;
+       const int err = glob(PROC_LCD_ENERGY_FILES_GLOBPATTERN, 0,
+                            NULL, &glob_buf);
+
+       if (err) {
+               LOG_ONCE_E("Globbing for LCD failed with error %d\n", err);
+               return 0;
+       }
+
+       for (i = 0; i < glob_buf.gl_pathc; ++i)
+               sum_energy += read_int64_from_file(glob_buf.gl_pathv[i]);
+
+       globfree(&glob_buf);
+       return sum_energy;
+}
+/*
+ * Calculates difference between current and previous sample (system).
+ * Stores mutable state in static variables.
+ */
+static uint32_t pop_sys_energy_per_device(enum supported_device dev)
+{
+       static uint64_t cpu_old, flash_old, lcd_old;
+       uint64_t cpu_new, flash_new, lcd_new;
+       uint64_t cpu_diff, flash_diff, lcd_diff;
+
+       switch (dev) {
+       case DEVICE_CPU:
+               cpu_new = swap_read_int64(cpu_idle/system) +
+                       swap_read_int64(cpu_running/system);
+               cpu_diff = val_diff(cpu_new, cpu_old);
+               cpu_old = cpu_new;
+               return (uint32_t)cpu_diff;
+
+       case DEVICE_FLASH:
+               flash_new = swap_read_int64(flash_read/system) +
+                       swap_read_int64(flash_write/system);
+               flash_diff = val_diff(flash_new, flash_old);
+               flash_old = flash_new;
+               return (uint32_t)flash_diff;
+       case DEVICE_LCD:
+               lcd_new = get_system_lcd_energy();
+               lcd_diff = val_diff(lcd_new, lcd_old);
+               lcd_old = lcd_new;
+               return (uint32_t)lcd_diff;
+       default:
+               assert(0 && "Unknown device. This should not happen");
+               return -41;
+       }
+}
+
+// Calculates difference between current and previous sample (app).
+// Stores mutable state in static variables.
+static uint32_t pop_app_energy_per_device(enum supported_device dev)
+{
+       static uint64_t cpu_old, flash_old;
+       uint64_t cpu_new, flash_new;
+       uint64_t cpu_diff, flash_diff;
+
+       switch (dev) {
+       case DEVICE_CPU:
+               cpu_new = swap_read_int64(cpu_running/apps);
+               cpu_diff = val_diff(cpu_new, cpu_old);
+               cpu_old = cpu_new;
+               return (uint32_t)cpu_diff;
+       case DEVICE_FLASH:
+               flash_new = swap_read_int64(flash_read/apps) +
+                       swap_read_int64(flash_write/apps);
+               flash_diff = val_diff(flash_new, flash_old);
+               flash_old = flash_new;
+               return (uint32_t)flash_diff;
+       case DEVICE_LCD:
+               /**
+                * Per-application energy accounting
+                * is not supported for LCD.
+                */
+               return 0;
+       default:
+               assert(0 && "Unknown device. This should not happen");
+               return -41;
+       }
+}
+
+static int get_inst_pid_array(pid_t *arr, const int n)
+{
+       int pid_count = 0;
+
+       if (manager.fd.inst_tasks == NULL)
+               return 0;
+
+       rewind(manager.fd.inst_tasks);
+       fflush(manager.fd.inst_tasks);
+
+       while (fscanf(manager.fd.inst_tasks, "%lu", arr) == 1) {
+               LOGI_th_samp("PID scaned %d\n", *arr);
+               arr++;
+               pid_count++;
+       }
+
+       return pid_count;
+}
+
+static int get_other_pid_array(pid_t inst_pid[], const int inst_n, pid_t arr[],
+                              const int n)
+{
+       DIR *d = opendir("/proc");
+       struct dirent *dirent;
+       int count = 0, i = 0;
+       static char dirent_buffer[ sizeof(struct dirent) + PATH_MAX + 1 ] = {0,};
+       static struct dirent *dirent_r = (struct dirent *)dirent_buffer;
+
+       if (!d) {
+               GETSTRERROR(errno, buf);
+               LOGW("Cannot open /proc dir (%s)\n", buf);
+               return 0;
+       }
+
+       while ((readdir_r(d, dirent_r, &dirent) == 0) && dirent) {
+               if (dirent->d_type == DT_DIR) {
+                       char *tmp;
+                       pid_t pid = strtol(dirent->d_name, &tmp, 10);
+                       if (*tmp == '\0') {
+                               for (i = 0; i < inst_n; i++) {
+                                       if (inst_pid[i] == pid)
+                                               break;
+                               }
+                               if (i == inst_n || inst_n == 0)
+                                       arr[count++] = pid;
+                       }
+               }
+       }
+
+       closedir(d);
+
+       return count;
+}
+
+// return log length (>0) for normal case
+// return negative value for error
+int get_system_info(struct system_info_t *sys_info)
+{
+       static int event_num = 0;
+       uint64_t sysmemtotal = 0;
+       uint64_t sysmemused = 0;
+       int res = 0;
+       float elapsed;
+       float factor;
+       int i = 0;
+
+       LOGI_th_samp("start\n");
+
+       memset(sys_info, 0, sizeof(*sys_info));
+
+       // common (cpu, processes, memory)
+       if (IS_OPT_SET(FL_SYSTEM_CPU) ||
+           IS_OPT_SET(FL_SYSTEM_PROCESS) ||
+           IS_OPT_SET(FL_SYSTEM_PROCESSES_LOAD) ||
+           IS_OPT_SET(FL_SYSTEM_THREAD_LOAD) ||
+           IS_OPT_SET(FL_SYSTEM_MEMORY)) {
+               const int max_pid_num = 1024; /* ugly hardcode */
+               pid_t other_pidarray[max_pid_num];
+               int other_pidcount = 0;
+               pid_t inst_pidarray[max_pid_num];
+               int inst_pidcount = 0;
+
+               inst_pidcount = get_inst_pid_array(inst_pidarray,
+                                                  max_pid_num);
+               other_pidcount = get_other_pid_array(inst_pidarray,
+                                                    inst_pidcount,
+                                                    other_pidarray,
+                                                    max_pid_num);
+               LOGI_th_samp("PID count : inst %d, other %d\n", inst_pidcount,
+                            other_pidcount);
+
+               if (update_process_data(&inst_prochead, inst_pidarray,
+                                       inst_pidcount, PROCDATA_STAT, 1) < 0) {
+                       LOGE("Failed to update inst process stat data\n");
+                       goto fail_exit;
+               }
+
+               if (update_process_data(&other_prochead, other_pidarray,
+                                       other_pidcount, PROCDATA_STAT, 0) < 0) {
+                       LOGE("Failed to update other process stat data\n");
+                       goto fail_exit;
+               }
+
+               /**
+                * This position is optimized position of timestamp. Just
+                * before get system cpu data and just after get process cpu
+                * data because cpu data is changed so fast and variance is so
+                * remarkable
+                */
+               elapsed = get_elapsed(); /* DO NOT MOVE THIS SENTENCE! */
+               factor = get_factor(elapsed);
+
+               if (update_system_cpu_data(event_num) < 0) {
+                       LOGE("Failed to update system cpu data\n");
+                       goto fail_exit;
+               }
+
+               if (update_system_cpu_frequency(event_num) < 0) {
+                       LOGE("Failed to update system cpu freq data\n");
+                       goto fail_exit;
+               }
+
+               /**
+                * Memory data is changed slowly and variance is not
+                * remarkable, so memory data is less related with timestamp
+                * then cpu data
+                */
+               if (update_process_data(&inst_prochead, inst_pidarray,
+                                       inst_pidcount, PROCDATA_SMAPS, 1) < 0) {
+                       LOGE("Failed to update inst process smaps data\n");
+                       goto fail_exit;
+               }
+/*
+               if (update_process_data(&other_prochead, other_pidarray,
+                                       other_pidcount, PROCDATA_SMAPS) < 0) {
+                       LOGE("Failed to update other process smaps data\n");
+                       goto fail_exit;
+               }
+*/
+               for (i = 0; i < inst_pidcount; i++)
+                       if (update_thread_data(inst_pidarray[i]) < 0) {
+                               LOGE("Failed to update thread stat data\n");
+                               goto fail_exit;
+                       }
+
+               if (update_system_memory_data(&sysmemtotal, &sysmemused) < 0) {
+                       LOGE("Failed to update system memory data\n");
+                       goto fail_exit;
+               }
+
+               if (update_cpus_info(event_num, elapsed) < 0) {
+                       LOGE("Failed to update cpus info\n");
+                       goto fail_exit;
+               }
+
+               /* calculate process load, memory, app_cpu_usage */
+               if (fill_system_processes_info(inst_prochead, factor, sys_info,
+                                              &(sys_info->count_of_inst_processes)) < 0) {
+                       LOGE("Failed to fill processes info\n");
+                       goto fail_exit;
+               }
+
+               /* calculate process load, memory, app_cpu_usage */
+               if (fill_system_processes_info(other_prochead, factor, sys_info,
+                                              &(sys_info->count_of_other_processes)) < 0) {
+                       LOGE("Failed to fill processes info\n");
+                       goto fail_exit;
+               }
+
+               /* calculate thread load */
+               if (fill_system_threads_info(factor, sys_info) < 0) {
+                       LOGE("Failed to fill threads info\n");
+                       goto fail_exit;
+               }
+
+               if (fill_system_cpu_info(sys_info) < 0) {
+                       LOGE("Failed to fill threads info\n");
+                       goto fail_exit;
+               }
+       }
+
+       if (IS_OPT_SET(FL_SYSTEM_MEMORY))
+               sys_info->system_memory_used = sysmemused;
+
+       LOGI_th_samp("Fill result structure\n");
+
+       if (IS_OPT_SET(FL_SYSTEM_DISK)) {
+               sys_info->total_used_drive = get_total_used_drive();
+               peek_disk_stat_diff(&sys_info->disk_reads,
+                                   &sys_info->disk_bytes_read,
+                                   &sys_info->disk_writes,
+                                   &sys_info->disk_bytes_write);
+       }
+
+       if (IS_OPT_SET(FL_SYSTEM_NETWORK))
+               peek_network_stat_diff(&sys_info->network_send_size,
+                                      &sys_info->network_receive_size);
+
+       if (IS_OPT_SET(FL_SYSTEM_DEVICE)) {
+               sys_info->wifi_status = get_wifi_status();
+               sys_info->bt_status = get_bt_status();
+               sys_info->gps_status = get_gps_status();
+               sys_info->brightness_status = get_brightness_status();
+               sys_info->camera_status = get_camera_status();
+               sys_info->sound_status = get_sound_status();
+               sys_info->audio_status = get_audio_status();
+               sys_info->vibration_status = get_vibration_status();
+               sys_info->voltage_status = get_voltage_status();
+               sys_info->rssi_status = get_rssi_status();
+               sys_info->video_status = get_video_status();
+               sys_info->call_status = get_call_status();
+               sys_info->dnet_status = get_dnet_status();
+       }
+
+       if (IS_OPT_SET(FL_SYSTEM_ENERGY)) {
+               int i;
+               uint32_t energy;
+               sys_info->energy = 0;
+               for (i = 0; i != supported_devices_count; ++i) {
+                       energy = pop_sys_energy_per_device(i);
+                       sys_info->energy_per_device[i] = energy;
+                       sys_info->energy += energy;
+                       sys_info->app_energy_per_device[i] = (i == DEVICE_LCD)
+                               ? sys_info->energy_per_device[i]
+                               : pop_app_energy_per_device(i);
+               }
+       }
+
+#ifdef THREAD_SAMPLING_DEBUG
+       print_sys_info(sys_info);
+#endif
+
+       event_num++;
+       LOGI_th_samp("exit\n");
+       return res;
+
+fail_exit:
+       /* Some data corrupted. Free allocated data. */
+       reset_system_info(sys_info);
+       LOGI_th_samp("fail exit\n");
+       return -1;
+}
+
+int initialize_system_info(void)
+{
+       int i;
+
+       num_of_cpu = sysconf(_SC_NPROCESSORS_CONF);
+       if(num_of_cpu < 1)
+               num_of_cpu = 1;
+       Hertz = sysconf(_SC_CLK_TCK);
+       LOGI("Hertz : %d\n", Hertz);
+
+       // alloc for cpus
+       if(cpus == NULL)
+               cpus = (CPU_t*) calloc((num_of_cpu + 1), sizeof(CPU_t));
+       if(cpus != NULL)
+       {
+               for(i = 0; i <= num_of_cpu; i++)
+               {
+                       cpus[i].cur_load_index = cpus[i].sav_load_index = -1;
+                       cpus[i].cur_freq_index = cpus[i].sav_freq_index = -1;
+               }
+       }
+       else
+       {
+               LOGE("Failed to alloc memory for cpu information\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+int finalize_system_info(void)
+{
+       int i;
+
+       if(cpus != NULL)
+       {
+               for(i = 0; i < num_of_cpu; i++)
+               {
+                       if(cpus[i].pfreq != NULL)
+                               free(cpus[i].pfreq);
+               }
+
+               free(cpus);
+       }
+
+       return 0;
+
+}
+
+static void test_and_close(int *fd)
+{
+       if (*fd > 0)
+               close(*fd);
+       *fd = -1;
+}
+
+static void ftest_and_close(FILE **fd)
+{
+       if (*fd != NULL)
+               fclose(*fd);
+       *fd = NULL;
+}
+
+#define strr(x) #x
+#define str(x) strr(x)
+#define dtest_and_close(fd) do {LOGI("CLOSE " str(fd) "\n");test_and_close(fd);} while(0)
+#define dftest_and_close(fd) do {LOGI("CLOSE " str(fd) "\n");ftest_and_close(fd);} while(0)
+void close_system_file_descriptors(void)
+{
+       dtest_and_close(&manager.fd.brightness);
+       dtest_and_close(&manager.fd.voltage);
+       dtest_and_close(&manager.fd.procmeminfo);
+
+       dftest_and_close(&manager.fd.video);
+       dftest_and_close(&manager.fd.procstat);
+       dftest_and_close(&manager.fd.networkstat);
+       dftest_and_close(&manager.fd.diskstats);
+}
+
+int init_system_file_descriptors(void)
+{
+       //inits
+       init_brightness_status();
+       init_voltage_status();
+       init_update_system_memory_data();
+
+       init_video_status();
+       init_system_cpu_data();
+       init_network_stat();
+       init_disk_stat();
+
+       if (manager.fd.brightness < 0)
+               LOGW("brightness file not found\n");
+       if (manager.fd.voltage < 0)
+               LOGW("voltage file not found\n");
+       if (manager.fd.procmeminfo < 0)
+               LOGW("procmeminfo file not found\n");
+
+       if (manager.fd.video == NULL)
+               LOGW("video file not found\n");
+       if (manager.fd.procstat == NULL)
+               LOGW("procstat file not found\n");
+       if (manager.fd.networkstat == NULL)
+               LOGW("networkstat file not found\n");
+       if (manager.fd.diskstats == NULL)
+               LOGW("diskstat file not found\n");
+       return 0;
+}
+
+//CMD SOCKET FUNCTIONS
+int fill_target_info(struct target_info_t *target_info)
+{
+       /* system_info_get_value_bool() changes only 1 byte
+          so we need to be sure that the integer as a whole is correct */
+       target_info->bluetooth_supp = 0;
+       target_info->gps_supp = 0;
+       target_info->wifi_supp = 0;
+       target_info->camera_count = 0;
+       target_info->network_type[0] = 0;
+
+       target_info->sys_mem_size = get_system_total_memory();
+       target_info->storage_size = stat_get_storageinfo(FSINFO_TYPE_TOTAL) *
+               1024 * 1024;
+
+       target_info->bluetooth_supp = is_bluetooth_available();
+       target_info->gps_supp = is_gps_available();
+       target_info->wifi_supp = is_wifi_available();
+
+       target_info->camera_count = get_camera_count();
+
+       get_device_network_type(target_info->network_type, NWTYPE_SIZE);
+
+
+       target_info->max_brightness = get_max_brightness();
+       target_info->cpu_core_count = sysconf(_SC_NPROCESSORS_CONF);
+       return 0;
+}
+
+int sys_stat_prepare(void)
+{
+       uint32_t reads, writes, bytes_reads, bytes_writes;
+       uint32_t recv, send;
+
+       peek_disk_stat_diff(&reads, &writes, &bytes_reads, &bytes_writes);
+       peek_network_stat_diff(&recv, &send);
+
+       return 0;
+}
+
+static uint32_t msg_data_payload_length(const struct system_info_t *sys_info)
+{
+       uint32_t len = sizeof(*sys_info);
+
+       /* num_of_cpu is unknown at compile time */
+       len += 2 * num_of_cpu * sizeof(float);
+
+       /* subtract pointers */
+       len -= sizeof(sys_info->cpu_frequency) + sizeof(sys_info->cpu_load);
+
+       if (IS_OPT_SET(FL_SYSTEM_THREAD_LOAD))
+               len += sys_info->count_of_threads * sizeof(struct thread_info_t);
+
+       if (IS_OPT_SET(FL_SYSTEM_PROCESS))
+               len += sys_info->count_of_inst_processes *
+                      sizeof(struct inst_process_info_t);
+
+       if (IS_OPT_SET(FL_SYSTEM_PROCESSES_LOAD))
+               len += sys_info->count_of_other_processes *
+                      sizeof(struct other_process_info_t);
+
+       return len;
+}
+
+struct msg_data_t *pack_system_info(struct system_info_t *sys_info)
+{
+       const int len = msg_data_payload_length(sys_info) + 0x100;
+       struct msg_data_t *msg = NULL;
+       char *p = NULL;
+       procNode *proc = NULL;
+       procNode *thread_proc = NULL;
+       int i = 0;
+       int thread_count = 0;
+       char *thread_count_p;
+
+       msg = malloc(MSG_DATA_HDR_LEN + len);
+       if (!msg) {
+               LOGE("Cannot alloc message: %d bytes\n", len);
+               return NULL;
+       }
+
+       fill_data_msg_head(msg, NMSG_SYSTEM, 0, len);
+       p = msg->payload;
+
+       // CPU
+       if (IS_OPT_SET(FL_SYSTEM_CPU)) {
+               //CPU frequency
+               for (i = 0; i < num_of_cpu; i++) {
+                       if (sys_info->cpu_frequency)
+                               pack_float(p, sys_info->cpu_frequency[i]);
+                       else
+                               pack_float(p, 0.0);
+               }
+
+               //CPU load
+               for (i = 0; i < num_of_cpu; i++) {
+                       if (sys_info->cpu_load)
+                               pack_float(p, sys_info->cpu_load[i]);
+                       else
+                               pack_float(p, 0.0);
+               }
+       } else {
+               for (i = 0; i < num_of_cpu; i++) {
+                       pack_float(p, 0.0); /* pack cpu_frequency */
+                       pack_float(p, 0.0); /* pack cpu_load */
+               }
+       }
+
+       /* memory */
+       pack_int64(p, sys_info->system_memory_used);
+
+       /* inst process / target process */
+       if (IS_OPT_SET(FL_SYSTEM_PROCESS)) {
+               pack_int32(p, sys_info->count_of_inst_processes);
+               proc = inst_prochead;
+               for (i = 0; i < sys_info->count_of_inst_processes; i++) {
+                       pack_int32(p, (uint32_t)proc->proc_data.pid);
+                       pack_float(p, proc->proc_data.cpu_load);
+                       pack_int64(p, (uint64_t)proc->proc_data.vir_mem);
+                       pack_int64(p, (uint64_t)proc->proc_data.res_memblock);
+                       pack_int64(p, (uint64_t)proc->proc_data.sh_mem);
+                       pack_int64(p, (uint64_t)proc->proc_data.pss);
+
+                       /* TODO total alloc for not ld preloaded processes */
+                       pack_int64(p, target_get_total_alloc(proc->proc_data.pid));
+                       //pack threads
+
+                       if (IS_OPT_SET(FL_SYSTEM_THREAD_LOAD)) {
+                               thread_count_p = p; //save real thread_count position
+                               pack_int32(p, 0); //dummy thread_count
+                               thread_count = 0;
+                               for (thread_proc = proc->thread_prochead;
+                                    thread_proc != NULL;
+                                    thread_proc = thread_proc->next) {
+                                       thread_count++;
+                                       pack_int32(p, thread_proc->proc_data.pid);
+                                       pack_float(p, thread_proc->proc_data.cpu_load);
+                               }
+                               //pack real thread count
+                               pack_int32(thread_count_p, thread_count);
+                       } else {
+                               pack_int32(p, 0); //thread_count
+                       }
+                       proc = proc->next;
+               }
+
+       } else {
+               pack_int32(p, 0); /* pack count_of_processes */
+       }
+
+
+       /* other process */
+       if (IS_OPT_SET(FL_SYSTEM_PROCESSES_LOAD)) {
+               pack_int32(p, sys_info->count_of_other_processes);
+               proc = other_prochead;
+               for (i = 0; i < sys_info->count_of_other_processes; i++) {
+                       pack_int32(p, proc->proc_data.pid);
+                       pack_float(p, proc->proc_data.cpu_load);
+                       proc = proc->next;
+               }
+       } else {
+               pack_int32(p, 0); /* pack count_of_processes */
+       }
+
+       pack_int32(p, sys_info->total_used_drive);
+       pack_int32(p, sys_info->disk_reads);
+       pack_int32(p, sys_info->disk_bytes_read);
+       pack_int32(p, sys_info->disk_writes);
+       pack_int32(p, sys_info->disk_bytes_write);
+
+       pack_int32(p, sys_info->network_send_size);
+       pack_int32(p, sys_info->network_receive_size);
+
+       pack_int32(p, sys_info->wifi_status);
+       pack_int32(p, sys_info->bt_status);
+       pack_int32(p, sys_info->gps_status);
+       pack_int32(p, sys_info->brightness_status);
+       pack_int32(p, sys_info->camera_status);
+       pack_int32(p, sys_info->sound_status);
+       pack_int32(p, sys_info->audio_status);
+       pack_int32(p, sys_info->vibration_status);
+       pack_int32(p, sys_info->voltage_status);
+       pack_int32(p, sys_info->rssi_status);
+       pack_int32(p, sys_info->video_status);
+       pack_int32(p, sys_info->call_status);
+       pack_int32(p, sys_info->dnet_status);
+
+       pack_int32(p, sys_info->energy);
+       for (i = 0; i < supported_devices_count; i++)
+               pack_int32(p, sys_info->energy_per_device[i]);
+       for (i = 0; i < supported_devices_count; i++)
+               pack_int32(p, sys_info->app_energy_per_device[i]);
+
+       return msg;
+}
diff --git a/daemon/sys_stat.h b/daemon/sys_stat.h
new file mode 100644 (file)
index 0000000..237ecbc
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Jaewon Lim <jaewon81.lim@samsung.com>
+ * Woojin Jung <woojin2.jung@samsung.com>
+ * Juyoung Kim <j0.kim@samsung.com>
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ * Nikita Kalyazin    <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#ifndef _SYS_STAT_
+#define _SYS_STAT_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define VOLTAGEFD                                      "/sys/class/power_supply/battery/voltage_now"
+
+#define BRIGHTNESS_FILENAME                    "brightness"
+#define MAX_BRIGHTNESS_FILENAME                "max_brightness"
+#define BRIGHTNESS_PARENT_DIR          "/sys/class/backlight"
+
+#define EMUL_BRIGHTNESSFD                      "/sys/class/backlight/emulator/brightness"
+#define EMUL_MAX_BRIGHTNESSFD          "/sys/class/backlight/emulator/max_brightness"
+
+#define MFCFD                                          "/sys/devices/platform/samsung-pd.0/power/runtime_status"
+
+#define CPUDIR                                         "/sys/devices/system/cpu"
+#define CPUFREQ_FILE                           "cpufreq/stats/time_in_state"
+#define CPUNUM_OF_FREQ                         CPUDIR"/cpu0/"CPUFREQ_FILE
+
+
+#define UMSFD                                          "/mnt/ums"
+#define MMCBLKFD                                       "/dev/mmcblk1"
+#define MMCFD                                          "/mnt/mmc"
+
+#define PROCSTAT                                       "/proc/stat"
+#define PROCMEMINFO                                    "/proc/meminfo"
+
+#define FSINFO_TYPE_TOTAL                      1
+#define FSINFO_TYPE_FREE                       2
+
+#define NWTYPE_SIZE 128
+#define MAXNAMESIZE 16
+
+
+#include <stdint.h>
+#include "da_protocol.h"
+
+struct target_info_t {
+       uint64_t sys_mem_size;
+       uint64_t storage_size;
+       uint32_t bluetooth_supp;
+       uint32_t gps_supp;
+       uint32_t wifi_supp;
+       uint32_t camera_count;
+       char network_type[NWTYPE_SIZE];
+       uint32_t max_brightness;
+       uint32_t cpu_core_count;
+};
+
+int get_system_info(struct system_info_t *sys_info);
+
+int initialize_system_info(void);
+
+int finalize_system_info(void);
+
+int fill_target_info(struct target_info_t *target_info);
+
+int init_system_file_descriptors(void);
+void close_system_file_descriptors(void);
+int sys_stat_prepare(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/daemon/target.c b/daemon/target.c
new file mode 100644 (file)
index 0000000..c3fb0c0
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#define _GNU_SOURCE    /* for accept4() */
+#include <sys/socket.h>
+
+#include "target.h"
+
+#include "thread.h"
+#include "daemon.h"    // for manager (it is need delete)
+#include "smack.h"
+#include "debug.h"
+
+
+static struct target *target_malloc(void);
+static void target_free(struct target *t);
+
+struct target *target_ctor(void)
+{
+       struct target *t;
+
+       t = target_malloc();
+       if (t) {
+               t->app_type = APP_TYPE_UNKNOWN;
+               t->pid = UNKNOWN_PID;
+               t->socket = UNKNOWN_FD;
+               t->event_fd = UNKNOWN_FD;
+               t->initial_log = 0;
+               t->allocmem = 0;
+
+               t->thread = thread_ctor();
+               if (t->thread == NULL) {
+                       target_free(t);
+                       t = NULL;
+               }
+       }
+
+       return t;
+}
+
+void target_dtor(struct target *t)
+{
+       t->allocmem = 0;
+       t->initial_log = 0;
+
+       if (t->event_fd != -1)
+               close(t->event_fd);
+       t->event_fd = -1;
+
+       if (t->socket != UNKNOWN_FD)
+               close(t->socket);
+       t->socket = -1;
+
+       thread_dtor(t->thread);
+       target_free(t);
+}
+
+
+int target_accept(struct target *t, int sockfd)
+{
+       int sock;
+
+       sock = accept4(sockfd, NULL, NULL, SOCK_CLOEXEC);
+       if (sock == UNKNOWN_FD)
+               return 1;
+
+       /* accept succeed */
+       fd_setup_attributes(sock);
+
+       t->socket = sock;
+
+       return 0;
+}
+
+int target_send_msg(struct target *t, struct msg_target_t *msg)
+{
+       return send_msg_to_sock(t->socket, msg);
+}
+
+int target_recv_msg(struct target *t, struct msg_target_t *msg)
+{
+       return recv_msg_from_sock(t->socket, msg);
+}
+
+
+int target_start(struct target *t, void *(*start_routine) (void *))
+{
+       return thread_start(t->thread, start_routine, (void *)t);
+}
+
+int target_wait(struct target *t)
+{
+       return thread_wait(t->thread);
+}
+
+
+pid_t target_get_pid(struct target *t)
+{
+       return t->pid;
+}
+
+void target_set_pid(struct target *t, pid_t pid)
+{
+       t->pid = pid;
+}
+
+pid_t target_get_ppid(struct target *t)
+{
+       return t->ppid;
+}
+
+void target_set_ppid(struct target *t, pid_t ppid)
+{
+       t->ppid = ppid;
+}
+
+static int target_cnt = 0;
+static pthread_mutex_t ts_mutex = PTHREAD_MUTEX_INITIALIZER;
+static int target_use[MAX_TARGET_COUNT] = {0};
+static struct target target_array[MAX_TARGET_COUNT];
+
+static void target_array_lock(void)
+{
+       pthread_mutex_lock(&ts_mutex);
+}
+
+static void target_array_unlock(void)
+{
+       pthread_mutex_unlock(&ts_mutex);
+}
+
+static struct target *target_malloc(void)
+{
+       int i;
+       struct target *t = NULL;
+
+       target_array_lock();
+       for (i = 0; i < MAX_TARGET_COUNT; i++) {
+               if (target_use[i] == 0) {
+                       target_use[i] = 1;
+                       t = &target_array[i];
+                       break;
+               }
+       }
+       target_array_unlock();
+
+       return t;
+}
+
+static void target_free(struct target *t)
+{
+       int id = t - target_array;
+
+       target_array_lock();
+       if (target_use[id] == 0)
+               LOGE("double free t=%p\n", t);
+       target_use[id] = 0;
+       target_array_unlock();
+}
+
+
+void target_cnt_set(int cnt)
+{
+       target_cnt = cnt;
+}
+
+int target_cnt_get(void)
+{
+       return target_cnt;
+}
+
+int target_cnt_sub_and_fetch(void)
+{
+       return __sync_sub_and_fetch(&target_cnt, 1);
+}
+
+
+struct target *target_get(int i)
+{
+       return &target_array[i];
+}
+
+
+
+
+
+/*
+ * for all targets
+ */
+int target_send_msg_to_all(struct msg_target_t *msg)
+{
+       int i, ret = 0;
+       struct target *t;
+
+       target_array_lock();
+       for (i = 0; i < MAX_TARGET_COUNT; ++i) {
+               if (target_use[i] == 0)
+                       continue;
+
+               t = target_get(i);
+               if (target_send_msg(t, msg))
+                       ret = 1;
+       }
+       target_array_unlock();
+
+       return ret;
+}
+
+void target_wait_all(void)
+{
+       int i;
+       struct target *t;
+
+       target_array_lock();
+       for (i = 0; i < MAX_TARGET_COUNT; ++i) {
+               if (target_use[i] == 0)
+                       continue;
+
+               t = target_get(i);
+
+               LOGI("join recv thread [%d] is started\n", i);
+               target_wait(t);
+               LOGI("join recv thread %d. done\n", i);
+       }
+       target_array_unlock();
+}
+
+uint64_t target_get_total_alloc(pid_t pid)
+{
+       int i;
+       uint64_t ret = 0;
+       struct target *t;
+
+       target_array_lock();
+       for (i = 0; i < MAX_TARGET_COUNT; i++) {
+               if (target_use[i] == 0)
+                       continue;
+
+               t = target_get(i);
+               if (target_get_pid(t) == pid) {
+                       ret = t->allocmem;
+                       goto unlock;
+               }
+       }
+unlock:
+       target_array_unlock();
+
+       return ret;
+}
diff --git a/daemon/target.h b/daemon/target.h
new file mode 100644 (file)
index 0000000..ce0a899
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#ifndef _TARGER_H_
+#define _TARGER_H_
+
+
+#include <inttypes.h>
+#include <pthread.h>
+
+#include <Ecore.h>
+
+#include "da_protocol.h"
+
+
+#define UNKNOWN_PID            ((pid_t)(-1))
+#define UNKNOWN_FD             (-1)
+
+
+struct thread;
+
+
+struct target {
+       enum app_type_t app_type;       /* calculated when connecting */
+       int64_t allocmem;               /* written only by recv thread */
+       pid_t pid;                      /* written only by recv thread */
+       pid_t ppid;                     /* written only by recv thread */
+       int socket;                     /* written only by main thread */
+       int event_fd;                   /* for thread communication
+                                        * (from recv thread to main thread) */
+       int initial_log;                /* written only by main thread */
+       Ecore_Fd_Handler *handler;      /* calculated when connecting */
+
+       struct thread *thread;
+};
+
+
+struct target *target_ctor(void);
+void target_dtor(struct target *t);
+
+int target_accept(struct target *t, int sockfd);
+
+int target_send_msg(struct target *t, struct msg_target_t *msg);
+int target_recv_msg(struct target *t, struct msg_target_t *msg);
+
+
+int target_start(struct target *t, void *(*start_routine) (void *));
+int target_wait(struct target *t);
+
+
+pid_t target_get_pid(struct target *t);
+void target_set_pid(struct target *t, pid_t pid);
+
+pid_t target_get_ppid(struct target *t);
+void target_set_ppid(struct target *t, pid_t ppid);
+
+
+void target_cnt_set(int cnt);
+int target_cnt_get(void);
+int target_cnt_sub_and_fetch(void);
+
+struct target *target_get(int i);
+
+/* for all targets */
+int target_send_msg_to_all(struct msg_target_t *msg);
+void target_wait_all(void);
+uint64_t target_get_total_alloc(pid_t pid);
+
+
+#endif /* _TARGER_H_ */
diff --git a/daemon/thread.c b/daemon/thread.c
new file mode 100644 (file)
index 0000000..f6b8f27
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#include <pthread.h>
+#include <errno.h>
+
+
+#include "debug.h"
+
+
+struct thread {
+       pthread_t thread;
+       pthread_mutex_t mutex;
+       unsigned run_flag:1;
+};
+
+
+struct thread *thread_ctor(void)
+{
+       struct thread *t;
+
+       t = malloc(sizeof(*t));
+       if (t) {
+               t->run_flag = 0;
+               pthread_mutex_init(&t->mutex, NULL);
+       }
+
+       return t;
+}
+
+void thread_dtor(struct thread *t)
+{
+       if (t->run_flag == 1)
+               LOGE("hanging thread: t=%p\n", t);
+
+       free(t);
+}
+
+int thread_start(struct thread *t, void *(*func) (void *), void *data)
+{
+       int ret = EBUSY;
+
+       pthread_mutex_lock(&t->mutex);
+       if (t->run_flag == 0) {
+               ret = pthread_create(&t->thread, NULL, func, data);
+               if (ret == 0)
+                       t->run_flag = 1;
+       }
+       pthread_mutex_unlock(&t->mutex);
+
+       return ret;
+}
+
+int thread_wait(struct thread *t)
+{
+       int ret = ESRCH;
+
+       pthread_mutex_lock(&t->mutex);
+       if (t->run_flag == 1) {
+               ret = pthread_join(t->thread, NULL);
+               t->run_flag = 0;
+       }
+       pthread_mutex_unlock(&t->mutex);
+
+       return ret;
+}
diff --git a/daemon/thread.h b/daemon/thread.h
new file mode 100644 (file)
index 0000000..529a2ee
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Vyacheslav Cherkashin <v.cherkashin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#ifndef _THREAD_H_
+#define _THREAD_H_
+
+
+struct thread;
+
+
+struct thread *thread_ctor(void);
+void thread_dtor(struct thread *t);
+
+
+int thread_start(struct thread *t, void *(*func) (void *), void *data);
+int thread_wait(struct thread *t);
+
+
+#endif /* _THREAD_H_ */
diff --git a/daemon/threads.c b/daemon/threads.c
new file mode 100644 (file)
index 0000000..fd2c188
--- /dev/null
@@ -0,0 +1,466 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Jaewon Lim <jaewon81.lim@samsung.com>
+ * Woojin Jung <woojin2.jung@samsung.com>
+ * Juyoung Kim <j0.kim@samsung.com>
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ * Nikita Kalyazin    <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>                    // for atoi, atol
+#include <string.h>                    // for strchr
+#include <stdint.h>                    // for uint64_t
+#include <sys/types.h>         // for recv
+#include <sys/socket.h>                // for recv
+#include <sys/time.h>          // for setitimer
+#include <signal.h>                    // for sigemptyset, sigset_t, sigaddset, ...
+#include <unistd.h>                    // for write
+#include <sys/wait.h>
+
+#include "daemon.h"
+#include "utils.h"
+#include "sys_stat.h"
+
+#include "da_protocol.h"
+#include "da_data.h"
+#include "da_inst.h"
+#include "debug.h"
+#include "buffer.h"
+#include "input_events.h"
+
+static chsmack(const char *filename)
+{
+       int res = 1;
+       pid_t pid;
+       char cmd[1024];
+       int status;
+
+       pid = fork();
+       switch (pid) {
+       case -1:
+               /* fail to fork */
+               LOGE("cannot fork");
+               break;
+       case 0:
+               /* child */
+               snprintf(cmd, sizeof(cmd), "chsmack -a sdbd \"%s\"", filename);
+               execl(SHELL_CMD, SHELL_CMD, "-c", cmd, NULL);
+
+               /* exec fail */
+               LOGE("exec fail! <%s>\n", cmd);
+               break;
+       default:
+               /* parent */
+               waitpid(pid, &status, 0);
+               res = 0;
+       }
+
+       return res;
+}
+static void* recvThread(void* data)
+{
+       struct target *target = data;
+       int pass = 0;
+       uint64_t event;
+       struct msg_target_t log;
+       int err;
+
+       // initialize target variable
+       target->allocmem = 0;
+
+       for (;;) {
+               err = target_recv_msg(target, &log);
+               if ((err != 0) || (log.length >= TARGER_MSG_MAX_LEN)) {
+                       /* disconnect */
+                       event = EVENT_STOP;
+                       write(target->event_fd, &event, sizeof(event));
+                       break;
+               }
+
+               if (IS_PROBE_MSG(log.type)) {
+                       struct msg_data_t *msg_data = (struct msg_data_t *)&log;
+
+                       if (write_to_buf(msg_data) != 0)
+                               LOGE("write to buf fail\n");
+
+                       continue;
+               }
+
+               log.data[log.length] = '\0';
+               if(log.type == MSG_ALLOC)
+               {
+                       target->allocmem = str_to_int64(log.data);
+                       continue;               // don't send to host
+               }
+               else if(log.type == MSG_PID)
+               {
+                       LOGI("MSG_PID arrived (pid ppid): %s\n", log.data);
+
+                       // only when first MSG_PID is arrived
+                       if (target_get_pid(target) == UNKNOWN_PID) {
+                               int n;
+                               pid_t pid, ppid;
+
+                               n = sscanf(log.data, "%d %d", &pid, &ppid);
+                               if (n != 2)
+                               {
+                                       /**
+                                        * TODO: complain to host about wrong
+                                        * pid message send stop message to
+                                        * main thread
+                                        */
+                                       event = EVENT_STOP;
+                                       write(target->event_fd, &event,
+                                             sizeof(uint64_t));
+                                       break;
+                               }
+
+                               /* set pid and ppid */
+                               target_set_pid(target, pid);
+                               target_set_ppid(target, ppid);
+
+                               /* send event */
+                               event = EVENT_PID;
+                               write(target->event_fd, &event, sizeof(uint64_t));
+                       }
+                       send_maps_inst_msg_to(target);
+                       continue;               // don't send to host
+               }
+               else if(log.type == MSG_TERMINATE)
+               {
+                       LOGI("MSG_TERMINATE arrived: pid[%d]\n",
+                            target_get_pid(target));
+
+                       // send stop message to main thread
+                       event = EVENT_STOP;
+                       write(target->event_fd, &event,
+                             sizeof(uint64_t));
+
+                       break;
+               } else if (log.type == MSG_MSG) {
+                       // don't send to host
+                       LOGI("EXTRA '%s'\n", log.data);
+                       continue;
+               } else if (log.type == MSG_ERROR) {
+                       // don't send to host
+                       LOGE("EXTRA '%s'\n", log.data);
+                       continue;
+               } else if (log.type == MSG_WARNING) {
+                       // don't send to host
+                       LOGW("EXTRA '%s'\n", log.data);
+                       continue;
+               } else if (log.type == MSG_IMAGE) {
+                       /* need chsmak */
+                       char *file_name = log.data;
+                       LOGI("MSG_IMAGE> <%s>\n", file_name);
+
+                       if (chsmack(file_name) == 0) {
+                               /* exctract probe message */
+                               file_name += strnlen(file_name, PATH_MAX) + 1;
+                               struct msg_data_t *msg_data = (struct msg_data_t *)file_name;
+                               if (write_to_buf(msg_data) != 0)
+                                       LOGE("write to buf fail\n");
+                       } else {
+                               LOGE("chsmack fail\n");
+                       }
+
+
+                       continue;
+               }
+#ifdef PRINT_TARGET_LOG
+               else if(log.type == MSG_LOG)
+               {
+                       switch(log.data[0])
+                       {
+                               case '2':       // UI control creation log
+                               case '3':       // UI event log
+                               case '6':       // UI lifecycle log
+                               case '7':       // screenshot log
+                               case '8':       // scene transition log
+                                       LOGI("%dclass|%s\n", log.data[0] - '0', log.data);
+                                       break;
+                               default:
+                                       break;
+                       }
+               }
+               else    // not MSG_LOG and not MSG_IMAGE
+               {
+                       LOGI("Extra MSG TYPE (%d|%d|%s)\n", log.type, log.length, log.data);
+               }
+#endif
+
+               // do not send any message to host until MSG_PID message arrives
+               if(unlikely(pass == 0))
+               {
+                       while(target->initial_log == 0)
+                       {
+                               sleep(0);
+                       }
+               }
+               pass = 1;
+       }
+
+       return NULL;
+}
+
+int makeRecvThread(struct target *target)
+{
+       if (target_start(target, recvThread) < 0) {
+               LOGE("Failed to create recv thread\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+static void *samplingThread(void *data)
+{
+       int err, signo;
+       sigset_t waitsigmask;
+
+       LOGI("sampling thread started\n");
+
+       sigemptyset(&waitsigmask);
+       sigaddset(&waitsigmask, SIGALRM);
+       sigaddset(&waitsigmask, SIGUSR1);
+
+       while (1) {
+               err = sigwait(&waitsigmask, &signo);
+               if (err != 0) {
+                       LOGE("Failed to sigwait() in sampling thread\n");
+                       continue;
+               }
+
+               if (signo == SIGALRM) {
+                       struct system_info_t sys_info;
+                       struct msg_data_t *msg;
+
+                       if (get_system_info(&sys_info) == -1) {
+                               LOGE("Cannot get system info\n");
+                               //do not send sys_info because
+                               //it is corrupted
+                               continue;
+                       }
+
+                       msg = pack_system_info(&sys_info);
+                       if (!msg) {
+                               LOGE("Cannot pack system info\n");
+                               reset_system_info(&sys_info);
+                               continue;
+                       }
+
+                       if (write_to_buf(msg) != 0)
+                               LOGE("write to buf fail\n");
+
+#ifdef THREAD_SAMPLING_DEBUG
+                       printBuf((char *)msg, MSG_DATA_HDR_LEN + msg->len);
+#endif
+
+                       free_msg_data(msg);
+                       reset_system_info(&sys_info);
+                       flush_buf();
+               }
+               else if(signo == SIGUSR1)
+               {
+                       LOGI("SIGUSR1 catched\n");
+                       // end this thread
+                       break;
+               }
+               else
+               {
+                       // never happen
+                       LOGE("This should never happen in sampling thread\n");
+               }
+       }
+
+       LOGI("sampling thread ended\n");
+       return NULL;
+}
+
+// return 0 if normal case
+// return minus value if critical error
+// return plus value if non-critical error
+int samplingStart(void)
+{
+       struct itimerval timerval;
+       time_t sec = prof_session.conf.system_trace_period / 1000;
+       suseconds_t usec = prof_session.conf.system_trace_period * 1000 %
+               1000000;
+
+       if(manager.sampling_thread != -1)       // already started
+               return 1;
+
+       if (check_running_status(&prof_session) == 0) {
+               LOGI("try to start sampling when running_status is 0\n");
+               return 1;
+       }
+
+       if(pthread_create(&(manager.sampling_thread), NULL, samplingThread, NULL) < 0)
+       {
+               LOGE("Failed to create sampling thread\n");
+               return -1;
+       }
+
+       timerval.it_interval.tv_sec = sec;
+       timerval.it_interval.tv_usec = usec;
+       timerval.it_value.tv_sec = sec;
+       timerval.it_value.tv_usec = usec;
+       setitimer(ITIMER_REAL, &timerval, NULL);
+
+       return 0;
+}
+
+int samplingStop(void)
+{
+       if(manager.sampling_thread != -1)
+       {
+               struct itimerval stopval;
+
+               // stop timer
+               stopval.it_interval.tv_sec = 0;
+               stopval.it_interval.tv_usec = 0;
+               stopval.it_value.tv_sec = 0;
+               stopval.it_value.tv_usec = 0;
+               setitimer(ITIMER_REAL, &stopval, NULL);
+
+               pthread_kill(manager.sampling_thread, SIGUSR1);
+               LOGI("join sampling thread started\n");
+               pthread_join(manager.sampling_thread, NULL);
+               LOGI("join sampling thread done\n");
+
+               manager.sampling_thread = -1;
+       }
+
+       return 0;
+}
+
+static useconds_t time_diff_us(struct timeval *tv1, struct timeval *tv2)
+{
+       return (tv1->tv_sec - tv2->tv_sec) * 1000000 +
+               ((int)tv1->tv_usec - (int)tv2->tv_usec);
+}
+
+static pthread_mutex_t replay_thread_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static void exit_replay_thread()
+{
+       pthread_mutex_lock(&replay_thread_mutex);
+       manager.replay_thread = -1;
+       reset_replay_event_seq(&prof_session.replay_event_seq);
+       pthread_mutex_unlock(&replay_thread_mutex);
+}
+
+static void *replay_thread(void *arg)
+{
+       struct replay_event_seq_t *event_seq = (struct replay_event_seq_t *)arg;
+       int i = 0;
+       useconds_t ms;
+       useconds_t prev_event_offset = 0;
+
+       struct replay_event_t * pevent = NULL;
+
+       LOGI_th_rep("replay events thread started\n");
+       if (event_seq->event_num != 0)
+       {
+               pevent = event_seq->events;
+       }
+
+       for (i = 0; i < event_seq->event_num; i++) {
+               useconds_t event_offset = time_diff_us(&pevent->ev.time, &event_seq->tv);
+               if (event_offset >= prev_event_offset)
+                       ms = event_offset - prev_event_offset;
+               else
+                       ms = 0;
+
+#ifdef THREAD_REPLAY_DEBUG
+               print_replay_event(pevent, i + 1, "\t");
+#endif
+               LOGI_th_rep("%d) sleep %d\n", i, ms);
+               usleep(ms);
+
+               write_input_event(pevent->id, &pevent->ev);
+
+               prev_event_offset = event_offset;
+
+               pevent++;
+       }
+
+       LOGI("replay events thread finished\n");
+
+       exit_replay_thread();
+
+       return arg;
+}
+
+int start_replay()
+{
+       int res = 0;
+
+       pthread_mutex_lock(&replay_thread_mutex);
+
+       if (manager.replay_thread != -1) {
+               LOGI("replay already started\n");
+               res = 1;
+               goto exit;
+       }
+
+       if (pthread_create(&(manager.replay_thread),
+                          NULL,
+                          replay_thread,
+                          &prof_session.replay_event_seq) < 0)
+       {
+               LOGE("Failed to create replay thread\n");
+               res = 1;
+               goto exit;
+       }
+
+exit:
+       pthread_mutex_unlock(&replay_thread_mutex);
+       return res;
+}
+
+
+void stop_replay()
+{
+       pthread_mutex_lock(&replay_thread_mutex);
+
+       if (manager.replay_thread == -1) {
+               LOGI("replay thread not running\n");
+               goto exit;
+       }
+       LOGI("stopping replay thread\n");
+       pthread_cancel(manager.replay_thread);
+       pthread_join(manager.replay_thread, NULL);
+       manager.replay_thread = -1;
+       LOGI("replay thread joined\n");
+
+       reset_replay_event_seq(&prof_session.replay_event_seq);
+
+exit:
+       pthread_mutex_unlock(&replay_thread_mutex);
+
+}
diff --git a/daemon/threads.h b/daemon/threads.h
new file mode 100644 (file)
index 0000000..ea4a670
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Jaewon Lim <jaewon81.lim@samsung.com>
+ * Woojin Jung <woojin2.jung@samsung.com>
+ * Juyoung Kim <j0.kim@samsung.com>
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ * Nikita Kalyazin    <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#ifndef _UTILS_H_
+#define _UTILS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct target;
+
+
+int makeRecvThread(struct target *target);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/daemon/transfer_thread.c b/daemon/transfer_thread.c
new file mode 100644 (file)
index 0000000..60fd1f4
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ * Nikita Kalyazin    <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#define _GNU_SOURCE
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include "daemon.h"
+#include "buffer.h"
+#include "debug.h"
+#include "transfer_thread.h"
+
+#define BUF_SIZE 4096
+
+static void transfer_thread_cleanup(void *arg)
+{
+       int *fd_pipe;
+       fd_pipe = (int *) arg;
+
+       close(fd_pipe[0]);
+       close(fd_pipe[1]);
+
+}
+
+static void *transfer_thread(void *arg)
+{
+       (void)arg;
+       int fd_pipe[2];
+       ssize_t nrd, nwr;
+
+       //init thread
+       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
+
+       //init pipe
+       if (pipe(fd_pipe) != 0) {
+               /* TODO posible need total instrumentation stop up there */
+               LOGE("can not pipe!\n");
+               return NULL;
+       }
+
+       //set cleanup function
+       pthread_cleanup_push(transfer_thread_cleanup, (void *)fd_pipe);
+
+       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+
+       LOGI("transfer thread started\n");
+
+       while (1) {
+               nrd = splice(manager.buf_fd, NULL,
+                            fd_pipe[1], NULL,
+                            BUF_SIZE, 0);
+               if (nrd == -1) {
+                       int errsv = errno;
+                       if (errsv == EAGAIN) {
+                               LOGI("No more data to read\n");
+                               break;
+                       }
+                       GETSTRERROR(errsv, err_buf);
+                       LOGE("Cannot splice read: %s\n", err_buf);
+                       goto thread_exit;
+               }
+
+               nwr = splice(fd_pipe[0], NULL,
+                            manager.host.data_socket, NULL,
+                            nrd, 0);
+
+               if (nwr == -1) {
+                       GETSTRERROR(errno, buf);
+                       LOGE("Cannot splice write: %s\n", buf);
+                       goto thread_exit;
+               }
+               if (nwr != nrd) {
+                       LOGW("nrd - nwr = %d\n", nrd - nwr);
+               }
+       }
+
+       thread_exit:
+       pthread_cleanup_pop(1);
+
+       LOGI("transfer thread finished. return\n");
+
+       return NULL;
+}
+
+int start_transfer(void)
+{
+       int saved_flags;
+
+       if (manager.host.data_socket == -1) {
+               LOGW("won't start transfer thread: data socket isn't open\n");
+               return 0;
+       }
+
+       if (manager.transfer_thread != -1) { // already started
+               LOGW("transfer already running\n");
+               stop_transfer();
+       }
+
+       saved_flags = fcntl(manager.buf_fd, F_GETFL);
+       if (fcntl(manager.buf_fd, F_SETFL, saved_flags & ~O_NONBLOCK) == -1) {
+               LOGE("can not set buf_fd flags\n");
+               return -1;
+       }
+
+       if(pthread_create(&(manager.transfer_thread),
+                         NULL,
+                         transfer_thread,
+                         NULL) < 0)
+       {
+               LOGE("Failed to create transfer thread\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+void stop_transfer(void)
+{
+       int saved_flags;
+       int ret = 0;
+
+       if (manager.transfer_thread == -1) {
+               LOGI("transfer thread not running\n");
+               return;
+       }
+       LOGI("stopping transfer\n");
+
+       flush_buf();
+       saved_flags = fcntl(manager.buf_fd, F_GETFL);
+       if (fcntl(manager.buf_fd, F_SETFL, saved_flags | O_NONBLOCK) == -1) {
+               /* TODO do something on error */
+               LOGE("can not set buf_fd flags\n");
+       }
+       wake_up_buf();
+
+       LOGI("joining thread...\n");
+       ret = pthread_join(manager.transfer_thread, NULL);
+       if (ret != 0)
+               LOGW("pthread_join: unknown error %d\n", ret);
+
+       manager.transfer_thread = -1;
+
+       LOGI("transfer thread stoped\n");
+}
diff --git a/daemon/transfer_thread.h b/daemon/transfer_thread.h
new file mode 100644 (file)
index 0000000..55e44a0
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ * Nikita Kalyazin    <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#ifndef _TRANSFER_THREAD_
+#define _TRANSFER_THREAD_
+
+int start_transfer(void);
+void stop_transfer(void);
+
+#endif /* _TRANSFER_THREAD_ */
diff --git a/daemon/utils.c b/daemon/utils.c
new file mode 100644 (file)
index 0000000..2dbefae
--- /dev/null
@@ -0,0 +1,473 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Jaewon Lim <jaewon81.lim@samsung.com>
+ * Woojin Jung <woojin2.jung@samsung.com>
+ * Juyoung Kim <j0.kim@samsung.com>
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ * Nikita Kalyazin    <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <signal.h>                    // for signal
+#include <pthread.h>
+#include <unistd.h>            // for unlink
+#include <dirent.h>            // for opendir, readdir
+#include <sys/types.h> // for open
+#include <sys/stat.h>  // for open
+#include <fcntl.h>             // for open
+#include <grp.h>               // for setgroups
+#include <sys/wait.h> /* waitpid */
+
+#include "daemon.h"
+#include "utils.h"
+#include "smack.h"
+#include "debug.h"
+
+#define BUFFER_MAX                     1024
+#define SID_APP                                5000
+#define MANIFEST_PATH          "/info/manifest.xml"
+
+#define PROC_FS                        "/proc"
+#define PROC_CMDLINE           "/proc/%s/cmdline"
+
+#define APPDIR1                                "/opt/apps/"
+#define APPDIR2                                "/opt/usr/apps/"
+
+uint64_t str_to_uint64(char* str)
+{
+       uint64_t res = 0;
+
+       if(str != NULL)
+       {
+               while(*str >= '0' && *str <= '9')
+               {
+                       res = res * 10 + (*str - '0');
+                       str++;
+               }
+       }
+
+       return res;
+}
+
+int64_t str_to_int64(char* str)
+{
+       int64_t res = 0;
+       int64_t factor = 1;
+
+       if(str != NULL)
+       {
+               if(*str == '-')
+               {
+                       factor = -1;
+                       str++;
+               }
+               else if(*str == '+')
+               {
+                       factor = 1;
+                       str++;
+               }
+
+               while(*str >= '0' && *str <= '9')
+               {
+                       res = res * 10 + (*str - '0');
+                       str++;
+               }
+       }
+
+       return (res * factor);
+}
+
+// return 0 if succeed
+// return -1 if error occured
+int remove_indir(const char *dirname)
+{
+       DIR *dir;
+       struct dirent *entry;
+       static char dirent_buffer[ sizeof(struct dirent) + PATH_MAX + 1 ] = {0,};
+       static struct dirent *dirent_r = (struct dirent *)dirent_buffer;
+       char path[PATH_MAX];
+
+       dir = opendir(dirname);
+       if(dir == NULL)
+       {
+               return -1;
+       }
+
+       while ((readdir_r(dir, dirent_r, &entry) == 0) && entry) {
+               if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, ".."))
+               {
+                       snprintf(path, (size_t) PATH_MAX, "%s/%s", dirname, entry->d_name);
+                       if (entry->d_type != DT_DIR)    // file
+                       {
+                               unlink(path);
+                       }
+                       else { }        // directory
+               }
+       }
+       closedir(dir);
+
+       return 0;
+}
+
+/* execute applcation with executable binary path */
+int exec_app_tizen(const char *app_id, const char *exec_path)
+{
+       pid_t pid;
+
+       LOGI("exec %s\n", exec_path);
+
+       if (exec_path == NULL || !strlen(exec_path)) {
+               LOGE("Executable path is not correct\n");
+               return -1;
+       }
+       LOGI("launch app path is %s, executable path is %s\n"
+            "launch app name (%s), app_id (%s)\n",
+            LAUNCH_APP_PATH, exec_path, LAUNCH_APP_NAME, app_id);
+       pid = fork();
+       if (pid == -1)
+               return -1;
+
+       if (pid > 0) { /* parent */
+               int status, ret;
+               do
+                       ret = waitpid(pid, &status, 0);
+               while (ret == -1 && errno == EINTR);
+               return 0;
+       } else { /* child */
+               execl(LAUNCH_APP_PATH, LAUNCH_APP_NAME, app_id, LAUNCH_APP_SDK,
+                     DA_PRELOAD_EXEC, NULL);
+               /* FIXME: If code flows here, it deserves greater attention */
+               _Exit(EXIT_FAILURE);
+       }
+}
+
+int exec_app_common(const char* exec_path)
+{
+       pid_t pid;
+       char command[PATH_MAX];
+
+       LOGI("exec %s\n", exec_path);
+       if (exec_path == NULL || !strlen(exec_path)) {
+               LOGE("Executable path is not correct\n");
+               return -1;
+       }
+
+       snprintf(command, sizeof(command), "%s %s", DA_PRELOAD_TIZEN, exec_path);
+       LOGI("cmd: %s\n", command);
+
+       pid = fork();
+       if (pid == -1)
+               return -1;
+
+       if (pid > 0) { /* parent */
+               return 0;
+       } else { /* child */
+               execl(SHELL_CMD, SHELL_CMD, "-c", command, NULL);
+               /* FIXME: Again, such case deserve much more attention */
+               _Exit(EXIT_FAILURE);
+       }
+}
+
+int exec_app_web(const char *app_id)
+{
+       pid_t pid;
+
+       LOGI("wrt-launcher path is %s,\n"
+            "wrt-launcher name (%s), app_id (%s)\n",
+            WRT_LAUNCHER_PATH, WRT_LAUNCHER_NAME, app_id);
+
+       pid = fork();
+       if (pid == -1)
+               return -1;
+
+       if (pid > 0) { /* parent */
+               int status, ret;
+               do
+                       ret = waitpid(pid, &status, 0);
+               while (ret == -1 && errno == EINTR);
+               return 0;
+       } else { /* child */
+               execl(WRT_LAUNCHER_PATH,
+                     WRT_LAUNCHER_NAME,
+                     WRT_LAUNCHER_START,
+                     app_id,
+                     NULL);
+               /* FIXME: If code flows here, it deserves greater attention */
+               LOGE("Cannot run exec!\n");
+               _Exit(EXIT_FAILURE);
+       }
+}
+
+void kill_app_web(const char *app_id)
+{
+       pid_t pid;
+
+       LOGI("wrt-launcher path is %s,\n"
+            "wrt-launcher name (%s), app_id (%s)\n",
+            WRT_LAUNCHER_PATH, WRT_LAUNCHER_NAME, app_id);
+
+       pid = fork();
+       if (pid == -1)
+               return;
+
+       if (pid > 0) { /* parent */
+               int status, ret;
+               do
+                       ret = waitpid(pid, &status, 0);
+               while (ret == -1 && errno == EINTR);
+               return;
+       } else { /* child */
+               execl(WRT_LAUNCHER_PATH,
+                     WRT_LAUNCHER_NAME,
+                     WRT_LAUNCHER_KILL,
+                     app_id,
+                     NULL);
+               /* FIXME: If code flows here, it deserves greater attention */
+               LOGE("Cannot run exec!\n");
+               _Exit(EXIT_FAILURE);
+       }
+}
+
+// find process id from executable binary path
+static pid_t find_pid_from_path(const char *path)
+{
+       char buf[BUFFER_MAX];
+       char cmdline[PATH_MAX];
+       DIR *proc;
+       FILE *fp;
+       static char dirent_buffer[ sizeof(struct dirent) + PATH_MAX + 1 ] = {0,};
+       static struct dirent *dirent_r = (struct dirent *)dirent_buffer;
+       struct dirent *entry;
+       int found, len = strlen(path);
+       pid_t pid = 0;
+
+       LOGI("look for <%s>\n", path);
+
+       proc = opendir(PROC_FS);
+       if (!proc)
+               goto out;
+
+       while ((readdir_r(proc, dirent_r, &entry) == 0) && entry) {
+               pid = (pid_t)atoi(entry->d_name);
+               if (pid == 0)
+                       continue;
+
+               snprintf(cmdline, sizeof(cmdline), PROC_CMDLINE, entry->d_name);
+
+               fp = fopen(cmdline, "r");
+               if (fp == NULL)
+                       continue;
+
+               found = 0;
+               if (fscanf(fp, "%s", buf) != EOF) /* read only argv[0] */
+                       found = (strncmp(path, buf, len) == 0);
+
+               fclose(fp);
+
+               if (found)
+                       goto out_close_dir;
+       }
+
+       pid = 0;
+
+out_close_dir:
+       closedir(proc);
+
+out:
+       return pid;
+}
+
+static pid_t get_pid_by_path(const char *binary_path)
+{
+       pid_t pkg_pid;
+       int len;
+       char *real_path;
+       static const char exe_line[] = ".exe";
+
+
+       pkg_pid = find_pid_from_path(binary_path);
+       if (pkg_pid == 0) {
+               len = strlen(binary_path);
+               real_path = malloc(len + sizeof(exe_line));
+               if (real_path == NULL) {
+                       LOGE("cannot alloc memory\n");
+                       return -1;
+               }
+               memcpy(real_path, binary_path, len + 1);
+
+               // try remove or add ".exe" and get pid
+               if (strcmp(real_path + len - (sizeof(exe_line) - 1), exe_line) == 0)
+                       // remove .exe from tPath
+                       real_path[len - (sizeof(exe_line) - 1)] = '\0';
+               else
+                       // add .exe
+                       memcpy(&real_path[len], exe_line, sizeof(exe_line));
+
+               pkg_pid = find_pid_from_path(real_path);
+               free(real_path);
+       }
+
+       return pkg_pid;
+}
+
+static int find_alternative_bin_path(const char *binary_path, char *alter_bin_path,
+          size_t  buflen)
+{
+       // alternative path may be /opt/apps/... or /opt/usr/apps/...)
+       char *add_fname;
+       char *p;
+       if (strncmp(binary_path, APPDIR1, strlen(APPDIR1)) == 0) {
+               strncpy(alter_bin_path, APPDIR2, buflen);
+               buflen -= strlen(alter_bin_path);
+               add_fname = binary_path + strlen(APPDIR1);
+               strncat(alter_bin_path, add_fname, buflen);
+       } else if (strncmp(binary_path, APPDIR2, strlen(APPDIR2)) == 0) {
+               strncpy(alter_bin_path, APPDIR1, buflen);
+               buflen -= strlen(alter_bin_path);
+               add_fname = binary_path + strlen(APPDIR2);
+               strncat(alter_bin_path, add_fname, buflen);
+       } else {
+               return 1;
+       }
+       return 0;
+}
+
+int kill_app(const char *binary_path)
+{
+       pid_t pkg_pid;
+       char alter_bin_path[PATH_MAX];
+
+       LOGI("kill %s (%d)\n", binary_path, SIGKILL);
+
+       pkg_pid = get_pid_by_path(binary_path);
+
+       if (pkg_pid == 0) {
+               if (find_alternative_bin_path(binary_path, alter_bin_path, PATH_MAX) == 0)
+                       pkg_pid = get_pid_by_path(alter_bin_path);
+       }
+
+       if (pkg_pid != 0) {
+               if (kill(pkg_pid, SIGTERM) == -1) {
+                       GETSTRERROR(errno, err_buf);
+                       LOGE("cannot kill %d -%d errno<%s>\n", pkg_pid, SIGKILL,
+                            err_buf);
+                       return -1;
+               } else {
+                       // we need sleep up there because kill() function
+                       // returns control immediately after send signal
+                       // without it app_launch returns err on start app
+                       sleep(1);
+                       LOGI("killed %d -%d\n", pkg_pid, SIGKILL);
+               }
+       } else
+               LOGI("cannot kill <%s>; process not found\n", binary_path);
+
+       return 0;
+}
+
+static char *dereference_tizen_exe_path(const char *path, char *resolved);
+
+int is_same_app_process(char* appPath, int pid)
+{
+       int ret = 0;
+       int tlen;
+       FILE *fp;
+       char buf[BUFFER_MAX];
+       char cmdPath[PATH_MAX];
+       char tPath[PATH_MAX];
+       char buf_res[PATH_MAX];
+       char tPath_res[PATH_MAX];
+
+       strncpy(tPath, appPath, PATH_MAX - 1);
+       tlen = strlen(tPath);
+       if(strcmp(tPath + tlen - 4, ".exe") == 0)
+       {
+               // remove .exe from tPath
+               tPath[tlen - 4] = '\0';
+       }
+
+       snprintf(cmdPath, sizeof(cmdPath), "/proc/%d/cmdline", pid);
+
+       if((fp = fopen(cmdPath, "r")) == NULL)
+       {
+               return 0;
+       }
+
+       if(fgets(buf, BUFFER_MAX, fp) != NULL)
+       {
+               tlen = strlen(buf);
+               if(strcmp(buf + tlen - 4, ".exe") == 0)
+               {
+                       // remove .exe from tPath
+                       buf[tlen - 4] = '\0';
+               }
+
+               dereference_tizen_exe_path(buf, buf_res);
+               dereference_tizen_exe_path(tPath, tPath_res);
+
+               if(strcmp(buf_res, tPath_res) == 0)
+                       ret = 1;
+               else
+                       ret = 0;
+       }
+       fclose(fp);
+
+       return ret;
+}
+
+static char *dereference_tizen_exe_path(const char *path, char *resolved)
+{
+       char *res = NULL;
+       char tmp_path[PATH_MAX];
+
+       resolved[0] = 0;
+       //try resolve <path>.exe
+       snprintf(tmp_path, sizeof(tmp_path), "%s.exe", path);
+       if ((res = realpath(tmp_path, resolved)) == NULL) {
+               //try to resolve path <path>
+               res = realpath(path, resolved);
+       }
+
+       return res;
+}
+
+float get_uptime(void)
+{
+       const char *LINUX_UPTIME_FILE = "/proc/uptime";
+       FILE *fp = fopen(LINUX_UPTIME_FILE, "r");
+       float uptime;
+       if (!fp)
+               return 0.0;
+
+       if (fscanf(fp, "%f", &uptime) != 1)
+               uptime = 0.0;
+
+       fclose(fp);
+       return uptime;
+}
diff --git a/daemon/utils.h b/daemon/utils.h
new file mode 100644 (file)
index 0000000..c401611
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Jaewon Lim <jaewon81.lim@samsung.com>
+ * Woojin Jung <woojin2.jung@samsung.com>
+ * Juyoung Kim <j0.kim@samsung.com>
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ * Nikita Kalyazin    <n.kalyazin@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#ifndef _UTILS_H_
+#define _UTILS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LAUNCH_APP_PATH                        "/usr/bin/launch_app"
+#define DEBUG_LAUNCH_PRELOAD_PATH      "/usr/bin/debug_launchpad_preloading_preinitializing_daemon"
+#define LAUNCH_APP_NAME                        "launch_app"
+#define WRT_LAUNCHER_PATH              "/usr/bin/wrt-launcher"
+#define WRT_LAUNCHER_NAME              "wrt-launcher"
+#define WRT_LAUNCHER_START             "-s"
+#define WRT_LAUNCHER_KILL              "-k"
+#define LAUNCH_APP_SDK                 "__AUL_SDK__"
+#define DA_PRELOAD_EXEC                        "DYNAMIC_ANALYSIS"
+#define DA_PRELOAD_TIZEN               "LD_PRELOAD=/usr/lib/da_probe_tizen.so"
+#define SHELL_CMD                              "/bin/sh"
+
+
+uint64_t       str_to_uint64(char* str);
+int64_t                str_to_int64(char* str);
+
+int remove_indir(const char *dirname);
+
+int kill_app(const char *binary_path);
+
+int is_same_app_process(char* appPath, int pid);
+
+int exec_app_tizen(const char *app_id, const char *exec_path);
+int exec_app_common(const char* exec_path);
+int exec_app_web(const char *app_id);
+void kill_app_web(const char *app_id);
+float get_uptime(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/packaging/swap-manager.spec b/packaging/swap-manager.spec
new file mode 100644 (file)
index 0000000..ede1927
--- /dev/null
@@ -0,0 +1,50 @@
+Name:       swap-manager
+Summary:    SWAP manager
+Version:    3.0
+Release:    1
+Group:      System/Libraries
+License:       Apache License, Version 2
+Source:    %{name}_%{version}.tar.gz
+BuildRequires:  smack-devel
+BuildRequires:  libattr-devel
+BuildRequires:  glib2-devel
+BuildRequires:  aul-devel
+BuildRequires:  vconf-devel
+BuildRequires:  capi-system-info-devel
+BuildRequires:  capi-system-runtime-info-devel
+BuildRequires:  pkgconfig(ecore)
+%ifarch %{arm}
+%else
+Requires:  swap-modules
+%endif
+Requires:  swap-probe
+Requires:  sdbd
+
+%description
+SWAP manager is a part of data collection back-end for DA.
+This binary will be installed in target.
+
+%prep
+%setup -q -n %{name}_%{version}
+
+%build
+cd daemon
+make
+
+%install
+rm -rf ${RPM_BUILD_ROOT}
+mkdir -p %{buildroot}/usr/share/license
+cp LICENSE %{buildroot}/usr/share/license/%{name}
+cd daemon
+%make_install
+
+%files
+/usr/share/license/%{name}
+%manifest swap-manager.manifest
+%defattr(-,root,root,-)
+%{_prefix}/bin/da_manager
+/opt/swap/sdk/start.sh
+/opt/swap/sdk/stop.sh
+
+%changelog
+
diff --git a/swap-manager.manifest b/swap-manager.manifest
new file mode 100644 (file)
index 0000000..4321b7c
--- /dev/null
@@ -0,0 +1,13 @@
+<manifest>
+       <define>
+               <domain name="swap" />
+    <permit>
+               <smack permit="system::use_internet" type="rw" />
+               <smack permit="system::debugging_network" type="rw" />
+               <smack permit="sdbd" type="rw" />
+    </permit>
+       </define>
+       <request>
+               <domain name="swap" />
+       </request>
+</manifest>