Update package version to 0.1.56
[platform/core/uifw/capi-ui-sticker.git] / receiver / src / ft.cpp
index 3f56506..670d30c 100644 (file)
 #include <pwd.h>
 #include <json-glib/json-glib.h>
 #include <vconf.h>
+#include <queue>
+#include <thumbnail_util.h>
+#include <Ecore.h>
+#include <app_preference.h>
 
 #include "ft.h"
 #include "log.h"
 #include "sticker_info.h"
+#include "../inc/sticker_data.h"
+#include "sticker_request.h"
 #include "message.h"
-#include "sync_alarm.h"
-
-#define ACCESSORY_SERVICE_PROFILE_ID "/sample/filetransfersender"
-#define ACCESSORY_SERVICE_CHANNEL_ID 107
+#include "config.h"
+#include "receiver_preference.h"
 
 #define STICKER_SYNC_FEATURE_REQ "sticker-sync-feature-req"
 #define STICKER_SYNC_FEATURE_RSP "sticker-sync-feature-rsp"
+#define STICKER_REQUEST_SYNC_REQ "sticker-request-sync-req"
+#define STICKER_REQUEST_NOTI_REQ "sticker-request-noti-req"
 #define STICKER_SYNC_START_REQ "sticker-sync-start-req"
 #define STICKER_SYNC_START_RSP "sticker-sync-start-rsp"
 #define STICKER_SEND_START_REQ "sticker-send-start-req"
 #define STICKER_SEND_FACE_DATA "sticker-send-face-data"
 #define STICKER_SEND_STOP_REQ  "sticker-send-stop-req"
 #define STICKER_SEND_STOP_RSP  "sticker-send-stop-rsp"
+#define STICKER_SEND_DISCONNECT_REQ "sticker-send-disconnect-req"
 
-using namespace std;
+#ifndef VCONFKEY_STICKER_SYNC_COMPLETE_DONE
+#define VCONFKEY_STICKER_SYNC_COMPLETE_DONE 0x1
+#endif
 
