--- /dev/null
+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>
--- /dev/null
+ 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
--- /dev/null
+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.
+
--- /dev/null
+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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+/*
+ * 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);
+};
--- /dev/null
+/*
+ * 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_
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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");
+ }
+}
--- /dev/null
+/*
+ * 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__*/
--- /dev/null
+/*
+ * 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
+ );
+}
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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);
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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_
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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_
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+/*
+ * 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");
+}
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+/*
+ * 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';
+}
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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);
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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__ */
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+
+#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 */
--- /dev/null
+#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__ */
--- /dev/null
+/*
+ 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));
+}
--- /dev/null
+/*
+ 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 */
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+#!/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
--- /dev/null
+#!/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
+
+
+
+
+
+
+
+
+
--- /dev/null
+/*
+ * 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(¤t_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;
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+/*
+ * 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);
+
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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");
+}
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+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
+
--- /dev/null
+<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>