[FEATURE] start ui viewer implementation 85/42785/79 SRR_20160331
authorAnastasia Lyupa <a.lyupa@samsung.com>
Thu, 2 Jul 2015 08:41:57 +0000 (11:41 +0300)
committerAlexander Aksenov <a.aksenov@samsung.com>
Tue, 1 Mar 2016 11:38:03 +0000 (14:38 +0300)
current protocol version : v0.6

add ui viewer lib files,
build it with da_manager,
set up connection with da_manager,
get ui hierarchy,
get ui properties for an object,
get ui rendering time

Change-Id: I5dd5fd22126fdc9dfc0faa4ca50ea1275c28fcb1
Signed-off-by: Anastasia Lyupa <a.lyupa@samsung.com>
23 files changed:
daemon/Makefile
daemon/da_msg_ids.h
daemon/da_protocol.c
daemon/da_protocol.h
daemon/daemon.c
daemon/daemon.h
daemon/main.c
daemon/target.c
daemon/target.h
daemon/threads.c
daemon/ui_viewer.c [new file with mode: 0644]
daemon/ui_viewer.h [new file with mode: 0644]
daemon/utils.c
packaging/swap-manager.spec
scripts/gen_preload_header.sh
ui_viewer/Makefile [new file with mode: 0644]
ui_viewer/ui_viewer_data.c [new file with mode: 0644]
ui_viewer/ui_viewer_data.h [new file with mode: 0644]
ui_viewer/ui_viewer_lib.c [new file with mode: 0644]
ui_viewer/ui_viewer_lib.h [new file with mode: 0644]
ui_viewer/ui_viewer_screenshot.c [new file with mode: 0644]
ui_viewer/ui_viewer_utils.c [new file with mode: 0644]
ui_viewer/ui_viewer_utils.h [new file with mode: 0644]

index ba5ef98..5d61d14 100644 (file)
@@ -26,7 +26,8 @@ INCLUDE := \
        -I/usr/include/eina-1/eina \
        -I/usr/include/efl-1 \
        -I/usr/include/json-c \
-       -I/usr/include/eo-1
+       -I/usr/include/eo-1 \
+       -I/usr/include/evas-1
 # CALL_MNGR
 ifeq ($(CALL_MNGR),y)
 INCLUDE += -I/usr/include/call-manager/
@@ -110,7 +111,8 @@ SRC_C := \
        malloc_debug.c \
        target.c \
        thread.c \
-       wsi.c
+       wsi.c \
+       ui_viewer.c
 
 SRC_CPP := \
        cpp/features/feature.cpp \
index 4dfd74c..bd29d30 100644 (file)
@@ -38,6 +38,9 @@ X(NMSG_GET_PROBE_MAP,         0x000A) \
 X(NMSG_KEEP_ALIVE,             0x000F) \
 X(NMSG_GET_SCREENSHOT,         0x0010) \
 X(NMSG_GET_PROCESS_ADD_INFO,   0x0011) \
+X(NMSG_GET_UI_HIERARCHY,       0x0012) \
+X(NMSG_GET_UI_SCREENSHOT,      0x0013) \
+X(NMSG_GET_UI_HIERARCHY_CANCEL,        0x0014) \
 X(NMSG_GET_REAL_PATH,          0x0020)
 
 #define DATA_MSG_ID_LIST \
@@ -52,4 +55,5 @@ X(NMSG_FUNCTION_ENTRY,                0x0008) /* N    irregular       swap instrumentation, Instrumente
 X(NMSG_FUNCTION_EXIT,          0x0009) /* N    irregular       swap instrumentation, Instrumented functions by AppInst and LibInst */ \
 X(NMSG_CONTEXT_SWITCH_ENTRY,   0x0010) /* N    irregular       swap instrumentation for kernel */ \
 X(NMSG_CONTEXT_SWITCH_EXIT,    0x0011) /* N    irregular       swap instrumentation for kernel */ \
+X(NMSG_UI_HIERARCHY,           0x0021) /* N    irregular       ui hierarchy */
 
index 43b51c0..8689481 100644 (file)
@@ -142,6 +142,12 @@ static char *msgErrStr(enum ErrorCode err)
                return "wrong message data";
        case ERR_CANNOT_START_PROFILING:
                return "cannot start profiling";
+       case ERR_UI_OBJ_NOT_FOUND:
+               return "requested ui object is not found";
+       case ERR_UI_OBJ_SCREENSHOT_FAILED:
+               return "taking ui screenshot failed because App is in background";
+       case ERR_NOT_SUPPORTED:
+               return "request not supported by security reason";
        case ERR_SERV_SOCK_CREATE:
                return "server socket creation failed (written in /tmp/da.port file)";
        case ERR_SERV_SOCK_BIND:
@@ -207,6 +213,7 @@ void feature_code_str(uint64_t feature0, uint64_t feature1, char *to,
        print_feature_0(FL_WEB_PROFILING);
        print_feature_0(FL_WEB_STARTUP_PROFILING);
        print_feature_0(FL_SYSTEM_FILE_ACTIVITY);
+       print_feature_0(FL_UI_VIEWER_PROFILING);
 
        goto exit;
 err_exit:
@@ -1342,6 +1349,90 @@ exit:
        return -(error_code != ERR_NO);
 }
 