-typedef enum {
-    REQUEST_TYPE_SYNC,
-    REQUEST_TYPE_FEATURE_REQ
-} request_type;
+using namespace std;
 
 enum {
     SYNC_START_RSP_SUCCESS = 1000,
-    SYNC_START_RSP_NO_STICKER = 1001
+    SYNC_START_RSP_NO_STICKER = 1001,
+    SYNC_START_RSP_BITMOJI_ALL_DELETE = 1002,
+    SYNC_START_RSP_AREMOJI_ALL_DELETE = 1003,
+    SYNC_START_RSP_SYNC_AFTER_DELETING_AREMOJI = 1004
 };
 
 struct sap_info_s {
@@ -70,37 +79,63 @@ struct sap_info_s {
     sap_file_transaction_h file_socket;
 };
 
-struct request {
-    request_type req_type;
-    string mode;
-    string category;
-    string type;
-};
+static struct sap_info_s priv_data = { 0 };
+static struct sticker_info sticker_data;
+static queue<StickerRequest> ReqQueue;
+static StickerRequest current_request;
 
-static void _reset_sticker_data();
+static gboolean file_on_progress = FALSE;
+static string incoming_file_name;
+static int t_id = 0;
+static int rec_file_cnt_in_group = 0;
+static int total_file_count_in_group = 0;
+static int sync_success_cnt = 0;
+static gboolean job_progress = FALSE;
+static int sync_complete_flags = 0;
 
-struct sticker_info {
-    string file_path;
-    string group;
-    string keyword;
-    string disp_type;
-    string description;
+static void save_last_sync_time()
+{
+    // save last sync time in preference
+    double current_time = ecore_time_unix_get();
+    if (preference_set_double(LAST_SYNC_TIME, current_time) == PREFERENCE_ERROR_NONE) {
+        LOGI("Succeed to set last sync time : %f", current_time);
+    }
+    else {
+        LOGW("Failed to set last sync time");
+    }
+}
 
-    sticker_info()
-    {
-        _reset_sticker_data();
+static void set_sync_first_complete()
+{
+    int complete_flags = 0;
+    if (vconf_get_int(VCONFKEY_STICKER_SYNC_COMPLETE, &complete_flags) == 0 && complete_flags == 0) {
+        // first sync
+        if (vconf_set_int(VCONFKEY_STICKER_SYNC_COMPLETE, VCONFKEY_STICKER_SYNC_COMPLETE_DONE) == 0)
+            LOGD("Succeed to set sync complete");
+        else
+            LOGW("Fail to set sync complete");
     }
-};
+}
 
-static struct sap_info_s priv_data = { 0 };
-static struct sticker_info sticker_data;
-static struct request pending_request, current_request;
+static void set_sync_complete()
+{
+    set_sync_first_complete();
+    save_last_sync_time();
+}
 
-gboolean file_on_progress = 0;
-static string incoming_file_name;
-static int t_id = 0;
-static int rec_file_cnt = 0;
-static int total_file_count = 0;
+static void set_sync_progressing(gboolean flag)
+{
+    job_progress = flag;
+#ifdef VCONFKEY_STICKER_SYNC_STATE
+    LOGD("sync progressing : %d", flag);
+    if (vconf_set_int(VCONFKEY_STICKER_SYNC_STATE, flag ? VCONFKEY_STICKER_SYNC_STATE_IN_PROGRESS :  VCONFKEY_STICKER_SYNC_STATE_WAITING) == 0)
+        LOGD("Succeed to set sync state");
+    else
+        LOGW("Fail to set sync state");
+#else
+    LOGW("No vconf sync state definition");
+#endif
+}
 
 static gboolean _send_json_data(JsonObject *obj)
 {
@@ -151,21 +186,17 @@ cleanup:
 
 static void notify_sync_progress(unsigned int file_progress)
 {
-    if (total_file_count == 0)
+    if (total_file_count_in_group == 0)
         return;
 
-    double total_progress = (((double)rec_file_cnt / (double)total_file_count) + (1.0/(double)total_file_count*file_progress/100))*100;
-
-    LOGI("(%2d / %2d), file progress : %3u%%, total progress : %3u%%", rec_file_cnt, total_file_count, file_progress, (unsigned int)total_progress);
-    char progress_str[32];
-    snprintf(progress_str, sizeof(progress_str), "%u", (unsigned int)total_progress);
-    send_message("sync_progress", progress_str);
+    LOGI("(%2d / %2d), file progress : %3u%%", rec_file_cnt_in_group+1, total_file_count_in_group, file_progress);
+    send_message("sync_progress", NULL);
 }
 
-static void _on_send_completed(sap_file_transaction_h file_transaction,
-                               sap_ft_transfer_e result,
-                               const char *file_path,
-                               void *user_data)
+static void _on_transfer_completed(sap_file_transaction_h file_transaction,
+                                   sap_ft_transfer_e result,
+                                   const char *file_path,
+                                   void *user_data)
 {
     if (priv_data.file_socket) {
         sap_file_transfer_destroy(file_transaction);
@@ -180,16 +211,34 @@ static void _on_send_completed(sap_file_transaction_h file_transaction,
         }
         else {
             LOGI("Succeed to change permission : %s", sticker_data.file_path.c_str());
-            if (create_sticker_provider_handle() == STICKER_ERROR_NONE) {
-                insert_sticker_data(sticker_data.file_path.c_str(), sticker_data.keyword.c_str(), sticker_data.group.c_str(), sticker_data.description.c_str());
-                destroy_sticker_provider_handle();
+            char thumb_path[PATH_MAX];
+            char *data_path = NULL;
+            data_path = app_get_shared_data_path();
+            snprintf(thumb_path, sizeof(thumb_path), "%s/thumbnail/%s", data_path, incoming_file_name.c_str());
+            sticker_data.thumbnail_path = string(thumb_path);
+
+            if (data_path)
+                free(data_path);
+
+            int ret = thumbnail_util_extract_to_file(sticker_data.file_path.c_str(), THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT, sticker_data.thumbnail_path.c_str());
+            if (ret != THUMBNAIL_UTIL_ERROR_NONE) {
+                LOGE("Failed to create thumbnail. msg : %s", get_error_message(ret));
+                sticker_data.thumbnail_path.clear();
+            }
+
+            insert_sticker_data(sticker_data.file_path.c_str(), sticker_data.keyword.c_str(), sticker_data.group.c_str(), sticker_data.description.c_str(),
+                                sticker_data.thumbnail_path.c_str(), sticker_data.disp_type.c_str());
 
-                if (unlink(sticker_data.file_path.c_str()) == -1)
-                    LOGE("Failed to remove sticker file");
+            if (unlink(sticker_data.file_path.c_str()) == -1)
+                LOGE("Failed to remove sticker file");
+
+            if (!sticker_data.thumbnail_path.empty()) {
+                if (unlink(sticker_data.thumbnail_path.c_str()) == -1)
+                    LOGE("Failed to remove sticker thumbnail");
             }
         }
 
-        rec_file_cnt++;
+        rec_file_cnt_in_group++;
     } else {
         switch (result) {
             case (SAP_FT_TRANSFER_FAIL_CHANNEL_IO): {
@@ -238,12 +287,13 @@ static void _on_send_completed(sap_file_transaction_h file_transaction,
         }
     }
 
-    file_on_progress = 0;
+    file_on_progress = FALSE;
+    sticker_data.reset();
 }
 
-static void _on_sending_file_in_progress(sap_file_transaction_h file_transaction,
-                                         unsigned short int percentage_progress,
-                                         void *user_data)
+static void _on_transfer_file_in_progress(sap_file_transaction_h file_transaction,
+                                          unsigned short int percentage_progress,
+                                          void *user_data)
 {
     notify_sync_progress(percentage_progress);
 }
@@ -251,9 +301,14 @@ static void _on_sending_file_in_progress(sap_file_transaction_h file_transaction
 static void __set_file_transfer_cb(sap_file_transaction_h file_socket)
 {
     LOGI("# set callbacks");
-    sap_file_transfer_set_progress_cb(file_socket, _on_sending_file_in_progress, NULL);
+    sap_file_transfer_set_progress_cb(file_socket, _on_transfer_file_in_progress, NULL);
 
-    sap_file_transfer_set_done_cb(file_socket, _on_send_completed, NULL);
+    sap_file_transfer_set_done_cb(file_socket, _on_transfer_completed, NULL);
+}
+
+bool get_job_progress()
+{
+    return job_progress;
 }
 
 void accept_file()
@@ -264,10 +319,12 @@ void accept_file()
 
     data_path = app_get_shared_data_path();
     LOGI("Path : %s", data_path);
-    sprintf(file_path, "%s/%s", data_path, incoming_file_name.c_str());
+    snprintf(file_path, sizeof(file_path), "%s/%s", data_path, incoming_file_name.c_str());
     LOGI("Receive filepath : %s", file_path);
     sticker_data.file_path = string(file_path);
-    free(data_path);
+
+    if (data_path)
+        free(data_path);
 
     ret = sap_file_transfer_receive(priv_data.file_socket, file_path);
     switch(ret) {
@@ -282,17 +339,58 @@ void accept_file()
             break;
     }
 
-    file_on_progress = 1;
+    file_on_progress = TRUE;
+}
+
+static int _create_thumbnail_directory()
+{
+    char thumb_path[PATH_MAX];
+    char *data_path = NULL;
+    data_path = app_get_shared_data_path();
+    snprintf(thumb_path, sizeof(thumb_path), "%s/thumbnail", data_path);
+
+    if (data_path)
+        free(data_path);
+
+    if (access(thumb_path, F_OK) == 0)
+        return 0;
+
+    if (mkdir(thumb_path, 0755) == -1) {
+        LOGE("directory create error");
+        return -1;
+    }
+
+    return 0;
 }
 
-void request_sticker_data(const char *mode, const char *category, const char *type)
+bool request_sticker_data(const char *mode, const char *category, const char *type)
 {
-    JsonObject *j_object = json_object_new();
+    bool result = false;
+    JsonObject *j_object = NULL;
+
+    if (!priv_data.socket) {
+        job_progress = TRUE;
+        StickerRequest pending_request;
+        pending_request.req_type = REQUEST_TYPE_SYNC;
+        pending_request.mode = string(mode ? mode : "manual");
+        pending_request.category = string(category ? category : "arsticker");
+        pending_request.type = string(type ? type : "input");
+
+        ReqQueue.push(pending_request);
+        LOGI("Push sync request");
+
+        return false;
+    }
+
+    j_object = json_object_new();
     if (j_object == NULL) {
         LOGE("json object create error");
-        return;
+        return false;
     }
 
+    if (_create_thumbnail_directory() != 0)
+        LOGE("Failed to create thumbnail directory");
+
     json_object_set_string_member(j_object, "msgId", STICKER_SYNC_START_REQ);
     json_object_set_int_member(j_object, "tID", ++t_id);
     json_object_set_string_member(j_object, "mode", mode);
@@ -300,26 +398,100 @@ void request_sticker_data(const char *mode, const char *category, const char *ty
     json_object_set_string_member(j_object, "type", type);
 
     if (_send_json_data(j_object) == FALSE) {
-        pending_request.req_type = REQUEST_TYPE_SYNC;
-        pending_request.mode = string(mode ? mode : "manual");
-        pending_request.category = string(category? category : "arsticker");
-        pending_request.type = string(type ? type : "input");
-
-        LOGI("Push sync request");
+        LOGE("Failed to send STICKER_SYNC_START_REQ");
+        result = false;
     }
     else {
         current_request.req_type = REQUEST_TYPE_SYNC;
         current_request.mode = string(mode ? mode : "manual");
-        current_request.category = string(category? category : "arsticker");
+        current_request.category = string(category ? category : "arsticker");
         current_request.type = string(type ? type : "input");
+        set_sync_progressing(TRUE);
+        result = true;
     }
 
     json_object_unref(j_object);
+
+    return result;
+}
+
+static bool process_request_queue()
+{
+    if (ReqQueue.empty())
+        return false;
+
+    StickerRequest request = ReqQueue.front();
+
+    if (request.req_type == REQUEST_TYPE_FEATURE_REQ) {
+        LOGD("[Request feature exchange]");
+        request_sticker_feature();
+        ReqQueue.pop();
+    }
+    else if (request.req_type == REQUEST_TYPE_SYNC) {
+        LOGD("[Request to sync sticker] mode: %s, category: %s, type : %s", request.mode.c_str(),
+                request.category.c_str(),
+                request.type.c_str());
+
+        if (request_sticker_data(request.mode.c_str(), request.category.c_str(), request.type.c_str()))
+            ReqQueue.pop();
+    }
+    else if (request.req_type == REQUEST_TYPE_SHOW_NOTIFICATION) {
+        LOGD("[Request to show notification]");
+        request_show_sync_notification();
+        ReqQueue.pop();
+    }
+
+    return true;
+}
+
+void request_all_sticker_data(const char *mode, const char *type)
+{
+    StickerRequest pending_request;
+    pending_request.req_type = REQUEST_TYPE_SYNC;
+    pending_request.mode = string(mode);
+    pending_request.type = string(type);
+
+#ifdef VCONFKEY_STICKER_SUPPORTED_FEATURE
+    int feature_flag = 0;
+    if (vconf_get_int(VCONFKEY_STICKER_SUPPORTED_FEATURE, &feature_flag) == 0)
+    {
+        if (feature_flag & VCONFKEY_STICKER_FEATURE_AREMOJI) {
+            pending_request.category = string("arsticker");
+            ReqQueue.push(pending_request);
+        }
+
+        if (feature_flag & VCONFKEY_STICKER_FEATURE_BITMOJI) {
+            pending_request.category = string("bitmoji");
+            ReqQueue.push(pending_request);
+        }
+    }
+    else
+        LOGW("Failed to get value of VCONFKEY_STICKER_SUPPORTED_FEATURE");
+#else
+    pending_request.category = string("arsticker");
+    ReqQueue.push(pending_request);
+    pending_request.category = string("bitmoji");
+    ReqQueue.push(pending_request);
+#endif
+
+    if (priv_data.socket)
+        process_request_queue();
 }
 
 void request_sticker_feature()
 {
-    JsonObject *j_object = json_object_new();
+    JsonObject *j_object = NULL;
+
+    if (!priv_data.socket) {
+        job_progress = TRUE;
+        StickerRequest pending_request;
+        pending_request.req_type = REQUEST_TYPE_FEATURE_REQ;
+        ReqQueue.push(pending_request);
+        LOGI("Push sync feature request");
+        return;
+    }
+
+    j_object = json_object_new();
     if (j_object == NULL) {
         LOGE("json object create error");
         return;
@@ -329,9 +501,64 @@ void request_sticker_feature()
     json_object_set_int_member(j_object, "tID", ++t_id);
 
     if (_send_json_data(j_object) == FALSE) {
-        pending_request.req_type = REQUEST_TYPE_FEATURE_REQ;
         LOGE("Failed to send STICKER_SYNC_FEATURE_REQ");
     }
+    else {
+        job_progress = TRUE;
+    }
+
+    json_object_unref(j_object);
+
+    if (_create_thumbnail_directory() != 0)
+        LOGE("Failed to create thumbnail directory");
+}
+
+void send_disconnect_message()
+{
+    JsonObject *j_object = NULL;
+    j_object = json_object_new();
+    if (j_object == NULL) {
+        LOGE("json object create error");
+        return;
+    }
+
+    json_object_set_string_member(j_object, "msgId", STICKER_SEND_DISCONNECT_REQ);
+    json_object_set_int_member(j_object, "tID", t_id);
+
+    if (_send_json_data(j_object) == FALSE) {
+        LOGE("Failed to send STICKER_SEND_DISCONNECT_REQ");
+    }
+
+    json_object_unref(j_object);
+}
+
+void request_show_sync_notification()
+{
+    JsonObject *j_object = NULL;
+
+    if (!priv_data.socket) {
+        job_progress = TRUE;
+        StickerRequest pending_request;
+        pending_request.req_type = REQUEST_TYPE_SHOW_NOTIFICATION;
+        ReqQueue.push(pending_request);
+        LOGI("Push show notification request");
+        return;
+    }
+
+    j_object = json_object_new();
+    if (j_object == NULL) {
+        LOGE("json object create error");
+        return;
+    }
+
+    json_object_set_string_member(j_object, "msgId", STICKER_REQUEST_NOTI_REQ);
+    json_object_set_int_member(j_object, "tID", ++t_id);
+
+    if (_send_json_data(j_object) == FALSE) {
+        LOGE("Failed to send STICKER_REQUEST_NOTI_REQ");
+    } else {
+        job_progress = TRUE;
+    }
 
     json_object_unref(j_object);
 }
@@ -341,15 +568,15 @@ void reject_file()
     int ret = sap_file_transfer_reject(priv_data.file_socket);
     LOGI("ret : %d", ret);
 
-    file_on_progress = 0;
+    file_on_progress = FALSE;
 }
 
-static void _on_receive_file_cb(sap_peer_agent_h peer_agent_h,
-                                sap_file_transaction_h socket,
-                                const char *file_path,
-                                void *user_data)
+static void _on_transfer_file_cb(sap_peer_agent_h peer_agent_h,
+                                 sap_file_transaction_h socket,
+                                 const char *file_path,
+                                 void *user_data)
 {
-    file_on_progress = 1;
+    file_on_progress = TRUE;
     priv_data.file_socket = socket;
     LOGI("# incoming file request.");
     __set_file_transfer_cb(priv_data.file_socket);
@@ -390,16 +617,88 @@ void conn_terminated(sap_peer_agent_h peer_agent,
     sap_socket_destroy(priv->socket);
     priv->socket = NULL;
 
+    set_sync_progressing(FALSE);
+    send_message("sync_stop_result", "cancel");
     service_app_exit();
 }
 
-static void _reset_sticker_data()
+static void quit()
 {
-    sticker_data.file_path.clear();
-    sticker_data.group.clear();
-    sticker_data.keyword.clear();
-    sticker_data.disp_type.clear();
-    sticker_data.description.clear();
+    job_progress = FALSE;
+    send_disconnect_message();
+    service_app_exit();
+}
+
+static void send_sync_start_response(int result_code)
+{
+    int feature_flag = 0;
+    string response_to_app;
+    switch (result_code) {
+        case SYNC_START_RSP_SUCCESS:
+        {
+            response_to_app = "success";
+            if (current_request.category == string("arsticker"))
+                sync_complete_flags |= VCONFKEY_STICKER_FEATURE_AREMOJI;
+            else if (current_request.category == string("bitmoji"))
+                sync_complete_flags |= VCONFKEY_STICKER_FEATURE_BITMOJI;
+        }
+        break;
+        case SYNC_START_RSP_NO_STICKER:
+            response_to_app = "no_sticker";
+            break;
+        case SYNC_START_RSP_BITMOJI_ALL_DELETE:
+        {
+            int is_synced = 0;
+            if (vconf_get_int(VCONFKEY_STICKER_SYNC_COMPLETE, &is_synced) != 0)
+                LOGW("Failed to read sync completion");
+
+            if (is_synced == VCONFKEY_STICKER_SYNC_COMPLETE_NONE)
+                response_to_app = "no_sticker";
+            else
+                response_to_app = "success";
+            break;
+        }
+        case SYNC_START_RSP_AREMOJI_ALL_DELETE:
+            response_to_app = "success";
+            break;
+        case SYNC_START_RSP_SYNC_AFTER_DELETING_AREMOJI:
+            response_to_app = "success";
+            break;
+        default:
+            response_to_app = "unknown_error";
+            break;
+    }
+
+    LOGD("result code : %d, sync complete flag : %d", result_code, sync_complete_flags);
+
+#ifdef VCONFKEY_STICKER_SUPPORTED_FEATURE
+    if (vconf_get_int(VCONFKEY_STICKER_SUPPORTED_FEATURE, &feature_flag) != 0)
+    {
+        LOGW("Failed to read support feature");
+        return;
+    }
+
+    LOGD("feature : %d, current request category : %s", feature_flag, current_request.category.c_str());
+    if (feature_flag == VCONFKEY_STICKER_FEATURE_AREMOJI ||
+        feature_flag == VCONFKEY_STICKER_FEATURE_BITMOJI)
+    {
+        LOGD("only standalone sync mode");
+        send_message("sync_start_response", response_to_app.c_str());
+    }
+    else {
+        if (current_request.category == string("arsticker"))
+        {
+            if (result_code == SYNC_START_RSP_SUCCESS)
+                send_message("sync_start_response", response_to_app.c_str());
+        }
+        else if (current_request.category == string("bitmoji"))
+        {
+            if (sync_complete_flags == 0 ||
+                sync_complete_flags == VCONFKEY_STICKER_FEATURE_BITMOJI)
+                send_message("sync_start_response", response_to_app.c_str());
+        }
+    }
+#endif
 }
 
 void
@@ -436,8 +735,11 @@ on_data_received(sap_socket_h socket, unsigned short int channel_id, unsigned in
 
     json_msgid = json_object_get_string_member(root_obj, "msgId");
     msg_id = string(json_msgid ? json_msgid : "");
-    if (msg_id == STICKER_SYNC_FEATURE_RSP) {
+    if (msg_id == STICKER_REQUEST_SYNC_REQ) {
+        request_all_sticker_data("manual", "input");
+    } else if (msg_id == STICKER_SYNC_FEATURE_RSP) {
         LOGD("msg : %s", msg_id.c_str());
+#ifdef VCONFKEY_STICKER_SUPPORTED_FEATURE
         const char *json_aremoji = json_object_get_string_member(root_obj, "arEmoji");
         const char *json_bitmoji = json_object_get_string_member(root_obj, "bitmoji");
         string support_aremoji = string(json_aremoji ? json_aremoji : "");
@@ -454,8 +756,13 @@ on_data_received(sap_socket_h socket, unsigned short int channel_id, unsigned in
             LOGD("Succeed to set supported feature");
         else
             LOGW("Fail to set supported feature");
+#else
+        LOGW("No vconf supported feature");
+#endif
 
-        service_app_exit();
+        if (!process_request_queue()) {
+            quit();
+        }
     } else if (msg_id == STICKER_SYNC_START_RSP) {
         LOGD("msg : %s", msg_id.c_str());
         const char *json_result = json_object_get_string_member(root_obj, "result");
@@ -463,27 +770,61 @@ on_data_received(sap_socket_h socket, unsigned short int channel_id, unsigned in
         int result_code = json_object_get_int_member(root_obj, "resultCode");
         LOGD("result : %s, resultCode : %d", result.c_str(), result_code);
 
-        string response_to_app;
-        switch (result_code) {
-        case SYNC_START_RSP_SUCCESS:
-            response_to_app = "success";
-            break;
-        case SYNC_START_RSP_NO_STICKER:
-            response_to_app = "no_sticker";
-            break;
-        default:
-            response_to_app = "unknown_error";
-            break;
-        }
+        if(result_code == SYNC_START_RSP_SUCCESS) {
+            send_sync_start_response(result_code);
+            if (current_request.category == string("bitmoji")) {
+                LOGD("Delete all bitmoji stickers");
+                delete_all_stickers("bitmoji");
+            }
+        } else if (result_code == SYNC_START_RSP_SYNC_AFTER_DELETING_AREMOJI) {
+            send_sync_start_response(result_code);
+            LOGD("Delete all AR Emoji stickers");
+            delete_all_stickers("arsticker");
+        } else {
+            if (result_code == SYNC_START_RSP_BITMOJI_ALL_DELETE) {
+                LOGD("Delete all bitmoji stickers");
+                delete_all_stickers("bitmoji");
+            } else if (result_code == SYNC_START_RSP_AREMOJI_ALL_DELETE) {
+                LOGD("Delete all AR Emoji stickers");
+                delete_all_stickers("arsticker");
+            }
 
-        send_message("sync_start_response", response_to_app.c_str());
+            if (!process_request_queue()) {
+#ifdef VCONFKEY_STICKER_SUPPORTED_FEATURE
+                int feature_flag = 0;
+
+                if (vconf_get_int(VCONFKEY_STICKER_SUPPORTED_FEATURE, &feature_flag) == 0)
+                {
+                    LOGD("feature : %d, current request category : %s", feature_flag, current_request.category.c_str());
+                    if (feature_flag & VCONFKEY_STICKER_FEATURE_BITMOJI)
+                    {
+                        if (current_request.category == string("bitmoji"))
+                        {
+                            /* other sticker group(s) has been synchronized completely */
+                            if (sync_success_cnt > 0) {
+                                set_sync_complete();
+                            }
+                        }
+                    }
+                }
+                else {
+                    LOGW("Failed to read support feature");
+                }
+#else
+                LOGW("No vconf supported feature");
+#endif /* VCONFKEY_STICKER_SUPPORTED_FEATURE */
 
-        if (result_code != SYNC_START_RSP_SUCCESS)
-            service_app_exit();
+                send_sync_start_response(result_code);
+                set_sync_progressing(FALSE);
+                save_last_sync_time();
+
+                quit();
+            }
+        }
     } else if (msg_id == STICKER_SEND_START_REQ) {
         LOGD("msg : %s", msg_id.c_str());
-        total_file_count = 0;
-        rec_file_cnt = 0;
+        total_file_count_in_group = 0;
+        rec_file_cnt_in_group = 0;
         t_id = json_object_get_int_member(root_obj, "tID");
         JsonArray *file_list = json_object_get_array_member(root_obj, "list");
         if (file_list) {
@@ -496,13 +837,23 @@ on_data_received(sap_socket_h socket, unsigned short int channel_id, unsigned in
 
                 if (file_len > 0) {
                     LOGD("Add file : %s, len : %d", file_name.c_str(), file_len);
-                    total_file_count++;
+                    total_file_count_in_group++;
                 } else {
-                    LOGD("Delete file : %s, len : %d", file_name.c_str(), file_len);
-                    if (create_sticker_provider_handle() == STICKER_ERROR_NONE) {
-                        delete_sticker_data(file_name.c_str());
-                        destroy_sticker_provider_handle();
-                    }
+                    char *app_id = NULL;
+                    char file_path[PATH_MAX];
+                    char del_path[PATH_MAX];
+                    std::size_t found = file_name.find_last_of("/");
+                    string del_file_name = file_name.substr(found+1);
+                    char *data_path = app_get_shared_data_path();
+                    app_get_id(&app_id);
+                    snprintf(file_path, sizeof(file_path), "%s/%s", data_path, del_file_name.c_str());
+                    snprintf(del_path, sizeof(del_path), "%s/%s%s",STICKER_DIRECTORY, app_id, file_path);
+
+                    LOGD("Delete file : %s, len : %d", del_path, file_len);
+                    delete_sticker_data(del_path);
+
+                    if (app_id)
+                        free(app_id);
                 }
             }
         }
@@ -523,8 +874,6 @@ on_data_received(sap_socket_h socket, unsigned short int channel_id, unsigned in
         json_object_unref(j_object);
     } else if (msg_id == STICKER_SEND_FACE_DATA) {
         LOGD("msg : %s", msg_id.c_str());
-        _reset_sticker_data();
-
         const char *type_data = json_object_get_string_member(root_obj, "type");
         if (type_data)
             sticker_data.disp_type = string(type_data);
@@ -549,47 +898,65 @@ on_data_received(sap_socket_h socket, unsigned short int channel_id, unsigned in
         json_object_set_string_member(j_object, "msgId", STICKER_SEND_STOP_RSP);
         json_object_set_int_member(j_object, "tID", t_id);
 
-        if (reason == "complete" && rec_file_cnt != file_len)
-            json_object_set_string_member(j_object, "result", "failure");
-        else {
-            int complete_flags = 0;
-            if (vconf_get_int(VCONFKEY_STICKER_SYNC_COMPLETE, &complete_flags) == 0) {
-                if (sticker_data.group == string("arsticker"))
-                    complete_flags |= 0x1;
-                else if (sticker_data.group == string("bitmoji"))
-                    complete_flags |= 0x2;
-
-                LOGD("sync complete flag : %x", complete_flags);
-
-                if (vconf_set_int(VCONFKEY_STICKER_SYNC_COMPLETE, complete_flags) == 0)
-                    LOGD("Succeed to set sync complete");
-                else
-                    LOGW("Fail to set sync complete");
+        if (reason == "complete") {
+            if (rec_file_cnt_in_group == file_len) {
+#ifdef VCONFKEY_STICKER_SUPPORTED_FEATURE
+                int feature_flag = 0;
+
+                if (vconf_get_int(VCONFKEY_STICKER_SUPPORTED_FEATURE, &feature_flag) == 0)
+                {
+                    LOGD("feature : %d, current request category : %s", feature_flag, current_request.category.c_str());
+                    if (feature_flag == VCONFKEY_STICKER_FEATURE_AREMOJI)
+                    {
+                        if (current_request.category == string("arsticker"))
+                        {
+                            set_sync_complete();
+                            set_sync_progressing(FALSE);
+                        }
+                    }
+                    else if (feature_flag & VCONFKEY_STICKER_FEATURE_BITMOJI)
+                    {
+                        if (current_request.category == string("bitmoji"))
+                        {
+                            set_sync_complete();
+                            set_sync_progressing(FALSE);
+                        }
+                    }
+                }
+                else {
+                    LOGW("Failed to read support feature");
+                }
+#else
+                LOGW("No vconf supported feature");
+#endif /* VCONFKEY_STICKER_SUPPORTED_FEATURE */
+
+                json_object_set_string_member(j_object, "result", "success");
+                sync_success_cnt++;
             }
             else {
-                LOGW("Failed to get sticker sync flags");
-            }
-
-            json_object_set_string_member(j_object, "result", "success");
-
-            if (current_request.mode == string("manual")) {
-                if (!sync_alarm_exist())
-                    sync_alarm_register(APP_CONTROL_OPERATION_SYNC_ALARM, SYNC_ALARM_DELAY, SYNC_ALARM_INTERVAL);
+                json_object_set_string_member(j_object, "result", "failure");
             }
         }
+        else {
+            json_object_set_string_member(j_object, "result", "failure");
+        }
 
         if (_send_json_data(j_object) == FALSE)
             LOGE("Failed to send message");
 
-        send_message("sync_stop_result", reason.c_str());
-
         json_object_unref(j_object);
 
+        send_message("sync_stop_result", reason.c_str());
+
         current_request.mode.clear();
         current_request.category.clear();
         current_request.type.clear();
 
-        service_app_exit();
+        if (!process_request_queue()) {
+            sync_success_cnt = 0;
+
+            quit();
+        }
     } else
         LOGW("unknown msg id : %s", msg_id.c_str());
 
@@ -662,25 +1029,7 @@ _on_service_connection_created(sap_peer_agent_h peer_agent,
         priv->socket = socket;
         LOGI("Connection Established");
 
-        LOGD("pending_request : %d", pending_request.req_type);
-
-        if (pending_request.req_type == REQUEST_TYPE_FEATURE_REQ) {
-            LOGD("[Request feature exchange]");
-            request_sticker_feature();
-        }
-        else if (pending_request.req_type == REQUEST_TYPE_SYNC) {
-            if (!pending_request.mode.empty()) {
-                LOGD("[Request to sync sticker] mode: %s, category: %s, type : %s", pending_request.mode.c_str(),
-                                                                                    pending_request.category.c_str(),
-                                                                                    pending_request.type.c_str());
-
-                request_sticker_data(pending_request.mode.c_str(), pending_request.category.c_str(), pending_request.type.c_str());
-
-                pending_request.mode.clear();
-                pending_request.category.clear();
-                pending_request.type.clear();
-            }
-        }
+        process_request_queue();
 
         break;
 
@@ -800,7 +1149,7 @@ static void on_agent_initialized(sap_agent_h agent,
 
             priv_data.agent = agent;
 
-            sap_file_transfer_set_incoming_file_cb(agent, _on_receive_file_cb, NULL);
+            sap_file_transfer_set_incoming_file_cb(agent, _on_transfer_file_cb, NULL);
             sap_agent_set_service_connection_requested_cb(agent, on_conn_req, NULL);
 
             break;
@@ -856,6 +1205,7 @@ static void _on_device_status_changed(sap_device_status_e status,
     switch (status) {
         case SAP_DEVICE_STATUS_DETACHED:
             LOGD("device is not connected.");
+            send_message("sync_stop_result", "cancel");
             break;
         case SAP_DEVICE_STATUS_ATTACHED:
             LOGD("Attached calling find peer now");
@@ -885,6 +1235,11 @@ gboolean initialize_sap(void)
 {
     sap_agent_h agent = NULL;
 
+    if (priv_data.agent) {
+        LOGW("duplicate initialize");
+        return FALSE;
+    }
+
     sap_agent_create(&agent);
 
     priv_data.agent = agent;
@@ -898,6 +1253,7 @@ gboolean initialize_sap(void)
 
 void deinitialize_sap(void)
 {
+    LOGD("deinitialize");
     if (priv_data.agent) {
         int ret = sap_agent_deinitialize(priv_data.agent, on_agent_deinitialized, NULL);
         switch (ret) {
@@ -919,3 +1275,8 @@ void deinitialize_sap(void)
         priv_data.agent = NULL;
     }
 }
+
+gboolean is_init_sap()
+{
+    return priv_data.agent ? TRUE : FALSE;
+}
\ No newline at end of file