+static int process_msg_get_ui_hierarchy(struct msg_buf_t *msg)
+{
+       struct msg_target_t sendlog;
+       enum ErrorCode err_code = ERR_UNKNOWN;
+       uint8_t rendering;
+
+       // get rendering time option
+       if (!parse_int8(msg, &rendering)) {
+               LOGE("NMSG_GET_UI_HIERARCHY error: No rendering time option\n");
+               err_code = ERR_WRONG_MESSAGE_DATA;
+               goto send_fail;
+       }
+
+       // send ui hierarchy request to target process
+       sendlog.type = APP_MSG_GET_UI_HIERARCHY;
+       *(uint8_t *)sendlog.data = rendering;
+       sendlog.length = sizeof(uint8_t);
+
+       if (target_send_msg_to_all(&sendlog) == 0)
+               err_code = ERR_NO;
+
+       if (!is_feature_enabled(FL_UI_VIEWER_PROFILING) ||
+           (target_cnt_get() == 0))
+               err_code = ERR_UNKNOWN;
+send_fail:
+       // in case of success we send ack after a message from ui viewer lib
+       if (err_code != ERR_NO)
+               sendACKToHost(NMSG_GET_UI_HIERARCHY, err_code, 0, 0);
+
+       return -(err_code != ERR_NO);
+}
+
+static int process_msg_get_ui_hierarchy_cancel(void)
+{
+       struct msg_target_t sendlog;
+       enum ErrorCode err_code = ERR_UNKNOWN;
+
+       // send ui hierarchy request to target process
+       sendlog.type = APP_MSG_GET_UI_HIERARCHY_CANCEL;
+
+       if (target_send_msg_to_all(&sendlog) == 0)
+               err_code = ERR_NO;
+
+       if (!is_feature_enabled(FL_UI_VIEWER_PROFILING) ||
+           (target_cnt_get() == 0))
+               err_code = ERR_UNKNOWN;
+
+       sendACKToHost(NMSG_GET_UI_HIERARCHY_CANCEL, err_code, 0, 0);
+
+       return -(err_code != ERR_NO);
+}
+
+static int process_msg_get_ui_screenshot(struct msg_buf_t *msg)
+{
+       struct msg_target_t sendlog;
+       enum ErrorCode err_code = ERR_UNKNOWN;
+       uint64_t obj_id;
+
+       // get ui object address
+       if (!parse_int64(msg, &obj_id)) {
+               LOGE("NMSG_GET_UI_PROPERTIES error: No object id\n");
+               err_code = ERR_WRONG_MESSAGE_DATA;
+               goto send_fail;
+       }
+
+       // send ui object properties request to target process
+       sendlog.type = APP_MSG_GET_UI_SCREENSHOT;
+       *(uint64_t *)sendlog.data = obj_id;
+       sendlog.length = sizeof(uint64_t);
+
+       if (target_send_msg_to_all(&sendlog) == 0)
+               err_code = ERR_NO;
+
+       if (!is_feature_enabled(FL_UI_VIEWER_PROFILING) ||
+           (target_cnt_get() == 0))
+               err_code = ERR_UNKNOWN;
+
+send_fail:
+       // in case of success we send ack after a message from ui viewer lib
+       if (err_code != ERR_NO)
+               sendACKToHost(NMSG_GET_UI_SCREENSHOT, err_code, 0, 0);
+
+       return -(err_code != ERR_NO);
+}
 
 int host_message_handler(struct msg_t *msg)
 {
@@ -1473,6 +1564,12 @@ int host_message_handler(struct msg_t *msg)
                return process_msg_get_process_add_info(&msg_control);
        case NMSG_GET_REAL_PATH:
                return process_msg_get_real_path(&msg_control);
+       case NMSG_GET_UI_HIERARCHY:
+               return process_msg_get_ui_hierarchy(&msg_control);
+       case NMSG_GET_UI_HIERARCHY_CANCEL:
+               return process_msg_get_ui_hierarchy_cancel();
+       case NMSG_GET_UI_SCREENSHOT:
+               return process_msg_get_ui_screenshot(&msg_control);
        default:
                LOGE("unknown message %d <0x%08X>\n", msg->id, msg->id);
                error_code = ERR_WRONG_MESSAGE_TYPE;
index fb927ee..15193d4 100644 (file)
@@ -67,26 +67,29 @@ enum DataMessageT {
 #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_TO_LONG_MESSAGE                     = -205, /* message is too long to process */
-       ERR_TARGET_NOT_FOUND                    = -206, /* some target in message not found like file or some else */
-       ERR_NOT_SUPPORTED                       = -207, /* request not supported by security reason */
-       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 */
+       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_UI_TARGET_SERVER_SOCKET_CREATE_FAILED       = -107, /* ui 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_TO_LONG_MESSAGE                             = -205, /* message is too long to process */
+       ERR_TARGET_NOT_FOUND                            = -206, /* some target in message not found like file or some else */
+       ERR_UI_OBJ_NOT_FOUND                            = -207, /* requested ui object is not found */
+       ERR_UI_OBJ_SCREENSHOT_FAILED                    = -208, /* taking ui screenshot failed because App is in background */
+       ERR_NOT_SUPPORTED                               = -800, /* request not supported by security reason */
+       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)
@@ -140,7 +143,9 @@ enum feature_code{
 
        FL_SYSTEM_FILE_ACTIVITY         = 0x1000000000000ULL, // 0x1 * 0x10^12 function entry/exit for probe type 04 (File syscall)
 
-       FL_RESERVED4                    = 0xe000000000000ULL, // reserved 1110
+       FL_UI_VIEWER_PROFILING          = 0x2000000000000ULL, // 0x2 * 0x10^12 load ui viewer library
+
+       FL_RESERVED4                    = 0xc000000000000ULL, // reserved 1110
 
        FL_ALL_FEATURES                 = 0x7FFFFFFFFFFFFULL &
                                          (~FL_RESERVED1) &
index a54b155..1395129 100644 (file)
@@ -62,6 +62,7 @@
 #include "smack.h"
 #include "swap_debug.h"
 #include "wsi.h"
+#include "ui_viewer.h"
 
 #define DA_WORK_DIR                    "/home/developer/sdk_tools/da/"
 #define DA_READELF_PATH                        "/home/developer/sdk_tools/da/readelf"
@@ -231,6 +232,7 @@ static int kill_app_by_info(const struct app_info_t *app_info)
 static int exec_app(const struct app_info_t *app_info)
 {
        int res = 0;
+       const char ui_viewer_log[] = "/tmp/uilib.log";
 
        if (app_info == NULL) {
                LOGE("Cannot exec app. app_info is NULL");
@@ -239,6 +241,19 @@ static int exec_app(const struct app_info_t *app_info)
 
        switch (app_info->app_type) {
        case APP_TYPE_TIZEN:
+               if (is_feature_enabled(FL_UI_VIEWER_PROFILING)) {
+                       if (ui_viewer_set_smack_rules(app_info)) {
+                               LOGE("Cannot set smack rules for ui viewer\n");
+                               res = -1;
+                       }
+                       if (ui_viewer_set_app_info(app_info)) {
+                               LOGE("Cannot set app info for ui viewer\n");
+                               res = -1;
+                       }
+               }
+               if (access(ui_viewer_log, F_OK) != -1) {
+                       remove(ui_viewer_log);
+               }
                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;
@@ -334,6 +349,32 @@ static void terminate_error(char *errstr, int send_to_host)
        terminate_all();
 }
 
+void restart_all(void)
+{
+       struct app_list_t *app = NULL;
+       const struct app_info_t *app_info = NULL;
+
+       LOGI("Restart all profiled apps\n");
+
+       terminate_all_target();
+       target_stop_all();
+       target_wait_all();
+       terminate_profiling_apps();
+
+       // exec all
+       app_info = app_info_get_first(&app);
+       if (app_info == NULL) {
+               LOGE("No app info found\n");
+               return;
+       }
+       while (app_info != NULL) {
+               if (exec_app(app_info)) {
+                       LOGE("Cannot exec app\n");
+               }
+               app_info = app_info_get_next(&app);
+       }
+}
+
 static Ecore_Fd_Handler *connect_timer_handler;
 
 static Eina_Bool connect_timer_cb(void *data, Ecore_Fd_Handler *fd_handler)
@@ -728,7 +769,7 @@ static Eina_Bool target_event_cb(void *data, Ecore_Fd_Handler *fd_handler)
  * return plus value if non critical error occur
  * return minus value if critical error occur
  */
-static int targetServerHandler(void)
+static int targetServerHandler(bool is_probe_sock)
 {
        int err;
        struct msg_target_t log;
@@ -740,7 +781,11 @@ static int targetServerHandler(void)
                return 1;
        }
 
-       err = target_accept(target, manager.target_server_socket);
+       if (is_probe_sock)
+               err = target_accept(target, manager.target_server_socket);
+       else
+               err = target_accept(target, manager.ui_target_server_socket);
+
        if (err == 0) {
                /* send config message to target process */
                log.type = APP_MSG_CONFIG;
@@ -1015,6 +1060,7 @@ static int hostServerHandler(void)
 
 static Ecore_Fd_Handler *host_connect_handler;
 static Ecore_Fd_Handler *target_connect_handler;
+static Ecore_Fd_Handler *ui_target_connect_handler;
 
 static Eina_Bool host_connect_cb(void *data, Ecore_Fd_Handler *fd_handler)
 {
@@ -1029,7 +1075,9 @@ static Eina_Bool host_connect_cb(void *data, Ecore_Fd_Handler *fd_handler)
 
 static Eina_Bool target_connect_cb(void *data, Ecore_Fd_Handler *fd_handler)
 {
-       if (targetServerHandler() < 0) {
+       bool is_probe_sock = *(bool*)data;
+
+       if (targetServerHandler(is_probe_sock) < 0) {
                // critical error
                terminate_error("Internal DA framework error, "
                                "Please re-run the profiling "
@@ -1039,8 +1087,12 @@ static Eina_Bool target_connect_cb(void *data, Ecore_Fd_Handler *fd_handler)
        return ECORE_CALLBACK_RENEW;
 }
 
+static bool is_probe_true = true;
+static bool is_probe_false = false;
+
 static bool initialize_events(void)
 {
+
        host_connect_handler =
                ecore_main_fd_handler_add(manager.host_server_socket,
                                          ECORE_FD_READ,
@@ -1056,13 +1108,22 @@ static bool initialize_events(void)
                ecore_main_fd_handler_add(manager.target_server_socket,
                                          ECORE_FD_READ,
                                          target_connect_cb,
-                                         NULL,
-                                         NULL, NULL);
+                                         &is_probe_true, NULL, NULL);
        if (!target_connect_handler) {
                LOGE("Target server socket add error\n");
                return false;
        }
 
+       ui_target_connect_handler =
+               ecore_main_fd_handler_add(manager.ui_target_server_socket,
+                                         ECORE_FD_READ,
+                                         target_connect_cb,
+                                         &is_probe_false, NULL, NULL);
+       if (!ui_target_connect_handler) {
+               LOGE("UI target server socket add error\n");
+               return false;
+       }
+
        return true;
 }
 
index 1ae55f4..dcc6d1a 100644 (file)
@@ -121,6 +121,7 @@ typedef struct
 {
        int host_server_socket;
        int target_server_socket;
+       int ui_target_server_socket;
        int apps_to_run;
        unsigned int config_flag;
        int app_launch_timerfd;
@@ -160,6 +161,7 @@ int reconfigure(struct conf_t conf, struct msg_t **msg_reply, struct msg_t **msg
 int is_feature_enabled(enum feature_code fcode);
 int sendACKCodeToHost(enum HostMessageType resp, int msgcode);
 void terminate_all(void);
+void restart_all(void);
 
 #ifdef __cplusplus
 }
index c8b6a2f..8d148f5 100644 (file)
@@ -55,6 +55,7 @@
 #define SINGLETON_LOCKFILE                     "/tmp/da_manager.lock"
 #define PORTFILE                                       "/tmp/port.da"
 #define UDS_NAME                                       "/tmp/da.socket"
+#define UIS_NAME                                       "/tmp/da_ui.socket"
 
 #define INIT_PORT                              8001
 #define LIMIT_PORT                             8100
@@ -65,6 +66,7 @@ __da_manager manager =
 {
        .host_server_socket = -1,
        .target_server_socket = -1,
+       .ui_target_server_socket = -1,
        .apps_to_run = 0,
        .config_flag = 0,
        .app_launch_timerfd = -1,
@@ -117,6 +119,8 @@ static void _close_server_socket(void)
                close(manager.host_server_socket);
        if(manager.target_server_socket != -1)
                close(manager.target_server_socket);
+       if(manager.ui_target_server_socket != -1)
+               close(manager.ui_target_server_socket);
 }
 
 static void _unlink_files(void)
@@ -137,31 +141,31 @@ void unlink_portfile(void)
 // =============================================================================
 
 // return 0 for normal case
-static int makeTargetServerSocket()
+static int makeTargetServerSocket(int *target_server_socket, const char *S_NAME)
 {
        struct sockaddr_un serverAddrUn;
 
-       if(manager.target_server_socket != -1)
+       if(*target_server_socket != -1)
                return -1;      // should be never happend
 
        // remove existed unix domain socket file
-       unlink(UDS_NAME);
+       unlink(S_NAME);
 
-       manager.target_server_socket = socket(AF_UNIX,
+       *target_server_socket = socket(AF_UNIX,
                                              SOCK_STREAM | SOCK_CLOEXEC, 0);
-       if (manager.target_server_socket < 0)
+       if (*target_server_socket < 0)
        {
                LOGE("Target server socket creation failed\n");
                return -1;
        }
 
-       fd_setup_attributes(manager.target_server_socket);
+       fd_setup_attributes(*target_server_socket);
 
        memset(&serverAddrUn, '\0', sizeof(serverAddrUn));
        serverAddrUn.sun_family = AF_UNIX;
-       snprintf(serverAddrUn.sun_path, sizeof(serverAddrUn.sun_path), "%s", UDS_NAME);
+       snprintf(serverAddrUn.sun_path, sizeof(serverAddrUn.sun_path), "%s", S_NAME);
 
-       if (-1 == bind(manager.target_server_socket, (struct sockaddr*) &serverAddrUn,
+       if (-1 == bind(*target_server_socket, (struct sockaddr*) &serverAddrUn,
                                        sizeof(serverAddrUn)))
        {
                LOGE("Target server socket binding failed\n");
@@ -174,13 +178,13 @@ static int makeTargetServerSocket()
        }
 
 
-       if (-1 == listen(manager.target_server_socket, 5))
+       if (-1 == listen(*target_server_socket, 5))
        {
                LOGE("Target server socket listening failed\n");
                return -1;
        }
 
-       LOGI("Created TargetSock %d\n", manager.target_server_socket);
+       LOGI("Created TargetSock %d\n", *target_server_socket);
        return 0;
 }
 
@@ -301,11 +305,16 @@ static int initializeManager(FILE *portfile)
                write_int(portfile, ERR_INITIALIZE_SYSTEM_INFO_FAILED);
                return -1;
        }
-       // make server socket
-       if (makeTargetServerSocket() != 0) {
+       // make server socket for probe library
+       if (makeTargetServerSocket(&(manager.target_server_socket), UDS_NAME) != 0) {
                write_int(portfile, ERR_TARGET_SERVER_SOCKET_CREATE_FAILED);
                return -1;
        }
+       // make server socket for ui viewer
+       if (makeTargetServerSocket(&(manager.ui_target_server_socket), UIS_NAME) != 0) {
+               write_int(portfile, ERR_UI_TARGET_SERVER_SOCKET_CREATE_FAILED);
+               return -1;
+       }
        if (!initialize_pthread_sigmask()) {
                write_int(portfile, ERR_SIGNAL_MASK_SETTING_FAILED);
                return -1;
index c16ebdc..8791632 100644 (file)
@@ -112,7 +112,6 @@ 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);
@@ -316,7 +315,25 @@ void target_wait_all(void)
                LOGI("target destroy [%d] start\n", i);
                target_dtor(t);
                LOGI("target destroy [%d] done\n", i);
+               target_use[i] = 0;
+       }
+}
+
+void target_stop_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);
+               ecore_main_fd_handler_del(t->handler);
+               t->event_fd_released = 1;
+               target_cnt_sub_and_fetch();
        }
+       target_array_unlock();
 }
 
 uint64_t target_get_total_alloc(pid_t pid)
index ac09db9..bd6cbea 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "malloc_debug_disable.h"
 #include <inttypes.h>
+#include <stdbool.h>
 #include <pthread.h>
 
 #include <Ecore.h>
@@ -69,7 +70,6 @@ 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);
 
@@ -91,6 +91,7 @@ struct target *target_get(int i);
 int target_send_msg_to_all(struct msg_target_t *msg);
 int target_send_terminate_to_all(void);
 void target_wait_all(void);
+void target_stop_all(void);
 uint64_t target_get_total_alloc(pid_t pid);
 
 
index 4c9d835..14e8040 100644 (file)
@@ -184,7 +184,7 @@ static void* recvThread(void* data)
                        if (chsmack(file_name) == 0) {
                                /* exctract probe message */
                                p += strnlen(file_name, PATH_MAX) + 1;
-                               struct msg_data_t *msg_data = (struct msg_data_t *)(p);
+                               struct msg_data_t *msg_data;
 
                                /* check packed size */
                                if (log.length != strnlen(file_name, PATH_MAX) + 1 +
@@ -201,6 +201,82 @@ static void* recvThread(void* data)
 
 
                        continue;
+               } else if (log.type == APP_MSG_GET_UI_HIERARCHY) {
+                       enum ErrorCode err_code = ERR_UNKNOWN;
+
+                       if (log.length == sizeof(uint32_t)) {
+                               err_code = *(uint32_t*)log.data;
+                       }
+
+                       sendACKToHost(NMSG_GET_UI_HIERARCHY, err_code, 0, 0);
+
+                       continue;
+               } else if (log.type == APP_MSG_GET_UI_HIERARCHY_DATA) {
+                       char *file_name = log.data;
+                       FILE * fp;
+                       struct msg_data_t *msg_data;
+                       const int len = log.length;
+                       char *p = NULL;
+
+                       if (len == sizeof(uint32_t)) {
+                               enum ErrorCode err_code = *(uint32_t*)log.data;
+
+                               LOGE("APP_MSG_GET_UI_HIERARCHY_DATA error <%d>\n", err_code);
+                               // TODO: system error
+                               if (err_code == ERR_UNKNOWN) {
+                                       restart_all();
+                                       continue;
+                               }
+                       }
+
+
+                       msg_data = malloc(MSG_DATA_HDR_LEN + len);
+                       if (!msg_data) {
+                               LOGE("Cannot alloc message: %d bytes\n", MSG_DATA_HDR_LEN + len);
+                               return NULL;
+                       }
+                       fill_data_msg_head(msg_data, NMSG_UI_HIERARCHY, 0, len);
+                       memcpy(msg_data->payload, log.data, log.length);
+
+                       if (access(file_name, F_OK) != -1) {
+                               LOGI("APP_MSG_GET_UI_HIERARCHY_DATA> File: <%s>\n",
+                                    file_name);
+
+                               if (chsmack(file_name) != 0) {
+                                       LOGE("chsmack failed\n");
+                               }
+                       } else {
+                               LOGE("APP_MSG_GET_UI_HIERARCHY> File not found <%s>\n",
+                                    file_name);
+                       }
+
+                       if (write_to_buf(msg_data) != 0)
+                               LOGE("write to buf fail\n");
+
+                       continue;
+               } else if (log.type == APP_MSG_GET_UI_SCREENSHOT) {
+                       enum ErrorCode err_code = ERR_UNKNOWN;
+                       char *payload = log.data;
+                       int payload_size = log.length;
+
+                       LOGI("APP_MSG_GET_UI_SCREENSHOT> log length = %d\n", log.length);
+
+                       if (payload_size >= sizeof(uint32_t)) {
+                               char *file_name;
+
+                               err_code = *(uint32_t*)payload;
+                               payload += sizeof(uint32_t);
+                               payload_size -= sizeof(uint32_t);
+
+                               file_name = payload;
+                               if (chsmack(file_name) != 0) {
+                                       LOGE("chsmack failed\n");
+                               }
+                       }
+
+                       sendACKToHost(NMSG_GET_UI_SCREENSHOT, err_code, payload, payload_size);
+
+                       continue;
                }
 #ifdef PRINT_TARGET_LOG
                else if (log.type == APP_MSG_LOG) {
diff --git a/daemon/ui_viewer.c b/daemon/ui_viewer.c
new file mode 100644 (file)
index 0000000..9f3d6f8
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Anastasia Lyupa <a.lyupa@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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "ui_viewer.h"
+#include "da_protocol.h"
+#include "swap_debug.h"
+#include "smack.h"
+
+int ui_viewer_set_smack_rules(const struct app_info_t *app_info)
+{
+       const char OBJECT[] = "swap";
+       const char ACCESS_TYPE[] = "r";
+       int ret = 0;
+
+       ret = apply_smack_rules(app_info->app_id, OBJECT, ACCESS_TYPE);
+
+       return ret;
+}
+
+int ui_viewer_set_app_info(const struct app_info_t *app_info)
+{
+       const char APP_INFO_FILE[] =
+               "/sys/kernel/debug/swap/preload/ui_viewer_app_info";
+       FILE *fp;
+       int ret = 0, c = 0;
+       uint64_t main_offset;
+
+       if (app_info->setup_data.data == NULL) {
+               LOGE("Setup data path is not correct\n");
+               ret = -EINVAL;
+               goto fail;
+       }
+
+       main_offset = *(uint64_t*)app_info->setup_data.data;
+
+       if (app_info->exe_path == NULL || !strlen(app_info->exe_path)) {
+               LOGE("Executable path is not correct\n");
+               ret = -EINVAL;
+               goto fail;
+       }
+
+       fp = fopen(APP_INFO_FILE, "w");
+       if (fp != NULL) {
+               c = fprintf(fp, "0x%lx:%s\n", (unsigned long)main_offset,
+                           app_info->exe_path);
+               if (c < 0) {
+                       LOGE("Can't write to file: %s\n", APP_INFO_FILE);
+                       ret = -EIO;
+               }
+               fclose(fp);
+       } else {
+               LOGE("Can't open file: %s\n", APP_INFO_FILE);
+               ret = -ENOENT;
+       }
+fail:
+       return ret;
+}
diff --git a/daemon/ui_viewer.h b/daemon/ui_viewer.h
new file mode 100644 (file)
index 0000000..65f4d5c
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Anastasia Lyupa <a.lyupa@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 UI_VIEWER_H_
+#define UI_VIEWER_H_
+
+#include "da_inst.h"
+
+int ui_viewer_set_smack_rules(const struct app_info_t *app_info);
+int ui_viewer_set_app_info(const struct app_info_t *app_info);
+
+#endif /* UI_VIEWER_H_ */
index bb9e841..93c3c60 100644 (file)
@@ -149,6 +149,7 @@ int exec_app_tizen(const char *app_id, const char *exec_path)
        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;
index 7221946..ff178f8 100644 (file)
@@ -42,9 +42,13 @@ BuildRequires:  launchpad-loader
 BuildRequires:  launchpad
 %endif
 BuildRequires:  app-core-efl
+BuildRequires:  evas-devel
+BuildRequires:  elementary-devel
+BuildRequires:  libXext-devel
 %if "%{TIZEN_PRODUCT_TV}" != "1"
 BuildRequires:  app-core-debuginfo
 %endif
+
 %if "%_project" != "Kirana_SWA_OPEN:Build" && "%_project" != "Kirana_SWA_OPEN:Daily"
 Requires:  swap-modules
 %endif
@@ -85,6 +89,9 @@ SWAP_BUILD_CMD+=" WSP_SUPPORT=y"
 SWAP_BUILD_CMD+=" make"
 eval ${SWAP_BUILD_CMD}
 
+cd ../ui_viewer
+$SWAP_BUILD_CONF make
+
 %install
 rm -rf ${RPM_BUILD_ROOT}
 mkdir -p %{buildroot}/usr/share/license
@@ -92,6 +99,9 @@ cp LICENSE %{buildroot}/usr/share/license/%{name}
 cd daemon
 %make_install
 
+cd ../ui_viewer
+%make_install
+
 %post
 mkdir -p /opt/usr/etc
 touch /opt/usr/etc/resourced_proc_exclude.ini
@@ -106,5 +116,6 @@ touch /opt/usr/etc/resourced_proc_exclude.ini
 /usr/bin/swap_init_preload.sh
 /usr/bin/swap_init_wsp.sh
 
-%changelog
+%{_prefix}/lib/da_ui_viewer.so
 
+%changelog
index 5616a17..b7fc3ce 100755 (executable)
@@ -3,6 +3,7 @@ preload_library_pattern="libdl[.-].*"
 preload_library_path="/lib/"
 preload_open_function="dlopen"
 handlers_lib="/usr/lib/da_probe_tizen.so"
+ui_viewer_lib="/usr/lib/da_ui_viewer.so"
 linker_path="/lib/"
 linker_sym="_r_debug"
 test_bin="/usr/bin/WebProcess"
@@ -37,6 +38,12 @@ function print_probe_lib()
     echo -e "/bin/echo \"$handlers_lib\" > /sys/kernel/debug/swap/preload/handlers_path" >> $filename
 }
 
+function print_ui_viewer_lib()
+{
+    filename=$1
+    echo -e "/bin/echo \"$ui_viewer_lib\" > /sys/kernel/debug/swap/preload/ui_viewer_path" >> $filename
+}
+
 function print_linker()
 {
     filename=$1
@@ -95,6 +102,7 @@ function print_ignored()
 print_header $output
 print_loader $output
 print_probe_lib $output
+print_ui_viewer_lib $output
 print_linker $output
 print_ignored $output
 
diff --git a/ui_viewer/Makefile b/ui_viewer/Makefile
new file mode 100644 (file)
index 0000000..36769e8
--- /dev/null
@@ -0,0 +1,109 @@
+CC := gcc
+
+COMM_FLAGS := -Wall -g -O0
+
+DEBUG_FLAGS = \
+       -DDEBUG \
+       -DUSE_LOG_ONCE \
+#      -DMALLOC_DEBUG_LEVEL=1 \
+#      -DMALLOC_DEBUG_LEVEL=2 \
+#      -DDEB_PRINTBUF \
+#      -DPARSE_DEBUG_ON \
+#      -DTHREAD_SAMPLING_DEBUG \
+#      -DTHREAD_REPLAY_DEBUG \
+#      -DNOLOGI=1
+
+INCLUDE := \
+       -I/usr/include \
+       -I/usr/include/elementary-1 \
+       -I/usr/include/efl-1 \
+       -I/usr/include/eina-1 \
+       -I/usr/include/eina-1/eina \
+       -I/usr/include/eet-1 \
+       -I/usr/include/evas-1 \
+       -I/usr/include/eo-1 \
+       -I/usr/include/ecore-1 \
+       -I/usr/include/ecore-evas-1 \
+       -I/usr/include/ecore-file-1 \
+       -I/usr/include/ecore-input-1 \
+       -I/usr/include/ecore-imf-1 \
+       -I/usr/include/ecore-con-1 \
+       -I/usr/include/edje-1 \
+       -I/usr/include/eldbus-1 \
+       -I/usr/include/efreet-1 \
+       -I/usr/include/ethumb-client-1 \
+       -I/usr/include/ethumb-1 \
+       -I/usr/include/e_dbus-1 \
+       -I/usr/include/dbus-1.0 \
+       -I/usr/lib/dbus-1.0/include
+
+WARN_CFLAGS = -g                        \
+                -Wall                   \
+                -funwind-tables         \
+                -fomit-frame-pointer    \
+                -Xlinker                \
+                --no-undefined          \
+                -Wextra                 \
+                -O2                     \
+                -Wwrite-strings         \
+                -Wlogical-op            \
+                -Wpacked                \
+                -Winline                \
+                -Wno-psabi
+#                -Werror
+
+FLAGS := \
+       $(COMM_FLAGS) \
+       $(INCLUDE) \
+       $(DEBUG_FLAGS) \
+       $(WARN_CFLAGS)
+
+ifeq (arm, $(findstring arm, $(shell uname -sm)))
+       FLAGS += -DDEVICE_ONLY
+endif
+
+
+# compiler flags
+CFLAGS := $(FLAGS) -D_GNU_SOURCE
+
+# linker flags
+LDFLAGS := \
+       -shared \
+       -lpthread \
+       -lecore \
+       -levas \
+       -lelementary \
+       -ldl
+
+
+SRC_C := \
+       ui_viewer_lib.c \
+       ui_viewer_utils.c \
+       ui_viewer_data.c \
+       ui_viewer_screenshot.c
+
+TARGET = da_ui_viewer.so
+
+all: debug
+
+release: CFLAGS += -DNOLOGI=1
+release: debug
+
+OBJS := $(SRC_C:.c=.o)
+
+.c.o:
+       $(CC) $(CFLAGS) -c -o $@ $<
+
+debug:  $(OBJS)
+       $(CC) $(OBJS) -o $(TARGET) $(LDFLAGS)
+
+
+install: BINDIR = $(DESTDIR)/usr/lib
+install: $(TARGET)
+       mkdir -p $(BINDIR)
+       install $(TARGET) -t $(BINDIR)
+clean:
+       rm -f $(TARGET) $(OBJS)
+
+.PHONY: all debug release clean install
+
diff --git a/ui_viewer/ui_viewer_data.c b/ui_viewer/ui_viewer_data.c
new file mode 100644 (file)
index 0000000..c05add2
--- /dev/null
@@ -0,0 +1,2001 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Lyupa Anastasia <a.lyupa@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 <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <poll.h>
+#include <Elementary.h>
+
+#include "ui_viewer_lib.h"
+#include "ui_viewer_utils.h"
+#include "ui_viewer_data.h"
+
+static pthread_mutex_t request_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t hierarchy_lock = PTHREAD_MUTEX_INITIALIZER;
+enum hierarchy_status_t hierarchy_status = HIERARCHY_NOT_RUNNING;
+
+static Eina_List *_get_obj(Eina_List *obj_list, Evas_Object *obj);
+static char *pack_ui_obj_prop(char *to, Evas_Object *obj, const char *type_name);
+static Eina_List *ui_viewer_get_all_objs(void);
+
+static enum ui_obj_category_t _get_object_category(const char *type_name)
+{
+       enum ui_obj_category_t category = UI_UNDEFINED;
+       const char evas_prefix[] = "Evas_";
+       const char elm_prefix[] = "elm_";
+
+       if (!strcmp(type_name, "rectangle") || !strcmp(type_name, "line") ||
+           !strcmp(type_name, "polygon") || !strcmp(type_name, "text") ||
+           !strcmp(type_name, "textblock") || !strcmp(type_name, "image") ||
+           !strcmp(type_name, "vectors") || !strcmp(type_name, "textgrid") ||
+           !strncmp(type_name, evas_prefix, strlen(evas_prefix)))
+               category = UI_EVAS;
+       else if (!strncmp(type_name, elm_prefix, strlen(elm_prefix)))
+               category = UI_ELM;
+       else if (!strcmp(type_name, "edje"))
+               category = UI_EDJE;
+       else
+               ui_viewer_log("cannot get category for type = %s\n", type_name);
+
+       return category;
+}
+
+static enum ui_obj_code_t _get_object_type_code(const char *type_name)
+{
+       enum ui_obj_code_t type_code = UI_CODE_UNDEFINED;
+       const char evas_prefix[] = "Evas_";
+       const char elm_prefix[] = "elm_";
+
+       if (!strcmp(type_name, "rectangle"))
+               type_code = UI_EVAS_RECTANGLE;
+       else if (!strcmp(type_name, "line"))
+               type_code = UI_EVAS_LINE;
+       else if (!strcmp(type_name, "polygon"))
+               type_code = UI_EVAS_POLYGON;
+       else if (!strcmp(type_name, "text"))
+               type_code = UI_EVAS_TEXT;
+       else if (!strcmp(type_name, "textblock"))
+               type_code = UI_EVAS_TEXTBLOCK;
+       else if (!strcmp(type_name, "image"))
+               type_code = UI_EVAS_IMAGE;
+       else if (!strcmp(type_name, "vectors"))
+               type_code = UI_EVAS_VECTORS;
+       else if (!strcmp(type_name, "Evas_Object_Table"))
+               type_code = UI_EVAS_TABLE;
+       else if (!strcmp(type_name, "Evas_Object_Box"))
+               type_code = UI_EVAS_BOX;
+       else if (!strcmp(type_name, "textgrid"))
+               type_code = UI_EVAS_TEXTGRID;
+       else if (!strcmp(type_name, "Evas_Object_Grid"))
+               type_code = UI_EVAS_GRID;
+       else if (!strcmp(type_name, "Evas_Object_Smart"))
+               type_code = UI_EVAS_SMART;
+       else if (!strncmp(type_name, evas_prefix, strlen(evas_prefix)))
+               type_code = UI_EVAS_UNDEFINED;
+       else if (!strcmp(type_name, "elm_bg"))
+               type_code = UI_ELM_BACKGROUND;
+       else if (!strcmp(type_name, "elm_button"))
+               type_code = UI_ELM_BUTTON;
+       else if (!strcmp(type_name, "elm_check"))
+               type_code = UI_ELM_CHECK;
+       else if (!strcmp(type_name, "elm_colorselector"))
+               type_code = UI_ELM_COLORSELECTOR;
+       else if (!strcmp(type_name, "elm_ctxpopup"))
+               type_code = UI_ELM_CTXPOPUP;
+       else if (!strcmp(type_name, "elm_datetime"))
+               type_code = UI_ELM_DATETIME;
+       else if (!strcmp(type_name, "elm_entry"))
+               type_code = UI_ELM_ENTRY;
+       else if (!strcmp(type_name, "elm_flip"))
+               type_code = UI_ELM_FLIP;
+       else if (!strcmp(type_name, "elm_gengrid"))
+               type_code = UI_ELM_GENGRID;
+       else if (!strcmp(type_name, "elm_genlist"))
+               type_code = UI_ELM_GENLIST;
+       else if (!strcmp(type_name, "elm_glview"))
+               type_code = UI_ELM_GLVIEW;
+       else if (!strcmp(type_name, "elm_icon"))
+               type_code = UI_ELM_ICON;
+       else if (!strcmp(type_name, "elm_image"))
+               type_code = UI_ELM_IMAGE;
+       else if (!strcmp(type_name, "elm_index"))
+               type_code = UI_ELM_INDEX;
+       else if (!strcmp(type_name, "elm_label"))
+               type_code = UI_ELM_LABEL;
+       else if (!strcmp(type_name, "elm_list"))
+               type_code = UI_ELM_LIST;
+       else if (!strcmp(type_name, "elm_map"))
+               type_code = UI_ELM_MAP;
+       else if (!strcmp(type_name, "elm_notify"))
+               type_code = UI_ELM_NOTIFY;
+       else if (!strcmp(type_name, "elm_panel"))
+               type_code = UI_ELM_PANEL;
+       else if (!strcmp(type_name, "elm_photo"))
+               type_code = UI_ELM_PHOTO;
+       else if (!strcmp(type_name, "elm_photocam"))
+               type_code = UI_ELM_PHOTOCAM;
+       else if (!strcmp(type_name, "elm_plug"))
+               type_code = UI_ELM_PLUG;
+       else if (!strcmp(type_name, "elm_popup"))
+               type_code = UI_ELM_POPUP;
+       else if (!strcmp(type_name, "elm_progressbar"))
+               type_code = UI_ELM_PROGRESSBAR;
+       else if (!strcmp(type_name, "elm_radio"))
+               type_code = UI_ELM_RADIO;
+       else if (!strcmp(type_name, "elm_segment_control"))
+               type_code = UI_ELM_SEGMENTCONTROL;
+       else if (!strcmp(type_name, "elm_slider"))
+               type_code = UI_ELM_SLIDER;
+       else if (!strcmp(type_name, "elm_spinner"))
+               type_code = UI_ELM_SPINNER;
+       else if (!strcmp(type_name, "elm_toolbar"))
+               type_code = UI_ELM_TOOLBAR;
+       else if (!strcmp(type_name, "elm_tooltip"))
+               type_code = UI_ELM_TOOLTIP;
+       else if (!strcmp(type_name, "elm_win"))
+               type_code = UI_ELM_WIN;
+       else if (!strncmp(type_name, elm_prefix, strlen(elm_prefix)))
+               type_code = UI_ELM_UNDEFINED;
+       else if (!strcmp(type_name, "edje"))
+               type_code = UI_EDJE_UNDEFINED;
+       else
+               ui_viewer_log("cannot get type code for type = %s\n", type_name);
+
+       return type_code;
+}
+
+static Eina_Bool _get_redraw(enum ui_obj_category_t category)
+{
+       Eina_Bool redraw = EINA_FALSE;
+
+       if (category != UI_EDJE)
+               redraw = EINA_TRUE;
+
+       return redraw;
+}
+
+static void _render_obj(Evas *evas, Evas_Object *obj, enum ui_obj_category_t category,
+                       enum ui_obj_code_t type_code EINA_UNUSED, struct timeval *tv,
+                       enum rendering_option_t rendering)
+{
+       Eina_Bool redraw;
+
+       if ((rendering == RENDER_NONE) ||
+           (rendering == RENDER_NONE_HOST_OPT) ||
+           (rendering == RENDER_ELM && category != UI_ELM)) {
+               timerclear(tv);
+               return;
+       }
+
+       redraw = _get_redraw(category);
+
+       if (redraw) {
+               struct timeval start_tv, finish_tv;
+               Eina_Bool visible;
+
+               visible = evas_object_visible_get(obj);
+               if (visible) {
+                       evas_object_hide(obj);
+                       evas_render(evas);
+               }
+               gettimeofday(&start_tv, NULL);
+               evas_object_show(obj);
+               evas_render(evas);
+               gettimeofday(&finish_tv, NULL);
+               if (!visible) {
+                       evas_object_hide(obj);
+                       evas_render(evas);
+               }
+               timersub(&finish_tv, &start_tv, tv);
+       } else {
+               timerclear(tv);
+       }
+}
+
+static Eina_List *_get_obj(Eina_List *obj_list, Evas_Object *obj)
+{
+       Eina_List *children;
+       Evas_Object *child;
+       char type_name[MAX_PATH_LENGTH];
+
+       evas_object_ref(obj);
+       obj_list = eina_list_append(obj_list, obj);
+
+       _strncpy(type_name, evas_object_type_get(obj), MAX_PATH_LENGTH);
+
+       evas_object_unref(obj);
+
+       if (!strcmp(type_name, "rectangle") || !strcmp(type_name, "line") ||
+           !strcmp(type_name, "polygon") || !strcmp(type_name, "text") ||
+           !strcmp(type_name, "textblock") || !strcmp(type_name, "image") ||
+           !strcmp(type_name, "vectors") || !strcmp(type_name, "textgrid"))
+               return obj_list;
+
+       children = evas_object_smart_members_get(obj);
+       EINA_LIST_FREE(children, child) {
+               obj_list = _get_obj(obj_list, child);
+       }
+       eina_list_free(children);
+
+       return obj_list;
+}
+
+char *pack_string(char *to, const char *str)
+{
+       if (!str) {
+               *to = '\0';
+               return to + 1;
+       } else {
+               size_t len = strlen(str) + 1;
+               strncpy(to, str, len);
+               return to + len;
+       }
+}
+
+static Eina_Bool _get_obj_exists(Evas_Object *obj)
+{
+       Eina_Bool exists = EINA_FALSE;
+
+       // this call is safe even if object doesn't exist (returns NULL)
+       if (evas_object_type_get(obj) != NULL)
+               exists = EINA_TRUE;
+
+       return exists;
+}
+
+static Evas_Object *_get_win_id(Evas *evas)
+{
+       Evas_Object *win_id = 0;
+       Eina_List *objs, *l;
+       Evas_Object *obj_i;
+
+       objs = evas_objects_in_rectangle_get(evas, SHRT_MIN, SHRT_MIN, USHRT_MAX, USHRT_MAX,
+                                            EINA_TRUE, EINA_TRUE);
+       EINA_LIST_FOREACH(objs, l, obj_i)
+       {
+               if (!strcmp(evas_object_type_get(obj_i), "elm_win")) {
+                       win_id = obj_i;
+                       break;
+               }
+       }
+       eina_list_free(objs);
+
+       return win_id;
+}
+
+static char *_pack_ui_obj_info(char *to, Evas_Object *obj,
+                              enum rendering_option_t rendering)
+{
+       ui_obj_info_t info;
+       Evas *evas;
+
+       if (!_get_obj_exists(obj)) {
+               ui_viewer_log("object %p doesn't exist\n", obj);
+               set_hierarchy_status(HIERARCHY_CANCELLED);
+               print_log_ui_viewer_hierarchy_error();
+               return to;
+       }
+
+       evas = evas_object_evas_get(obj);
+
+       info.id = obj;
+       _strncpy(info.name, evas_object_type_get(obj), MAX_PATH_LENGTH);
+       info.parent_id = evas_object_smart_parent_get(obj);
+       info.category = _get_object_category(info.name);
+       info.code = _get_object_type_code(info.name);
+
+       // we set window as parent for objects without it
+       if (info.parent_id == 0 && strcmp(info.name, "elm_win"))
+               info.parent_id = _get_win_id(evas);
+
+       _render_obj(evas, obj, info.category, info.code, &(info.rendering_tv), rendering);
+
+       ui_viewer_log("object : 0x%lx, category : %x, type_code: %x, "
+                       "type_name : %s, rendering time : %d sec, %d nano sec, parent : 0x%lx\n",
+                       (unsigned long)info.id, info.category, info.code,
+                       info.name, info.rendering_tv.tv_sec, info.rendering_tv.tv_usec * 1000,
+                       (unsigned long)info.parent_id);
+
+
+       to = pack_ptr(to, info.id);
+       to = pack_int8(to, info.category);
+       to = pack_int32(to, info.code);
+       to = pack_string(to, info.name);
+       to = pack_timeval(to, info.rendering_tv);
+       to = pack_ptr(to, info.parent_id);
+       to = pack_ui_obj_prop(to, info.id, info.name);
+
+       evas_object_unref(obj);
+
+       return to;
+}
+
+char *pack_ui_obj_info_list(char *to, enum rendering_option_t rendering,
+                           Eina_Bool *cancelled)
+{
+       Eina_List *obj_list;
+       Evas_Object *obj;
+       unsigned int info_cnt;
+       char *start_ptr = to;
+       Eina_List *ee_list = NULL, *ee_list_tmp = NULL;
+       Ecore_Evas *ee;
+
+       ee_list = ecore_evas_ecore_evas_list_get();
+       EINA_LIST_FOREACH(ee_list, ee_list_tmp, ee)
+       {
+               Evas *evas = ecore_evas_get(ee);
+               evas_event_freeze(evas);
+       }
+
+       pthread_mutex_lock(&request_lock);
+       obj_list = ui_viewer_get_all_objs();
+       info_cnt = eina_list_count(obj_list);
+       to = pack_int8(to, rendering);
+       to = pack_int32(to, info_cnt);
+       pthread_mutex_unlock(&request_lock);
+
+       *cancelled = EINA_FALSE;
+
+       if (info_cnt == 0) {
+               ui_viewer_log("no objects exist\n");
+               set_hierarchy_status(HIERARCHY_CANCELLED);
+               to = start_ptr;
+               *cancelled = EINA_TRUE;
+               print_log_ui_viewer_hierarchy_error();
+       }
+
+       EINA_LIST_FREE(obj_list, obj)
+       {
+               pthread_mutex_lock(&request_lock);
+               // check if hierarchy request is active
+               if (get_hierarchy_status() == HIERARCHY_RUNNING) {
+                       to = _pack_ui_obj_info(to, obj, rendering);
+               } else {
+                       ui_viewer_log("break packing hierarchy info\n");
+                       // don't save any data if request was cancelled
+                       to = start_ptr;
+                       *cancelled = EINA_TRUE;
+                       pthread_mutex_unlock(&request_lock);
+                       break;
+               }
+               pthread_mutex_unlock(&request_lock);
+       }
+
+       pthread_mutex_lock(&request_lock);
+
+       // unref remained objects
+       EINA_LIST_FREE(obj_list, obj)
+       {
+               evas_object_unref(obj);
+       }
+       eina_list_free(obj_list);
+
+       EINA_LIST_FREE(ee_list, ee)
+       {
+               Evas *evas = ecore_evas_get(ee);
+               evas_event_thaw(evas);
+       }
+       eina_list_free(ee_list);
+
+       pthread_mutex_unlock(&request_lock);
+
+       return to;
+}
+
+enum hierarchy_status_t get_hierarchy_status(void)
+{
+       enum hierarchy_status_t status;
+
+       pthread_mutex_lock(&hierarchy_lock);
+       status = hierarchy_status;
+       pthread_mutex_unlock(&hierarchy_lock);
+
+       return status;
+}
+
+void set_hierarchy_status(enum hierarchy_status_t status)
+{
+       pthread_mutex_lock(&hierarchy_lock);
+       hierarchy_status = status;
+       pthread_mutex_unlock(&hierarchy_lock);
+}
+
+static Eina_List *_get_all_objs_in_rect(Evas_Coord x, Evas_Coord y, Evas_Coord w,
+                                Evas_Coord h,
+                                Eina_Bool      include_pass_events_objects,
+                                Eina_Bool      include_hidden_objects)
+{
+       Eina_List *ecore_evas_list = NULL, *obj_list = NULL;
+       Ecore_Evas *ee;
+
+       ecore_evas_list = ecore_evas_ecore_evas_list_get();
+
+       EINA_LIST_FREE(ecore_evas_list, ee)
+       {
+               Evas *evas;
+               Eina_List *objs, *l;
+               Evas_Object *obj_i;
+
+               evas = ecore_evas_get(ee);
+
+               objs = evas_objects_in_rectangle_get(evas, x, y, w, h,
+                                                    include_pass_events_objects,
+                                                    include_hidden_objects);
+
+               EINA_LIST_FOREACH(objs, l, obj_i)
+               {
+                       obj_list = _get_obj(obj_list, obj_i);
+               }
+               eina_list_free(objs);
+       }
+
+       eina_list_free(ecore_evas_list);
+
+       return obj_list;
+}
+
+static Eina_List *ui_viewer_get_all_objs(void)
+{
+       return _get_all_objs_in_rect(SHRT_MIN, SHRT_MIN, USHRT_MAX, USHRT_MAX,
+                                   EINA_TRUE, EINA_TRUE);
+}
+
+static char *_pack_ui_obj_evas_prop(char *to, ui_obj_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("evas prop: geometry : [%d,%d,%d,%d], "
+                       "focus : %d, name : %s, visible : %d, \n\t"
+                       "color : [%d,%d,%d,%d], anti_alias : %d, scale : %f, "
+                       "size_min : [%d,%d], size_max : [%d,%d], size_request : [%d,%d], \n\t"
+                       "size_align : [%f,%f], size_weight : [%f,%f], "
+                       "size_padding : [%d,%d,%d,%d], render_op : %d\n",
+                       prop->geometry[0], prop->geometry[1],
+                       prop->geometry[2], prop->geometry[3],
+                       prop->focus, prop->name, prop->visible,
+                       prop->color[0], prop->color[1],
+                       prop->color[2], prop->color[3],
+                       prop->anti_alias, prop->scale,
+                       prop->size_min[0], prop->size_min[1],
+                       prop->size_max[0], prop->size_max[1],
+                       prop->size_request[0], prop->size_request[1],
+                       prop->size_align[0], prop->size_align[1],
+                       prop->size_weight[0], prop->size_weight[1],
+                       prop->size_padding[0], prop->size_padding[1],
+                       prop->size_padding[2], prop->size_padding[3],
+                       prop->render_op);
+
+       to = pack_int32(to, prop->geometry[0]);
+       to = pack_int32(to, prop->geometry[1]);
+       to = pack_int32(to, prop->geometry[2]);
+       to = pack_int32(to, prop->geometry[3]);
+       to = pack_int8(to, prop->focus);
+       to = pack_string(to, prop->name);
+       to = pack_int8(to, prop->visible);
+       to = pack_int32(to, prop->color[0]);
+       to = pack_int32(to, prop->color[1]);
+       to = pack_int32(to, prop->color[2]);
+       to = pack_int32(to, prop->color[3]);
+       to = pack_int8(to, prop->anti_alias);
+       to = pack_float(to, prop->scale);
+       to = pack_int32(to, prop->size_min[0]);
+       to = pack_int32(to, prop->size_min[1]);
+       to = pack_int32(to, prop->size_max[0]);
+       to = pack_int32(to, prop->size_max[1]);
+       to = pack_int32(to, prop->size_request[0]);
+       to = pack_int32(to, prop->size_request[1]);
+       to = pack_float(to, prop->size_align[0]);
+       to = pack_float(to, prop->size_align[1]);
+       to = pack_float(to, prop->size_weight[0]);
+       to = pack_float(to, prop->size_weight[1]);
+       to = pack_int32(to, prop->size_padding[0]);
+       to = pack_int32(to, prop->size_padding[1]);
+       to = pack_int32(to, prop->size_padding[2]);
+       to = pack_int32(to, prop->size_padding[3]);
+       to = pack_int8(to, prop->render_op);
+
+       return to;
+}
+
+static char *_pack_ui_obj_elm_prop(char *to, ui_obj_elm_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("elm prop: text : %s, style : %s, disabled : %d, type : %s\n",
+                     prop->text, prop->style, prop->disabled, prop->type);
+
+       to = pack_string(to, prop->text);
+       to = pack_string(to, prop->style);
+       to = pack_int8(to, prop->disabled);
+       to = pack_string(to, prop->type);
+
+       return to;
+}
+
+static char *_pack_ui_obj_edje_prop(char *to, ui_obj_edje_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("edje prop: animation : %d, play : %d, scale : %f, base_scale : %f, "
+                     "size_min : [%d,%d], size_max : [%d,%d]\n",
+                     prop->animation, prop->play, prop->scale, prop->base_scale,
+                     prop->size_min[0], prop->size_min[1], prop->size_max[0],
+                     prop->size_max[1]);
+
+       to = pack_int8(to, prop->animation);
+       to = pack_int8(to, prop->play);
+       to = pack_float(to, prop->scale);
+       to = pack_float(to, prop->base_scale);
+       to = pack_int32(to, prop->size_min[0]);
+       to = pack_int32(to, prop->size_min[1]);
+       to = pack_int32(to, prop->size_max[0]);
+       to = pack_int32(to, prop->size_max[1]);
+
+       return to;
+}
+
+static char *_pack_image_prop(char *to, image_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("image prop: load_dpi : %f, source_clip : %d, filled : %d, content_hint : %d, "
+                     "alpha : %d, border : [%d,%d,%d,%d], border_scale : %f, pixels_dirty : %d,\n\t"
+                     "load_orientation : %d, border_center_fill : %d, size : [%d,%d], source_visible: %d, "
+                     "fill : [%d,%d,%d,%d], load_scale_down : %d,\n\tscale_hint : %d, source_events : %d, "
+                     "frame_count : %d, evas_image_stride : %d\n",
+                     prop->load_dpi, prop->source_clip, prop->filled, prop->content_hint,
+                     prop->alpha, prop->border[0], prop->border[1], prop->border[2],
+                     prop->border[3], prop->border_scale, prop->pixels_dirty, prop->load_orientation,
+                     prop->border_center_fill, prop->size[0], prop->size[1], prop->source_visible,
+                     prop->fill[0], prop->fill[1], prop->fill[2], prop->fill[3], prop->load_scale_down,
+                     prop->scale_hint, prop->source_events, prop->frame_count, prop->evas_image_stride);
+
+       to = pack_float(to, prop->load_dpi);
+       to = pack_int8(to, prop->source_clip);
+       to = pack_int8(to, prop->filled);
+       to = pack_int8(to, prop->content_hint);
+       to = pack_int8(to, prop->alpha);
+       to = pack_int32(to, prop->border[0]);
+       to = pack_int32(to, prop->border[1]);
+       to = pack_int32(to, prop->border[2]);
+       to = pack_int32(to, prop->border[3]);
+       to = pack_float(to, prop->border_scale);
+       to = pack_int8(to, prop->pixels_dirty);
+       to = pack_int8(to, prop->load_orientation);
+       to = pack_int8(to, prop->border_center_fill);
+       to = pack_int32(to, prop->size[0]);
+       to = pack_int32(to, prop->size[1]);
+       to = pack_int8(to, prop->source_visible);
+       to = pack_int32(to, prop->fill[0]);
+       to = pack_int32(to, prop->fill[1]);
+       to = pack_int32(to, prop->fill[2]);
+       to = pack_int32(to, prop->fill[3]);
+       to = pack_int32(to, prop->load_scale_down);
+       to = pack_int8(to, prop->scale_hint);
+       to = pack_int8(to, prop->source_events);
+       to = pack_int32(to, prop->frame_count);
+       to = pack_int32(to, prop->evas_image_stride);
+
+       return to;
+}
+
+static char *_pack_line_prop(char *to, line_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("line prop: xy : [%d,%d,%d,%d]\n",
+                     prop->xy[0], prop->xy[1], prop->xy[2], prop->xy[3]);
+
+       to = pack_int32(to, prop->xy[0]);
+       to = pack_int32(to, prop->xy[1]);
+       to = pack_int32(to, prop->xy[2]);
+       to = pack_int32(to, prop->xy[3]);
+
+       return to;
+}
+
+static char *_pack_text_prop(char *to, text_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("text prop: font : %s, size : %d, text : %s, delim : %s, "
+                     "ellipsis : %s, style : %d, shadow_color : [%d,%d,%d,%d], glow_color : [%d,%d,%d,%d],\n\t"
+                     "glow2_color : [%d,%d,%d,%d], outline_color : [%d,%d,%d,%d], style_pad: [%d,%d,%d,%d], "
+                     "direction : %d\n",
+                     prop->font, prop->size, prop->text, prop->delim, prop->ellipsis, prop->style,
+                     prop->shadow_color[0], prop->shadow_color[1], prop->shadow_color[2], prop->shadow_color[3],
+                     prop->glow_color[0], prop->glow_color[1], prop->glow_color[2], prop->glow_color[3],
+                     prop->glow2_color[0], prop->glow2_color[1], prop->glow2_color[2], prop->glow2_color[3],
+                     prop->outline_color[0], prop->outline_color[1], prop->outline_color[2], prop->outline_color[3],
+                     prop->style_pad[0], prop->style_pad[1], prop->style_pad[2], prop->style_pad[3],
+                     prop->direction);
+
+       to = pack_string(to, prop->font);
+       to = pack_int32(to, prop->size);
+       to = pack_string(to, prop->text);
+       to = pack_string(to, prop->delim);
+       to = pack_float(to, prop->ellipsis);
+       to = pack_int8(to, prop->style);
+       to = pack_int32(to, prop->shadow_color[0]);
+       to = pack_int32(to, prop->shadow_color[1]);
+       to = pack_int32(to, prop->shadow_color[2]);
+       to = pack_int32(to, prop->shadow_color[3]);
+       to = pack_int32(to, prop->glow_color[0]);
+       to = pack_int32(to, prop->glow_color[1]);
+       to = pack_int32(to, prop->glow_color[2]);
+       to = pack_int32(to, prop->glow_color[3]);
+       to = pack_int32(to, prop->glow2_color[0]);
+       to = pack_int32(to, prop->glow2_color[1]);
+       to = pack_int32(to, prop->glow2_color[2]);
+       to = pack_int32(to, prop->glow2_color[3]);
+       to = pack_int32(to, prop->outline_color[0]);
+       to = pack_int32(to, prop->outline_color[1]);
+       to = pack_int32(to, prop->outline_color[2]);
+       to = pack_int32(to, prop->outline_color[3]);
+       to = pack_int32(to, prop->style_pad[0]);
+       to = pack_int32(to, prop->style_pad[1]);
+       to = pack_int32(to, prop->style_pad[2]);
+       to = pack_int32(to, prop->style_pad[3]);
+       to = pack_int8(to, prop->direction);
+
+       return to;
+}
+
+static char *_pack_textblock_prop(char *to, textblock_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("textblock prop: replace_char : %s, valign : %f, delim : %s, newline : %d, "
+                     "markup : %s\n",
+                     prop->replace_char, prop->valign, prop->delim, prop->newline,
+                     prop->markup);
+
+       to = pack_string(to, prop->replace_char);
+       to = pack_float(to, prop->valign);
+       to = pack_string(to, prop->delim);
+       to = pack_int8(to, prop->newline);
+       to = pack_string(to, prop->markup);
+
+       return to;
+}
+
+static char *_pack_table_prop(char *to, table_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("table prop: homogeneous : %d, align : [%f,%f], padding : [%d,%d], mirrored : %d, "
+                     "col_row_size : [%d,%d]\n",
+                     prop->homogeneous, prop->align[0], prop->align[1], prop->padding[0],
+                     prop->padding[1], prop->mirrored, prop->col_row_size[0], prop->col_row_size[1]);
+
+       to = pack_int8(to, prop->homogeneous);
+       to = pack_float(to, prop->align[0]);
+       to = pack_float(to, prop->align[1]);
+       to = pack_int32(to, prop->padding[0]);
+       to = pack_int32(to, prop->padding[1]);
+       to = pack_int8(to, prop->mirrored);
+       to = pack_int32(to, prop->col_row_size[0]);
+       to = pack_int32(to, prop->col_row_size[1]);
+
+       return to;
+}
+
+static char *_pack_box_prop(char *to, box_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("box prop: align : [%f,%f]\n",
+                     prop->align[0], prop->align[1]);
+
+       to = pack_float(to, prop->align[0]);
+       to = pack_float(to, prop->align[1]);
+
+       return to;
+}
+
+static char *_pack_grid_prop(char *to, grid_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("grid prop: mirrored : %d\n",
+                     prop->mirrored);
+
+       to = pack_int8(to, prop->mirrored);
+
+       return to;
+}
+
+static char *_pack_textgrid_prop(char *to, textgrid_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("textgrid prop: size : [%d,%d], cell_size : [%d,%d]\n",
+                     prop->size[0], prop->size[1], prop->cell_size[0],
+                     prop->cell_size[1]);
+
+       to = pack_int32(to, prop->size[0]);
+       to = pack_int32(to, prop->size[1]);
+       to = pack_int32(to, prop->cell_size[0]);
+       to = pack_int32(to, prop->cell_size[1]);
+
+       return to;
+}
+
+static char *_pack_bg_prop(char *to, bg_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("bg prop: color : [%d,%d,%d], option : %d\n",
+                     prop->color[0], prop->color[1], prop->color[2],
+                     prop->option);
+
+       to = pack_int32(to, prop->color[0]);
+       to = pack_int32(to, prop->color[1]);
+       to = pack_int32(to, prop->color[2]);
+       to = pack_int8(to, prop->option);
+
+       return to;
+}
+
+static char *_pack_button_prop(char *to, button_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("button prop: initial_timeout : %f, gap_timeout : %f, autorepeat : %d\n",
+                     prop->initial_timeout, prop->gap_timeout, prop->autorepeat);
+
+       to = pack_float(to, prop->initial_timeout);
+       to = pack_float(to, prop->gap_timeout);
+       to = pack_int8(to, prop->autorepeat);
+
+       return to;
+}
+
+static char *_pack_check_prop(char *to, check_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("check prop: state : %d\n",
+                     prop->state);
+
+       to = pack_int8(to, prop->state);
+
+       return to;
+}
+
+static char *_pack_colorselector_prop(char *to, colorselector_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("colorselector prop: color : [%d,%d,%d,%d], palette_name : %s, "
+                     "mode : %d\n",
+                     prop->color[0], prop->color[1], prop->color[2], prop->color[3], prop->palette_name,
+                     prop->mode);
+
+       to = pack_int32(to, prop->color[0]);
+       to = pack_int32(to, prop->color[1]);
+       to = pack_int32(to, prop->color[2]);
+       to = pack_int32(to, prop->color[3]);
+       to = pack_string(to, prop->palette_name);
+       to = pack_int8(to, prop->mode);
+
+       return to;
+}
+
+static char *_pack_ctxpopup_prop(char *to, ctxpopup_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("ctxpopup prop: horizontal : %d\n",
+                     prop->horizontal);
+
+       to = pack_int8(to, prop->horizontal);
+
+       return to;
+}
+
+static char *_pack_datetime_prop(char *to, datetime_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("datetime prop: format : %s, value : [%d,%d,%d,%d,%d,%d,%d,%d]\n",
+                     prop->format, prop->value[0], prop->value[1], prop->value[2], prop->value[3],
+                     prop->value[4], prop->value[5], prop->value[6], prop->value[7]);
+
+       to = pack_string(to, prop->format);
+       to = pack_int32(to, prop->value[0]);
+       to = pack_int32(to, prop->value[1]);
+       to = pack_int32(to, prop->value[2]);
+       to = pack_int32(to, prop->value[3]);
+       to = pack_int32(to, prop->value[4]);
+       to = pack_int32(to, prop->value[5]);
+       to = pack_int32(to, prop->value[6]);
+       to = pack_int32(to, prop->value[7]);
+
+       return to;
+}
+
+static char *_pack_entry_prop(char *to, entry_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("entry prop: entry : %s, scrollable : %d, panel_show_on_demand : %d, menu_disabled : %d, "
+                     "cnp_mode : %d, editable : %d, hover_style : %s, single_line : %d,\n\t"
+                     "password : %d, autosave : %d, prediction_allow : %d, panel_enabled: %d, "
+                     "cursor_pos : %d, cursor_is_format : %d,\n\tcursor_content : %s, "
+                     "selection : %s, is_visible_format : %d\n",
+                     prop->entry, prop->scrollable, prop->panel_show_on_demand, prop->menu_disabled,
+                     prop->cnp_mode, prop->editable, prop->hover_style, prop->single_line,
+                     prop->password, prop->autosave, prop->prediction_allow, prop->panel_enabled,
+                     prop->cursor_pos, prop->cursor_is_format, prop->cursor_content, prop->selection,
+                     prop->is_visible_format);
+
+       to = pack_string(to, prop->entry);
+       to = pack_int8(to, prop->scrollable);
+       to = pack_int8(to, prop->panel_show_on_demand);
+       to = pack_int8(to, prop->menu_disabled);
+       to = pack_int8(to, prop->cnp_mode);
+       to = pack_int8(to, prop->editable);
+       to = pack_string(to, prop->hover_style);
+       to = pack_int8(to, prop->single_line);
+       to = pack_int8(to, prop->password);
+       to = pack_int8(to, prop->autosave);
+       to = pack_int8(to, prop->prediction_allow);
+       to = pack_int8(to, prop->panel_enabled);
+       to = pack_int32(to, prop->cursor_pos);
+       to = pack_int8(to, prop->cursor_is_format);
+       to = pack_string(to, prop->cursor_content);
+       free(prop->cursor_content); // we need free it according to efl docs
+       to = pack_string(to, prop->selection);
+       to = pack_int8(to, prop->is_visible_format);
+
+       return to;
+}
+
+static char *_pack_flip_prop(char *to, flip_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("flip prop: interaction : %d, front_visible : %d\n",
+                     prop->interaction, prop->front_visible);
+
+       to = pack_int8(to, prop->interaction);
+       to = pack_int8(to, prop->front_visible);
+
+       return to;
+}
+
+static char *_pack_gengrid_prop(char *to, gengrid_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("gengrid prop: align : [%f,%f], filled : %d, relative : [%f,%f], "
+                     "multi_select : %d, group_item_size : [%d,%d], select_mode : %d, render_mode : %d,\n\t"
+                     "highlight_mode : %d, item_size : [%d,%d], multi_select_mode: %d, "
+                     "horizontal : %d, wheel_disabled : %d, items_count : %d\n",
+                     prop->align[0], prop->align[1], prop->filled, prop->relative[0],
+                     prop->relative[1], prop->multi_select, prop->group_item_size[0], prop->group_item_size[1],
+                     prop->select_mode, prop->render_mode, prop->highlight_mode, prop->item_size[0],
+                     prop->item_size[1], prop->multi_select_mode, prop->horizontal, prop->wheel_disabled,
+                     prop->items_count);
+
+       to = pack_float(to, prop->align[0]);
+       to = pack_float(to, prop->align[1]);
+       to = pack_int8(to, prop->filled);
+       to = pack_float(to, prop->relative[0]);
+       to = pack_float(to, prop->relative[1]);
+       to = pack_int8(to, prop->multi_select);
+       to = pack_int32(to, prop->group_item_size[0]);
+       to = pack_int32(to, prop->group_item_size[1]);
+       to = pack_int8(to, prop->select_mode);
+       to = pack_int8(to, prop->render_mode);
+       to = pack_int8(to, prop->highlight_mode);
+       to = pack_int32(to, prop->item_size[0]);
+       to = pack_int32(to, prop->item_size[1]);
+       to = pack_int8(to, prop->multi_select_mode);
+       to = pack_int8(to, prop->horizontal);
+       to = pack_int8(to, prop->wheel_disabled);
+       to = pack_int32(to, prop->items_count);
+
+       return to;
+}
+
+static char *_pack_genlist_prop(char *to, genlist_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("genlist prop: multi_select : %d, genlist_mode : %d, items_count : %d, homogeneous : %d, "
+                     "block_count : %d, timeout : %f, reorder_mode : %d,\n\t"
+                     "decorate_mode : %d, effect_enabled : %d, select_mode: %d, "
+                     "highlight_mode : %d, realization_mode : %d\n",
+                     prop->multi_select, prop->genlist_mode, prop->items_count, prop->homogeneous,
+                     prop->block_count, prop->timeout, prop->reorder_mode, prop->decorate_mode,
+                     prop->effect_enabled, prop->select_mode, prop->highlight_mode, prop->realization_mode);
+
+       to = pack_int8(to, prop->multi_select);
+       to = pack_int8(to, prop->genlist_mode);
+       to = pack_int32(to, prop->items_count);
+       to = pack_int8(to, prop->homogeneous);
+       to = pack_int32(to, prop->block_count);
+       to = pack_float(to, prop->timeout);
+       to = pack_int8(to, prop->reorder_mode);
+       to = pack_int8(to, prop->decorate_mode);
+       to = pack_int8(to, prop->effect_enabled);
+       to = pack_int8(to, prop->select_mode);
+       to = pack_int8(to, prop->highlight_mode);
+       to = pack_int8(to, prop->realization_mode);
+
+       return to;
+}
+
+static char *_pack_glview_prop(char *to, glview_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("glview prop: size : [%d,%d], rotation: %d\n",
+                     prop->size[0], prop->size[1], prop->rotation);
+
+       to = pack_int32(to, prop->size[0]);
+       to = pack_int32(to, prop->size[1]);
+       to = pack_int32(to, prop->rotation);
+
+       return to;
+}
+
+static char *_pack_icon_prop(char *to, icon_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("icon prop: lookup : %d, standard : %s\n",
+                     prop->lookup, prop->standard);
+
+       to = pack_int8(to, prop->lookup);
+       to = pack_string(to, prop->standard);
+
+       return to;
+}
+
+static char *_pack_elm_image_prop(char *to, elm_image_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("elm_image prop: editable : %d, play : %d, smooth : %d, no_scale : %d, "
+                     "animated : %d, aspect_fixed : %d, orient : %d,\n\t"
+                     "fill_outside : %d, resizable : [%d,%d], animated_available: %d, "
+                     "size : [%d,%d]\n",
+                     prop->editable, prop->play, prop->smooth, prop->no_scale,
+                     prop->animated, prop->aspect_fixed, prop->orient, prop->fill_outside,
+                     prop->resizable[0], prop->resizable[1], prop->animated_available,
+                     prop->size[0], prop->size[1]);
+
+       to = pack_int8(to, prop->editable);
+       to = pack_int8(to, prop->play);
+       to = pack_int8(to, prop->smooth);
+       to = pack_int8(to, prop->no_scale);
+       to = pack_int8(to, prop->animated);
+       to = pack_int8(to, prop->aspect_fixed);
+       to = pack_int8(to, prop->orient);
+       to = pack_int8(to, prop->fill_outside);
+       to = pack_int8(to, prop->resizable[0]);
+       to = pack_int8(to, prop->resizable[1]);
+       to = pack_int8(to, prop->animated_available);
+       to = pack_int32(to, prop->size[0]);
+       to = pack_int32(to, prop->size[1]);
+
+       return to;
+}
+
+static char *_pack_index_prop(char *to, index_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("index prop: autohide_disabled : %d, omit_enabled : %d, priority : %d, horizontal : %d, "
+                     "change_time : %f,\n\tindicator_disabled : %d, item_level : %d\n",
+                     prop->autohide_disabled, prop->omit_enabled, prop->priority, prop->horizontal,
+                     prop->change_time, prop->indicator_disabled, prop->item_level);
+
+       to = pack_int8(to, prop->autohide_disabled);
+       to = pack_int8(to, prop->omit_enabled);
+       to = pack_int32(to, prop->priority);
+       to = pack_int8(to, prop->horizontal);
+       to = pack_float(to, prop->change_time);
+       to = pack_int8(to, prop->indicator_disabled);
+       to = pack_int32(to, prop->item_level);
+
+       return to;
+}
+
+static char *_pack_label_prop(char *to, label_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("label prop: wrap_width : %d, speed : %f, mode : %d\n",
+                     prop->wrap_width, prop->speed, prop->mode);
+
+       to = pack_int32(to, prop->wrap_width);
+       to = pack_float(to, prop->speed);
+       to = pack_int8(to, prop->mode);
+
+       return to;
+}
+
+static char *_pack_list_prop(char *to, list_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("list prop: horizontal : %d, select_mode : %d, focus_on_selection : %d, multi_select : %d, "
+                     "multi_select_mode : %d, mode : %d\n",
+                     prop->horizontal, prop->select_mode, prop->focus_on_selection, prop->multi_select,
+                     prop->multi_select_mode, prop->mode);
+
+       to = pack_int8(to, prop->horizontal);
+       to = pack_int8(to, prop->select_mode);
+       to = pack_int8(to, prop->focus_on_selection);
+       to = pack_int8(to, prop->multi_select);
+       to = pack_int8(to, prop->multi_select_mode);
+       to = pack_int8(to, prop->mode);
+
+       return to;
+}
+
+static char *_pack_map_prop(char *to, map_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("map prop: zoom : %d, paused : %d, wheel_disabled : %d, zoom_min : %d, "
+                     "rotate_degree : %f, rotate : [%d,%d],\n\tagent : %s, zoom_max : %d, "
+                     "zoom_mode : %d, region : [%f,%f]\n",
+                     prop->zoom, prop->paused, prop->wheel_disabled, prop->zoom_min,
+                     prop->rotate_degree, prop->rotate[0], prop->rotate[1],
+                     prop->agent, prop->zoom_max, prop->zoom_mode, prop->region[0], prop->region[1]);
+
+       to = pack_int32(to, prop->zoom);
+       to = pack_int8(to, prop->paused);
+       to = pack_int8(to, prop->wheel_disabled);
+       to = pack_int32(to, prop->zoom_min);
+       to = pack_float(to, prop->rotate_degree);
+       to = pack_int32(to, prop->rotate[0]);
+       to = pack_int32(to, prop->rotate[1]);
+       to = pack_string(to, prop->agent);
+       to = pack_int32(to, prop->zoom_max);
+       to = pack_int8(to, prop->zoom_mode);
+       to = pack_float(to, prop->region[0]);
+       to = pack_float(to, prop->region[1]);
+
+       return to;
+}
+
+static char *_pack_notify_prop(char *to, notify_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("notify prop: align : [%f,%f], allow_events: %d, "
+                     "timeout : %f\n",
+                     prop->align[0], prop->align[1], prop->allow_events,
+                     prop->timeout);
+
+       to = pack_float(to, prop->align[0]);
+       to = pack_float(to, prop->align[1]);
+       to = pack_int8(to, prop->allow_events);
+       to = pack_float(to, prop->timeout);
+
+       return to;
+}
+
+static char *_pack_panel_prop(char *to, panel_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("panel prop: orient : %d, hidden : %d, scrollable : %d\n",
+                     prop->orient, prop->hidden, prop->scrollable);
+
+       to = pack_int8(to, prop->orient);
+       to = pack_int8(to, prop->hidden);
+       to = pack_int8(to, prop->scrollable);
+
+       return to;
+}
+
+static char *_pack_photo_prop(char *to, photo_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("photo prop: editable : %d, fill_inside : %d, aspect_fixed : %d, size : %d\n",
+                     prop->editable, prop->fill_inside, prop->aspect_fixed, prop->size);
+
+       to = pack_int8(to, prop->editable);
+       to = pack_int8(to, prop->fill_inside);
+       to = pack_int8(to, prop->aspect_fixed);
+       to = pack_int32(to, prop->size);
+
+       return to;
+}
+
+static char *_pack_photocam_prop(char *to, photocam_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("photocam prop: paused : %d, file : %f, gesture_enabled : %d, zoom : %f, "
+                     "zoom_mode : %d, image_size : [%d,%d]\n",
+                     prop->paused, prop->file, prop->gesture_enabled, prop->zoom,
+                     prop->zoom_mode, prop->image_size[0], prop->image_size[1]);
+
+       to = pack_int8(to, prop->paused);
+       to = pack_string(to, prop->file);
+       to = pack_int8(to, prop->gesture_enabled);
+       to = pack_float(to, prop->zoom);
+       to = pack_int8(to, prop->zoom_mode);
+       to = pack_int32(to, prop->image_size[0]);
+       to = pack_int32(to, prop->image_size[1]);
+
+       return to;
+}
+
+static char *_pack_popup_prop(char *to, popup_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("popup prop: align : [%f,%f], allow_events : %d, wrap_type : %d, orient : %d, "
+                     "timeout : %f\n",
+                     prop->align[0], prop->align[1], prop->allow_events, prop->wrap_type,
+                     prop->orient, prop->timeout);
+
+       to = pack_float(to, prop->align[0]);
+       to = pack_float(to, prop->align[1]);
+       to = pack_int8(to, prop->allow_events);
+       to = pack_int8(to, prop->wrap_type);
+       to = pack_int8(to, prop->orient);
+       to = pack_float(to, prop->timeout);
+
+       return to;
+}
+
+static char *_pack_progressbar_prop(char *to, progressbar_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("progressbar prop: span_size : %d, pulse : %d, value : %f, inverted : %d, "
+                     "horizontal : %d, unit_format : %s\n",
+                     prop->span_size, prop->pulse, prop->value, prop->inverted,
+                     prop->horizontal, prop->unit_format);
+
+       to = pack_int32(to, prop->span_size);
+       to = pack_int8(to, prop->pulse);
+       to = pack_float(to, prop->value);
+       to = pack_int8(to, prop->inverted);
+       to = pack_int8(to, prop->horizontal);
+       to = pack_string(to, prop->unit_format);
+
+       return to;
+}
+
+static char *_pack_radio_prop(char *to, radio_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("radio prop: state_value : %d, value : %d\n",
+                     prop->state_value, prop->value);
+
+       to = pack_int32(to, prop->state_value);
+       to = pack_int32(to, prop->value);
+
+       return to;
+}
+
+static char *_pack_segmencontrol_prop(char *to, segmencontrol_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("segmencontrol prop: item_count : %d\n",
+                     prop->item_count);
+
+       to = pack_int32(to, prop->item_count);
+
+       return to;
+}
+
+static char *_pack_slider_prop(char *to, slider_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("slider prop: horizontal : %d, value : %f, format : %s\n",
+                     prop->horizontal, prop->value, prop->format);
+
+       to = pack_int8(to, prop->horizontal);
+       to = pack_float(to, prop->value);
+       to = pack_string(to, prop->format);
+
+       return to;
+}
+
+static char *_pack_spinner_prop(char *to, spinner_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("spinner prop: min : %f, max : %f, step : %f, wrap : %d, "
+                     "interval : %f, round : %d, editable : %d, "
+                     "base : %f, value : %f, format : %s\n",
+                     prop->min_max[0], prop->min_max[1], prop->step, prop->wrap,
+                     prop->interval, prop->round, prop->editable, prop->base,
+                     prop->value, prop->format);
+
+       to = pack_float(to, prop->min_max[0]);
+       to = pack_float(to, prop->min_max[1]);
+       to = pack_float(to, prop->step);
+       to = pack_int8(to, prop->wrap);
+       to = pack_float(to, prop->interval);
+       to = pack_int32(to, prop->round);
+       to = pack_int8(to, prop->editable);
+       to = pack_float(to, prop->base);
+       to = pack_float(to, prop->value);
+       to = pack_string(to, prop->format);
+
+       return to;
+}
+
+static char *_pack_toolbar_prop(char *to, toolbar_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("toolbar prop: reorder_mode : %d, transverse_expanded : %d, homogeneous : %d, align : %f, "
+                     "select_mode : %d, icon_size : %d, horizontal : %d,\n\tstandard_priority : %d, "
+                     "items_count : %d\n",
+                     prop->reorder_mode, prop->transverse_expanded, prop->homogeneous, prop->align,
+                     prop->select_mode, prop->icon_size, prop->horizontal, prop->standard_priority,
+                     prop->items_count);
+
+       to = pack_int8(to, prop->reorder_mode);
+       to = pack_int8(to, prop->transverse_expanded);
+       to = pack_int8(to, prop->homogeneous);
+       to = pack_float(to, prop->align);
+       to = pack_int8(to, prop->select_mode);
+       to = pack_int32(to, prop->icon_size);
+       to = pack_int8(to, prop->horizontal);
+       to = pack_int32(to, prop->standard_priority);
+       to = pack_int32(to, prop->items_count);
+
+       return to;
+}
+
+static char *_pack_tooltip_prop(char *to, tooltip_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("tooltip prop: style : %s, window_mode : %d\n",
+                     prop->style, prop->window_mode);
+
+       to = pack_string(to, prop->style);
+       to = pack_int8(to, prop->window_mode);
+
+       return to;
+}
+
+static char *_pack_win_prop(char *to, win_prop_t *prop)
+{
+       if (!prop)
+               return to;
+
+       ui_viewer_log("win prop: iconfield : %d, maximized : %d, modal : %d, icon_name : %s, "
+                     "withdrawn : %d, role : %s, size_step : [%d,%d], highlight_style : %s,\n\t"
+                     "borderless : %d, highlight_enabled : %d, title : %s, alpha: %d, "
+                     "urgent : %d, rotation : %d, sticky : %d, highlight_animate : %d,\n\t"
+                     "aspect : %f, indicator_opacity : %d, demand_attention : %d, "
+                     "layer : %d, profile : %s, shaped : %d, indicator_mode : %d, conformant : %d,\n\t"
+                     "size_base : [%d,%d], quickpanel : %d, rotation_supported : %d, screen_dpi : [%d,%d], "
+                     "win_type : %d\n",
+                     prop->iconfield, prop->maximized, prop->modal, prop->icon_name,
+                     prop->withdrawn, prop->role, prop->size_step[0], prop->size_step[1],
+                     prop->highlight_style, prop->borderless, prop->highlight_enabled, prop->title,
+                     prop->alpha, prop->urgent, prop->rotation, prop->sticky,
+                     prop->highlight_animate, prop->aspect, prop->indicator_opacity, prop->demand_attention, prop->layer,
+                     prop->profile, prop->shaped, prop->fullscreen, prop->indicator_mode, prop->conformant,
+                     prop->size_base[0], prop->size_base[1], prop->quickpanel, prop->rotation_supported, prop->screen_dpi[0],
+                     prop->screen_dpi[1], prop->win_type);
+
+       to = pack_int8(to, prop->iconfield);
+       to = pack_int8(to, prop->maximized);
+       to = pack_int8(to, prop->modal);
+       to = pack_string(to, prop->icon_name);
+       to = pack_int8(to, prop->withdrawn);
+       to = pack_string(to, prop->role);
+       to = pack_int32(to, prop->size_step[0]);
+       to = pack_int32(to, prop->size_step[1]);
+       to = pack_string(to, prop->highlight_style);
+       to = pack_int8(to, prop->borderless);
+       to = pack_int8(to, prop->highlight_enabled);
+       to = pack_string(to, prop->title);
+       to = pack_int8(to, prop->alpha);
+       to = pack_int8(to, prop->urgent);
+       to = pack_int32(to, prop->rotation);
+       to = pack_int8(to, prop->sticky);
+       to = pack_int8(to, prop->highlight_animate);
+       to = pack_float(to, prop->aspect);
+       to = pack_int8(to, prop->indicator_opacity);
+       to = pack_int8(to, prop->demand_attention);
+       to = pack_int32(to, prop->layer);
+       to = pack_string(to, prop->profile);
+       to = pack_int8(to, prop->shaped);
+       to = pack_int8(to, prop->fullscreen);
+       to = pack_int8(to, prop->indicator_mode);
+       to = pack_int8(to, prop->conformant);
+       to = pack_int32(to, prop->size_base[0]);
+       to = pack_int32(to, prop->size_base[1]);
+       to = pack_int8(to, prop->quickpanel);
+       to = pack_int8(to, prop->rotation_supported);
+       to = pack_int32(to, prop->screen_dpi[0]);
+       to = pack_int32(to, prop->screen_dpi[1]);
+       to = pack_int8(to, prop->win_type);
+
+       return to;
+}
+
+static char *pack_ui_obj_prop(char *to, Evas_Object *obj, const char *type_name)
+{
+       ui_obj_prop_t obj_prop;
+       enum ui_obj_category_t category;
+       enum ui_obj_code_t code;
+
+       evas_object_geometry_get(obj, &obj_prop.geometry[0], &obj_prop.geometry[1],
+                                &obj_prop.geometry[2], &obj_prop.geometry[3]);
+       obj_prop.focus = evas_object_focus_get(obj);
+       _strncpy(obj_prop.name, evas_object_name_get(obj), MAX_PATH_LENGTH);
+       obj_prop.visible = evas_object_visible_get(obj);
+       evas_object_color_get(obj, &obj_prop.color[0], &obj_prop.color[1],
+                             &obj_prop.color[2], &obj_prop.color[3]);
+       obj_prop.anti_alias = evas_object_anti_alias_get(obj);
+       obj_prop.scale = evas_object_scale_get(obj);
+       evas_object_size_hint_min_get(obj, &obj_prop.size_min[0], &obj_prop.size_min[1]);
+       evas_object_size_hint_max_get(obj, &obj_prop.size_max[0], &obj_prop.size_max[1]);
+       evas_object_size_hint_request_get(obj, &obj_prop.size_request[0], &obj_prop.size_request[1]);
+       evas_object_size_hint_align_get(obj, &obj_prop.size_align[0], &obj_prop.size_align[1]);
+       evas_object_size_hint_weight_get(obj, &obj_prop.size_weight[0], &obj_prop.size_weight[1]);
+       evas_object_size_hint_padding_get(obj, &obj_prop.size_padding[0], &obj_prop.size_padding[1],
+                                         &obj_prop.size_padding[2], &obj_prop.size_padding[3]);
+       obj_prop.render_op = evas_object_render_op_get(obj);
+
+       to = _pack_ui_obj_evas_prop(to, &obj_prop);
+
+       category = _get_object_category(type_name);
+       if (category == UI_UNDEFINED) {
+               return to;
+       } else if (category == UI_ELM) {
+               ui_obj_elm_prop_t elm_prop;
+
+               if (!strcmp(type_name, "elm_pan")) {
+                       strcpy(elm_prop.text, "");
+                       strcpy(elm_prop.style, "");
+                       elm_prop.disabled = 0;
+               } else {
+                       _strncpy(elm_prop.text, elm_object_text_get(obj), MAX_TEXT_LENGTH);
+                       _strncpy(elm_prop.style, elm_object_style_get(obj), MAX_PATH_LENGTH);
+                       elm_prop.disabled = elm_object_disabled_get(obj);
+               }
+               _strncpy(elm_prop.type, elm_object_widget_type_get(obj), MAX_PATH_LENGTH);
+
+               to = _pack_ui_obj_elm_prop(to, &elm_prop);
+
+       } else if (category == UI_EDJE) {
+               ui_obj_edje_prop_t edje_prop;
+               edje_prop.animation = edje_object_animation_get(obj);
+               edje_prop.play = edje_object_play_get(obj);
+               edje_prop.scale = edje_object_scale_get(obj);
+               edje_prop.base_scale = edje_object_base_scale_get(obj);
+               edje_object_size_min_get(obj, &edje_prop.size_min[0], &edje_prop.size_min[1]);
+               edje_object_size_max_get(obj, &edje_prop.size_max[0], &edje_prop.size_max[1]);
+
+               to = _pack_ui_obj_edje_prop(to, &edje_prop);
+       }
+
+       code = _get_object_type_code(type_name);
+
+       if (code == 0) {
+               return to;
+       } else if (code == UI_EVAS_IMAGE) {
+               image_prop_t image_prop;
+
+               image_prop.load_dpi = evas_object_image_load_dpi_get(obj);
+               image_prop.source_clip = evas_object_image_source_clip_get(obj);
+               image_prop.filled = evas_object_image_filled_get(obj);
+               image_prop.content_hint = evas_object_image_content_hint_get(obj);
+               image_prop.alpha = evas_object_image_alpha_get(obj);
+               evas_object_image_border_get(obj, &(image_prop.border[0]),
+                                         &(image_prop.border[1]),
+                                         &(image_prop.border[2]),
+                                         &(image_prop.border[3]));
+               image_prop.border_scale = evas_object_image_border_scale_get(obj);
+               image_prop.pixels_dirty = evas_object_image_pixels_dirty_get(obj);
+               image_prop.load_orientation = evas_object_image_load_orientation_get(obj);
+               image_prop.border_center_fill = evas_object_image_border_center_fill_get(obj);
+               evas_object_image_size_get(obj, &(image_prop.size[0]), &(image_prop.size[1]));
+               image_prop.source_visible = evas_object_image_source_visible_get(obj);
+               evas_object_image_fill_get(obj, &(image_prop.fill[0]),
+                                       &(image_prop.fill[1]),
+                                       &(image_prop.fill[2]),
+                                       &(image_prop.fill[3]));
+               image_prop.load_scale_down = evas_object_image_load_scale_down_get(obj);
+               image_prop.scale_hint = evas_object_image_scale_hint_get(obj);
+               image_prop.source_events = evas_object_image_source_events_get(obj);
+               //evas_object_image_animated_frame_count_get(obj); - unstable
+               image_prop.frame_count = 0;
+               image_prop.evas_image_stride = evas_object_image_stride_get(obj);
+
+               to = _pack_image_prop(to, &image_prop);
+       } else if (code == UI_EVAS_LINE) {
+               line_prop_t line_prop;
+
+               evas_object_line_xy_get(obj, &(line_prop.xy[0]),
+                                    &(line_prop.xy[1]),
+                                    &(line_prop.xy[2]),
+                                    &(line_prop.xy[3]));
+
+               to = _pack_line_prop(to, &line_prop);
+       } else if (code == UI_EVAS_TEXT) {
+               text_prop_t text_prop;
+               const char *text_font;
+
+               evas_object_text_font_get(obj, &text_font, &(text_prop.size));
+               _strncpy(text_prop.font, text_font, MAX_PATH_LENGTH);
+               _strncpy(text_prop.text, evas_object_text_text_get(obj), MAX_PATH_LENGTH);
+               _strncpy(text_prop.delim, evas_object_text_bidi_delimiters_get(obj), MAX_PATH_LENGTH);
+               text_prop.ellipsis = evas_object_text_ellipsis_get(obj);
+               text_prop.style = evas_object_text_style_get(obj);
+               evas_object_text_shadow_color_get(obj, &(text_prop.shadow_color[0]),
+                                              &(text_prop.shadow_color[1]),
+                                              &(text_prop.shadow_color[2]),
+                                              &(text_prop.shadow_color[3]));
+               evas_object_text_glow_color_get(obj, &(text_prop.glow_color[0]),
+                                            &(text_prop.glow_color[1]),
+                                            &(text_prop.glow_color[2]),
+                                            &(text_prop.glow_color[3]));
+               evas_object_text_glow2_color_get(obj, &(text_prop.glow2_color[0]),
+                                             &(text_prop.glow2_color[1]),
+                                             &(text_prop.glow2_color[2]),
+                                             &(text_prop.glow2_color[3]));
+               evas_object_text_outline_color_get(obj, &(text_prop.outline_color[0]),
+                                               &(text_prop.outline_color[1]),
+                                               &(text_prop.outline_color[2]),
+                                               &(text_prop.outline_color[3]));
+               evas_object_text_style_pad_get(obj, &(text_prop.style_pad[0]),
+                                           &(text_prop.style_pad[1]),
+                                           &(text_prop.style_pad[2]),
+                                           &(text_prop.style_pad[3]));
+               text_prop.direction = evas_object_text_direction_get(obj);
+
+               to = _pack_text_prop(to, &text_prop);
+       } else if (code == UI_EVAS_TEXTBLOCK) {
+               textblock_prop_t textblock_prop;
+
+               _strncpy(textblock_prop.replace_char, evas_object_textblock_replace_char_get(obj), MAX_PATH_LENGTH);
+               textblock_prop.valign = evas_object_textblock_valign_get(obj);
+               _strncpy(textblock_prop.delim, evas_object_textblock_bidi_delimiters_get(obj), MAX_PATH_LENGTH);
+               textblock_prop.newline = evas_object_textblock_legacy_newline_get(obj);
+               _strncpy(textblock_prop.markup, evas_object_textblock_text_markup_get(obj), MAX_PATH_LENGTH);
+
+               to = _pack_textblock_prop(to, &textblock_prop);
+       } else if (code == UI_EVAS_TABLE) {
+               table_prop_t table_prop;
+
+               table_prop.homogeneous = evas_object_table_homogeneous_get(obj);
+               evas_object_table_align_get(obj, &(table_prop.align[0]),
+                                        &(table_prop.align[1]));
+               evas_object_table_padding_get(obj, &(table_prop.padding[0]),
+                                          &(table_prop.padding[1]));
+               table_prop.mirrored = evas_object_table_mirrored_get(obj);
+               evas_object_table_col_row_size_get(obj, &(table_prop.col_row_size[0]),
+                                               &(table_prop.col_row_size[1]));
+
+               to = _pack_table_prop(to, &table_prop);
+       } else if (code == UI_EVAS_BOX) {
+               box_prop_t box_prop;
+
+               evas_object_box_align_get(obj, &(box_prop.align[0]),
+                                      &(box_prop.align[1]));
+
+               to = _pack_box_prop(to, &box_prop);
+       } else if (code == UI_EVAS_GRID) {
+               grid_prop_t grid_prop;
+
+               grid_prop.mirrored = evas_object_grid_mirrored_get(obj);
+
+               to = _pack_grid_prop(to, &grid_prop);
+       } else if (code == UI_EVAS_TEXTGRID) {
+               textgrid_prop_t textgrid_prop;
+
+               evas_object_textgrid_size_get(obj, &(textgrid_prop.size[0]),
+                                          &(textgrid_prop.size[1]));
+               evas_object_textgrid_cell_size_get(obj, &(textgrid_prop.cell_size[0]),
+                                               &(textgrid_prop.cell_size[1]));
+
+               to = _pack_textgrid_prop(to, &textgrid_prop);
+       } else if (code == UI_ELM_BACKGROUND) {
+               bg_prop_t bg_prop;
+
+               elm_bg_color_get(obj, &(bg_prop.color[0]),
+                                     &(bg_prop.color[1]),
+                                     &(bg_prop.color[2]));
+               bg_prop.option = elm_bg_option_get(obj);
+
+               to = _pack_bg_prop(to, &bg_prop);
+       } else if (code == UI_ELM_BUTTON) {
+               button_prop_t button_prop;
+
+               button_prop.initial_timeout = elm_button_autorepeat_initial_timeout_get(obj);
+               button_prop.gap_timeout = elm_button_autorepeat_gap_timeout_get(obj);
+               button_prop.autorepeat = elm_button_autorepeat_get(obj);
+
+               to = _pack_button_prop(to, &button_prop);
+       } else if (code == UI_ELM_CHECK) {
+               check_prop_t check_prop;
+
+               check_prop.state = elm_check_state_get(obj);
+
+               to = _pack_check_prop(to, &check_prop);
+       } else if (code == UI_ELM_COLORSELECTOR) {
+               colorselector_prop_t colorselector_prop;
+
+               elm_colorselector_color_get(obj, &(colorselector_prop.color[0]),
+                                        &(colorselector_prop.color[1]),
+                                        &(colorselector_prop.color[2]),
+                                        &(colorselector_prop.color[3]));
+               _strncpy(colorselector_prop.palette_name, elm_colorselector_palette_name_get(obj), MAX_PATH_LENGTH);
+               colorselector_prop.mode = elm_colorselector_mode_get(obj);
+
+               to = _pack_colorselector_prop(to, &colorselector_prop);
+       } else if (code == UI_ELM_CTXPOPUP) {
+               ctxpopup_prop_t ctxpopup_prop;
+
+               ctxpopup_prop.horizontal = elm_ctxpopup_horizontal_get(obj);
+
+               to = _pack_ctxpopup_prop(to, &ctxpopup_prop);
+       } else if (code == UI_ELM_DATETIME) {
+               datetime_prop_t datetime_prop;
+               struct tm currtime;
+
+               _strncpy(datetime_prop.format, elm_datetime_format_get(obj), MAX_PATH_LENGTH);
+               elm_datetime_value_get(obj, &currtime);
+               datetime_prop.value[0] = currtime.tm_sec;
+               datetime_prop.value[1] = currtime.tm_min;
+               datetime_prop.value[2] = currtime.tm_hour;
+               datetime_prop.value[3] = currtime.tm_mday;
+               datetime_prop.value[4] = currtime.tm_mon;
+               datetime_prop.value[5] = currtime.tm_year;
+               datetime_prop.value[6] = currtime.tm_wday;
+               datetime_prop.value[7] = currtime.tm_yday;
+
+               to = _pack_datetime_prop(to, &datetime_prop);
+       } else if (code == UI_ELM_ENTRY) {
+               entry_prop_t entry_prop;
+
+               _strncpy(entry_prop.entry, elm_entry_entry_get(obj), MAX_PATH_LENGTH);
+               entry_prop.scrollable = elm_entry_scrollable_get(obj);
+               entry_prop.panel_show_on_demand = elm_entry_input_panel_show_on_demand_get(obj);
+               entry_prop.menu_disabled = elm_entry_context_menu_disabled_get(obj);
+               entry_prop.cnp_mode = elm_entry_cnp_mode_get(obj);
+               entry_prop.editable = elm_entry_editable_get(obj);
+               _strncpy(entry_prop.hover_style, elm_entry_anchor_hover_style_get(obj), MAX_PATH_LENGTH);
+               entry_prop.single_line= elm_entry_single_line_get(obj);
+               entry_prop.password = elm_entry_password_get(obj);
+               entry_prop.autosave = elm_entry_autosave_get(obj);
+               entry_prop.prediction_allow = elm_entry_prediction_allow_get(obj);
+               entry_prop.panel_enabled = elm_entry_input_panel_enabled_get(obj);
+               entry_prop.cursor_pos = elm_entry_cursor_pos_get(obj);
+               entry_prop.cursor_is_format = elm_entry_cursor_is_format_get(obj);
+               entry_prop.cursor_content = elm_entry_cursor_content_get(obj);
+               _strncpy(entry_prop.selection, elm_entry_selection_get(obj), MAX_PATH_LENGTH);
+               entry_prop.is_visible_format = elm_entry_cursor_is_visible_format_get(obj);
+
+               to = _pack_entry_prop(to, &entry_prop);
+       } else if (code == UI_ELM_FLIP) {
+               flip_prop_t flip_prop;
+
+               flip_prop.interaction = elm_flip_interaction_get(obj);
+               flip_prop.front_visible = elm_flip_front_visible_get(obj);
+
+               to = _pack_flip_prop(to, &flip_prop);
+       } else if (code == UI_ELM_GENGRID) {
+               gengrid_prop_t gengrid_prop;
+
+               elm_gengrid_align_get(obj, &(gengrid_prop.align[0]),
+                                  &(gengrid_prop.align[1]));
+               gengrid_prop.filled = elm_gengrid_filled_get(obj);
+               elm_gengrid_page_relative_get(obj, &(gengrid_prop.relative[0]),
+                                          &(gengrid_prop.relative[1]));
+               gengrid_prop.multi_select = elm_gengrid_multi_select_get(obj);
+               elm_gengrid_group_item_size_get(obj, &(gengrid_prop.group_item_size[0]),
+                                            &(gengrid_prop.group_item_size[1]));
+               gengrid_prop.select_mode = elm_gengrid_select_mode_get(obj);
+               gengrid_prop.render_mode = elm_gengrid_reorder_mode_get(obj);
+               gengrid_prop.highlight_mode = elm_gengrid_highlight_mode_get(obj);
+               elm_gengrid_item_size_get(obj, &(gengrid_prop.item_size[0]),
+                                      &(gengrid_prop.item_size[1]));
+               gengrid_prop.multi_select_mode = elm_gengrid_multi_select_mode_get(obj);
+               gengrid_prop.horizontal = elm_gengrid_horizontal_get(obj);
+               gengrid_prop.wheel_disabled = elm_gengrid_wheel_disabled_get(obj);
+               gengrid_prop.items_count = elm_gengrid_items_count(obj);
+
+               to = _pack_gengrid_prop(to, &gengrid_prop);
+       } else if (code == UI_ELM_GENLIST) {
+               genlist_prop_t genlist_prop;
+
+               genlist_prop.multi_select = elm_genlist_multi_select_get(obj);
+               genlist_prop.genlist_mode = elm_genlist_mode_get(obj);
+               genlist_prop.items_count = elm_genlist_items_count(obj);
+               genlist_prop.homogeneous = elm_genlist_homogeneous_get(obj);
+               genlist_prop.block_count = elm_genlist_block_count_get(obj);
+               genlist_prop.timeout = elm_genlist_longpress_timeout_get(obj);
+               genlist_prop.reorder_mode = elm_genlist_reorder_mode_get(obj);
+               genlist_prop.decorate_mode = elm_genlist_decorate_mode_get(obj);
+               genlist_prop.effect_enabled = elm_genlist_tree_effect_enabled_get(obj);
+               genlist_prop.select_mode = elm_genlist_select_mode_get(obj);
+               genlist_prop.highlight_mode = elm_genlist_highlight_mode_get(obj);
+               genlist_prop.realization_mode = elm_genlist_realization_mode_get(obj);
+
+               to = _pack_genlist_prop(to, &genlist_prop);
+       } else if (code == UI_ELM_GLVIEW) {
+               glview_prop_t glview_prop;
+
+               elm_glview_size_get(obj, &(glview_prop.size[0]),
+                                &(glview_prop.size[1]));
+               glview_prop.rotation = elm_glview_rotation_get(obj);
+
+               to = _pack_glview_prop(to, &glview_prop);
+       } else if (code == UI_ELM_ICON) {
+               icon_prop_t icon_prop;
+
+               icon_prop.lookup = elm_icon_order_lookup_get(obj);
+               _strncpy(icon_prop.standard, elm_icon_standard_get(obj), MAX_PATH_LENGTH);
+
+               to = _pack_icon_prop(to, &icon_prop);
+       } else if (code == UI_ELM_IMAGE) {
+               elm_image_prop_t elm_image_prop;
+
+               elm_image_prop.editable = elm_image_editable_get(obj);
+               // elm_image_animated_available_get(obj); - unstable
+               elm_image_prop.animated_available = EINA_FALSE;
+               // elm_image_animated_play_get(obj); - unstable
+               elm_image_prop.play = EINA_FALSE;
+               elm_image_prop.smooth = elm_image_smooth_get(obj);
+               elm_image_prop.no_scale = elm_image_no_scale_get(obj);
+               elm_image_prop.animated = elm_image_animated_get(obj);
+               elm_image_prop.aspect_fixed = elm_image_aspect_fixed_get(obj);
+               elm_image_prop.orient = elm_image_orient_get(obj);
+               elm_image_prop.fill_outside = elm_image_fill_outside_get(obj);
+               elm_image_resizable_get(obj, &(elm_image_prop.resizable[0]),
+                                    &(elm_image_prop.resizable[1]));
+               elm_image_object_size_get(obj, &(elm_image_prop.size[0]),
+                                      &(elm_image_prop.size[1]));
+
+               to = _pack_elm_image_prop(to, &elm_image_prop);
+       } else if (code == UI_ELM_INDEX) {
+               index_prop_t index_prop;
+
+               index_prop.autohide_disabled = elm_index_autohide_disabled_get(obj);
+               index_prop.omit_enabled = elm_index_omit_enabled_get(obj);
+               index_prop.priority = elm_index_priority_get(obj);
+               index_prop.horizontal = elm_index_horizontal_get(obj);
+               index_prop.change_time = elm_index_delay_change_time_get(obj);
+               index_prop.indicator_disabled = elm_index_indicator_disabled_get(obj);
+               index_prop.item_level = elm_index_item_level_get(obj);
+
+               to = _pack_index_prop(to, &index_prop);
+       } else if (code == UI_ELM_LABEL) {
+               label_prop_t label_prop;
+
+               label_prop.wrap_width = elm_label_wrap_width_get(obj);
+               label_prop.speed = elm_label_slide_speed_get(obj);
+               label_prop.mode = elm_label_slide_mode_get(obj);
+
+               to = _pack_label_prop(to, &label_prop);
+       } else if (code == UI_ELM_LIST) {
+               list_prop_t list_prop;
+
+               list_prop.horizontal = elm_list_horizontal_get(obj);
+               list_prop.select_mode = elm_list_select_mode_get(obj);
+               list_prop.focus_on_selection = elm_list_focus_on_selection_get(obj);
+               list_prop.multi_select = elm_list_multi_select_get(obj);
+               list_prop.multi_select_mode = elm_list_multi_select_mode_get(obj);
+               list_prop.mode = elm_list_mode_get(obj);
+
+               to = _pack_list_prop(to, &list_prop);
+       } else if (code == UI_ELM_MAP) {
+               map_prop_t map_prop;
+
+               map_prop.zoom = elm_map_zoom_get(obj);
+               map_prop.paused = elm_map_paused_get(obj);
+               map_prop.wheel_disabled = elm_map_wheel_disabled_get(obj);
+               map_prop.zoom_min = elm_map_zoom_min_get(obj);
+               elm_map_rotate_get(obj, &(map_prop.rotate_degree),
+                               &(map_prop.rotate[0]),
+                               &(map_prop.rotate[1]));
+               _strncpy(map_prop.agent, elm_map_user_agent_get(obj), MAX_PATH_LENGTH);
+               map_prop.zoom_max = elm_map_zoom_max_get(obj);
+               map_prop.zoom_mode = elm_map_zoom_mode_get(obj);
+               elm_map_region_get(obj, &(map_prop.region[0]),
+                               &(map_prop.region[1]));
+
+               to = _pack_map_prop(to, &map_prop);
+       } else if (code == UI_ELM_NOTIFY) {
+               notify_prop_t notify_prop;
+
+               elm_notify_align_get(obj, &(notify_prop.align[0]),
+                                 &(notify_prop.align[1]));
+               notify_prop.allow_events = elm_notify_allow_events_get(obj);
+               notify_prop.timeout = elm_notify_timeout_get(obj);
+
+               to = _pack_notify_prop(to, &notify_prop);
+       } else if (code == UI_ELM_PANEL) {
+               panel_prop_t panel_prop;
+
+               panel_prop.orient = elm_panel_orient_get(obj);
+               panel_prop.hidden = elm_panel_hidden_get(obj);
+               panel_prop.scrollable = elm_panel_scrollable_get(obj);
+
+               to = _pack_panel_prop(to, &panel_prop);
+       } else if (code == UI_ELM_PHOTO) {
+               photo_prop_t photo_prop;
+
+               photo_prop.editable = elm_photo_editable_get(obj);
+               photo_prop.fill_inside = elm_photo_fill_inside_get(obj);
+               photo_prop.aspect_fixed = elm_photo_aspect_fixed_get(obj);
+               photo_prop.size = elm_photo_size_get(obj);
+
+               to = _pack_photo_prop(to, &photo_prop);
+       } else if (code == UI_ELM_PHOTOCAM) {
+               photocam_prop_t photocam_prop;
+
+               photocam_prop.paused = elm_photocam_paused_get(obj);
+               _strncpy(photocam_prop.file, elm_photocam_file_get(obj), MAX_PATH_LENGTH);
+               photocam_prop.gesture_enabled = elm_photocam_gesture_enabled_get(obj);
+               photocam_prop.zoom = elm_photocam_zoom_get(obj);
+               photocam_prop.zoom_mode = elm_photocam_zoom_mode_get(obj);
+               elm_photocam_image_size_get(obj, &(photocam_prop.image_size[0]),
+                                        &(photocam_prop.image_size[1]));
+
+               to = _pack_photocam_prop(to, &photocam_prop);
+       } else if (code == UI_ELM_POPUP) {
+               popup_prop_t popup_prop;
+
+               elm_popup_align_get(obj, &(popup_prop.align[0]),
+                                &(popup_prop.align[1]));
+               popup_prop.allow_events = elm_popup_allow_events_get(obj);
+               popup_prop.wrap_type = elm_popup_content_text_wrap_type_get(obj);
+               popup_prop.orient = elm_popup_orient_get(obj);
+               popup_prop.timeout = elm_popup_timeout_get(obj);
+
+               to = _pack_popup_prop(to, &popup_prop);
+       } else if (code == UI_ELM_PROGRESSBAR) {
+               progressbar_prop_t progressbar_prop;
+
+               progressbar_prop.span_size = elm_progressbar_span_size_get(obj);
+               progressbar_prop.pulse = elm_progressbar_pulse_get(obj);
+               progressbar_prop.value = elm_progressbar_value_get(obj);
+               progressbar_prop.inverted = elm_progressbar_inverted_get(obj);
+               progressbar_prop.horizontal = elm_progressbar_horizontal_get(obj);
+               _strncpy(progressbar_prop.unit_format, elm_progressbar_unit_format_get(obj), MAX_PATH_LENGTH);
+
+               to = _pack_progressbar_prop(to, &progressbar_prop);
+       } else if (code == UI_ELM_RADIO) {
+               radio_prop_t radio_prop;
+
+               radio_prop.state_value = elm_radio_state_value_get(obj);
+               radio_prop.value = elm_radio_value_get(obj);
+
+               to = _pack_radio_prop(to, &radio_prop);
+       } else if (code == UI_ELM_SEGMENTCONTROL) {
+               segmencontrol_prop_t segmencontrol_prop;
+
+               segmencontrol_prop.item_count = elm_segment_control_item_count_get(obj);
+
+               to = _pack_segmencontrol_prop(to, &segmencontrol_prop);
+       } else if (code == UI_ELM_SLIDER) {
+               slider_prop_t slider_prop;
+
+               slider_prop.horizontal = elm_slider_horizontal_get(obj);
+               slider_prop.value = elm_slider_value_get(obj);
+               _strncpy(slider_prop.format, elm_slider_indicator_format_get(obj), MAX_PATH_LENGTH);
+
+               to = _pack_slider_prop(to, &slider_prop);
+       } else if (code == UI_ELM_SPINNER) {
+               spinner_prop_t spinner_prop;
+
+               elm_spinner_min_max_get(obj, &(spinner_prop.min_max[0]),
+                                    &(spinner_prop.min_max[1]));
+               spinner_prop.step = elm_spinner_step_get(obj);
+               spinner_prop.wrap = elm_spinner_wrap_get(obj);
+               spinner_prop.interval = elm_spinner_interval_get(obj);
+               spinner_prop.round = elm_spinner_round_get(obj);
+               spinner_prop.editable = elm_spinner_editable_get(obj);
+               spinner_prop.base = elm_spinner_base_get(obj);
+               spinner_prop.value = elm_spinner_value_get(obj);
+               _strncpy(spinner_prop.format, elm_spinner_label_format_get(obj), MAX_PATH_LENGTH);
+
+               to = _pack_spinner_prop(to, &spinner_prop);
+       } else if (code == UI_ELM_TOOLBAR) {
+               toolbar_prop_t toolbar_prop;
+
+               toolbar_prop.reorder_mode = elm_toolbar_reorder_mode_get(obj);
+               toolbar_prop.transverse_expanded = elm_toolbar_transverse_expanded_get(obj);
+               toolbar_prop.homogeneous = elm_toolbar_homogeneous_get(obj);
+               toolbar_prop.align = elm_toolbar_align_get(obj);
+               toolbar_prop.select_mode = elm_toolbar_select_mode_get(obj);
+               toolbar_prop.icon_size = elm_toolbar_icon_size_get(obj);
+               toolbar_prop.horizontal = elm_toolbar_horizontal_get(obj);
+               toolbar_prop.standard_priority = elm_toolbar_standard_priority_get(obj);
+               toolbar_prop.items_count = elm_toolbar_items_count(obj);
+
+               to = _pack_toolbar_prop(to, &toolbar_prop);
+       } else if (code == UI_ELM_TOOLTIP) {
+               tooltip_prop_t tooltip_prop;
+
+               _strncpy(tooltip_prop.style, elm_object_tooltip_style_get(obj), MAX_PATH_LENGTH);
+               tooltip_prop.window_mode = elm_object_tooltip_window_mode_get(obj);
+
+               to = _pack_tooltip_prop(to, &tooltip_prop);
+       } else if (code == UI_ELM_WIN) {
+               win_prop_t win_prop;
+
+               win_prop.iconfield = elm_win_iconified_get(obj);
+               win_prop.maximized = elm_win_maximized_get(obj);
+               win_prop.modal = elm_win_modal_get(obj);
+               _strncpy(win_prop.icon_name, elm_win_icon_name_get(obj), MAX_PATH_LENGTH);
+               win_prop.withdrawn = elm_win_withdrawn_get(obj);
+               _strncpy(win_prop.role, elm_win_role_get(obj), MAX_PATH_LENGTH);
+               elm_win_size_step_get(obj, &(win_prop.size_step[0]),
+                                  &(win_prop.size_step[1]));
+               _strncpy(win_prop.highlight_style, elm_win_focus_highlight_style_get(obj), MAX_PATH_LENGTH);
+               win_prop.borderless = elm_win_borderless_get(obj);
+               win_prop.highlight_enabled = elm_win_focus_highlight_enabled_get(obj);
+               _strncpy(win_prop.title, elm_win_title_get(obj), MAX_PATH_LENGTH);
+               win_prop.alpha = elm_win_alpha_get(obj);
+               win_prop.urgent = elm_win_urgent_get(obj);
+               win_prop.rotation = elm_win_rotation_get(obj);
+               win_prop.sticky = elm_win_sticky_get(obj);
+               win_prop.highlight_animate = elm_win_focus_highlight_animate_get(obj);
+               win_prop.aspect = elm_win_aspect_get(obj);
+               win_prop.indicator_opacity = elm_win_indicator_opacity_get(obj);
+               win_prop.demand_attention = elm_win_demand_attention_get(obj);
+               win_prop.layer = elm_win_layer_get(obj);
+               _strncpy(win_prop.profile, elm_win_profile_get(obj), MAX_PATH_LENGTH);
+               win_prop.shaped = elm_win_shaped_get(obj);
+               win_prop.fullscreen = elm_win_fullscreen_get(obj);
+               win_prop.indicator_mode = elm_win_indicator_mode_get(obj);
+               win_prop.conformant = elm_win_conformant_get(obj);
+               elm_win_size_base_get(obj, &(win_prop.size_base[0]),
+                                  &(win_prop.size_base[1]));
+               win_prop.quickpanel = elm_win_quickpanel_get(obj);
+               win_prop.rotation_supported = elm_win_wm_rotation_supported_get(obj);
+               elm_win_screen_dpi_get(obj, &(win_prop.screen_dpi[0]),
+                                   &(win_prop.screen_dpi[1]));
+               win_prop.win_type = elm_win_type_get(obj);
+               to = _pack_win_prop(to, &win_prop);
+
+       }
+
+       return to;
+}
+
+Eina_Bool _get_shot_in_bg(Evas_Object *obj)
+{
+       char type_name[MAX_PATH_LENGTH];
+       Eina_Bool can_shot_in_bg = EINA_FALSE;
+
+       _strncpy(type_name, evas_object_type_get(obj), MAX_PATH_LENGTH);
+
+       if (!strcmp(type_name, "rectangle") ||
+           !strcmp(type_name, "image") ||
+           !strcmp(type_name, "elm_image") ||
+           !strcmp(type_name, "elm_icon"))
+               can_shot_in_bg = EINA_TRUE;
+
+       return can_shot_in_bg;
+}
+
+char *pack_ui_obj_screenshot(char *to, Evas_Object *obj)
+{
+       char screenshot[MAX_PATH_LENGTH];
+       enum ErrorCode err_code = ERR_NO;
+       Eina_Bool exists;
+
+       screenshot[0] = '\0';
+
+       pthread_mutex_lock(&request_lock);
+
+       exists = _get_obj_exists(obj);
+
+       if (!exists) {
+               err_code = ERR_UI_OBJ_NOT_FOUND;
+               ui_viewer_log("can't take screenshot of not existing obj = %p\n", obj);
+       } else {
+               Evas_Object *win_id;
+               Eina_Bool win_focus;
+               Evas *evas;
+
+               evas_object_ref(obj);
+               evas = evas_object_evas_get(obj);
+               evas_event_freeze(evas);
+               win_id = _get_win_id(evas);
+               win_focus = elm_win_focus_get(win_id);
+
+               if (win_focus || _get_shot_in_bg(obj))
+                       ui_viewer_capture_screen(screenshot, obj);
+               else
+                       err_code = ERR_UI_OBJ_SCREENSHOT_FAILED;
+               evas_event_thaw(evas);
+               evas_object_unref(obj);
+       }
+
+       ui_viewer_log("screenshot: obj : %p, err_code : %d, path : %s\n", obj, err_code, screenshot);
+
+       to = pack_int32(to, err_code);
+       to = pack_string(to, screenshot);
+
+       pthread_mutex_unlock(&request_lock);
+
+       return to;
+}
diff --git a/ui_viewer/ui_viewer_data.h b/ui_viewer/ui_viewer_data.h
new file mode 100644 (file)
index 0000000..a16ef41
--- /dev/null
@@ -0,0 +1,551 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Lyupa Anastasia <a.lyupa@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 _UI_VIEWER_DATA_
+#define _UI_VIEWER_DATA_
+
+#include <Evas.h>
+
+#define MAX_PATH_LENGTH                256
+#define MAX_TEXT_LENGTH                1024
+
+enum ErrorCode {
+       ERR_NO                          = 0,    /* success */
+       ERR_ALREADY_RUNNING             = -102, /* already running */
+       ERR_UI_OBJ_NOT_FOUND            = -207, /* requested ui object is not found */
+       ERR_UI_OBJ_SCREENSHOT_FAILED    = -208, /* requested ui object is in background */
+       ERR_UNKNOWN                     = -999  /* unknown error */
+};
+
+enum hierarchy_status_t {
+       HIERARCHY_NOT_RUNNING,
+       HIERARCHY_RUNNING,
+       HIERARCHY_CANCELLED
+};
+
+enum rendering_option_t {
+       RENDER_NONE = 0x0,
+       RENDER_ALL = 0x1,
+       RENDER_ELM = 0x2,
+       RENDER_NONE_HOST_OPT = 0x3 /* it's equal to RENDER_NONE for target*/
+};
+
+enum ui_obj_category_t {
+       UI_UNDEFINED    = 0x00,
+       UI_EVAS         = 0x01,
+       UI_ELM          = 0x02,
+       UI_EDJE         = 0x03
+};
+
+enum ui_obj_code_t {
+       UI_CODE_UNDEFINED       = 0x0000,
+       /* Evas */
+       UI_EVAS_UNDEFINED       = 0x0100,
+       UI_EVAS_IMAGE           = 0x0101,
+       UI_EVAS_LINE            = 0x0102,
+       UI_EVAS_POLYGON         = 0X0103,
+       UI_EVAS_RECTANGLE       = 0X0104,
+       UI_EVAS_TEXT            = 0x0105,
+       UI_EVAS_TEXTBLOCK       = 0x0106,
+       UI_EVAS_VECTORS         = 0x0107,
+       UI_EVAS_TABLE           = 0x0108,
+       UI_EVAS_BOX             = 0x0109,
+       UI_EVAS_GRID            = 0x010A,
+       UI_EVAS_TEXTGRID        = 0x010B,
+       UI_EVAS_SMART           = 0x010C,
+       /* Elementary */
+       UI_ELM_UNDEFINED        = 0x0200,
+       UI_ELM_BACKGROUND       = 0x0201,
+       UI_ELM_BUTTON           = 0x0202,
+       UI_ELM_CHECK            = 0x0203,
+       UI_ELM_COLORSELECTOR    = 0x0204,
+       UI_ELM_CTXPOPUP         = 0x0205,
+       UI_ELM_DATETIME         = 0x0206,
+       UI_ELM_ENTRY            = 0x0207,
+       UI_ELM_FLIP             = 0x0208,
+       UI_ELM_GENGRID          = 0x0209,
+       UI_ELM_GENLIST          = 0x020A,
+       UI_ELM_GLVIEW           = 0x020B,
+       UI_ELM_ICON             = 0x020C,
+       UI_ELM_IMAGE            = 0x020D,
+       UI_ELM_INDEX            = 0x020E,
+       UI_ELM_LABEL            = 0x020F,
+       UI_ELM_LIST             = 0x0210,
+       UI_ELM_MAP              = 0x0211,
+       UI_ELM_NOTIFY           = 0x0212,
+       UI_ELM_PANEL            = 0x0213,
+       UI_ELM_PHOTO            = 0x0214,
+       UI_ELM_PHOTOCAM         = 0x0215,
+       UI_ELM_PLUG             = 0x0216,
+       UI_ELM_POPUP            = 0x0217,
+       UI_ELM_PROGRESSBAR      = 0x0218,
+       UI_ELM_RADIO            = 0x0219,
+       UI_ELM_SEGMENTCONTROL   = 0x021A,
+       UI_ELM_SLIDER           = 0x021B,
+       UI_ELM_SPINNER          = 0x021C,
+       UI_ELM_TOOLBAR          = 0x021D,
+       UI_ELM_TOOLTIP          = 0x021E,
+       UI_ELM_WIN              = 0x021F,
+       /* Edje */
+       UI_EDJE_UNDEFINED       = 0x0300,
+       UI_EDJE_EDJE            = 0x0301,
+       UI_EDJE_BOX             = 0x0302,
+       UI_EDJE_DRAG            = 0x0303,
+       UI_EDJE_SWALLOW         = 0x0304,
+       UI_EDJE_TABLE           = 0x0305,
+       UI_EDJE_TEXT            = 0x0306,
+       UI_EDJE_TEXTBLOCK       = 0x0307,
+       UI_EDJE_RECTANGLE       = 0x0308,
+       UI_EDJE_VECTORS         = 0x0309,
+       UI_EDJE_BACKGROUND      = 0x0309
+};
+
+typedef struct _ui_obj_info_t {
+       Evas_Object *id;
+       enum ui_obj_category_t category;
+       enum ui_obj_code_t code;
+       char name[MAX_PATH_LENGTH];
+       struct timeval rendering_tv;
+       Evas_Object *parent_id;
+} ui_obj_info_t;
+
+typedef struct _ui_obj_elm_prop_t {
+       char text[MAX_TEXT_LENGTH];
+       char style[MAX_PATH_LENGTH];
+       Eina_Bool disabled;
+       char type[MAX_PATH_LENGTH];
+} ui_obj_elm_prop_t;
+
+typedef struct _ui_obj_edje_prop_t {
+       Eina_Bool animation;
+       Eina_Bool play;
+       double scale;
+       double base_scale;
+       Evas_Coord size_min[2];
+       Evas_Coord size_max[2];
+} ui_obj_edje_prop_t;
+
+typedef struct _ui_obj_prop_t {
+       Evas_Coord geometry[4];
+       Eina_Bool focus;
+       char name[MAX_PATH_LENGTH];
+       Eina_Bool visible;
+       int color[4];
+       Eina_Bool anti_alias;
+       float scale;
+       Evas_Coord size_min[2];
+       Evas_Coord size_max[2];
+       Evas_Coord size_request[2];
+       double size_align[2];
+       double size_weight[2];
+       Evas_Coord size_padding[4];
+       Evas_Render_Op render_op;
+} ui_obj_prop_t;
+
+typedef struct _image_prop_t {
+       double load_dpi;
+       Eina_Bool source_clip;
+       Eina_Bool filled;
+       char content_hint;
+       Eina_Bool alpha;
+       int border[4];
+       double border_scale;
+       Eina_Bool pixels_dirty;
+       Eina_Bool load_orientation;
+       char border_center_fill;
+       int size[2];
+       Eina_Bool source_visible;
+       Evas_Coord fill[4];
+       int load_scale_down;
+       char scale_hint;
+       Eina_Bool source_events;
+       int frame_count;
+       int evas_image_stride;
+} image_prop_t;
+
+typedef struct _line_prop_t {
+       Evas_Coord xy[4];
+} line_prop_t;
+
+typedef struct _text_prop_t {
+       char font[MAX_PATH_LENGTH];
+       int size;
+       char text[MAX_PATH_LENGTH];
+       char delim[MAX_PATH_LENGTH];
+       double ellipsis;
+       char style;
+       int shadow_color[4];
+       int glow_color[4];
+       int glow2_color[4];
+       int outline_color[4];
+       int style_pad[4];
+       char direction;
+} text_prop_t;
+
+typedef struct _textblock_prop_t {
+       char replace_char[MAX_PATH_LENGTH];
+       double valign;
+       char delim[MAX_PATH_LENGTH];
+       Eina_Bool newline;
+       char markup[MAX_PATH_LENGTH];
+} textblock_prop_t;
+
+typedef struct _table_prop_t {
+       char homogeneous;
+       double align[2];
+       Evas_Coord padding[2];
+       Eina_Bool mirrored;
+       int col_row_size[2];
+} table_prop_t;
+
+typedef struct _box_prop_t {
+       double align[2];
+} box_prop_t;
+
+typedef struct _grid_prop_t {
+       Eina_Bool mirrored;
+} grid_prop_t;
+
+typedef struct _textgrid_prop_t {
+       int size[2];
+       int cell_size[2];
+} textgrid_prop_t;
+
+typedef struct _bg_prop_t {
+       int color[3];
+       char option;
+} bg_prop_t;
+
+typedef struct _button_prop_t {
+       double initial_timeout;
+       double gap_timeout;
+       Eina_Bool autorepeat;
+} button_prop_t;
+
+typedef struct _check_prop_t {
+       Eina_Bool state;
+} check_prop_t;
+
+typedef struct _colorselector_prop_t {
+       int color[4];
+       char palette_name[MAX_PATH_LENGTH];
+       char mode;
+} colorselector_prop_t;
+
+typedef struct _ctxpopup_prop_t {
+       Eina_Bool horizontal;
+} ctxpopup_prop_t;
+
+typedef struct _datetime_prop_t {
+       char format[MAX_PATH_LENGTH];
+       int value[8];
+} datetime_prop_t;
+
+typedef struct _entry_prop_t {
+       char entry[MAX_PATH_LENGTH];
+       Eina_Bool scrollable;
+       Eina_Bool panel_show_on_demand;
+       Eina_Bool menu_disabled;
+       char cnp_mode;
+       Eina_Bool editable;
+       char hover_style[MAX_PATH_LENGTH];
+       Eina_Bool single_line;
+       Eina_Bool password;
+       Eina_Bool autosave;
+       Eina_Bool prediction_allow;
+       Eina_Bool panel_enabled;
+       int cursor_pos;
+       Eina_Bool cursor_is_format;
+       char *cursor_content;
+       char selection[MAX_PATH_LENGTH];
+       Eina_Bool is_visible_format;
+} entry_prop_t;
+
+typedef struct _flip_prop_t {
+       char interaction;
+       Eina_Bool front_visible;
+} flip_prop_t;
+
+typedef struct _gengrid_prop_t {
+       double align[2];
+       Eina_Bool filled;
+       double relative[2];
+       Eina_Bool multi_select;
+       Evas_Coord group_item_size[2];
+       char select_mode;
+       Eina_Bool render_mode;
+       Eina_Bool highlight_mode;
+       Evas_Coord item_size[2];
+       char multi_select_mode;
+       Eina_Bool horizontal;
+       Eina_Bool wheel_disabled;
+       int items_count;
+} gengrid_prop_t;
+
+typedef struct _genlist_prop_t {
+       Eina_Bool multi_select;
+       char genlist_mode;
+       int items_count;
+       Eina_Bool homogeneous;
+       int block_count;
+       double timeout;
+       Eina_Bool reorder_mode;
+       Eina_Bool decorate_mode;
+       Eina_Bool effect_enabled;
+       char select_mode;
+       Eina_Bool highlight_mode;
+       Eina_Bool realization_mode;
+} genlist_prop_t;
+
+typedef struct _glview_prop_t {
+       int size[2];
+       int rotation;
+} glview_prop_t;
+
+typedef struct _icon_prop_t {
+       char lookup;
+       char standard[MAX_PATH_LENGTH];
+} icon_prop_t;
+
+typedef struct _elm_image_prop_t {
+       Eina_Bool editable;
+       Eina_Bool play;
+       Eina_Bool smooth;
+       Eina_Bool no_scale;
+       Eina_Bool animated;
+       Eina_Bool aspect_fixed;
+       char orient;
+       Eina_Bool fill_outside;
+       Eina_Bool resizable[2];
+       Eina_Bool animated_available;
+       int size[2];
+} elm_image_prop_t;
+
+typedef struct _index_prop_t {
+       Eina_Bool autohide_disabled;
+       Eina_Bool omit_enabled;
+       int priority;
+       Eina_Bool horizontal;
+       double change_time;
+       Eina_Bool indicator_disabled;
+       int item_level;
+} index_prop_t;
+
+typedef struct _label_prop_t {
+       int wrap_width;
+       double speed;
+       char mode;
+} label_prop_t;
+
+typedef struct _list_prop_t {
+       Eina_Bool horizontal;
+       char select_mode;
+       Eina_Bool focus_on_selection;
+       Eina_Bool multi_select;
+       char multi_select_mode;
+       char mode;
+} list_prop_t;
+
+typedef struct _map_prop_t {
+       int zoom;
+       Eina_Bool paused;
+       Eina_Bool wheel_disabled;
+       int zoom_min;
+       double rotate_degree;
+       Evas_Coord rotate[2];
+       char agent[MAX_PATH_LENGTH];
+       int zoom_max;
+       char zoom_mode;
+       double region[2];
+} map_prop_t;
+
+typedef struct _notify_prop_t {
+       double align[2];
+       Eina_Bool allow_events;
+       double timeout;
+} notify_prop_t;
+
+typedef struct _panel_prop_t {
+       char orient;
+       Eina_Bool hidden;
+       Eina_Bool scrollable;
+} panel_prop_t;
+
+typedef struct _photo_prop_t {
+       Eina_Bool editable;
+       Eina_Bool fill_inside;
+       Eina_Bool aspect_fixed;
+       int size;
+} photo_prop_t;
+
+typedef struct _photocam_prop_t {
+       Eina_Bool paused;
+       char file[MAX_PATH_LENGTH];
+       Eina_Bool gesture_enabled;
+       double zoom;
+       char zoom_mode;
+       int image_size[2];
+} photocam_prop_t;
+
+typedef struct _popup_prop_t {
+       double align[2];
+       Eina_Bool allow_events;
+       char wrap_type;
+       char orient;
+       double timeout;
+} popup_prop_t;
+
+typedef struct _progressbar_prop_t {
+       Evas_Coord span_size;
+       Eina_Bool pulse;
+       double value;
+       Eina_Bool inverted;
+       Eina_Bool horizontal;
+       char unit_format[MAX_PATH_LENGTH];
+} progressbar_prop_t;
+
+typedef struct _radio_prop_t {
+       int state_value;
+       int value;
+} radio_prop_t;
+
+typedef struct _segmencontrol_prop_t {
+       int item_count;
+} segmencontrol_prop_t;
+
+typedef struct _slider_prop_t {
+       Eina_Bool horizontal;
+       double value;
+       char format[MAX_PATH_LENGTH];
+} slider_prop_t;
+
+typedef struct _spinner_prop_t {
+       double min_max[2];
+       double step;
+       Eina_Bool wrap;
+       double interval;
+       int round;
+       Eina_Bool editable;
+       double base;
+       double value;
+       char format[MAX_PATH_LENGTH];
+} spinner_prop_t;
+
+typedef struct _toolbar_prop_t {
+       Eina_Bool reorder_mode;
+       Eina_Bool transverse_expanded;
+       Eina_Bool homogeneous;
+       double align;
+       char select_mode;
+       int icon_size;
+       Eina_Bool horizontal;
+       int standard_priority;
+       int items_count;
+} toolbar_prop_t;
+
+typedef struct _tooltip_prop_t {
+       char style[MAX_PATH_LENGTH];
+       Eina_Bool window_mode;
+} tooltip_prop_t;
+
+typedef struct _win_prop_t {
+       Eina_Bool iconfield;
+       Eina_Bool maximized;
+       Eina_Bool modal;
+       char icon_name[MAX_PATH_LENGTH];
+       Eina_Bool withdrawn;
+       char role[MAX_PATH_LENGTH];
+       int size_step[2];
+       char highlight_style[MAX_PATH_LENGTH];
+       Eina_Bool borderless;
+       Eina_Bool highlight_enabled;
+       char title[MAX_PATH_LENGTH];
+       Eina_Bool alpha;
+       Eina_Bool urgent;
+       int rotation;
+       Eina_Bool sticky;
+       Eina_Bool highlight_animate;
+       double aspect;
+       char indicator_opacity;
+       Eina_Bool demand_attention;
+       int layer;
+       char profile[MAX_PATH_LENGTH];
+       Eina_Bool shaped;
+       Eina_Bool fullscreen;
+       char indicator_mode;
+       Eina_Bool conformant;
+       int size_base[2];
+       Eina_Bool quickpanel;
+       Eina_Bool rotation_supported;
+       int screen_dpi[2];
+       char win_type;
+} win_prop_t;
+
+char *pack_string(char *to, const char *str);
+char *pack_ui_obj_info_list(char *to, enum rendering_option_t rendering,
+                           Eina_Bool *cancelled);
+char *pack_ui_obj_screenshot(char *to, Evas_Object *obj);
+enum hierarchy_status_t get_hierarchy_status(void);
+void set_hierarchy_status(enum hierarchy_status_t status);
+
+static inline char *pack_int8(char *to, uint8_t val)
+{
+       *(uint8_t *)to = val;
+       return to + sizeof(uint8_t);
+}
+
+static inline char *pack_int32(char *to, uint32_t val)
+{
+       *(uint32_t *)to = val;
+       return to + sizeof(uint32_t);
+}
+
+static inline char *pack_int64(char *to, uint64_t val)
+{
+       *(uint64_t *)to = val;
+       return to + sizeof(uint64_t);
+}
+
+static inline char *pack_float(char *to, float val)
+{
+       *(float *)to = val;
+       return to + sizeof(float);
+}
+static inline char *pack_ptr(char *to, const void *val)
+{
+       *(uint64_t *)to = (uint64_t)(uintptr_t)val;
+       return to + sizeof(uint64_t);
+}
+
+static inline char *pack_timeval(char *to, struct timeval tv)
+{
+       to = pack_int32(to, tv.tv_sec);
+       to = pack_int32(to, tv.tv_usec * 1000);
+
+       return to;
+}
+
+#endif /* _UI_VIEWER_DATA_ */
diff --git a/ui_viewer/ui_viewer_lib.c b/ui_viewer/ui_viewer_lib.c
new file mode 100644 (file)
index 0000000..ecd05a1
--- /dev/null
@@ -0,0 +1,401 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Lyupa Anastasia <a.lyupa@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 <stdlib.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+
+#include "ui_viewer_lib.h"
+#include "ui_viewer_utils.h"
+#include "ui_viewer_data.h"
+
+static const char socket_name[] = "/tmp/da_ui.socket";
+
+int            g_timerfd = 0;
+long           g_total_alloc_size = 0;
+pthread_t      g_recvthread_id;
+
+__traceInfo gTraceInfo;
+
+static int createSocket(void);
+static int create_recv_thread(void);
+static void *recvThread(void __unused *data);
+
+__attribute__((constructor)) void init_ui_viewer(void)
+{
+       ui_viewer_clean_log();
+       ui_viewer_log("constructor started\n");
+
+       if (createSocket() == 0) {
+               create_recv_thread();
+       }
+}
+
+__attribute__((destructor)) void finite_ui_viewer (void)
+{
+       ui_viewer_log("destructor started\n");
+
+       if (gTraceInfo.socket.daemonSock != -1)
+               close(gTraceInfo.socket.daemonSock);
+}
+
+static int create_recv_thread(void)
+{
+       int err = pthread_create(&g_recvthread_id, NULL, recvThread, NULL);
+
+       if (err)
+               PRINTMSG("failed to crate recv thread\n");
+
+       return err;
+}
+
+// runtime configure the probe option
+static void _configure(char* configstr)
+{
+       gTraceInfo.optionflag = atoll(configstr);
+}
+
+void application_exit()
+{
+       pid_t gpid;
+       FILE *f = NULL;
+       char buf[MAX_PATH_LENGTH];
+       const char manager_name[] = "da_manager";
+
+       gpid = getpgrp();
+       snprintf(buf, sizeof(buf), "/proc/%d/cmdline", gpid);
+       f = fopen(buf, "r");
+       if (f != NULL) {
+               fscanf(f, "%s", buf);
+               fclose(f);
+               if (strlen(buf) == strlen(manager_name) &&
+                   strncmp(buf, manager_name, sizeof(manager_name)) == 0) {
+                       PRINTMSG("App termination: EXIT(0)");
+                       exit(0);
+               }
+       }
+
+       PRINTMSG("App termination: kill all process group");
+       killpg(gpid, SIGKILL);
+}
+
+// create socket to daemon and connect
+#define MSG_CONFIG_RECV 0x01
+#define MSG_MAPS_INST_LIST_RECV 0x02
+static int createSocket(void)
+{
+       char strerr_buf[MAX_PATH_LENGTH];
+       ssize_t recvlen;
+       int clientLen, ret = 0;
+       struct sockaddr_un clientAddr;
+       log_t log;
+
+       gTraceInfo.socket.daemonSock =
+         socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
+       if (gTraceInfo.socket.daemonSock != -1) {
+               memset(&clientAddr, '\0', sizeof(clientAddr));
+               clientAddr.sun_family = AF_UNIX;
+               snprintf(clientAddr.sun_path, sizeof(socket_name), "%s", socket_name);
+
+               clientLen = sizeof(clientAddr);
+               if (connect(gTraceInfo.socket.daemonSock,
+                           (struct sockaddr *)&clientAddr, clientLen) >= 0)
+               {
+                       char buf[64];
+                       int recved = 0;
+
+                       snprintf(buf, sizeof(buf), "%d %d", getpid(), getppid());
+                       print_log_str(APP_MSG_PID, buf);
+
+                       while (((recved & MSG_CONFIG_RECV) == 0) ||
+                              ((recved & MSG_MAPS_INST_LIST_RECV) == 0))
+                       {
+                               PRINTMSG("wait incoming message %d\n",
+                                        gTraceInfo.socket.daemonSock);
+                               recvlen = recv(gTraceInfo.socket.daemonSock, &log,
+                                              sizeof(log.type) + sizeof(log.length),
+                                              MSG_WAITALL);
+
+                               ui_viewer_log("recv %d\n", recvlen);
+                               if (recvlen > 0) {
+                                       char *data_buf = NULL;
+
+                                       data_buf = malloc(log.length);
+
+                                       if (data_buf == NULL) {
+                                               PRINTERR("cannot allocate buf to recv msg");
+                                               break;
+                                       }
+
+                                       recvlen = recv(gTraceInfo.socket.daemonSock, data_buf,
+                                                      log.length, MSG_WAITALL);
+
+                                       if (recvlen != log.length) {
+                                               PRINTERR("Can not get data from daemon sock\n");
+                                               goto free_data_buf;
+                                       }
+
+                                       if (log.type == APP_MSG_CONFIG) {
+                                               PRINTMSG("APP_MSG_CONFIG");
+                                               _configure(data_buf);
+                                               recved |= MSG_CONFIG_RECV;
+                                       } else if(log.type ==  APP_MSG_MAPS_INST_LIST) {
+                                               PRINTMSG("APP_MSG_MAPS_INST_LIST <%u>", *((uint32_t *)data_buf));
+                                               // do nothing
+                                               recved |= MSG_MAPS_INST_LIST_RECV;
+                                       } else {
+                                               // unexpected case
+                                               PRINTERR("unknown message! %d", log.type);
+                                       }
+
+free_data_buf:
+                                       if (data_buf != NULL)
+                                               free(data_buf);
+
+                               } else if (recvlen < 0) {
+                                       close(gTraceInfo.socket.daemonSock);
+                                       gTraceInfo.socket.daemonSock = -1;
+                                       PRINTERR("recv failed with error(%d)\n",
+                                                recvlen);
+                                       ret = -1;
+                                       application_exit();
+                                       break;
+                               } else {
+                                       close(gTraceInfo.socket.daemonSock);
+                                       gTraceInfo.socket.daemonSock = -1;
+                                       PRINTERR("closed by other peer\n");
+                                       ret = -1;
+                                       application_exit();
+                                       break;
+                               }
+
+                       }
+
+                       PRINTMSG("createSocket connect() success\n");
+               } else {
+                       close(gTraceInfo.socket.daemonSock);
+                       gTraceInfo.socket.daemonSock = -1;
+                       strerror_r(errno, strerr_buf, sizeof(strerr_buf));
+                       PRINTERR("cannot connect to da_manager. err <%s>\n",
+                                strerr_buf);
+                       ret = -1;
+               }
+       } else {
+               strerror_r(errno, strerr_buf, sizeof(strerr_buf));
+               PRINTERR("cannot create socket. err <%s>\n", strerr_buf);
+               ret = -1;
+       }
+
+       PRINTMSG("socket create done with result = %d", ret);
+       return ret;
+}
+
+static void *recvThread(void __unused *data)
+{
+       fd_set readfds, workfds;
+       int maxfd = 0, rc;
+       uint64_t xtime;
+       uint32_t tmp;
+       ssize_t recvlen;
+       log_t log;
+       char *data_buf = NULL;
+       sigset_t profsigmask;
+       pthread_t hierarchy_thread_id;
+       bool hierarchy_thread_running = false;
+
+       if(gTraceInfo.socket.daemonSock == -1)
+               return NULL;
+
+       sigemptyset(&profsigmask);
+       sigaddset(&profsigmask, SIGPROF);
+       pthread_sigmask(SIG_BLOCK, &profsigmask, NULL);
+
+       FD_ZERO(&readfds);
+       if(g_timerfd > 0)
+       {
+               maxfd = g_timerfd;
+               FD_SET(g_timerfd, &readfds);
+       }
+       if(maxfd < gTraceInfo.socket.daemonSock)
+               maxfd = gTraceInfo.socket.daemonSock;
+       FD_SET(gTraceInfo.socket.daemonSock, &readfds);
+
+       while(1)
+       {
+               workfds = readfds;
+               rc = select(maxfd + 1, &workfds, NULL, NULL, NULL);
+               if(rc < 0)
+               {
+                       continue;
+               }
+
+               if(g_timerfd > 0 && FD_ISSET(g_timerfd, &workfds))
+               {
+                       recvlen = read(g_timerfd, &xtime, sizeof(xtime));
+                       if(recvlen > 0)
+                       {
+                               log.length = snprintf(log.data, sizeof(log.data), "%ld", g_total_alloc_size) + 1;
+                               printLog(&log, APP_MSG_ALLOC);
+                       }
+                       else
+                       {
+                               // read failed
+                       }
+                       continue;
+               }
+               else if(FD_ISSET(gTraceInfo.socket.daemonSock, &workfds))
+               {
+                       recvlen = recv(gTraceInfo.socket.daemonSock, &log,
+                                       sizeof(log.type) + sizeof(log.length), MSG_WAITALL);
+
+                       if(recvlen > 0) // recv succeed
+                       {
+
+                               if(log.length > 0) {
+                                       data_buf = malloc(log.length);
+                                       if (data_buf == NULL) {
+                                               PRINTERR("cannot allocate buf to recv msg");
+                                               break;
+                                       }
+                                       recvlen = recv(gTraceInfo.socket.daemonSock, data_buf,
+                                               log.length, MSG_WAITALL);
+                                       if (recvlen != log.length) {
+                                               PRINTERR("Can not recv data from\n");
+                                               goto free_data_buf;
+                                       }
+                               }
+
+                               if (log.type == APP_MSG_CONFIG) {
+                                       _configure(data_buf);
+                               } else if(log.type == APP_MSG_STOP) {
+                                       PRINTMSG("APP_MSG_STOP");
+                                       if (data_buf) {
+                                               free(data_buf);
+                                               data_buf = NULL;
+                                       }
+                                       application_exit();
+                                       break;
+                               } else if(log.type == APP_MSG_MAPS_INST_LIST) {
+                                       if(log.length > 0) {
+                                               tmp = *((uint32_t *)data_buf);
+                                               PRINTMSG("APP_MSG_MAPS_INST_LIST <%u>", tmp);
+                                               continue;
+                                       } else {
+                                               PRINTERR("WRONG APP_MSG_MAPS_INST_LIST");
+                                       }
+                               } else if(log.type == APP_MSG_GET_UI_HIERARCHY) {
+                                       enum ErrorCode err_code = ERR_UNKNOWN;
+
+                                       print_log_ui_viewer_hierarchy_status(&err_code);
+
+                                       if (err_code != ERR_NO) {
+                                               PRINTERR("APP_MSG_GET_UI_HIERARCHY error <%d>", err_code);
+                                               continue;
+                                       }
+
+                                       if(log.length > 0) {
+                                               Eina_Bool rendering;
+
+                                               hierarchy_thread_running = false;
+                                               rendering = (enum rendering_option_t)*((uint8_t *)data_buf);
+                                               PRINTMSG("APP_MSG_GET_UI_HIERARCHY, rendering option <%d>", rendering);
+                                               raise_app_window();
+                                               if (pthread_create(&hierarchy_thread_id, NULL, print_log_ui_viewer_info_list,
+                                                                  (void*)&rendering)) {
+                                                       PRINTERR("failed to crate hierarchy thread");
+                                               } else {
+                                                       hierarchy_thread_running = true;
+                                               }
+                                       } else {
+                                               PRINTERR("WRONG APP_MSG_GET_UI_PROPERTIES");
+                                       }
+
+                                       continue;
+                               } else if(log.type == APP_MSG_GET_UI_HIERARCHY_CANCEL) {
+                                       PRINTMSG("APP_MSG_GET_UI_HIERARCHY_CANCEL");
+                                       set_hierarchy_status(HIERARCHY_CANCELLED);
+                                       if (hierarchy_thread_running) {
+                                               pthread_join(hierarchy_thread_id, NULL);
+                                               hierarchy_thread_running = false;
+                                       }
+
+                                       continue;
+                               } else if(log.type == APP_MSG_GET_UI_SCREENSHOT) {
+                                       if(log.length > 0) {
+                                               Evas_Object *obj;
+
+                                               obj = (Evas_Object*)(unsigned long)*((uint64_t *)data_buf);
+                                               PRINTMSG("APP_MSG_GET_UI_SCREENSHOT <0x%lx>", obj);
+                                               raise_app_window();
+                                               print_log_ui_obj_screenshot(obj);
+                                       } else {
+                                               PRINTERR("WRONG APP_MSG_GET_UI_SCREENSHOT");
+                                       }
+
+                                       continue;
+                               } else {
+                                       PRINTERR("recv unknown message. id = (%d)", log.type);
+                               }
+
+free_data_buf:
+                               if (data_buf) {
+                                       free(data_buf);
+                                       data_buf = NULL;
+                               }
+
+                       }
+                       else if(recvlen == 0)   // closed by other peer
+                       {
+                               close(gTraceInfo.socket.daemonSock);
+                               gTraceInfo.socket.daemonSock = -1;
+                               break;
+                       }
+                       else    // recv error
+                       {
+                               PRINTERR("recv failed in recv thread with error(%d)", recvlen);
+                               continue;
+                       }
+               }
+               else    // unknown case
+               {
+                       continue;
+               }
+       }
+
+       if (data_buf)
+               free(data_buf);
+
+       return NULL;
+}
diff --git a/ui_viewer/ui_viewer_lib.h b/ui_viewer/ui_viewer_lib.h
new file mode 100644 (file)
index 0000000..0f3d1fe
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Lyupa Anastasia <a.lyupa@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 _UI_VIEWER_LIB_
+#define _UI_VIEWER_LIB_
+
+#include <stdlib.h>
+#include <pthread.h>
+
+typedef struct
+{
+       int daemonSock;
+       pthread_mutex_t sockMutex;
+} __socketInfo;
+
+typedef struct
+{
+       __socketInfo            socket;
+       uint64_t                optionflag;
+} __traceInfo;
+
+
+#endif /* _UI_VIEWER_LIB_ */
diff --git a/ui_viewer/ui_viewer_screenshot.c b/ui_viewer/ui_viewer_screenshot.c
new file mode 100644 (file)
index 0000000..610bf08
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Lyupa Anastasia <a.lyupa@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 <stdlib.h>
+#include <stdbool.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/shm.h>
+#include <pthread.h>
+#include <dlfcn.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/extensions/XShm.h>
+
+#include <Ecore.h>
+#include <Evas.h>
+#include <Evas_Engine_Buffer.h>
+#include <Elementary.h>
+
+#include "ui_viewer_utils.h"
+
+typedef struct _screenshot_data
+{
+       XImage*                 ximage;
+       Display*                dpy;
+       XShmSegmentInfo         x_shm_info;
+} screenshot_data;
+
+static int screenshotIndex = 0;
+static pthread_mutex_t captureScreenLock = PTHREAD_MUTEX_INITIALIZER;
+
+static char* captureScreenShotX(screenshot_data* sdata)
+{
+       Window root;
+       int width, height;
+
+       sdata->dpy = XOpenDisplay(NULL);
+       if(sdata->dpy == NULL)
+       {
+               ui_viewer_log("ERROR: XOpenDisplay failed\n");
+               return NULL;
+       }
+
+       width = DisplayWidth(sdata->dpy, DefaultScreen(sdata->dpy));
+       height = DisplayHeight(sdata->dpy, DefaultScreen(sdata->dpy));
+
+       root = RootWindow(sdata->dpy, DefaultScreen(sdata->dpy));
+
+       sdata->ximage = XShmCreateImage(sdata->dpy, DefaultVisualOfScreen (DefaultScreenOfDisplay (sdata->dpy)), 24,
+                                       ZPixmap, NULL, &sdata->x_shm_info, (unsigned int)width, (unsigned int)height);
+
+       if (sdata->ximage != NULL)
+       {
+               sdata->x_shm_info.shmid = shmget(IPC_PRIVATE, sdata->ximage->bytes_per_line * sdata->ximage->height, IPC_CREAT | 0777);
+               sdata->x_shm_info.shmaddr = sdata->ximage->data = shmat(sdata->x_shm_info.shmid, 0, 0);
+               sdata->x_shm_info.readOnly = False;
+
+               if (XShmAttach(sdata->dpy, &sdata->x_shm_info))
+               {
+                       if (XShmGetImage(sdata->dpy, root, sdata->ximage, 0, 0, AllPlanes))
+                       {
+                               XSync(sdata->dpy, False);
+                               return sdata->ximage->data;
+                       }
+                       else
+                       {
+                               ui_viewer_log("ERROR: XShmGetImage failed\n");
+                       }
+
+                       XShmDetach(sdata->dpy, &sdata->x_shm_info);
+               }
+               else
+               {
+                       ui_viewer_log("ERROR: XShmAttach failed\n");
+               }
+
+               shmdt (sdata->x_shm_info.shmaddr);
+               shmctl (sdata->x_shm_info.shmid, IPC_RMID, NULL);
+               XDestroyImage(sdata->ximage);
+               sdata->ximage = NULL;
+       }
+       else
+       {
+               ui_viewer_log("ERROR: XShmCreateImage failed\n");
+       }
+
+       return NULL;
+}
+
+static void releaseScreenShotX(screenshot_data* sdata)
+{
+       if(sdata->ximage)
+       {
+               XShmDetach(sdata->dpy, &sdata->x_shm_info);
+               shmdt (sdata->x_shm_info.shmaddr);
+               shmctl (sdata->x_shm_info.shmid, IPC_RMID, NULL);
+               XDestroyImage(sdata->ximage);
+       }
+       else { }
+
+       if(sdata->dpy)
+       {
+               XCloseDisplay(sdata->dpy);
+       }
+}
+
+static int capture_object(char *screenshot_path, int width, int height,
+                         Evas_Object *obj, const char *type_name) {
+       char dstpath[MAX_PATH_LENGTH];
+       Evas_Object *img;
+       Evas *canvas, *sub_canvas;
+       Ecore_Evas *ee, *sub_ee;
+       int ret = 0;
+       char *image_data = NULL;
+
+       screenshotIndex++;
+
+       canvas = evas_object_evas_get(obj);
+       ee = ecore_evas_ecore_evas_get(canvas);
+       img = ecore_evas_object_image_new(ee);
+       evas_object_image_filled_set(img, EINA_TRUE);
+       evas_object_image_size_set(img, width, height);
+       sub_ee = ecore_evas_object_ecore_evas_get(img);
+       sub_canvas = ecore_evas_object_evas_get(img);
+       evas_object_resize(img, width, height);
+       ecore_evas_resize(sub_ee, width, height);
+
+       if (!strcmp(type_name, "rectangle")) {
+               Evas_Object* rect;
+               int r, g, b, a;
+
+               rect = evas_object_rectangle_add(sub_canvas);
+               evas_object_color_get(obj, &r, &g, &b, &a);
+               evas_object_color_set(rect, r, g, b, a);
+               evas_object_resize(rect, width, height);
+               evas_object_show(rect);
+       } else if (!strcmp(type_name, "image")) {
+               Evas_Object *image;
+               void *img_data;
+               int w, h;
+
+               img_data = evas_object_image_data_get(obj, EINA_FALSE);
+               evas_object_image_size_get(obj, &w, &h);
+               image = evas_object_image_filled_add(sub_canvas);
+               evas_object_image_size_set(image, w, h);
+               evas_object_image_data_set(image, img_data);
+               evas_object_image_data_update_add(image, 0, 0, w, h);
+               evas_object_resize(image, width, height);
+
+               evas_object_show(image);
+       } else {
+               char* scrimage;
+               screenshot_data sdata;
+               int x, y;
+               int screen_w;
+               Evas_Object *image;
+               int i, j;
+               int bytes_per_pixel;
+
+               evas_object_geometry_get(obj, &x, &y, NULL, NULL);
+
+               sdata.ximage = NULL;
+               scrimage = captureScreenShotX(&sdata);
+               if (!scrimage) {
+                       ui_viewer_log("ERROR: capture_object : no scrimage\n");
+                       ret = -1;
+                       goto finish;
+               }
+               bytes_per_pixel = sdata.ximage->bits_per_pixel / 8;
+               screen_w = sdata.ximage->width;
+
+               image_data = malloc(width * height * bytes_per_pixel);
+               if (!image_data) {
+                       ui_viewer_log("ERROR: capture_object : can't allocate %d bytes\n",
+                                     width * height * bytes_per_pixel);
+                       ret = -1;
+                       goto finish;
+               }
+
+               // crop image
+               for (j = 0; j < height; j++) {
+                       for (i = 0; i < width * bytes_per_pixel; i++) {
+                               image_data[i + j * width * bytes_per_pixel] =
+                               scrimage[(i + x * bytes_per_pixel) + (j + y) * screen_w * bytes_per_pixel];
+                       }
+               }
+
+               image = evas_object_image_filled_add(sub_canvas);
+               evas_object_image_size_set(image, width, height);
+               evas_object_image_data_set(image, image_data);
+               evas_object_image_data_update_add(image, 0, 0, width, height);
+               evas_object_resize(image, width, height);
+               evas_object_show(image);
+finish:
+               releaseScreenShotX(&sdata);
+       }
+
+       ecore_evas_manual_render(sub_ee);
+
+       snprintf(dstpath, sizeof(dstpath), TMP_DIR"/%d_%d.png", _getpid(),
+                screenshotIndex);
+
+       if (evas_object_image_save(img, dstpath, NULL, "compress=5") != 0) {
+               strcpy(screenshot_path, dstpath);
+       } else {
+               ui_viewer_log("ERROR: capture_object : can't save image\n");
+               ret = -1;
+       }
+
+       evas_object_del(img);
+       free(image_data);
+
+       return ret;
+}
+
+int ui_viewer_capture_screen(char *screenshot_path, Evas_Object *obj)
+{
+       int view_w, view_h;
+       int obj_x, obj_y, obj_w, obj_h;
+       int ret = 0;
+       Evas *evas;
+       char type_name[MAX_PATH_LENGTH];
+
+       if (!screenshot_path) {
+               ui_viewer_log("ui_viewer_capture_screen : no screenshot path\n");
+               ret = -1;
+               return ret;
+       }
+
+       pthread_mutex_lock(&captureScreenLock);
+
+       _strncpy(type_name, evas_object_type_get(obj), MAX_PATH_LENGTH);
+
+       evas = evas_object_evas_get(obj);
+       evas_output_viewport_get(evas, NULL, NULL, &view_w, &view_h);
+       evas_object_geometry_get(obj, &obj_x, &obj_y, &obj_w, &obj_h);
+
+       if (obj_w == 0 || obj_h == 0) {
+               ui_viewer_log("ui_viewer_capture_screen : object %p[%d,%d] has zero width or height\n",
+                             obj, obj_w, obj_h);
+               ret = -1;
+       } else if (!strcmp(type_name, "rectangle")) {
+               int width, height;
+
+               // restrict rectangle area
+               width = (obj_w <= view_w) ? obj_w : view_w;
+               height = (obj_h <= view_h) ? obj_h : view_h;
+
+               ret = capture_object(screenshot_path, width, height, obj, type_name);
+       } else if (!strcmp(type_name, "image")) {
+               ret = capture_object(screenshot_path, obj_w, obj_h, obj, type_name);
+       } else if (!strcmp(type_name, "vectors")) {
+               ret = -1;
+       } else if (!strcmp(type_name, "elm_image") ||
+           !strcmp(type_name, "elm_icon")) {
+               Evas_Object *internal_img;
+               int img_w, img_h;
+
+               internal_img = elm_image_object_get(obj);
+               evas_object_geometry_get(internal_img, NULL, NULL, &img_w, &img_h);
+
+               ret = capture_object(screenshot_path, img_w, img_h, internal_img, type_name);
+       } else if (obj_x > view_w || obj_y > view_h) {
+               ui_viewer_log("ui_viewer_capture_screen : object %p lies beside view area\n",
+                             obj);
+               ret = -1;
+       } else if (!evas_object_visible_get(obj)) {
+               ui_viewer_log("ui_viewer_capture_screen : object %p is unvisible\n",
+                             obj);
+               ret = -1;
+       } else {
+               int width, height;
+
+               // take visible on screen part of object
+               width = (view_w < obj_w + obj_x) ? (view_w - obj_x) : obj_w;
+               height = (view_h < obj_h + obj_y) ? (view_h - obj_y) : obj_h;
+
+               ret = capture_object(screenshot_path, width, height, obj, type_name);
+       }
+
+       if (ret)
+               screenshot_path[0] = '\0';
+
+       pthread_mutex_unlock(&captureScreenLock);
+       return ret;
+}
diff --git a/ui_viewer/ui_viewer_utils.c b/ui_viewer/ui_viewer_utils.c
new file mode 100644 (file)
index 0000000..c3da116
--- /dev/null
@@ -0,0 +1,346 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Lyupa Anastasia <a.lyupa@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 <stdlib.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <sys/syscall.h>
+#include <sys/socket.h>
+
+#include <Elementary.h>
+
+#include "ui_viewer_lib.h"
+#include "ui_viewer_utils.h"
+#include "ui_viewer_data.h"
+
+static const ssize_t TMP_BUF_SIZE = 262144;
+static const char log_filename[] = "/tmp/uilib.log";
+static pthread_mutex_t log_lock = PTHREAD_MUTEX_INITIALIZER;
+static pid_t gPid = -1;
+static __thread pid_t          gTid = -1;
+
+extern __traceInfo gTraceInfo;
+
+void reset_pid_tid()
+{
+       gPid = -1;
+       gTid = -1;
+}
+
+// return current process id
+pid_t _getpid()
+{
+       if (gPid == -1)
+               gPid = getpid();
+       return gPid;
+}
+
+// return current thread id
+pid_t _gettid()
+{
+       if(gTid == -1)
+               gTid = syscall(__NR_gettid);    // syscall is very expensive
+       return gTid;
+}
+
+char * _strncpy(char *dest, const char *src, size_t n)
+{
+       if (!src) {
+               if (dest)
+                       dest[0] = '\0';
+       } else {
+               strncpy(dest, src, n);
+               if (n > 0)
+                       dest[n - 1] = '\0';
+       }
+
+       return dest;
+}
+
+bool printLog(log_t *log, int msgType)
+{
+       ssize_t res, len;
+       if (gTraceInfo.socket.daemonSock == -1)
+               return false;
+
+       if (log == NULL)
+               return false;
+
+       log->type = msgType;
+       len = sizeof(log->type) + sizeof(log->length) + log->length;
+
+       pthread_mutex_lock(&(gTraceInfo.socket.sockMutex));
+       res = send(gTraceInfo.socket.daemonSock, log, len, 0);
+       pthread_mutex_unlock(&(gTraceInfo.socket.sockMutex));
+
+       return (res == len);
+}
+
+bool print_log_str(int msgType, char *str)
+{
+       log_t log;
+       ssize_t res, len;
+
+       if (gTraceInfo.socket.daemonSock == -1)
+               return false;
+
+       log.type = msgType;
+       if (str != NULL)
+               log.length = snprintf(log.data, sizeof(log.data), str);
+       else
+               log.length = 0;
+
+       len = sizeof(log.type) + sizeof(log.length) + log.length;
+
+       pthread_mutex_lock(&(gTraceInfo.socket.sockMutex));
+       res = send(gTraceInfo.socket.daemonSock, &log, len, 0);
+       pthread_mutex_unlock(&(gTraceInfo.socket.sockMutex));
+
+       return (res == len);
+}
+
+bool print_log_fmt(int msgType, const char *func_name, int line, ...)
+{
+       ssize_t res = 0, len = 0;
+       char *fmt, *p;
+       int n;
+       log_t log;
+       va_list ap;
+
+       log.type = msgType;
+
+       p = log.data;
+       n = snprintf(p, sizeof(log.data), "[%05d:%05d]%s:%d)", _getpid(),
+                    _gettid(),  func_name, line);
+       p += n;
+
+       va_start(ap, line);
+       fmt = va_arg(ap, char *);
+       if (fmt != NULL) {
+               if (strchr(fmt, '%') == NULL)
+                       n += snprintf(p, sizeof(log.data) - n, "%s", fmt);
+               else
+                       n += vsnprintf(p, sizeof(log.data) - n, fmt, ap);
+       }
+       va_end(ap);
+
+       if (n > -1 && n < (int)sizeof(log.data)) {
+               log.length = n;
+       } else {
+               ui_viewer_log("Log pack error\n");
+               log.length = 0;
+       }
+
+       len = sizeof(log.type) + sizeof(log.length) + log.length;
+
+       pthread_mutex_lock(&(gTraceInfo.socket.sockMutex));
+
+       if (gTraceInfo.socket.daemonSock != -1) {
+               res = send(gTraceInfo.socket.daemonSock, &log, len, MSG_DONTWAIT);
+       } else {
+               ui_viewer_log("%d %s\n", msgType, log.data);
+               fflush(stderr);
+       }
+
+       pthread_mutex_unlock(&(gTraceInfo.socket.sockMutex));
+
+       return (res == len);
+}
+
+static char *pack_string_to_file(char *to, char *st, ssize_t data_len)
+{
+       char template_name[] = TMP_DIR"/swap_ui_viewer_XXXXXX";
+       FILE *file;
+       mktemp(template_name);
+       file = fopen(template_name, "w");
+       if (file != NULL) {
+               fwrite(st, data_len, 1, file);
+               fclose(file);
+       }
+       to = pack_string(to, template_name);
+
+       return to;
+}
+
+bool print_log_ui_viewer_hierarchy_status(enum ErrorCode *err_code)
+{
+       log_t log;
+       ssize_t res, len;
+       char *log_ptr;
+
+       *err_code = ERR_NO;
+
+       if (gTraceInfo.socket.daemonSock == -1)
+               return false;
+
+       // check if hierarchy request is proceeding now
+       if (get_hierarchy_status() == HIERARCHY_RUNNING)
+               *err_code = ERR_ALREADY_RUNNING;
+
+       log.type = APP_MSG_GET_UI_HIERARCHY;
+       log_ptr = pack_int32(log.data, (uint32_t)*err_code);
+       log.length = log_ptr - log.data;
+       len = sizeof(log.type) + sizeof(log.length) + log.length;
+
+       pthread_mutex_lock(&(gTraceInfo.socket.sockMutex));
+       res = send(gTraceInfo.socket.daemonSock, &log, len, 0);
+       pthread_mutex_unlock(&(gTraceInfo.socket.sockMutex));
+
+       return (res == len);
+}
+
+bool print_log_ui_viewer_hierarchy_error(void)
+{
+       log_t log;
+       ssize_t res, len;
+       char *log_ptr;
+       enum ErrorCode err_code;
+
+       // TODO: system error
+       err_code = ERR_UNKNOWN;
+
+       if (gTraceInfo.socket.daemonSock == -1)
+               return false;
+
+       log.type = APP_MSG_GET_UI_HIERARCHY_DATA;
+       log_ptr = pack_int32(log.data, (uint32_t)err_code);
+       log.length = log_ptr - log.data;
+       len = sizeof(log.type) + sizeof(log.length) + log.length;
+
+       pthread_mutex_lock(&(gTraceInfo.socket.sockMutex));
+       res = send(gTraceInfo.socket.daemonSock, &log, len, 0);
+       pthread_mutex_unlock(&(gTraceInfo.socket.sockMutex));
+
+       return (res == len);
+}
+
+void* print_log_ui_viewer_info_list(void *prendering)
+{
+       log_t log;
+       ssize_t res, len;
+       char *log_ptr, *tmp_ptr;
+       char *tmp_buf;
+       struct timeval start_tv, finish_tv, tv;
+       Eina_Bool rendering, cancelled = EINA_FALSE;
+
+       if (gTraceInfo.socket.daemonSock == -1)
+               return NULL;
+
+       if (get_hierarchy_status() == HIERARCHY_RUNNING)
+               return NULL;
+
+       set_hierarchy_status(HIERARCHY_RUNNING);
+
+       rendering = *(Eina_Bool*)prendering;
+
+       tmp_buf = malloc(TMP_BUF_SIZE);
+       if (!tmp_buf) {
+               ui_viewer_log("Cannot alloc buffer: %d bytes\n", TMP_BUF_SIZE);
+               return NULL;
+       }
+
+       gettimeofday(&start_tv, NULL);
+       tmp_ptr = pack_ui_obj_info_list(tmp_buf, rendering, &cancelled);
+       gettimeofday(&finish_tv, NULL);
+       timersub(&finish_tv, &start_tv, &tv);
+       ui_viewer_log("getting hierarchy time : %d sec, %d usec\n",
+                     tv.tv_sec, tv.tv_usec);
+
+       if (!cancelled) {
+               log.type = APP_MSG_GET_UI_HIERARCHY_DATA;
+               log_ptr = pack_string_to_file(log.data, tmp_buf, tmp_ptr - tmp_buf);
+               log.length = log_ptr - log.data;
+               len = sizeof(log.type) + sizeof(log.length) + log.length;
+
+               pthread_mutex_lock(&(gTraceInfo.socket.sockMutex));
+               res = send(gTraceInfo.socket.daemonSock, &log, len, 0);
+               pthread_mutex_unlock(&(gTraceInfo.socket.sockMutex));
+
+               ui_viewer_log("getting hierarchy filename: %s filesize: %d\n",
+                             log.data, tmp_ptr - tmp_buf);
+
+               if (res != len)
+                       ui_viewer_log("can't send hierarchy info\n");
+               set_hierarchy_status(HIERARCHY_NOT_RUNNING);
+       }
+       free(tmp_buf);
+
+       return NULL;
+}
+
+bool print_log_ui_obj_screenshot(Evas_Object *obj)
+{
+       log_t log;
+       ssize_t res, len;
+       char *log_ptr;
+
+       if (gTraceInfo.socket.daemonSock == -1)
+               return false;
+
+       log.type = APP_MSG_GET_UI_SCREENSHOT;
+       log_ptr = pack_ui_obj_screenshot(log.data, obj);
+       log.length = log_ptr - log.data;
+       len = sizeof(log.type) + sizeof(log.length) + log.length;
+
+       pthread_mutex_lock(&(gTraceInfo.socket.sockMutex));
+       res = send(gTraceInfo.socket.daemonSock, &log, len, 0);
+       pthread_mutex_unlock(&(gTraceInfo.socket.sockMutex));
+
+       return (res == len);
+}
+
+void raise_app_window(void)
+{
+       x_raise_win(gPid);
+}
+
+void ui_viewer_clean_log(void)
+{
+       remove(log_filename);
+}
+
+void ui_viewer_log(const char *format, ...)
+{
+       FILE *fp;
+       va_list args;
+
+       pthread_mutex_lock(&log_lock);
+       fp = fopen(log_filename, "a");
+       if (fp == NULL)
+               return;
+       va_start (args, format);
+       vfprintf (fp, format, args);
+       va_end (args);
+       fclose(fp);
+       pthread_mutex_unlock(&log_lock);
+}
diff --git a/ui_viewer/ui_viewer_utils.h b/ui_viewer/ui_viewer_utils.h
new file mode 100644 (file)
index 0000000..3a4fe0f
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ *  DA manager
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Lyupa Anastasia <a.lyupa@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 _UI_VIEWER_UTILS_
+#define _UI_VIEWER_UTILS_
+
+#include <stdint.h>
+#include <Eina.h>
+
+#include "app_protocol.h" /* from swap-probe-devel package */
+
+#include "ui_viewer_data.h"
+
+#define DA_LOG_MAX             (MAX_PATH_LENGTH + 4)
+#define TMP_DIR "/tmp/da"
+
+#define __unused __attribute__((unused))
+
+typedef struct
+{
+       int type;
+       int length;
+       char data[DA_LOG_MAX];
+} log_t;
+
+// ========================= print log =====================================
+#define PRINTMSG(...)  print_log_fmt(APP_MSG_MSG, __FUNCTION__, __LINE__, __VA_ARGS__)
+#define PRINTWRN(...)  print_log_fmt(APP_MSG_WARNING, __FUNCTION__, __LINE__, __VA_ARGS__)
+#define PRINTERR(...)  print_log_fmt(APP_MSG_ERROR, __FUNCTION__, __LINE__, __VA_ARGS__)
+
+#define INIT_INFO                                              \
+               info.host_ip = 0;                               \
+               info.host_port = 0;                             \
+               info.msg_total_size = 0;                        \
+               info.msg_pack_size = 0;                         \
+               info.sock = NULL;                               \
+               info.msg_buf = (char *)""
+
+typedef struct {
+       uint32_t host_port;
+       uint32_t host_ip;
+       struct sockaddr *sock;
+
+       uint64_t msg_total_size;
+       uint32_t msg_pack_size;
+       char *msg_buf;
+
+} info_t;
+
+void reset_pid_tid();
+pid_t _getpid();
+pid_t _gettid();
+char * _strncpy(char *dest, const char *src, size_t n);
+bool print_log_fmt(int msgType, const char *func_name, int line, ...);
+bool print_log_str(int msgType, char *st);
+bool print_log_ui_viewer_hierarchy_status(enum ErrorCode *err_code);
+void* print_log_ui_viewer_info_list(void *prendering);
+bool print_log_ui_viewer_hierarchy_error(void);
+bool print_log_ui_obj_screenshot(Evas_Object *obj);
+bool printLog(log_t* log, int msgType);
+void raise_app_window(void);
+
+int ui_viewer_capture_screen(char *screenshot_path, Evas_Object *obj);
+
+void ui_viewer_clean_log(void);
+void ui_viewer_log(const char *format, ...);
+
+#endif /* _UI_VIEWER_UTILS_ */