Merge "Revert "[SystemInfo] Replace deprecated native wifi API with wifi-manager... accepted/tizen/common/20160908.134425 accepted/tizen/ivi/20160908.122649 accepted/tizen/mobile/20160908.122606 accepted/tizen/tv/20160908.122630 accepted/tizen/wearable/20160908.122641 submit/tizen/20160908.010303 submit/tizen/20160908.033928
authorJeongkyun Pu <jk.pu@samsung.com>
Thu, 8 Sep 2016 02:46:41 +0000 (19:46 -0700)
committerGerrit Code Review <gerrit@review.vlan103.tizen.org>
Thu, 8 Sep 2016 02:46:41 +0000 (19:46 -0700)
52 files changed:
packaging/webapi-plugins.spec
src/bluetooth/bluetooth_api.js
src/bluetooth/bluetooth_le_device.cc
src/common/filesystem/filesystem_provider_deviced.cc
src/content/content_instance.cc
src/content/content_instance.h
src/content/content_manager.cc
src/content/content_manager.h
src/content/js/manager.js
src/convergence/convergence.gyp [new file with mode: 0644]
src/convergence/convergence_api.js [new file with mode: 0644]
src/convergence/convergence_app_communication_service.cc [new file with mode: 0644]
src/convergence/convergence_app_communication_service.h [new file with mode: 0644]
src/convergence/convergence_channel.cc [new file with mode: 0644]
src/convergence/convergence_channel.h [new file with mode: 0644]
src/convergence/convergence_client_info.cc [new file with mode: 0644]
src/convergence/convergence_client_info.h [new file with mode: 0644]
src/convergence/convergence_device.cc [new file with mode: 0644]
src/convergence/convergence_device.h [new file with mode: 0644]
src/convergence/convergence_extension.cc [new file with mode: 0644]
src/convergence/convergence_extension.h [moved from src/secureelement/secureelement_reader.h with 55% similarity]
src/convergence/convergence_instance.cc [new file with mode: 0644]
src/convergence/convergence_instance.h [new file with mode: 0644]
src/convergence/convergence_manager.cc [new file with mode: 0644]
src/convergence/convergence_manager.h [new file with mode: 0644]
src/convergence/convergence_payload.cc [new file with mode: 0644]
src/convergence/convergence_payload.h [new file with mode: 0644]
src/convergence/convergence_remote_app_control_service.cc [new file with mode: 0644]
src/convergence/convergence_remote_app_control_service.h [new file with mode: 0644]
src/convergence/convergence_service.cc [new file with mode: 0644]
src/convergence/convergence_service.h [new file with mode: 0644]
src/convergence/convergence_utils.cc [new file with mode: 0644]
src/convergence/convergence_utils.h [moved from src/secureelement/secureelement_channel.h with 53% similarity]
src/iotcon/iotcon_api.js
src/iotcon/iotcon_instance.cc
src/iotcon/iotcon_instance.h
src/iotcon/iotcon_server_manager.cc
src/iotcon/iotcon_utils.cc
src/iotcon/iotcon_utils.h
src/messaging/messaging_database_manager.cc
src/secureelement/secureelement.gyp
src/secureelement/secureelement_api.js
src/secureelement/secureelement_channel.cc [deleted file]
src/secureelement/secureelement_instance.cc
src/secureelement/secureelement_instance.h
src/secureelement/secureelement_reader.cc [deleted file]
src/secureelement/secureelement_seservice.cc [deleted file]
src/secureelement/secureelement_seservice.h [deleted file]
src/secureelement/secureelement_session.cc [deleted file]
src/secureelement/secureelement_session.h [deleted file]
src/tizen-wrt.gyp
src/tool/desc_gentool.cc

index eb12889..861613c 100644 (file)
@@ -10,7 +10,7 @@
 %define crosswalk_extensions_path %{_libdir}/%{crosswalk_extensions}
 
 Name:       webapi-plugins
-Version:    1.23
+Version:    1.27
 Release:    0
 License:    Apache-2.0 and BSD-2.0 and MIT
 Group:      Development/Libraries
@@ -174,6 +174,12 @@ Source0:    %{name}-%{version}.tar.gz
 
 %define tizen_feature_tvinputdevice_support           0
 
+%if 0%{?tizen_is_emulator}
+%define tizen_feature_convergence_support             0
+%else
+%define tizen_feature_convergence_support             1
+%endif
+
 %endif # tizen_profile_mobile
 
 ####################################################################
@@ -232,11 +238,7 @@ Source0:    %{name}-%{version}.tar.gz
 %define tizen_feature_message_port_support            1
 %define tizen_feature_messaging_support               0
 %define tizen_feature_nfc_emulation_support           0
-%if 0%{?tizen_is_emulator}
-%define tizen_feature_nfc_support                     0
-%else
 %define tizen_feature_nfc_support                     1
-%endif
 %define tizen_feature_notification_support            1
 %define tizen_feature_package_support                 1
 %define tizen_feature_power_support                   1
@@ -274,6 +276,12 @@ Source0:    %{name}-%{version}.tar.gz
 %define    tizen_feature_nbs_support                  0
 %endif
 
+%if 0%{?tizen_is_emulator}
+%define tizen_feature_convergence_support             0
+%else
+%define tizen_feature_convergence_support             1
+%endif
+
 %endif # tizen_profile_wearable
 
 ####################################################################
@@ -329,6 +337,7 @@ Source0:    %{name}-%{version}.tar.gz
 %define tizen_feature_wi_fi_support                   1
 %define tizen_feature_inputdevice_support             0
 %define tizen_feature_tvinputdevice_support           1
+%define tizen_feature_convergence_support             1
 
 %endif # tizen_profile_tv
 
@@ -481,8 +490,7 @@ BuildRequires: pkgconfig(feedback)
 %endif
 
 %if 0%{?tizen_feature_se_support}
-BuildRequires:  pkgconfig(smartcard-service)
-BuildRequires:  pkgconfig(smartcard-service-common)
+BuildRequires:  pkgconfig(capi-network-smartcard)
 %endif
 
 %if 0%{?tizen_feature_message_port_support}
@@ -505,6 +513,10 @@ BuildRequires: pkgconfig(capi-system-sensor)
 BuildRequires:  pkgconfig(capi-system-media-key)
 %endif
 
+%if 0%{?tizen_feature_convergence_support}
+BuildRequires: pkgconfig(d2d-conv-manager)
+%endif
+
 %if 0%{?tizen_feature_widget_service_support}
 BuildRequires: pkgconfig(widget_service)
 %endif
@@ -580,6 +592,7 @@ GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_web_setting_support=%{?tizen_feature_w
 GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_widget_service_support=%{?tizen_feature_widget_service_support}"
 GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_wi_fi_support=%{?tizen_feature_wi_fi_support}"
 GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_tvinputdevice_support=%{?tizen_feature_tvinputdevice_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_convergence_support=%{?tizen_feature_convergence_support}"
 
 ./tools/gyp/gyp $GYP_OPTIONS src/tizen-wrt.gyp
 
index c1c1864..bebe73e 100755 (executable)
@@ -559,7 +559,7 @@ BluetoothSocket.prototype.close = function() {
 //class BluetoothLEDevice ////////////////////////////////////////////////////
 var BluetoothLEDevice = function(data) {
     var address = "", name = null, txpowerlevel = null, appearance = null, uuids = null,
-        solicitationuuids = null, serviceData = null, manufacturerData = null;
+        solicitationuuids = null, serviceData = null, manufacturerData = null, rssi = null;
 
     if (data) {
       address = data.address;
@@ -576,6 +576,9 @@ var BluetoothLEDevice = function(data) {
       if (data.manufacturerData) {
         manufacturerData = new tizen.BluetoothLEManufacturerData(data.manufacturerData);
       }
+      if (data.rssi) {
+        rssi = data.rssi;
+      }
     }
 
     Object.defineProperties(this, {
@@ -604,7 +607,8 @@ var BluetoothLEDevice = function(data) {
         manufacturerData : {
             value: manufacturerData,
             writable: false,
-            enumerable: true}
+            enumerable: true},
+        rssi : {value: rssi, writable: false, enumerable: true}
     });
 };
 
index 2c57160..a4f27dc 100755 (executable)
@@ -48,6 +48,7 @@ const std::string kManufacturerData = "manufacturerData";
 const std::string kId = "id";
 const std::string kData = "data";
 const std::string kAction = "action";
+const std::string kRSSI = "rssi";
 
 const std::string kOnConnected = "onconnected";
 const std::string kOnDisconnected = "ondisconnected";
@@ -305,6 +306,10 @@ PlatformResult BluetoothLEDevice::ToJson(
     g_free(manufacturer_data);
   }
 
+  le_device->insert(
+      std::make_pair(kRSSI,
+                     picojson::value(static_cast<double>(info->rssi))));
+
   return PlatformResult(ErrorCode::NO_ERROR);
 }
 
index e8613a8..f3bb5a0 100644 (file)
 #include <algorithm>
 #include <memory>
 #include <utility>
-
 #include "common/filesystem/filesystem_storage.h"
 #include "common/logger.h"
 
 namespace {
 static const char* kBus = "org.tizen.system.storage";
-static const char* kBlockIface = "org.tizen.system.storage.BlockManager";
-static const char* kBlackManagerIface = "org.tizen.system.storage.BlockManager";
+static const char* kBlockManagerIface = "org.tizen.system.storage.BlockManager";
 static const char* kPath = "/Org/Tizen/System/Storage/Block/Manager";
 static const char* kDeviceChangedMethod = "DeviceChanged";
 static const char* kGetDeviceListMethod = "GetDeviceList";
@@ -173,7 +171,7 @@ void FilesystemProviderDeviced::RegisterDeviceChangeState(
   if (device_changed_callback_ == nullptr) {
     LoggerD("Registering dbus signal subscription");
     block_signal_subscribe_id_ = g_dbus_connection_signal_subscribe(
-        dbus_, nullptr, kBlockIface, kDeviceChangedMethod,
+        dbus_, nullptr, kBlockManagerIface, kDeviceChangedMethod,
         nullptr, nullptr, G_DBUS_SIGNAL_FLAGS_NONE, BlockSignalProxy, this,
         nullptr);
   }
@@ -240,7 +238,7 @@ Storages FilesystemProviderDeviced::GetStorages() {
   GVariant* variant = g_dbus_connection_call_sync(dbus_,
                                                   kBus,
                                                   kPath,
-                                                  kBlackManagerIface,
+                                                  kBlockManagerIface,
                                                   kGetDeviceListMethod,
                                                   g_variant_new("(s)", "all"),
                                                   NULL,
index 9008f68..8491b1d 100755 (executable)
@@ -31,6 +31,8 @@
 #include "content/content_manager.h"
 #include "common/filesystem/filesystem_provider.h"
 
+using namespace common;
+
 namespace extension {
 namespace content {
 
@@ -47,7 +49,9 @@ using common::PlatformResult;
 
 ContentInstance::ContentInstance() :
     noti_handle_(nullptr),
-    listener_data_(nullptr) {
+    listener_handle_(nullptr),
+    listener_data_(nullptr),
+    callback_data_(nullptr) {
   using std::placeholders::_1;
   using std::placeholders::_2;
 
@@ -59,6 +63,8 @@ ContentInstance::ContentInstance() :
   REGISTER_SYNC("ContentManager_scanFile", ContentManagerScanfile);
   REGISTER_SYNC("ContentManager_scanDirectory", ContentManagerScanDirectory);
   REGISTER_SYNC("ContentManager_cancelScanDirectory", ContentManagerCancelScanDirectory);
+  REGISTER_SYNC("ContentManager_addChangeListener", ContentManagerAddChangeListener);
+  REGISTER_SYNC("ContentManager_removeChangeListener", ContentManagerRemoveChangeListener);
   REGISTER_SYNC("ContentManager_unsetChangeListener", ContentManagerUnsetchangelistener);
   REGISTER_SYNC("ContentManager_setChangeListener", ContentManagerSetchangelistener);
   REGISTER_SYNC("ContentManager_getDirectories", ContentManagerGetdirectories);
@@ -88,14 +94,27 @@ ContentInstance::ContentInstance() :
 
 ContentInstance::~ContentInstance() {
   LoggerD("entered");
+
   if (noti_handle_) {
     media_content_remove_db_updated_cb(noti_handle_);
     noti_handle_ = nullptr;
   }
+
+  if (listener_handle_) {
+    media_content_remove_db_updated_cb(listener_handle_);
+    listener_handle_ = nullptr;
+  }
+
   if (listener_data_) {
     delete listener_data_;
     listener_data_ = nullptr;
   }
+
+  if (callback_data_) {
+    delete callback_data_;
+    callback_data_ = nullptr;
+  }
+
   ContentManager::getInstance()->setContentInstance(nullptr);
 }
 
@@ -226,8 +245,8 @@ static void ScanDirectoryCallback(media_content_error_e error, void* user_data)
   common::Instance::PostMessage(cbData->instance, picojson::value(out).serialize().c_str());
 }
 
-
-static void changedContentCallback(media_content_error_e error,
+// DEPRECATED CALLBACK. contentChangeCallback() is currently in use
+static void changedContentV1Callback(media_content_error_e error,
                                    int pid,
                                    media_content_db_update_item_type_e update_item,
                                    media_content_db_update_type_e update_type,
@@ -285,6 +304,7 @@ static void changedContentCallback(media_content_error_e error,
   }
 }
 
+// DEPRECATED CALLBACK. contentChangeCallback() is currently in use
 static void changedContentV2Callback(media_content_error_e error,
                                    int pid,
                                    media_content_db_update_item_type_e update_item,
@@ -343,6 +363,137 @@ static void changedContentV2Callback(media_content_error_e error,
   }
 }
 
+static PlatformResult prepareDirectoryChangeResponse(media_content_db_update_type_e update_type,
+                                                     char* uuid,
+                                                     picojson::object& obj) {
+  LoggerD("Media item is a directory");
+
+  if (MEDIA_CONTENT_DELETE == update_type) {
+    ReportSuccess(picojson::value(std::string(uuid)), obj);
+    obj["state"] = picojson::value("oncontentdirremoved");
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  media_folder_h folder = nullptr;
+  int ret = media_folder_get_folder_from_db(uuid, &folder);
+
+  if (MEDIA_CONTENT_ERROR_NONE != ret || nullptr == folder) {
+    LoggerE("Failed to get media item (media_folder_get_folder_from_db): %d", ret);
+    return PlatformResult(ErrorCode::ABORT_ERR);
+  }
+
+  picojson::object o;
+  ContentDirToJson(folder, o);
+
+  ret = media_folder_destroy(folder);
+
+  if (MEDIA_CONTENT_ERROR_NONE != ret) {
+    LoggerE("Failed to destroy media folder (media_folder_destroy): %d", ret);
+    return PlatformResult(ErrorCode::ABORT_ERR);
+  }
+
+  ReportSuccess(picojson::value(o), obj);
+
+  if (MEDIA_CONTENT_INSERT == update_type) {
+    obj["state"] = picojson::value("oncontentdiradded");
+  } else if (MEDIA_CONTENT_UPDATE == update_type) {
+    obj["state"] = picojson::value("oncontentdirupdated");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static PlatformResult prepareFileChangeResponse(media_content_db_update_type_e update_type,
+                                                char* uuid,
+                                                picojson::object& obj) {
+  LoggerD("Media item is a file");
+
+  if (MEDIA_CONTENT_DELETE == update_type) {
+    ReportSuccess(picojson::value(std::string(uuid)), obj);
+    obj["state"] = picojson::value("oncontentremoved");
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  media_info_h media = nullptr;
+  int ret = media_info_get_media_from_db(uuid, &media);
+
+  if (MEDIA_CONTENT_ERROR_NONE != ret || nullptr == media) {
+    LoggerE("Failed to get media item (media_info_get_media_from_db): %d", ret);
+    return PlatformResult(ErrorCode::ABORT_ERR);
+  }
+
+  picojson::object o;
+  ContentToJson(media, o);
+
+  ret = media_info_destroy(media);
+
+  if (MEDIA_CONTENT_ERROR_NONE != ret) {
+    LoggerE("Failed to destroy media info (media_info_destroy): %d", ret);
+    return PlatformResult(ErrorCode::ABORT_ERR);
+  }
+
+  ReportSuccess(picojson::value(o), obj);
+
+  if (MEDIA_CONTENT_INSERT == update_type) {
+    obj["state"] = picojson::value("oncontentadded");
+  } else if (MEDIA_CONTENT_UPDATE == update_type) {
+    obj["state"] = picojson::value("oncontentupdated");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static void contentChangeCallback(media_content_error_e error,
+                                  int pid,
+                                  media_content_db_update_item_type_e update_item,
+                                  media_content_db_update_type_e update_type,
+                                  media_content_type_e media_type,
+                                  char* uuid,
+                                  char* path,
+                                  char* mime_type,
+                                  void* user_data) {
+  LoggerD("Entered directory and file change callback");
+
+  if (MEDIA_CONTENT_ERROR_NONE != error) {
+    LoggerE("Failed to perform contentChangeCallback: %d", error);
+    return;
+  }
+
+  if (!uuid) {
+    LoggerE("Provided uuid is NULL, ignoring");
+    return;
+  }
+
+  if (nullptr == user_data) {
+    LoggerE("Provided user data is NULL, ignoring");
+    return;
+  }
+
+  if (MEDIA_ITEM_DIRECTORY != update_item && MEDIA_ITEM_FILE != update_item) {
+    LoggerD("Media item is not a directory nor a file, skipping");
+    return;
+  }
+
+  ReplyCallbackData* cbData = static_cast<ReplyCallbackData*>(user_data);
+
+  picojson::value result = picojson::value(picojson::object());
+  picojson::object& obj = result.get<picojson::object>();
+
+  PlatformResult ret(ErrorCode::NO_ERROR);
+  if (MEDIA_ITEM_DIRECTORY == update_item) {
+    ret = prepareDirectoryChangeResponse(update_type, uuid, obj);
+  } else if (MEDIA_ITEM_FILE == update_item) {
+    ret = prepareFileChangeResponse(update_type, uuid, obj);
+  }
+
+  if (ret.IsSuccess()) {
+    obj["listenerId"] = picojson::value("ContentManagerChangeCallback");
+    Instance::PostMessage(cbData->instance, result.serialize().c_str());
+  } else {
+    LoggerD("Failed to prepare content change callback, ignoring");
+  }
+}
+
 #define CHECK_EXIST(args, name, out) \
   if (!args.contains(name)) {\
     LogAndReportError(common::PlatformResult(common::ErrorCode::TYPE_MISMATCH_ERR, (name" is required argument")), &out);\
@@ -482,10 +633,52 @@ void ContentInstance::ContentManagerCancelScanDirectory(const picojson::value& a
   }
 }
 
+void ContentInstance::ContentManagerAddChangeListener(const picojson::value& args,
+                                                      picojson::object& out) {
+  LoggerD("Entered");
+
+  callback_data_ = new ReplyCallbackData();
+  callback_data_->instance = this;
+  callback_data_->args = args;
+
+  if (ContentManager::getInstance()->isConnected()) {
+    callback_data_->cbType = ContentManagerAddChangeListenerCallback;
+  } else {
+    callback_data_->cbType = ContentManagerErrorCallback;
+  }
+
+  PlatformResult result =
+      ContentManager::getInstance()->addChangeListener(&listener_handle_,
+                                                       contentChangeCallback,
+                                                       static_cast<void*>(callback_data_));
+
+  if (result.IsError()) {
+    delete callback_data_;
+    callback_data_ = nullptr;
+    LogAndReportError(result, &out);
+  }
+}
+
+void ContentInstance::ContentManagerRemoveChangeListener(const picojson::value& args,
+                                                         picojson::object& out) {
+  LoggerD("Entered");
+
+  PlatformResult result = ContentManager::getInstance()->removeChangeListener(listener_handle_);
+
+  if (result.IsSuccess()) {
+    listener_handle_ = nullptr;
+    delete callback_data_;
+    callback_data_ = nullptr;
+  } else {
+    LogAndReportError(result, &out);
+  }
+}
 
 void ContentInstance::ContentManagerSetchangelistener(const picojson::value& args,
                                                       picojson::object& out) {
   LoggerD("entered");
+  LoggerW("DEPRECATION WARNING: setChangeListener() is deprecated and will be removed from next release. "
+      "Use addChangeListener() instead.");
   //CHECK_PRIVILEGE_ACCESS(kPrivilegeContentRead, &out);
   CHECK_PRIVILEGE_ACCESS(kPrivilegeContentWrite, &out);
 
@@ -503,29 +696,36 @@ void ContentInstance::ContentManagerSetchangelistener(const picojson::value& arg
     listener_data_->cbType = ContentManagerErrorCallback;
   }
 
-  if (ContentManager::getInstance()->setChangeListener(changedContentCallback,
+  if (ContentManager::getInstance()->setChangeListener(changedContentV1Callback,
                                                        static_cast<void*>(listener_data_)).IsError()) {
     LogAndReportError(
         common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, "The callback did not register properly"), &out);
   }
-  if (ContentManager::getInstance()->setV2ChangeListener(&noti_handle_,
-                                                       changedContentV2Callback,
-                                                       static_cast<void*>(listener_data_)).IsError()) {
-    LogAndReportError(
-        common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, "The callback did not register properly"), &out);
+
+  if (nullptr == noti_handle_) { // To remain consistency with the previous implementation
+    if (ContentManager::getInstance()->addChangeListener(&noti_handle_,
+                                                         changedContentV2Callback,
+                                                         static_cast<void*>(listener_data_)).IsError()) {
+      LogAndReportError(
+          common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, "The callback did not register properly"), &out);
+    }
   }
 }
 
 void ContentInstance::ContentManagerUnsetchangelistener(const picojson::value& args, picojson::object& out) {
   LoggerD("entered");
+  LoggerW("DEPRECATION WARNING: unsetChangeListener() is deprecated and will be removed from next release. "
+        "Use removeChangeListener() instead.");
   //CHECK_PRIVILEGE_ACCESS(kPrivilegeContentRead, &out);
   CHECK_PRIVILEGE_ACCESS(kPrivilegeContentWrite, &out);
 
   if (ContentManager::getInstance()->unSetChangeListener().IsError()) {
     LoggerD("unsuccesfull deregistering of callback");
   }
-  if (ContentManager::getInstance()->unSetV2ChangeListener(&noti_handle_).IsError()) {
+  if (ContentManager::getInstance()->removeChangeListener(noti_handle_).IsError()) {
     LoggerD("unsuccesfull deregistering of callback");
+  } else {
+    noti_handle_ = nullptr; // To remain consistency with the previous implementation
   }
 }
 
index a631e62..af1b717 100755 (executable)
@@ -17,6 +17,8 @@
 #ifndef CONTENT_CONTENT_INSTANCE_H_
 #define CONTENT_CONTENT_INSTANCE_H_
 
+#include <map>
+
 #include <media_content_internal.h>
 #include "common/extension.h"
 
@@ -26,6 +28,8 @@ namespace content {
 enum ContentCallbacks {
   ContentManagerFindCallback,
   ContentManagerScanfileCallback,
+  ContentManagerAddChangeListenerCallback,
+  ContentManagerRemoveChangeListenerCallback,
   ContentManagerUnsetchangelistenerCallback,
   ContentManagerSetchangelistenerCallback,
   ContentManagerGetdirectoriesCallback,
@@ -71,6 +75,8 @@ class ContentInstance : public common::ParsedInstance {
   void ContentManagerScanfile(const picojson::value& args, picojson::object& out);
   void ContentManagerScanDirectory(const picojson::value& args, picojson::object& out);
   void ContentManagerCancelScanDirectory(const picojson::value& args, picojson::object& out);
+  void ContentManagerAddChangeListener(const picojson::value& args, picojson::object& out);
+  void ContentManagerRemoveChangeListener(const picojson::value& args, picojson::object& out);
   void ContentManagerSetchangelistener(const picojson::value& args, picojson::object& out);
   void ContentManagerUnsetchangelistener(const picojson::value& args, picojson::object& out);
   void ContentManagerGetplaylists(const picojson::value& args, picojson::object& out);
@@ -92,8 +98,11 @@ class ContentInstance : public common::ParsedInstance {
   void PlaylistSetThumbnailUri(const picojson::value& args, picojson::object& out);
   void PlaylistGetNumberOfTracks(const picojson::value& args, picojson::object& out);
 
-  media_content_noti_h noti_handle_;
-  ReplyCallbackData* listener_data_;
+  media_content_noti_h noti_handle_; // Deprecated handle
+  media_content_noti_h listener_handle_;
+
+  ReplyCallbackData* listener_data_; // Deprecated callback data
+  ReplyCallbackData* callback_data_;
 };
 
 
index 2673604..bda7506 100644 (file)
@@ -893,63 +893,68 @@ PlatformResult ContentManager::cancelScanDirectory(const std::string& content_di
   return PlatformResult(ErrorCode::NO_ERROR);
 }
 
-PlatformResult ContentManager::setChangeListener(media_content_db_update_cb callback,
+PlatformResult ContentManager::addChangeListener(media_content_noti_h* noti_handle,
+                                                 media_content_db_update_cb callback,
                                                  void *user_data) {
   LoggerD("Enter");
 
-  int ret = media_content_set_db_updated_cb(callback, user_data);
-  if(ret != MEDIA_CONTENT_ERROR_NONE) {
+  int ret = media_content_add_db_updated_cb(callback, user_data, noti_handle);
+
+  if (MEDIA_CONTENT_ERROR_NONE != ret) {
     return LogAndCreateResult(
-              ErrorCode::UNKNOWN_ERR, "registering the listener is failed.",
-              ("Failed: registering the listener is failed %d (%s)", ret, get_error_message(ret)));
+        ErrorCode::ABORT_ERR,
+        "Failed to add the listener.",
+        ("Failed to add the listener: %d (%s)", ret, get_error_message(ret)));
   }
+
   return PlatformResult(ErrorCode::NO_ERROR);
 }
 
-PlatformResult ContentManager::unSetChangeListener() {
+PlatformResult ContentManager::removeChangeListener(media_content_noti_h noti_handle) {
   LoggerD("Enter");
 
-  int ret = media_content_unset_db_updated_cb();
-  if(ret != MEDIA_CONTENT_ERROR_NONE) {
-    return LogAndCreateResult(
-              ErrorCode::UNKNOWN_ERR, "unregistering the listener is failed.",
-              ("Failed: unregistering the listener is failed: %d (%s)", ret, get_error_message(ret)));
+  int ret = media_content_remove_db_updated_cb(noti_handle);
+
+  switch (ret) {
+    case MEDIA_CONTENT_ERROR_NONE:
+      return PlatformResult(ErrorCode::NO_ERROR);
+    case MEDIA_CONTENT_ERROR_INVALID_PARAMETER:
+      // Trying to remove non-existent listener, ignoring
+      LoggerI("Failed to remove the listener: %d (%s)", ret, get_error_message(ret));
+      return PlatformResult(ErrorCode::NO_ERROR);
+    default:
+      return LogAndCreateResult(
+          ErrorCode::ABORT_ERR,
+          "Failed to remove the listener.",
+          ("Failed to remove the listener: %d (%s)", ret, get_error_message(ret)));
   }
-  return PlatformResult(ErrorCode::NO_ERROR);
 }
 
-PlatformResult ContentManager::setV2ChangeListener(media_content_noti_h* noti_handle,
-                                                 media_content_db_update_cb callback,
+PlatformResult ContentManager::setChangeListener(media_content_db_update_cb callback,
                                                  void *user_data) {
   LoggerD("Enter");
-  if (nullptr == *noti_handle) {
-    int ret = media_content_add_db_updated_cb(callback, user_data, noti_handle);
-    if(ret != MEDIA_CONTENT_ERROR_NONE) {
-      return LogAndCreateResult(
-                ErrorCode::UNKNOWN_ERR, "registering the listener is failed.",
-                ("Failed: registering the listener of cb_v2 is failed: %d (%s)",
-                    ret, get_error_message(ret)));
-    }
+
+  int ret = media_content_set_db_updated_cb(callback, user_data);
+  if(ret != MEDIA_CONTENT_ERROR_NONE) {
+    return LogAndCreateResult(
+              ErrorCode::UNKNOWN_ERR, "registering the listener is failed.",
+              ("Failed: registering the listener is failed %d (%s)", ret, get_error_message(ret)));
   }
   return PlatformResult(ErrorCode::NO_ERROR);
 }
 
-PlatformResult ContentManager::unSetV2ChangeListener(media_content_noti_h* noti_handle) {
+PlatformResult ContentManager::unSetChangeListener() {
   LoggerD("Enter");
 
-  int ret = media_content_remove_db_updated_cb(*noti_handle);
+  int ret = media_content_unset_db_updated_cb();
   if(ret != MEDIA_CONTENT_ERROR_NONE) {
     return LogAndCreateResult(
               ErrorCode::UNKNOWN_ERR, "unregistering the listener is failed.",
-              ("Failed: unregistering the listener of cb_v2 is failed %d (%s)",
-                  ret, get_error_message(ret)));
+              ("Failed: unregistering the listener is failed: %d (%s)", ret, get_error_message(ret)));
   }
-  *noti_handle = nullptr;
-
   return PlatformResult(ErrorCode::NO_ERROR);
 }
 
-
 void ContentManager::createPlaylist(std::string name,
   const std::shared_ptr<ReplyCallbackData>& user_data) {
   LoggerD("Enter");
index 60a177f..5c8ed6d 100644 (file)
@@ -54,13 +54,13 @@ class ContentManager {
   int scanFile(std::string& uri);
   common::PlatformResult scanDirectory(media_scan_completed_cb callback, ReplyCallbackData* cbData);
   common::PlatformResult cancelScanDirectory(const std::string& content_dir_uri);
+  common::PlatformResult addChangeListener(media_content_noti_h* noti_handle,
+                                           media_content_db_update_cb callback,
+                                           void *user_data);
+  common::PlatformResult removeChangeListener(media_content_noti_h noti_handle);
   common::PlatformResult setChangeListener(media_content_db_update_cb callback,
                                            void *user_data);
   common::PlatformResult unSetChangeListener();
-  common::PlatformResult setV2ChangeListener(media_content_noti_h* noti_handler,
-                                           media_content_db_update_cb callback,
-                                           void *user_data);
-  common::PlatformResult unSetV2ChangeListener(media_content_noti_h* noti_handler);
 
 //Lyrics
   int getLyrics(const picojson::value& args,picojson::object& result);
index 00ffadd..6498d59 100755 (executable)
  *    limitations under the License.
  */
 
+var T_ = xwalk.utils.type;
+var CONTENT_MANAGER_LISTENER_ID = 'ContentManagerChangeCallback';
+
+
 function _ContentManagerChangeCallback(result) {
   if (result.state === 'oncontentadded' || result.state === 'oncontentupdated') {
     var content = native_.getResultObject(result);
@@ -26,6 +30,78 @@ function _ContentManagerChangeCallback(result) {
   }
 }
 
+
+var ContentListenersManager = (function() {
+
+  function changeContent(event) {
+    if (T_.isEmptyObject(this.listeners)) {
+      return;
+    }
+
+    var result = null;
+
+    if (event.state === 'oncontentadded' || event.state === 'oncontentupdated') {
+      result = createContentObject_(native_.getResultObject(event));
+    } else if (event.state === 'oncontentdiradded' || event.state === 'oncontentdirupdated') {
+      result = createContentDirObject_(native_.getResultObject(event));
+    } else if (event.state === 'oncontentremoved' || event.state === 'oncontentdirremoved') {
+      result = native_.getResultObject(event);
+    }
+
+    if (!result) {
+      return;
+    }
+
+    var callback;
+    for (var listenerId in this.listeners) {
+      if (this.listeners.hasOwnProperty(listenerId)) {
+        callback = this.listeners[listenerId];
+        if (T_.isFunction(callback[event.state])) {
+          callback[event.state](result);
+        }
+      }
+    }
+  }
+
+  function _ContentListenersManager() {
+    this.listeners = {};
+    this.lastListenerId = 0;
+    this.changeContent = changeContent.bind(this);
+  }
+
+  _ContentListenersManager.prototype.addChangeListener = function(changeCallback) {
+    if (T_.isEmptyObject(this.listeners)) {
+      var result = native_.callSync('ContentManager_addChangeListener');
+      if (native_.isFailure(result)) {
+        throw native_.getErrorObject(result);
+      }
+
+      native_.addListener(CONTENT_MANAGER_LISTENER_ID, this.changeContent);
+    }
+
+    this.listeners[++this.lastListenerId] = changeCallback;
+    return this.lastListenerId;
+  };
+
+  _ContentListenersManager.prototype.removeChangeListener = function(listenerId) {
+    delete this.listeners[listenerId];
+
+    if (T_.isEmptyObject(this.listeners)) {
+      var result = native_.callSync('ContentManager_removeChangeListener');
+      if (native_.isFailure(result)) {
+        throw native_.getErrorObject(result);
+      }
+
+      native_.removeListener(CONTENT_MANAGER_LISTENER_ID);
+    }
+  };
+
+  return _ContentListenersManager;
+})();
+
+var listenersManager = new ContentListenersManager();
+
+
 function ContentManager() {
 }
 
@@ -239,14 +315,36 @@ ContentManager.prototype.cancelScanDirectory = function(contentDirURI) {
   }
 };
 
+ContentManager.prototype.addChangeListener = function() {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'changeCallback',
+    type: types_.LISTENER,
+    values: ['oncontentadded', 'oncontentupdated', 'oncontentremoved', 'oncontentdiradded', 'oncontentdirupdated', 'oncontentdirremoved']
+  }]);
+
+  return listenersManager.addChangeListener(args.changeCallback);
+};
+
+ContentManager.prototype.removeChangeListener = function() {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'listenerId',
+    type: types_.LONG
+  }]);
+
+  listenersManager.removeChangeListener(args.listenerId);
+};
+
 ContentManager.prototype.setChangeListener = function(changeCallback) {
+  console.warn('DEPRECATION WARNING: setChangeListener() is deprecated and will be removed '
+      + 'from next release. Use addChangeListener() instead.');
+
   var args = validator_.validateArgs(arguments, [{
     name: 'changeCallback',
     type: types_.LISTENER,
     values: ['oncontentadded', 'oncontentupdated', 'oncontentremoved', 'oncontentdiradded', 'oncontentdirupdated', 'oncontentdirremoved']
   }]);
 
-  var listenerId = 'ContentManagerChangeCallback';
+  var listenerId = 'ContentManagerChangeCallback_';
 
   var data = {
     listenerId: listenerId
@@ -261,17 +359,20 @@ ContentManager.prototype.setChangeListener = function(changeCallback) {
     oncontentdirremoved: args.changeCallback.oncontentdirremoved
   };
 
-  native_.addListener('ContentManagerChangeCallback',
-      _ContentManagerChangeCallback.bind(callbacks));
-
   var result = native_.callSync('ContentManager_setChangeListener', data);
 
   if (native_.isFailure(result)) {
     throw native_.getErrorObject(result);
   }
+
+  native_.addListener('ContentManagerChangeCallback_',
+      _ContentManagerChangeCallback.bind(callbacks));
 };
 
 ContentManager.prototype.unsetChangeListener = function() {
+  console.warn('DEPRECATION WARNING: unsetChangeListener() is deprecated and will be removed '
+      + 'from next release. Use removeChangeListener() instead.');
+
   var data = {};
 
   var result = native_.callSync('ContentManager_unsetChangeListener', data);
@@ -279,6 +380,8 @@ ContentManager.prototype.unsetChangeListener = function() {
   if (native_.isFailure(result)) {
     throw native_.getErrorObject(result);
   }
+
+  native_.removeListener('ContentManagerChangeCallback_');
 };
 
 ContentManager.prototype.getPlaylists = function(successCallback, errorCallback) {
diff --git a/src/convergence/convergence.gyp b/src/convergence/convergence.gyp
new file mode 100644 (file)
index 0000000..1ab30fc
--- /dev/null
@@ -0,0 +1,48 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_convergence',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'convergence_api.js',
+        'convergence_extension.cc',
+        'convergence_extension.h',
+        'convergence_instance.cc',
+        'convergence_instance.h',
+        'convergence_utils.cc',
+        'convergence_utils.h',
+        'convergence_manager.cc',
+        'convergence_manager.h',
+        'convergence_device.cc',
+        'convergence_device.h',
+        'convergence_service.cc',
+        'convergence_service.h',
+        'convergence_remote_app_control_service.cc',
+        'convergence_remote_app_control_service.h',
+        'convergence_app_communication_service.cc',
+        'convergence_app_communication_service.h',
+        'convergence_channel.cc',
+        'convergence_channel.h',
+        'convergence_payload.cc',
+        'convergence_payload.h',
+        'convergence_client_info.cc',
+        'convergence_client_info.h',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'd2d-conv-manager',
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/src/convergence/convergence_api.js b/src/convergence/convergence_api.js
new file mode 100644 (file)
index 0000000..1d048f7
--- /dev/null
@@ -0,0 +1,916 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+
+
+var validator_ = xwalk.utils.validator;
+var types_ = validator_.Types;
+var utils_ = xwalk.utils;
+var native_ = new utils_.NativeManager(extension);
+var T_ = utils_.type;
+
+// Flag showing if the discovery procedure has started
+var discoveryStarted = false;
+
+// Currently available devices
+var convergenceDevices = [];
+
+// Issued service objects
+// We should stor it for proper calling user callbacks
+var nextServiceId = 0;  // Next service id (internally used on JS layer)
+var convergenceServices = {}; // Issued services
+
+var ConnectionState = {
+  CONNECTED: 'CONNECTED',
+  NOT_CONNECTED: 'NOT_CONNECTED',
+  CONNECTING: 'CONNECTING'
+};
+
+var DeviceProfile = {
+  MOBILE: 'MOBILE',
+  WEARABLE: 'WEARABLE',
+  TV: 'TV'
+};
+
+
+var PayloadType = {
+  STRING: 'STRING',
+  RAW_BYTES: 'RAW_BYTES'
+};
+
+function SetReadOnlyProperty(obj, n, v) {
+  if (arguments.length > 2)
+    Object.defineProperty(
+      obj, n, {
+        value: v,
+        writable: false,
+        enumerable: true,
+        configurable: true
+      });
+  else
+    Object.defineProperty(obj, n, {
+      writable: false,
+      enumerable: true,
+      configurable: true
+    });
+}
+
+
+function getServiceConnectionStateName(connectionStateNumber) {
+  switch(connectionStateNumber) {
+  case 0:
+    return ConnectionState.CONNECTED;
+  case 1:
+    return ConnectionState.NOT_CONNECTED;
+  case 2:
+    return ConnectionState.CONNECTING;
+  default:
+    console.log('ERROR: Unknown connection state');
+    return -1; // TODO throw exception
+  }
+}
+
+function Device(id, name, profile, services) {
+  validator_.isConstructorCall(this, Device);
+  this.id = id;
+  this.name = name;
+  this.profile = profile;
+  this.services = services;
+}
+
+function ConvergenceManager() {
+  // constructor of ConvergenceManager
+}
+
+ConvergenceManager.prototype.startDiscovery = function(successCallback,
+  errorCallback, timeout) {
+  console.log('Entered ConvergenceManager.startDiscovery()');
+  var args = validator_.validateArgs(arguments, [
+    {name: 'successCallback', type: types_.LISTENER, values: ['onfound', 'onfinished' ]},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'timeout', type: types_.LONG, optional: true, nullable: true}
+  ]);
+
+  // Indicate, that discovery procedure is on
+  discoveryStarted = true;
+
+  // Reset currently available device list
+  convergenceDevices = [];
+
+  native_.addListener('CONVERGENCE_DISCOVERY_LISTENER', function(result) {
+    console.log('Entered discovery listener');
+
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(errorCallback, native_.getErrorObject(result));
+    } else {
+      if (result.discovery_status == 'device_found') {
+
+        // Prepare service array
+        if (!result || !result.device || !result.device.services) {
+          console.log('INVALID device info obtained from Native API'); // TODO throw exception
+          return;
+        }
+
+        // Create an instance of the device
+        var d = new Device(result.device.id, result.device.name, result.device.type, []);
+
+        console.log('Service number: ' + result.device.services.length);
+        for (var i = 0; i < result.device.services.length; ++i) {
+          var service_data = result.device.services[i];
+          var s;
+          if (service_data.serviceType == 0) { // App Communication Client
+            s = new AppCommunicationClientService();
+          } else if (service_data.serviceType == 1) { // Remote App Control
+            s = new RemoteAppControlService();
+          } else {
+            // Error: unknown service type
+            // TODO throw exception
+            console.log('UNKNOWN SERVICE TYPE: ' + service_data.serviceType);
+            continue;
+          }
+
+          s.connectionState = getServiceConnectionStateName(
+            result.device.services[i].connectionState);
+          s._deviceId = d.id;
+          d.services.push(s);
+        }
+
+        // Store newly found device internally
+        convergenceDevices.push(d);
+
+        // Invoke user callback retrieving newly found device
+        native_.callIfPossible(successCallback.onfound, d);
+
+      } else if (result.discovery_status == 'discovery_finished') {
+        // Unregister discovery listener, because Convergence Manager is a
+        // singleton object and no one else can receive discovery results
+        native_.removeListener('CONVERGENCE_DISCOVERY_LISTENER');
+
+        // Notify the customer about discovery results
+        native_.callIfPossible(successCallback.onfinished, convergenceDevices.slice());
+        convergenceDevices = [];
+
+      } else {
+        console.log('UNKNOWN discovery state exception'); // TODO throw exception
+      }
+    }
+  });
+
+  // Start the discovery using Native API
+  var result = native_.call('ConvergenceManager_startDiscovery', {
+      timeout: (args.timeout) ? args.timeout : 0
+    }, function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(errorCallback, native_.getErrorObject(result));
+    }
+  });
+  if (native_.isFailure(result))
+    throw native_.getErrorObject(result);
+};
+
+ConvergenceManager.prototype.stopDiscovery = function() {
+  console.log('Entered ConvergenceManager.stopDiscovery()');
+
+  if (!discoveryStarted)
+    throw new WebAPIException('InvalidStateError', 'Discovery has not started yet.');
+
+  discoveryStarted = false;
+
+  var result = native_.callSync('ConvergenceManager_stopDiscovery', null);
+  if (native_.isFailure(result))
+    throw native_.getErrorObject(result);
+};
+
+function Service() {
+  console.log('Entered Service.constructor()');
+
+  //validator_.isConstructorCall(this, Service);
+  this.connectionState = ConnectionState.NOT_CONNECTED;
+}
+
+native_.addListener('REMOTE_APP_CONTROL_SERVICE_LISTENER', function(result) {
+  if (native_.isFailure(result)) {
+    //native_.callIfPossible(errorCallback, native_.getErrorObject(result));
+    console.log('Error in REMOTE_APP_CONTROL_SERVICE_LISTENER');
+  } else {
+
+      console.log('');
+      console.log('REMOTE_APP_CONTROL_SERVICE_LISTENER invoked with data');
+      console.log(JSON.stringify(result));
+      console.log('');
+
+    // Invoke corresponding callback
+    var lid = result.curListenerId;
+    if (!lid || !convergenceServices.hasOwnProperty(lid)) {
+      console.log('ERROR: Remote App Ctrl listener is not registered [' + lid + ']');
+      return; // Something is wrong: listener MUST be there
+    }
+    var s = convergenceServices[lid];
+
+    var result_type = result.result_type;
+
+    switch (result_type) {
+    case 'Connected':
+      if (s) { // Service MUST NOT be null here
+        s.connectionState = ConnectionState.CONNECTED;
+        convergenceServices[lid] = s;
+      }
+      native_.callIfPossible(s._connectCallback, s);
+      break;
+    case 'onPublish':
+      native_.callIfPossible(s._remoteAppControlCallback,
+        result.payload);
+      break;
+    default:
+      console.log('Ignoring result type: [' + result_type + ']');
+      break;
+    }
+  }
+});
+
+function RemoteAppControlService() {
+  console.log('Entered RemoteAppControlService.constructor()');
+
+  validator_.isConstructorCall(this, RemoteAppControlService);
+
+  // The device id is needed for getting the valid service handle on the
+  // native layer
+  // I have to implement this property here instead of base constructor in order
+  // to mask it from accessing
+  Object.defineProperties(this, {
+    _serviceId : {
+      value: ++nextServiceId,
+      writable: false,
+      enumerable: false
+    },
+    // The id of device of the service or 'localhost' for local service
+   _deviceId : {
+      value: 'localhost',
+      writable: true,
+      enumerable: false
+    },
+    // Remote App Control Service user-defined callbacks
+    _connectCallback : {
+      value: null,
+      writable: true,
+      enumerable: false
+    },
+    _remoteAppControlCallback : {
+      value: null,
+      writable: true,
+      enumerable: false
+    }
+  });
+
+  // Registering the service in the table of issued services
+  convergenceServices[this._serviceId] = this;
+}
+
+RemoteAppControlService.prototype = new Service();
+
+RemoteAppControlService.prototype.connect = function(successCallback, errorCallback) {
+  console.log('Entered RemoteAppControlService.connect()');
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'successCallback',
+      type: types_.FUNCTION,
+      //values: ConnectSuccessCallback,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'errorCallback',
+      type: types_.FUNCTION,
+      //values: ErrorCallback,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  if (this.serviceState == ConnectionState.CONNECTED)
+    throw new WebAPIException('InvalidStateError', 'Service is connected already.');
+
+  var lid = this._serviceId;
+  this._connectCallback = successCallback;
+  convergenceServices[lid] = this;
+
+  var result = native_.call('RemoteAppControlService_connect', {
+      deviceId: this._deviceId,
+      curListenerId: lid
+    }, function(result) {
+    if (native_.isFailure(result))
+      native_.callIfPossible(errorCallback, native_.getErrorObject(result));
+  });
+  if (native_.isFailure(result))
+    throw native_.getErrorObject(result);
+};
+
+RemoteAppControlService.prototype.disconnect = function(successCallback, errorCallback) {
+  console.log('Entered RemoteAppControlService.disconnect()');
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'successCallback',
+      type: types_.FUNCTION,
+      //values: ConnectSuccessCallback,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'errorCallback',
+      type: types_.FUNCTION,
+      //values: ErrorCallback,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  if (this.serviceState != ConnectionState.CONNECTED) {
+    throw new WebAPIException('InvalidStateError', 'Service is not connected yet.');
+  }
+
+  var result = native_.callSync('RemoteAppControlService_disconnect', {
+      deviceId: this._deviceId
+    });
+
+  if (native_.isFailure(result))
+    throw native_.getErrorObject(result);
+  else
+    connectionState = ConnectionState.DISCONNECTED;
+
+  native_.callIfPossible(successCallback, this);
+};
+
+RemoteAppControlService.prototype.launch = function(appId, successCallback, errorCallback) {
+  console.log('Entered RemoteAppControlService.launch()');
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'appId',
+      //type: types_.PLATFORM_OBJECT,
+      type: types_.STRING,
+      values: tizen.ApplicationId,
+      optional: false,
+      nullable:false
+    },
+    {
+      name: 'successCallback',
+      type: types_.FUNCTION,
+      //values: RemoteAppControlCallback,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'errorCallback',
+      type: types_.FUNCTION,
+      //values: ErrorCallback,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  if (this.serviceState == ConnectionState.CONNECTED)
+    throw new WebAPIException('InvalidStateError', 'Service is connected already.');
+
+  var lid = this._serviceId;
+  // TODO In fact it must be a list of callbacks
+  // But untill D2D FW suppurts transaction management, it is meaningless to
+  // have more than one callback, because all payload is delivered to
+  // a single point without identification of initial request
+  this._remoteAppControlCallback = successCallback;
+  convergenceServices[lid] = this;
+
+  var needReply = !(successCallback == null);
+
+  var result = native_.call('RemoteAppControlService_launch', {
+      appId: args.appId,
+      reply: needReply,
+      deviceId: this._deviceId,
+      curListenerId: lid
+    }, function(result) {
+    if (native_.isFailure(result))
+      native_.callIfPossible(errorCallback, native_.getErrorObject(result));
+  });
+  if (native_.isFailure(result))
+    throw native_.getErrorObject(result);
+};
+
+RemoteAppControlService.prototype.launchAppControl = function(
+    appControl, appId, successCallback, errorCallback) {
+  console.log('Entered RemoteAppControlService.launchAppControl()');
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'appControl',
+      type: types_.PLATFORM_OBJECT,
+      values: tizen.ApplicationControl,
+      optional: false,
+      nullable:false
+    },
+    {
+      name: 'appId',
+      type: types_.PLATFORM_OBJECT,
+      values: tizen.ApplicationId,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'successCallback',
+      type: types_.FUNCTION,
+      //values: RemoteAppControlCallback,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'errorCallback',
+      type: types_.FUNCTION,
+      //values: ErrorCallback,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  // TODO Implement pls
+
+  return; // TODO remove when native layer is implemented
+};
+
+function AppCommunicationService() {
+  console.log('Entered AppCommunicationService.constructor()');
+
+  // The device id is needed for getting the valid service handle on the
+  // native layer
+  // I have to implement this property here instead of base constructor in order
+  // to mask it from accessing
+  Object.defineProperties(this, {
+    _serviceId : {
+      value: ++nextServiceId,
+      writable: false,
+      enumerable: false
+    },
+    // The id of device of the service or 'localhost' for local service
+    _deviceId : {
+      value: 'localhost',
+      writable: true,
+      enumerable: false
+    },
+    // App Communication Service basic callbacks
+    _connectCallback : {
+      value: null,
+      writable: true,
+      enumerable: false
+    },
+    _startCallback : {
+      value: null,
+      writable: true,
+      enumerable: false
+    },
+    _sendCallback : {
+      value: null,
+      writable: true,
+      enumerable: false
+    },
+    _stopCallback : {
+      value: null,
+      writable: true,
+      enumerable: false
+    },
+    _listenerCallback : {
+      value: null,
+      writable: true,
+      enumerable: false
+    },
+    _getClientListCallback : {
+      value: null,
+      writable: true,
+      enumerable: false
+    }
+  });
+
+  // TODO add callbacks in runtime instead of constructor
+
+  // Registering the service in the table of issued services
+  convergenceServices[this._serviceId] = this;
+}
+
+AppCommunicationService.prototype = new Service();
+
+native_.addListener('APP_COMMUNICATION_SERVICE_LISTENER', function(result) {
+
+  console.log('On App Communication Service Success Callback');
+
+  if (native_.isFailure(result)) {
+    console.log('ERROR in APP_COMMUNICATION_SERVICE_LISTENER');
+    //native_.callIfPossible(errorCallback, native_.getErrorObject(result));
+  } else {
+
+      console.log('');
+      console.log('APP_COMMUNICATION_SERVICE_LISTENER invoked with data');
+      console.log(JSON.stringify(result));
+      console.log('');
+
+    // Invoke corresponding callback
+    var lid = result.curListenerId;
+    if (!lid || !convergenceServices.hasOwnProperty(lid)) {
+      console.log('ERROR: App Comm listener is not registered [' + lid + ']');
+      return; // Something is wrong: listener MUST be there
+    }
+    var s = convergenceServices[lid];
+
+    var result_type = result.result_type;
+
+    switch (result_type) {
+    case 'Connected':
+      if (s) { // Service MUST NOT be null here
+        s.connectionState = ConnectionState.CONNECTED;
+        convergenceServices[lid] = s;
+      }
+      native_.callIfPossible(s._connectCallback, s);
+      break;
+    case 'onStart':
+      native_.callIfPossible(s._startCallback,
+        new Channel(result.channel.uri, result.channel.id), null);
+      break;
+    case 'onPublish':
+      native_.callIfPossible(s._sendCallback,
+        new Channel(result.channel.uri, result.channel.id), null);
+      break;
+    case 'onStop':
+      native_.callIfPossible(s._stopCallback,
+        new Channel(result.channel.uri, result.channel.id), null);
+      break;
+    case 'onMessage': {
+        var payload = [];
+        for(var i = 0; i < result.payload.length; i++) {
+          var curPl = result.payload[i];
+          switch(curPl.type) {
+          case PayloadType.STRING:
+            payload.push(new PayloadString(curPl.key, curPl.value));
+            break;
+          case PayloadType.RAW_BYTES:
+            payload.push(new PayloadRawBytes(curPl.key, curPl.value));
+            break;
+          default:
+            console.log('ERROR: Unknown payload type');
+            break;
+          }
+        }
+
+        native_.callIfPossible(s._listenerCallback,
+          new Channel(result.channel.uri, result.channel.id),
+          payload, result.senderId);
+      }
+      break;
+    default:
+      console.log('Ignoring result type: [' + result_type + ']');
+      break;
+    }
+
+    /*
+    // TODO uncomment when implemented (or remove thid data from the protocol)
+    *var clientInfo = new ClientInfo(
+      result.clientInfo.isHost,
+      result.clientInfo.lientId,
+      result.clientInfo.connectionTime);*
+    var clientInfo = null;
+    */
+  }
+});
+
+AppCommunicationService.prototype.start = function(channel, successCallback, errorCallback) {
+  console.log('Entered AppCommunicationService.start()');
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'channel',
+      type: types_.PLATFORM_OBJECT,
+      values: tizen.Channel,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'successCallback',
+      type: types_.FUNCTION,
+      //values: ConnectSuccessCallback,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'errorCallback',
+      type: types_.FUNCTION,
+      //values: ErrorCallback,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  // TODO check if the service is connected and started
+  // Raise the exception instead
+
+  var lid = this._serviceId;
+  this._startCallback = successCallback;
+  convergenceServices[lid] = this;
+
+  var result = native_.call('AppCommunicationService_start', {
+      deviceId: this._deviceId,
+      curListenerId: lid,
+      channel_data: channel
+    }, function(result) {
+    if (native_.isFailure(result))
+      native_.callIfPossible(errorCallback, native_.getErrorObject(result));
+  });
+  if (native_.isFailure(result))
+    throw native_.getErrorObject(result);
+};
+
+AppCommunicationService.prototype.stop = function(channel, successCallback, errorCallback) {
+  console.log('Entered AppCommunicationService.stop()');
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'channel',
+      type: types_.PLATFORM_OBJECT,
+      values: tizen.Channel,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'successCallback',
+      type: types_.FUNCTION,
+      //values: ConnectSuccessCallback,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'errorCallback',
+      type: types_.FUNCTION,
+      //values: ErrorCallback,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  // TODO check if the service is connected and started
+  // Raise the exception instead
+
+  var lid = -1;
+  if (successCallback) {
+    lid = this._serviceId;
+    this._stopCallback = successCallback;
+    convergenceServices[lid] = this;
+  }
+
+  var result = native_.call('AppCommunicationService_stop', {
+      deviceId: this._deviceId,
+      curListenerId: lid,
+      channel_data: channel
+    }, function(result) {
+    if (native_.isFailure(result))
+      native_.callIfPossible(errorCallback, native_.getErrorObject(result));
+  });
+  if (native_.isFailure(result))
+    throw native_.getErrorObject(result);
+};
+
+AppCommunicationService.prototype.send = function(channel, payload, successCallback, errorCallback) {
+  console.log('Entered AppCommunicationService.send()');
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'channel',
+      type: types_.PLATFORM_OBJECT,
+      values: tizen.Channel,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'payload',
+      type: types_.PLATFORM_OBJECT,
+      values: [tizen.PayloadString, tizen.PayloadRawBytes],
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'successCallback',
+      type: types_.FUNCTION,
+      //values: ConnectSuccessCallback,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'errorCallback',
+      type: types_.FUNCTION,
+      //values: ErrorCallback,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  // TODO check if the service is connected and started
+  // Raise the exception instead
+
+  var lid = this._serviceId;
+  this._sendCallback = successCallback;
+  convergenceServices[lid] = this;
+
+  var result = native_.call('AppCommunicationService_send', {
+      deviceId: this._deviceId,
+      curListenerId: lid,
+      channel_data: channel,
+      payload: payload
+    }, function(result) {
+    if (native_.isFailure(result))
+      native_.callIfPossible(errorCallback, native_.getErrorObject(result));
+  });
+  if (native_.isFailure(result))
+    throw native_.getErrorObject(result);
+};
+
+AppCommunicationService.prototype.addListener = function(listenerCallback) {
+  console.log('Entered AppCommunicationService.addListener()');
+  var args = validator_.validateArgs(arguments, [
+    {name: 'listenerCallback', type: types_.FUNCTION}
+  ]);
+
+  var lid = this._serviceId;
+  // TODO in fact, it should be even the list of callbacks instead of
+  // the single callback
+  this._listenerCallback = listenerCallback;
+  convergenceServices[lid] = this;
+
+      console.log('');
+      console.log('AppCommunicationServiceCommandListeners ADDED [' + lid + ']');
+      console.log('');
+
+  var result = native_.callSync('AppCommunicationService_addListener', {
+      deviceId: this._deviceId,
+      curListenerId: lid
+    });
+  if (native_.isFailure(result))
+    throw native_.getErrorObject(result);
+
+  return args.curListenerId; // TODO return proper index of listener
+};
+
+AppCommunicationService.prototype.removeListener = function(id) {
+  console.log('Entered AppCommunicationService.removeListener()');
+  var args = validator_.validateArgs(arguments, [
+    {name: 'id', type: types_.LONG, optional: false}
+  ]);
+
+  var result = native_.callSync('AppCommunicationService_removeListener', {
+      deviceId: this._deviceId
+      //curListenerId: id // not needed in below layers
+    });
+  if (native_.isFailure(result))
+    throw native_.getErrorObject(result);
+
+  var lid = this._serviceId;
+  if (this._listenerCallback) {// TODO extend this to manage the list of callbacks
+    //delete this._listenerCallback;
+    this._listenerCallback = null;
+  }
+  convergenceServices[lid] = this;
+};
+
+function AppCommunicationServerService() {
+  console.log('Entered AppCommunicationServerService.constructor()');
+
+  validator_.isConstructorCall(this, AppCommunicationServerService);
+
+  this.connectionState = ConnectionState.NOT_CONNECTED;
+
+  native_.callSync('AppCommunicationServerService_constructLocal', {
+      deviceId: this._deviceId
+    });
+}
+
+AppCommunicationServerService.prototype = new AppCommunicationService();
+
+function AppCommunicationClientService() {
+  console.log('Entered AppCommunicationClientService.constructor()');
+
+  validator_.isConstructorCall(this, AppCommunicationClientService);
+
+  this.connectionState = ConnectionState.NOT_CONNECTED;
+}
+
+AppCommunicationClientService.prototype = new AppCommunicationService();
+
+AppCommunicationClientService.prototype.connect = function(successCallback, errorCallback) {
+  console.log('Entered AppCommunicationClientService.connect()');
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'successCallback',
+      type: types_.FUNCTION,
+      //values: ConnectSuccessCallback,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'errorCallback',
+      type: types_.FUNCTION,
+      //values: ErrorCallback,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  if (this.serviceState == ConnectionState.CONNECTED)
+    throw new WebAPIException('InvalidStateError', 'Service is connected already.');
+
+  var lid = this._serviceId;
+  this._connectCallback = successCallback;
+  convergenceServices[lid] = this;
+
+  var result = native_.call('AppCommunicationClientService_connect', {
+      deviceId: this._deviceId,
+      curListenerId: lid
+    }, function(result) {
+    if (native_.isFailure(result))
+      native_.callIfPossible(errorCallback, native_.getErrorObject(result));
+  });
+  if (native_.isFailure(result))
+    throw native_.getErrorObject(result);
+};
+
+AppCommunicationClientService.prototype.disconnect = function(successCallback, errorCallback) {
+  console.log('Entered AppCommunicationClientService.disconnect()');
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'successCallback',
+      type: types_.FUNCTION,
+      //values: ConnectSuccessCallback,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'errorCallback',
+      type: types_.FUNCTION,
+      //values: ErrorCallback,
+      optional: true,
+      nullable: true
+    }
+  ]);
+  if (this.serviceState != ConnectionState.CONNECTED)
+    throw new WebAPIException('InvalidStateError', 'Service is not connected yet.');
+
+  var result = native_.callSync('AppCommunicationClientService_disconnect', {
+      deviceId: this._deviceId
+    });
+
+  if (native_.isFailure(result))
+    throw native_.getErrorObject(result);
+  else
+    connectionState = ConnectionState.DISCONNECTED;
+
+  native_.callIfPossible(successCallback, this);
+};
+
+function Channel(uri, id) {
+  validator_.isConstructorCall(this, Channel);
+  this.uri = uri;
+  this.id = id;
+}
+
+function PayloadString(key, value) {
+  validator_.isConstructorCall(this, PayloadString);
+  this.key = key;
+  this.value = value;
+  SetReadOnlyProperty(this, 'type', PayloadType.STRING); // read only property
+}
+
+function PayloadRawBytes(key, value) {
+  validator_.isConstructorCall(this, PayloadRawBytes);
+  this.key = key;
+  this.value = value;
+  SetReadOnlyProperty(this, 'type', PayloadType.RAW_BYTES); // read only property
+}
+
+function ClientInfo(isHost, clientId, connectionTime) {
+  validator_.isConstructorCall(this, ClientInfo);
+  this.isHost = isHost;
+  this.clientId = clientId;
+  this.connectionTime = connectionTime;
+}
+
+exports = new ConvergenceManager();
+tizen.RemoteAppControlService = RemoteAppControlService;
+tizen.AppCommunicationServerService = AppCommunicationServerService;
+tizen.AppCommunicationClientService = AppCommunicationClientService;
+tizen.Channel = Channel;
+tizen.PayloadString = PayloadString;
+tizen.PayloadRawBytes = PayloadRawBytes;
diff --git a/src/convergence/convergence_app_communication_service.cc b/src/convergence/convergence_app_communication_service.cc
new file mode 100644 (file)
index 0000000..0cc7bd6
--- /dev/null
@@ -0,0 +1,550 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+
+// TODO check includes
+#include "convergence/convergence_app_communication_service.h"
+
+#include <glib.h>
+#include <d2d_conv_internal.h>
+#include <stdlib.h>
+
+#include "convergence/convergence_instance.h"
+#include "convergence/convergence_channel.h"
+#include "convergence/convergence_payload.h"
+#include "convergence/convergence_client_info.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace convergence {
+
+using common::TizenResult;
+using common::TizenSuccess;
+
+namespace {
+// Payload data keys and some values
+static const std::string kPayload = "payload"; // ---
+
+// Service connection status keys
+static const std::string kServiceConnectionStatus = "connect_status"; // ---
+static const std::string kServiceConnectionStatusConnected = "service_connected";
+static const std::string kServiceConnectionStatusNotConnected = "service_not_connected";
+
+// Service listener status keys
+static const std::string kServiceListenerStatus = "listener_status"; //---
+static const std::string kServiceListenerStatusOk = "listener_ok"; // ---
+static const std::string kServiceListenerStatusError = "listener_error"; //---
+static const std::string kServiceListenerError = "listener_error"; //---
+} // namespace
+
+ConvergenceAppCommunicationService::ConvergenceAppCommunicationService()
+ : ConvergenceService() {
+  ScopeLogger();
+}
+
+ConvergenceAppCommunicationService::ConvergenceAppCommunicationService(conv_device_h device, ConvergenceInstance *convergence_plugin)
+ : ConvergenceService(device, CONV_SERVICE_APP_TO_APP_COMMUNICATION, convergence_plugin) {
+  ScopeLogger();
+}
+
+ConvergenceAppCommunicationService::~ConvergenceAppCommunicationService() {
+  ScopeLogger();
+
+  // Release all memory, used by callback paramerers
+  for (size_t i = 0; i < callback_param_gc_.size(); i++) {
+    delete callback_param_gc_[i];
+  }
+  callback_param_gc_.clear();
+}
+
+common::TizenResult ConvergenceAppCommunicationService::Start(
+  ConvergenceChannel *channel,
+  const int cur_listener_id) {
+  ScopeLogger();
+
+  LoggerI("Starting service [0x%x] with handle [0x%x]", this, service_handle_);
+
+  conv_service_h service_handle = FindServiceHandle();
+  if (!service_handle) {
+    LoggerE("AAAAAA!!! Service not found");
+    return LogAndCreateTizenError(NotFoundError,
+      "Service with specified type does not exist");
+  }
+
+LoggerI("1");
+
+  UpdateListener(cur_listener_id);
+
+LoggerI("2");
+
+
+  { // DBG
+    conv_channel_h ch = channel->GetHandle();
+    char *id = NULL;
+    conv_channel_get_string(ch, "channel_id", &id);
+    char *uri = NULL;
+    conv_channel_get_string(ch, "uri", &uri);
+    LoggerI("===== CHANNEL ID [%s] URI [%s]", id, uri);
+  }
+
+  const int error = conv_service_start(service_handle,
+    channel->GetHandle(), nullptr);
+  if (CONV_ERROR_NONE != error) {
+    // TODO: Handle error
+    trace_conv_error(error, __LINE__, "conv_service_start");
+  }
+
+LoggerI("3");
+  delete channel;
+LoggerI("4");
+  return TizenSuccess();
+}
+
+common::TizenResult ConvergenceAppCommunicationService::Stop(
+  ConvergenceChannel *channel,
+  const int cur_listener_id) {
+  ScopeLogger();
+
+  conv_service_h service_handle = FindServiceHandle();
+  if (!service_handle) {
+    return LogAndCreateTizenError(NotFoundError,
+      "Service with specified type does not exist");
+  }
+
+  UpdateListener(cur_listener_id);
+
+  const int error = conv_service_stop(service_handle,
+    channel->GetHandle(), nullptr);
+  if (CONV_ERROR_NONE != error) {
+    // TODO: Handle error
+    trace_conv_error(error, __LINE__, "conv_service_stop");
+  }
+
+  delete channel;
+  return TizenSuccess();
+}
+
+common::TizenResult ConvergenceAppCommunicationService::Send(
+  ConvergenceChannel *channel,
+  ConvergencePayloadArray *payload,
+  const int cur_listener_id) {
+  ScopeLogger();
+
+  conv_service_h service_handle = FindServiceHandle();
+  if (!service_handle) {
+    return LogAndCreateTizenError(NotFoundError,
+      "Service with specified type does not exist");
+  }
+
+  UpdateListener(cur_listener_id);
+
+  { // DBG
+    LoggerI("...PUBLISHING for service handle [0x0%x]", service_handle);
+
+    conv_service_e t = CONV_SERVICE_NONE;
+    int e = conv_service_get_type(service_handle, &t);
+    if (CONV_ERROR_NONE != e) {
+      trace_conv_error(e, __LINE__, "get service type");
+    }
+    LoggerI("....type [%d]", t);
+
+    char *sid = nullptr;
+    e = conv_service_get_property_string(service_handle, CONV_SERVICE_ID, &sid);
+    if (CONV_ERROR_NONE != e) {
+      trace_conv_error(e, __LINE__, "get service id");
+    }
+    LoggerI("....id [%s]", sid);
+    free(sid);
+
+    conv_channel_h ch = channel->GetHandle();
+    char *id = NULL;
+    conv_channel_get_string(ch, "channel_id", &id);
+    char *uri = NULL;
+    conv_channel_get_string(ch, "uri", &uri);
+    LoggerI("===== CHANNEL ID [%s] URI [%s]", id, uri);
+  }
+
+  const int error = conv_service_publish(service_handle,
+    channel->GetHandle(), payload->GetHandle());
+  if (CONV_ERROR_NONE != error) {
+    // TODO: Handle error
+    trace_conv_error(error, __LINE__, "conv_service_publish");
+  } else {
+    LoggerI("PUBLISHED SUCCESSFULY listener is [%d]", cur_listener_id);
+  }
+
+  delete channel;
+  delete payload;
+  return TizenSuccess();
+}
+
+
+// TODO move to Payload class
+
+
+void ConvergenceAppCommunicationService::ServiceListenerCb(conv_service_h service_handle,
+  conv_channel_h channel_handle,
+  conv_error_e error, conv_payload_h result, void* user_data) {
+  ScopeLogger();
+
+  CallbackParam *callbackParam = static_cast<CallbackParam *>(user_data);
+  if (!callbackParam) {
+    LoggerE("ERROR! NULL user data in Service Listener Callback");
+    return;
+  }
+
+  // TODO Send all payload and channel to the JS layer and parse it there
+
+  // TODO parse the payload and fill the param
+  LoggerI("YAY! Got the Callback (TODO implement it)");
+
+  if (CONV_ERROR_NONE != error) { // Error occured during connection
+    picojson::object param;
+    param[kServiceListenerStatus] = picojson::value(kServiceListenerStatusError);
+    param[kServiceListenerError] = picojson::value(static_cast<double>(error));
+    callbackParam->plugin_->ReplyAsync(kAppCommunicationListenerCallback,
+      callbackParam->callback_id_, false, param);
+    return;
+  }
+
+  // Parse the payload
+  const std::string result_type = ConvergencePayloadArray::ExtractPayloadString(result, "result_type"); // TODO extract to constant kResultType = "result_type";
+  LoggerI("Callback type [%s]", result_type.c_str());
+
+  picojson::object param;
+  param[kServiceListenerStatus] = picojson::value(kServiceListenerStatusOk);
+  param["channel"] = ConvergenceChannel::ToJson(channel_handle);
+  param["result_type"] = picojson::value(result_type);
+
+  if (("onStart" == result_type)
+   || ("onPublish" == result_type)
+   || ("onStop" == result_type)) {
+    // The service doesn't send any callback with thie response
+  } else if ("onMessage" == result_type) {
+    param["senderId"] = picojson::value(
+      ConvergencePayloadArray::ExtractPayloadString(result, "from")); // Define the string as a constant
+    param["payload"] = ConvergencePayloadArray::ToJson(result);
+  } else if ("onConnect" == result_type) {
+    //param["clientInfo"] = ConvergenceClientInfo(result).ToJson();
+    //callbackParam->plugin_->ReplyAsync(kAppCommunicationClientServiceConnectCallback,
+    //  callbackParam->callback_id_, true, param);
+    return;
+  } else if ("onClientConnect" == result_type) {
+    // TODO the service doesn't send any callback with thie response
+    return; // TODO
+  } else if ("onDisconnect" == result_type) {
+    return; // TODO
+  } else if ("onClientDisconnect" == result_type) {
+    return; // TODO
+  } else if ("onRead" == result_type) {
+    // TODO
+  } else {
+    // Unsupported payload type, ignoring it
+    LoggerE("ERROR: Unsupported payload type; ignored");
+    return;
+  }
+
+  callbackParam->plugin_->ReplyAsync(kAppCommunicationListenerCallback,
+    callbackParam->callback_id_, true, param);
+
+  // TODO Remove callbackParam from GC
+  // TODO delete callbackParam
+}
+
+void ConvergenceAppCommunicationService::UpdateListener(const int cur_listener_id) {
+  ScopeLogger();
+
+  // TODO make sure that callback is not called twice for the same listener
+
+  // TODO: make a garbage collection and release this memory when callback unset
+  // and when whole manager is destructed
+  CallbackParam *param = new CallbackParam(convergence_plugin_, cur_listener_id);
+  callback_param_gc_.push_back(param);
+
+  conv_service_h service_handle = FindServiceHandle();
+  if (!service_handle) {
+    LoggerE("AAAAAA!!! Service not found");
+    return;
+  }
+
+  { // dbg
+    LoggerI("...found service handle [%x0x]", service_handle);
+
+    conv_service_e t = CONV_SERVICE_NONE;
+    int e = conv_service_get_type(service_handle, &t);
+    if (CONV_ERROR_NONE != e) {
+      trace_conv_error(e, __LINE__, "get service type");
+    }
+    LoggerI("....type [%d]", t);
+
+    char *sid = nullptr;
+    e = conv_service_get_property_string(service_handle, CONV_SERVICE_ID, &sid);
+    if (CONV_ERROR_NONE != e) {
+      trace_conv_error(e, __LINE__, "get service id");
+    }
+    LoggerI("....id [%s]", sid);
+    free(sid);
+
+    char *sver = nullptr;
+    e = conv_service_get_property_string(service_handle, CONV_SERVICE_VERSION, &sver);
+    if (CONV_ERROR_NONE != e) {
+      trace_conv_error(e, __LINE__, "get service version");
+    }
+    LoggerI("....ver [%s]", sver);
+    free(sver);
+  }
+
+  const int error = conv_service_set_listener_cb(service_handle, ServiceListenerCb, param);
+  if (CONV_ERROR_NONE != error) {
+    // TODO: Handle error
+    trace_conv_error(error, __LINE__, "conv_service_set_listener_cb");
+  } else {
+    LoggerI("APP COMMUNICATION SERVICE LISTENER SET SUCCESSFULY [%d]", cur_listener_id);
+  }
+}
+
+common::TizenResult ConvergenceAppCommunicationService::SetListener(const int cur_listener_id) {
+  ScopeLogger();
+  conv_service_h service_handle = FindServiceHandle();
+  if (!service_handle)
+    return LogAndCreateTizenError(NotFoundError,
+      "Service with specified type does not exist");
+
+  UpdateListener(cur_listener_id);
+
+  return TizenSuccess();
+}
+
+common::TizenResult ConvergenceAppCommunicationService::RemoveListener() {
+  ScopeLogger();
+
+  conv_service_h service_handle = FindServiceHandle();
+  if (!service_handle) {
+    LoggerE("AAAAAA!!! Service not found");
+    return LogAndCreateTizenError(NotFoundError,
+      "Service with specified type does not exist");
+  }
+
+  const int error = conv_service_unset_listener_cb(service_handle);
+  if (CONV_ERROR_NONE != error) {
+    // TODO: Handle error
+    trace_conv_error(error, __LINE__, "conv_service_set_listener_cb");
+    return LogAndCreateTizenError(NotFoundError,
+      "Unset Listener Failed");
+  }
+
+  return TizenSuccess();
+}
+
+picojson::value ConvergenceAppCommunicationService::PayloadToJson(conv_payload_h payload) {
+  ScopeLogger();
+  picojson::value payload_json;
+
+  // TODO convert payload to array of ApplicationControlData
+
+  return payload_json;
+}
+
+
+
+ConvergenceAppCommunicationServerService::ConvergenceAppCommunicationServerService()
+ : ConvergenceAppCommunicationService() {
+  ScopeLogger();
+}
+
+ConvergenceAppCommunicationServerService::ConvergenceAppCommunicationServerService(
+  conv_device_h device, ConvergenceInstance *convergence_plugin)
+ : ConvergenceAppCommunicationService(device, convergence_plugin) {
+  ScopeLogger();
+
+  // Creating the handle of local service instance
+  int error = conv_service_create(&service_handle_);
+  if (CONV_ERROR_NONE != error) {
+    // TODO: Handle error
+    trace_conv_error(error, __LINE__, "conv_service_create App Comm Service");
+  }
+
+  error = conv_service_set_type(service_handle_, CONV_SERVICE_APP_TO_APP_COMMUNICATION);
+  if (CONV_ERROR_NONE != error) {
+    // TODO: Handle error
+    trace_conv_error(error, __LINE__, "conv_service_set_type App Comm Service");
+  }
+
+  /*
+   * Consider a constructor of App Communication Server Service with parameters:
+   *  - Id
+   *  - Version
+   */
+
+  error = conv_service_set_property_string(service_handle_, CONV_SERVICE_ID, "test_app"); // TODO set a proper service ID
+  if (CONV_ERROR_NONE != error) {
+    // TODO: Handle error
+    trace_conv_error(error, __LINE__, "conv_service_set_property Id");
+  }
+
+  error = conv_service_set_property_string(service_handle_, CONV_SERVICE_VERSION, "1.0");
+  if (CONV_ERROR_NONE != error) {
+    // TODO: Handle error
+    trace_conv_error(error, __LINE__, "conv_service_set_property Version");
+  }
+}
+
+ConvergenceAppCommunicationServerService::~ConvergenceAppCommunicationServerService() {
+  ScopeLogger();
+}
+
+common::TizenResult ConvergenceAppCommunicationServerService::Start(
+  ConvergenceChannel *channel,
+  const int cur_listener_id) {
+  ScopeLogger();
+
+
+  /* By implementation, the local App Communication Service doesn't send
+   * the callback confirming that the Start is successful.
+   * So we are sending this callback manually
+   */
+  picojson::object param;
+  param[kServiceListenerStatus] = picojson::value(kServiceListenerStatusOk);
+
+  // The object 'channel' will be deleted in the super::Start() so we should
+  // add its json before
+  param["channel"] = ConvergenceChannel::ToJson(channel->GetHandle()); // Define string as constant
+  param["result_type"] = picojson::value("onStart");
+
+  common::TizenResult result = ConvergenceAppCommunicationService::Start(
+    channel, cur_listener_id);
+
+  // TODO check if result value is OK
+
+  convergence_plugin_->ReplyAsync(kAppCommunicationListenerCallback,
+    cur_listener_id, true, param);
+  return result;
+}
+
+common::TizenResult ConvergenceAppCommunicationServerService::Stop(
+  ConvergenceChannel *channel,
+  const int cur_listener_id) {
+  ScopeLogger();
+
+  /* By implementation, the local App Communication Service doesn't send
+   * the callback confirming that the Start is successful.
+   * So we are sending this callback manually
+   */
+  picojson::object param;
+  param[kServiceListenerStatus] = picojson::value(kServiceListenerStatusOk);
+
+  // The object 'channel' will be deleted in the super::Start() so we should
+  // add its json before
+  param["channel"] = ConvergenceChannel::ToJson(channel->GetHandle());
+  param["result_type"] = picojson::value("onStop");
+
+  common::TizenResult result = ConvergenceAppCommunicationService::Stop(
+    channel, cur_listener_id);
+
+  // TODO check if result value is OK
+
+  convergence_plugin_->ReplyAsync(kAppCommunicationListenerCallback,
+    cur_listener_id, true, param);
+  return result;
+}
+
+ConvergenceAppCommunicationClientService::ConvergenceAppCommunicationClientService()
+ : ConvergenceAppCommunicationService() {
+  ScopeLogger();
+}
+
+ConvergenceAppCommunicationClientService::ConvergenceAppCommunicationClientService(
+  conv_device_h device, ConvergenceInstance *convergence_plugin)
+ : ConvergenceAppCommunicationService(device, convergence_plugin) {
+  ScopeLogger();
+}
+
+ConvergenceAppCommunicationClientService::~ConvergenceAppCommunicationClientService() {
+  ScopeLogger();
+}
+
+void ConvergenceAppCommunicationClientService::ServiceConnectedCb(conv_service_h service_handle,
+  conv_error_e error, conv_payload_h result, void* user_data) {
+  ScopeLogger();
+
+  CallbackParam *callbackParam = static_cast<CallbackParam *>(user_data);
+  if (!callbackParam) {
+    LoggerE("ERROR! NULL user data in Service Connect Callback");
+    return;
+  }
+
+  picojson::object param;
+  param[kPayload] = ConvergenceAppCommunicationService::PayloadToJson(result);
+  param["result_type"] = picojson::value("Connected");
+
+  if (CONV_ERROR_NONE == error) {
+    param[kServiceConnectionStatus] = picojson::value(kServiceConnectionStatusConnected);
+    callbackParam->plugin_->ReplyAsync(kAppCommunicationListenerCallback,
+      callbackParam->callback_id_,
+      true,
+      param);
+  } else {
+    // Error occured during connection
+    param[kServiceConnectionStatus] = picojson::value(kServiceConnectionStatusNotConnected);
+    callbackParam->plugin_->ReplyAsync(kAppCommunicationListenerCallback,
+      callbackParam->callback_id_,
+      false,
+      param);
+  }
+}
+
+common::TizenResult ConvergenceAppCommunicationClientService::Connect(const int cur_listener_id) {
+  ScopeLogger();
+
+  conv_service_h service = FindServiceHandle();
+  if (!service) {
+    return LogAndCreateTizenError(NotFoundError,
+      "Service with specified type does not exist");
+  }
+
+  // TODO: make a garbage collection and release this memory when service is disconnected
+  // and when whole manager is destructed
+  CallbackParam *param = new CallbackParam(convergence_plugin_, cur_listener_id);
+  callback_param_gc_.push_back(param);
+
+  const int error = conv_service_connect(service, ServiceConnectedCb, param);
+  if (CONV_ERROR_NONE != error) {
+    // TODO: Handle error
+    trace_conv_error(error, __LINE__, "conv_service_connect");
+  }
+
+  return TizenSuccess();
+}
+
+common::TizenResult ConvergenceAppCommunicationClientService::Disconnect() {
+  ScopeLogger();
+
+  conv_service_h service = FindServiceHandle();
+  if (!service)
+    return LogAndCreateTizenError(NotFoundError,
+      "Service with specified type does not exist");
+
+  const int error = conv_service_disconnect(service);
+  if (CONV_ERROR_NONE != error) {
+    // TODO: Handle error
+    trace_conv_error(error, __LINE__, "conv_service_disconnect");
+  }
+
+  return TizenSuccess();
+}
+
+
+} // namespace convergence
+}  // namespace extension
diff --git a/src/convergence/convergence_app_communication_service.h b/src/convergence/convergence_app_communication_service.h
new file mode 100644 (file)
index 0000000..49ad8e6
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+
+#ifndef CONVERGENCE_CONVERGENCE_APP_COMMUNICATION_SERVICE_H__
+#define CONVERGENCE_CONVERGENCE_APP_COMMUNICATION_SERVICE_H__
+
+// TODO check includes
+#include <d2d_conv_manager.h>
+
+#include <string>
+#include <unordered_map>
+
+#include "convergence/convergence_service.h"
+#include "convergence/convergence_utils.h"
+#include "common/tizen_result.h"
+
+namespace extension {
+namespace convergence {
+
+class ConvergenceChannel;
+class ConvergencePayloadArray;
+
+class ConvergenceAppCommunicationService : public ConvergenceService {
+ public:
+  ConvergenceAppCommunicationService();
+  ConvergenceAppCommunicationService(conv_device_h device, ConvergenceInstance *convergence_plugin);
+  virtual ~ConvergenceAppCommunicationService();
+  ConvergenceAppCommunicationService(const ConvergenceAppCommunicationService&) = delete;
+  ConvergenceAppCommunicationService(ConvergenceAppCommunicationService&&) = delete;
+  ConvergenceAppCommunicationService& operator=(const ConvergenceAppCommunicationService&) = delete;
+  ConvergenceAppCommunicationService& operator=(ConvergenceAppCommunicationService&&) = delete;
+ public:
+  virtual common::TizenResult Start(ConvergenceChannel *channel,
+   const int cur_listener_id);
+  virtual common::TizenResult Stop(ConvergenceChannel *channel,
+   const int cur_listener_id);
+  virtual common::TizenResult Send(ConvergenceChannel *channel,
+   ConvergencePayloadArray *payload,
+   const int cur_listener_id);
+  common::TizenResult SetListener(const int cur_listener_id);
+  common::TizenResult RemoveListener();
+ protected:
+  static picojson::value PayloadToJson(conv_payload_h payload);
+ private:
+  void UpdateListener(const int cur_listener_id);
+  static void ServiceListenerCb(conv_service_h service_handle,
+   conv_channel_h channel_handle,
+   conv_error_e error, conv_payload_h result, void* user_data);
+
+ protected:
+  std::vector<CallbackParam *> callback_param_gc_;
+};
+
+class ConvergenceAppCommunicationServerService : public ConvergenceAppCommunicationService {
+ public:
+  ConvergenceAppCommunicationServerService();
+  ConvergenceAppCommunicationServerService(conv_device_h device, ConvergenceInstance *convergence_plugin);
+  virtual ~ConvergenceAppCommunicationServerService();
+  ConvergenceAppCommunicationServerService(const ConvergenceAppCommunicationServerService&) = delete;
+  ConvergenceAppCommunicationServerService(ConvergenceAppCommunicationServerService&&) = delete;
+  ConvergenceAppCommunicationServerService& operator=(const ConvergenceAppCommunicationServerService&) = delete;
+  ConvergenceAppCommunicationServerService& operator=(ConvergenceAppCommunicationServerService&&) = delete;
+
+ public:
+  virtual common::TizenResult Start(ConvergenceChannel *channel,
+   const int cur_listener_id);
+  virtual common::TizenResult Stop(ConvergenceChannel *channel,
+   const int cur_listener_id);
+};
+
+class ConvergenceAppCommunicationClientService : public ConvergenceAppCommunicationService {
+ public:
+  ConvergenceAppCommunicationClientService();
+  ConvergenceAppCommunicationClientService(conv_device_h device, ConvergenceInstance *convergence_plugin);
+  virtual ~ConvergenceAppCommunicationClientService();
+  ConvergenceAppCommunicationClientService(const ConvergenceAppCommunicationClientService&) = delete;
+  ConvergenceAppCommunicationClientService(ConvergenceAppCommunicationClientService&&) = delete;
+  ConvergenceAppCommunicationClientService& operator=(const ConvergenceAppCommunicationClientService&) = delete;
+  ConvergenceAppCommunicationClientService& operator=(ConvergenceAppCommunicationClientService&&) = delete;
+ public:
+  common::TizenResult Connect(const int cur_listener_id);
+  common::TizenResult Disconnect();
+ private:
+  static void ServiceConnectedCb(conv_service_h service_handle,
+   conv_error_e error, conv_payload_h result, void* user_data);
+};
+
+} // namespace convergence
+} // namespace extension
+
+#endif // CONVERGENCE_CONVERGENCE_APP_COMMUNICATION_SERVICE_H__
diff --git a/src/convergence/convergence_channel.cc b/src/convergence/convergence_channel.cc
new file mode 100644 (file)
index 0000000..45e77c8
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+
+// TODO check includes
+#include "convergence/convergence_channel.h"
+
+#include <glib.h>
+#include <d2d_conv_internal.h>
+
+#include "convergence/convergence_instance.h"
+#include "convergence/convergence_utils.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace convergence {
+
+namespace {
+// Channel keys
+static const std::string kId = "id"; // This id is used in arguments (comes from JS layer)
+static const std::string kChannelId = "channel_id"; // This id is used in the App Comm Service engine
+static const std::string kUri = "uri";
+} // namespace
+
+ConvergenceChannel::ConvergenceChannel()
+  : channel_handle_(nullptr) {
+  ScopeLogger();
+}
+
+ConvergenceChannel::ConvergenceChannel(const picojson::value &channel_json)
+  : channel_handle_(nullptr) {
+  ScopeLogger();
+  FromJson(channel_json);
+}
+
+ConvergenceChannel::~ConvergenceChannel() {
+  ScopeLogger();
+
+  if (channel_handle_) {
+    conv_channel_destroy(channel_handle_);
+    channel_handle_ = NULL;
+  }
+}
+
+conv_channel_h ConvergenceChannel::GetHandle() const {
+  ScopeLogger();
+  return channel_handle_;
+}
+
+
+void ConvergenceChannel::FromJson(const picojson::value &channel_json) {
+  ScopeLogger();
+  if (channel_json.is<picojson::null>()) {
+    LoggerE("ERROR: Channel json value is NULL");
+    return;
+  }
+
+  if (channel_handle_) {
+    conv_channel_destroy(channel_handle_);
+    channel_handle_ = NULL;
+  }
+
+  int error = conv_channel_create(&channel_handle_);
+  if ((CONV_ERROR_NONE != error) || !channel_handle_) {
+    trace_conv_error(error, __LINE__, "creating channel handle");
+    return;
+  }
+
+  const std::string id = channel_json.get(kId).to_str();
+  error = conv_channel_set_string(channel_handle_, kChannelId.c_str(), id.c_str());
+  if (CONV_ERROR_NONE != error) {
+    trace_conv_error(error, __LINE__, "setting channel string Id");
+  }
+
+  const std::string uri = channel_json.get(kUri).to_str();
+  error = conv_channel_set_string(channel_handle_, kUri.c_str(), uri.c_str());
+  if (CONV_ERROR_NONE != error) {
+    trace_conv_error(error, __LINE__, "setting channel string URI");
+  }
+}
+
+picojson::value ConvergenceChannel::ToJson(conv_channel_h channel_handle) {
+  ScopeLogger();
+
+  picojson::object channel_object;
+  if (!channel_handle) {
+    LoggerE("Error: trying to convert NULL channel handle to json");
+    return picojson::value(channel_object);
+  }
+
+  { // Extracting channel ID
+    char *id = nullptr;
+    const int error = conv_channel_get_string(channel_handle, kChannelId.c_str(), &id);
+    if (CONV_ERROR_NONE != error) {
+      trace_conv_error(error, __LINE__, "getting channel string Id");
+    } else {
+      channel_object[kId] = picojson::value(id);
+      free(id);
+    }
+  }
+
+  { // Extracting channel URI
+    char *uri = nullptr;
+    const int error = conv_channel_get_string(channel_handle, kUri.c_str(), &uri);
+    if (CONV_ERROR_NONE != error) {
+      trace_conv_error(error, __LINE__, "getting channel string URI");
+    } else {
+      channel_object[kUri] = picojson::value(uri);
+      free(uri);
+    }
+  };
+
+  return picojson::value(channel_object);
+}
+
+
+} // namespace convergence
+}  // namespace extension
diff --git a/src/convergence/convergence_channel.h b/src/convergence/convergence_channel.h
new file mode 100644 (file)
index 0000000..952838c
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+
+#ifndef CONVERGENCE_CONVERGENCE_CHANNEL_H__
+#define CONVERGENCE_CONVERGENCE_CHANNEL_H__
+
+// TODO check includes
+#include <d2d_conv_manager.h>
+
+#include <string>
+#include <unordered_map>
+
+#include "common/tizen_result.h"
+
+namespace extension {
+namespace convergence {
+
+class ConvergenceChannel {
+
+ public:
+  ConvergenceChannel();
+  ConvergenceChannel(const picojson::value &channel_json);
+  virtual ~ConvergenceChannel();
+  ConvergenceChannel(const ConvergenceChannel&) = delete;
+  ConvergenceChannel(ConvergenceChannel&&) = delete;
+  ConvergenceChannel& operator=(const ConvergenceChannel&) = delete;
+  ConvergenceChannel& operator=(ConvergenceChannel&&) = delete;
+
+ public:
+  conv_channel_h GetHandle() const;
+  void FromJson(const picojson::value &channel_json);
+
+ public:
+  static picojson::value ToJson(conv_channel_h channel_handle);
+
+ private:
+  conv_channel_h channel_handle_;
+};
+
+} // namespace convergence
+} // namespace extension
+
+#endif // CONVERGENCE_CONVERGENCE_CHANNEL_H__
diff --git a/src/convergence/convergence_client_info.cc b/src/convergence/convergence_client_info.cc
new file mode 100644 (file)
index 0000000..6dece11
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+
+// TODO check includes
+#include "convergence/convergence_client_info.h"
+
+#include <glib.h>
+#include <d2d_conv_internal.h>
+#include <stdlib.h>
+
+#include "convergence/convergence_instance.h"
+#include "convergence/convergence_utils.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace convergence {
+
+namespace {
+// Service keys
+static const std::string kIsHost = "client_is_host";
+static const std::string kConnectionTime = "client_connect_time"; //--
+static const std::string kClientId = "client_id";
+} // namespace
+
+ConvergenceClientInfo::ConvergenceClientInfo()
+ : isHost_(false)
+ , connectionTime_(0) {
+  ScopeLogger();
+}
+
+ConvergenceClientInfo::ConvergenceClientInfo(conv_payload_h payload)
+ : isHost_(false)
+ , connectionTime_(0) {
+  ScopeLogger();
+
+  isHost_ = ExtractPayloadString(payload, "client_is_host") == "1";
+  connectionTime_ = atol(ExtractPayloadString(payload, "client_connect_time").c_str());
+  clientId_ = ExtractPayloadString(payload, "client_id").c_str();
+}
+
+ConvergenceClientInfo::~ConvergenceClientInfo() {
+  ScopeLogger();
+}
+
+std::string ConvergenceClientInfo::ExtractPayloadString(conv_payload_h payload, const char *key) {
+  ScopeLogger();
+  char *value = nullptr;
+  const int error = conv_payload_get_string(payload, key, &value);
+  if (CONV_ERROR_NONE != error) {
+    trace_conv_error(error, __LINE__, "conv_payload_get_string");
+    return "";
+  }
+
+  if (value) {
+    const std::string result = std::string(value);
+    free(value);
+    return result;
+  }
+  return "";
+}
+
+picojson::value ConvergenceClientInfo::ToJson() const {
+  ScopeLogger();
+  picojson::object clientInfo;
+  clientInfo["isHost"] = picojson::value(static_cast<double>(isHost_));
+  clientInfo["connectionTime"] = picojson::value(static_cast<double>(connectionTime_));
+  clientInfo["clientId"] = picojson::value(clientId_);
+  return picojson::value(clientInfo);
+}
+
+
+} // namespace convergence
+}  // namespace extension
diff --git a/src/convergence/convergence_client_info.h b/src/convergence/convergence_client_info.h
new file mode 100644 (file)
index 0000000..665200c
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+
+#ifndef CONVERGENCE_CONVERGENCE_CLIENT_INFO_H__
+#define CONVERGENCE_CONVERGENCE_CLIENT_INFO_H__
+
+// TODO check includes
+#include <d2d_conv_manager.h>
+
+#include <string>
+#include <unordered_map>
+
+#include "common/tizen_result.h"
+
+namespace extension {
+namespace convergence {
+
+class ConvergenceClientInfo {
+ public:
+  ConvergenceClientInfo();
+  ConvergenceClientInfo(conv_payload_h payload);
+  virtual ~ConvergenceClientInfo();
+  ConvergenceClientInfo(const ConvergenceClientInfo&) = delete;
+  ConvergenceClientInfo(ConvergenceClientInfo&&) = delete;
+  ConvergenceClientInfo& operator=(const ConvergenceClientInfo&) = delete;
+  ConvergenceClientInfo& operator=(ConvergenceClientInfo&&) = delete;
+
+ public:
+  picojson::value ToJson() const;
+
+ private:
+  std::string ExtractPayloadString(conv_payload_h payload, const char *key);
+
+ private:
+  bool isHost_;
+  std::string clientId_;
+  long connectionTime_;
+};
+
+} // namespace convergence
+} // namespace extension
+
+#endif // CONVERGENCE_CONVERGENCE_CLIENT_INFO_H__
diff --git a/src/convergence/convergence_device.cc b/src/convergence/convergence_device.cc
new file mode 100644 (file)
index 0000000..6e82033
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+
+// TODO check includes
+#include "convergence/convergence_device.h"
+
+#include <glib.h>
+#include <d2d_conv_internal.h>
+
+#include "convergence/convergence_instance.h"
+#include "convergence/convergence_service.h"
+#include "convergence/convergence_remote_app_control_service.h"
+#include "convergence/convergence_app_communication_service.h"
+#include "convergence/convergence_utils.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace convergence {
+
+namespace {
+// Service keys
+static const std::string kId = "id";
+static const std::string kName = "name"; //--
+static const std::string kDeviceType = "profile";
+static const std::string kDeviceServices = "services";
+} // namespace
+
+ConvergenceDevice::ConvergenceDevice()
+ : device_handle_(nullptr)
+ , convergence_plugin_(NULL) {
+  ScopeLogger();
+}
+
+ConvergenceDevice::ConvergenceDevice(conv_device_h device, ConvergenceInstance *convergence_plugin)
+ : device_handle_(device)
+ , convergence_plugin_(convergence_plugin) {
+  ScopeLogger();
+}
+
+ConvergenceDevice::~ConvergenceDevice() {
+  ScopeLogger();
+
+  // Releasing all registered services
+  for (auto it = services_.begin(); it != services_.end(); ++it) {
+    delete it->second;
+  }
+  services_.clear();
+
+  conv_device_destroy(device_handle_);
+}
+
+std::string ConvergenceDevice::ExtractDevicePropery(const char *property) {
+  ScopeLogger();
+  char *value = nullptr;
+  const int error = conv_device_get_property_string(device_handle_, property, &value);
+  if (CONV_ERROR_NONE != error) {
+    trace_conv_error(error, __LINE__, "conv_device_get_property_string");
+    return "";
+  }
+
+  if (value) {
+    const std::string result = std::string(value);
+    free(value);
+    return result;
+  }
+  return "";
+}
+
+ConvergenceService *ConvergenceDevice::SwapService(const int service_type) {
+  ScopeLogger();
+  LoggerI("Swapping service of type [%d]", service_type);
+  if (services_.count(service_type) <= 0) {
+    switch(service_type) {
+      case CONV_SERVICE_APP_TO_APP_COMMUNICATION: {
+        services_[service_type] =
+          new ConvergenceAppCommunicationService(device_handle_,
+            convergence_plugin_);
+        break;
+      }
+      case CONV_SERVICE_REMOTE_APP_CONTROL: {
+        LoggerI("Adding Remote App Control service");
+        services_[service_type]  =
+          new ConvergenceRemoteAppControlService(device_handle_,
+            convergence_plugin_);
+        break;
+      }
+      default: {
+        LoggerE("ERROR! UNKNOWN SERVICE TYPE [%d]", service_type);
+        return nullptr;
+      }
+    }
+  }
+  return services_[service_type];
+}
+
+ConvergenceService *ConvergenceDevice::RegisterLocalService(const int service_type) {
+  ScopeLogger();
+  LoggerI("Registering the local service of type [%d]", service_type);
+  if (services_.count(service_type) <= 0) {
+    switch(service_type) {
+      case CONV_SERVICE_APP_TO_APP_COMMUNICATION: {
+        services_[service_type] =
+          new ConvergenceAppCommunicationServerService(device_handle_,
+            convergence_plugin_);
+        LoggerI("Registered for local device [%s] the service [0x%0x] of type [%d]",
+          id_.c_str(), services_[service_type], CONV_SERVICE_APP_TO_APP_COMMUNICATION);
+        break;
+      }
+      default: {
+        LoggerE("ERROR! UNKNOWN SERVICE TYPE [%d]", service_type);
+        return nullptr;
+      }
+    }
+  }
+  return services_[service_type];
+}
+
+void ConvergenceDevice::ForEachServiceCb(conv_service_h service_handle,
+  void* user_data) {
+  ScopeLogger();
+  if (!service_handle || !user_data) {
+    LoggerE("ERROR! Invalid parameters of D2D API Callback");
+    return;
+  }
+  ConvergenceDevice *owner = static_cast<ConvergenceDevice *>(user_data);
+
+  // Extracting service type
+  conv_service_e type = CONV_SERVICE_NONE;
+  int error = conv_service_get_type(service_handle, &type);
+  if (CONV_ERROR_NONE != error) {
+    LoggerE("ERROR! D2D API Get Service Type error [%d]", error);
+    return;
+  }
+
+  ConvergenceService *s = owner->SwapService(type);
+  if (!s) {
+    LoggerE("ERROR! Cannot add NULL service");
+    return;
+  }
+
+  s->Refresh();
+}
+
+void ConvergenceDevice::Refresh() {
+  ScopeLogger();
+  // Getting device properties from handle
+  id_ = ExtractDevicePropery(CONV_DEVICE_ID);
+  name_ = ExtractDevicePropery(CONV_DEVICE_NAME);
+  type_ = ExtractDevicePropery(CONV_DEVICE_TYPE);
+
+  LoggerE("Refreshed device id [%s] name [%s] type [%s]",
+    id_.c_str(), name_.c_str(), type_.c_str());
+
+  // Extracting services
+  const int error = conv_device_foreach_service(device_handle_, ForEachServiceCb, this);
+  if (CONV_ERROR_NONE != error) {
+    trace_conv_error(error, __LINE__, "conv_device_foreach_service");
+  }
+}
+
+picojson::value ConvergenceDevice::ToJson() const {
+  ScopeLogger();
+  picojson::object device_json;
+
+  // Convert device props and services into JSON
+  device_json[kId] = picojson::value(id_);
+  device_json[kName] = picojson::value(name_);
+  device_json[kDeviceType] = picojson::value(type_);
+
+  picojson::array services;
+  for (auto it = services_.begin(); it != services_.end(); ++it) {
+    ConvergenceService *s = it->second;
+    services.push_back(s->ToJson());
+  }
+  device_json[kDeviceServices] = picojson::value(services);
+
+  return picojson::value(device_json);
+}
+
+ConvergenceService *ConvergenceDevice::GetService(const int service_type) const {
+  ScopeLogger();
+  if (services_.count(service_type) <= 0)
+    return nullptr;
+  else
+    return services_[service_type];
+}
+
+
+} // namespace convergence
+}  // namespace extension
diff --git a/src/convergence/convergence_device.h b/src/convergence/convergence_device.h
new file mode 100644 (file)
index 0000000..e16e410
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+
+#ifndef CONVERGENCE_CONVERGENCE_DEVICE_H__
+#define CONVERGENCE_CONVERGENCE_DEVICE_H__
+
+// TODO check includes
+#include <d2d_conv_manager.h>
+
+#include <string>
+#include <unordered_map>
+
+#include "common/tizen_result.h"
+
+namespace extension {
+namespace convergence {
+
+class ConvergenceInstance;
+class ConvergenceService;
+
+class ConvergenceDevice {
+
+ public:
+  ConvergenceDevice();
+  ConvergenceDevice(conv_device_h device_handle, ConvergenceInstance *convergence_plugin);
+  virtual ~ConvergenceDevice();
+  ConvergenceDevice(const ConvergenceDevice&) = delete;
+  ConvergenceDevice(ConvergenceDevice&&) = delete;
+  ConvergenceDevice& operator=(const ConvergenceDevice&) = delete;
+  ConvergenceDevice& operator=(ConvergenceDevice&&) = delete;
+
+
+ public:
+  void Refresh();
+  ConvergenceService *GetService(const int service_type) const;
+  //picojson::object ToJson() const;
+  picojson::value ToJson() const;
+  //std::string get_device() const {return device_handle_; }
+
+ public:
+  ConvergenceService *RegisterLocalService(const int service_type);
+  void SetId(const std::string &id) { id_ = id; }
+
+ private:
+  ConvergenceService *SwapService(const int service_type);
+  std::string ExtractDevicePropery(const char *property);
+  static void ForEachServiceCb(conv_service_h service_handle, void* user_data);
+
+ private:
+  conv_device_h device_handle_;
+  ConvergenceInstance *convergence_plugin_;
+  mutable std::unordered_map<int, ConvergenceService *> services_;
+
+ private:
+  std::string id_;
+  std::string name_;
+  std::string type_; // Device profile: mobile, wearable, TV
+};
+
+} // namespace convergence
+} // namespace extension
+
+#endif // CONVERGENCE_CONVERGENCE_DEVICE_H__
diff --git a/src/convergence/convergence_extension.cc b/src/convergence/convergence_extension.cc
new file mode 100644 (file)
index 0000000..6ddea57
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+
+#include "convergence/convergence_extension.h"
+
+#include "convergence/convergence_instance.h"
+
+// This will be generated from convergence_api.js
+extern const char kSource_convergence_api[];
+
+common::Extension* CreateExtension() {
+  return new ConvergenceExtension;
+}
+
+ConvergenceExtension::ConvergenceExtension() {
+  SetExtensionName("tizen.convergence");
+  SetJavaScriptAPI(kSource_convergence_api);
+
+  const char* entry_points[] = {
+      "tizen.RemoteAppControlService",
+      "tizen.AppCommunicationServerService",
+      "tizen.AppCommunicationClientService",
+      "tizen.Channel",
+      "tizen.PayloadString",
+      "tizen.PayloadRawBytes",
+      nullptr
+    };
+  SetExtraJSEntryPoints(entry_points);
+}
+
+ConvergenceExtension::~ConvergenceExtension() {}
+
+common::Instance* ConvergenceExtension::CreateInstance() {
+  return new extension::convergence::ConvergenceInstance;
+}
similarity index 55%
rename from src/secureelement/secureelement_reader.h
rename to src/convergence/convergence_extension.h
index fc2d777..1a043d2 100644 (file)
  *    limitations under the License.
  */
 
-#ifndef SECUREELEMENT_READER_H_
-#define SECUREELEMENT_READER_H_
+#ifndef CONVERGENCE_CONVERGENCE_EXTENSION_H_
+#define CONVERGENCE_CONVERGENCE_EXTENSION_H_
 
-#include "common/picojson.h"
-#include <Reader.h>
+#include "common/extension.h"
 
-namespace extension {
-namespace secureelement {
+class ConvergenceExtension : public common::Extension {
+ public:
+  ConvergenceExtension();
+  virtual ~ConvergenceExtension();
 
-class SEReader {
-public:
-    SEReader(smartcard_service_api::Reader* reader_ptr) : m_reader(reader_ptr) {};
-    ~SEReader() {};
-
-    picojson::value getName();
-    picojson::value isPresent();
-    picojson::value openSession();
-    void closeSessions();
-private:
-    smartcard_service_api::Reader* m_reader;
+ private:
+  virtual common::Instance* CreateInstance();
 };
 
-} // secureelement
-} // extension
-
-#endif // SECUREELEMENT_READER_H_
+#endif // CONVERGENCE_CONVERGENCE_EXTENSION_H_
diff --git a/src/convergence/convergence_instance.cc b/src/convergence/convergence_instance.cc
new file mode 100644 (file)
index 0000000..22bd337
--- /dev/null
@@ -0,0 +1,683 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+
+#include "convergence/convergence_instance.h"
+
+#include <functional>
+#include <string>
+
+#include "convergence/convergence_manager.h"
+#include "convergence/convergence_remote_app_control_service.h"
+#include "convergence/convergence_app_communication_service.h"
+#include "convergence/convergence_channel.h"
+#include "convergence/convergence_payload.h"
+#include "common/logger.h"
+#include "common/picojson.h"
+#include "common/task-queue.h"
+#include "common/tools.h"
+
+
+namespace extension {
+namespace convergence {
+
+namespace {
+// The privileges that required in Convergence API
+const std::string kPrivilegeInternet = "http://tizen.org/privilege/internet";
+const std::string kPrivilegeBluetooth = "http://tizen.org/privilege/bluetooth";
+const std::string kPrivilegeWifiDirect = "http://tizen.org/privilege/wifidirect";
+
+// JS listener keys
+static const std::string kJSListenerStatus = "status";
+static const std::string kJSCurrentListenerId = "curListenerId";
+static const std::string kJSTargetListenerId = "listenerId";
+static const std::string kSuccess = "success";
+static const std::string kError = "error";
+
+// Arguments, passed from JS
+static const std::string kJSCallbackId = "callbackId";
+static const std::string kJSArgumentDeviceId = "deviceId";
+static const std::string kJSArgumentServiceTypeNumber = "serviceTypeNumber";
+static const std::string kJSArgumentChannel = "channel_data";
+static const std::string kJSArgumentPayload = "payload";
+static const std::string kJSArgumentAppId = "appId";
+static const std::string kJSArgumentReply = "reply";
+static const std::string kJSArgumentTimeout = "timeout";
+static const std::string kJSArgumentService = "service";
+} // namespace
+
+using namespace common;
+
+ConvergenceInstance::ConvergenceInstance() {
+  using namespace std::placeholders;
+  #define REGISTER_SYNC(c,x) \
+    RegisterSyncHandler(c, std::bind(&ConvergenceInstance::x, this, _1, _2));
+  REGISTER_SYNC("ConvergenceManager_stopDiscovery",
+    ConvergenceManagerStopDiscovery);
+
+  REGISTER_SYNC("AppCommunicationService_addListener", AppCommunicationServiceAddListener);
+  REGISTER_SYNC("AppCommunicationService_removeListener", AppCommunicationServiceRemoveListener);
+  //REGISTER_SYNC("Service_createLocalService", ServiceCreateLocal);
+  #undef REGISTER_SYNC
+  #define REGISTER_ASYNC(c,x) \
+    RegisterSyncHandler(c, std::bind(&ConvergenceInstance::x, this, _1, _2));
+  REGISTER_ASYNC("ConvergenceManager_startDiscovery",
+    ConvergenceManagerStartDiscovery);
+
+  REGISTER_ASYNC("RemoteAppControlService_connect", RemoteAppControlServiceConnect);
+  REGISTER_ASYNC("RemoteAppControlService_disconnect", RemoteAppControlServiceDisconnect);
+  REGISTER_ASYNC("RemoteAppControlService_launch", RemoteAppControlServiceLaunch);
+
+  REGISTER_ASYNC("AppCommunicationService_start", AppCommunicationServiceStart);
+  REGISTER_ASYNC("AppCommunicationService_stop", AppCommunicationServiceStop);
+  REGISTER_ASYNC("AppCommunicationService_send", AppCommunicationServiceSend);
+
+  REGISTER_ASYNC("AppCommunicationServerService_constructLocal", AppCommunicationServerServiceConstructLocal);
+
+  REGISTER_ASYNC("AppCommunicationClientService_connect", AppCommunicationClientServiceConnect);
+  REGISTER_ASYNC("AppCommunicationClientService_disconnect", AppCommunicationClientServiceDisconnect);
+  #undef REGISTER_ASYNC
+}
+
+ConvergenceInstance::~ConvergenceInstance() {
+}
+
+void ConvergenceInstance::ReplyAsync(ConvergenceCallbacks callback_function_type,
+  int curListenerId, bool isSuccess, picojson::object& param) {
+  ScopeLogger();
+
+  param[kJSListenerStatus] = picojson::value(isSuccess ? kSuccess : kError);
+  param[kJSCurrentListenerId] = picojson::value(static_cast<double>(curListenerId));
+
+  switch(callback_function_type) {
+    case kConvergenceManagerDiscoveryCallback: {
+      param[kJSTargetListenerId] = picojson::value("CONVERGENCE_DISCOVERY_LISTENER");
+      break;
+    }
+    /*case kRemoteAppControlServiceConnectCallback: {
+      param[kJSTargetListenerId] =
+        picojson::value("REMOTE_APP_CONTROL_SERVICE_CONNECT_LISTENER");
+      break;
+    }*/
+    case kRemoteAppControlListenerCallback: {
+      param[kJSTargetListenerId] =
+        picojson::value("REMOTE_APP_CONTROL_SERVICE_LISTENER");
+      break;
+    }
+    /*case kAppCommunicationSuccessCallback: {
+      param[kJSTargetListenerId] =
+        picojson::value("APP_COMMUNICATION_SERVICE_SUCCESS_LISTENER");
+      break;
+    }*/
+    case kAppCommunicationListenerCallback: {
+      param[kJSTargetListenerId] =
+        picojson::value("APP_COMMUNICATION_SERVICE_LISTENER");
+      break;
+    }
+    /*case kAppCommunicationClientServiceConnectCallback: {
+      param[kJSTargetListenerId] =
+        picojson::value("APP_COMMUNICATON_CLIENT_SERVICE_CONNECT_LISTENER");
+      break;
+    }*/
+    default: {
+      LoggerE("Invalid Callback Type");
+      return;
+    }
+  }
+
+  picojson::value result = picojson::value(param);
+  LoggerD("---> %s", result.serialize().c_str()); // TODO remove
+
+  PostMessage(result.serialize().c_str());
+}
+
+#define CHECK_EXIST(args, name, out) \
+    if (!args.contains(name)) {\
+      ReportError(TypeMismatchException(name" is required argument"), out);\
+      return;\
+    }
+
+void ConvergenceInstance::ConvergenceManagerStartDiscovery(
+  const picojson::value& args, picojson::object& out) {
+  ScopeLogger();
+  CHECK_EXIST(args, "callbackId", out)
+  CHECK_EXIST(args, "timeout", out)
+
+  /*CHECK_PRIVILEGE_ACCESS(kPrivilegeInternet, &out)
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeBluetooth, &out)
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeWifiDirect, &out)*/
+
+  LoggerI("ARGS: %s", args.serialize().c_str());
+
+  auto start_discovery =
+    [this, args](const std::shared_ptr<picojson::value>& result) {
+    ScopeLogger("start_discovery");
+
+    // Start the discovery procedure
+    ConvergenceManager::GetInstance(this).StartDiscovery(
+      static_cast<long>(args.get(kJSArgumentTimeout).get<double>()));
+
+    picojson::object& object = result->get<picojson::object>();
+    object[kJSCallbackId] = args.get(kJSCallbackId);
+    ReportSuccess(object);
+  };
+
+  auto start_discovery_result =
+    [this, args](const std::shared_ptr<picojson::value>& result) {
+    ScopeLogger("start_discovery_result");
+    result->get<picojson::object>()[kJSCallbackId] = args.get(kJSCallbackId);
+    Instance::PostMessage(this, result->serialize().c_str());
+  };
+
+  auto data =
+    std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}};
+
+  TaskQueue::GetInstance().Queue<picojson::value>(
+    start_discovery,
+    start_discovery_result,
+    data);
+
+  ReportSuccess(out);
+}
+
+void ConvergenceInstance::ConvergenceManagerStopDiscovery(
+  const picojson::value& args, picojson::object& out) {
+  ScopeLogger();
+
+  /*CHECK_PRIVILEGE_ACCESS(kPrivilegeInternet, &out)
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeBluetooth, &out)
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeWifiDirect, &out)*/
+
+  // Running the discovery stop procedure
+  ConvergenceManager::GetInstance(this).StopDiscovery();
+  //out[kJSCallbackId] = args.get(kJSCallbackId);
+  ReportSuccess(out);
+}
+
+void ConvergenceInstance::RemoteAppControlServiceConnect(
+  const picojson::value& args, picojson::object& out) {
+  ScopeLogger();
+  CHECK_EXIST(args, "callbackId", out)
+
+  /*CHECK_PRIVILEGE_ACCESS(kPrivilegeInternet, &out)
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeBluetooth, &out)
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeWifiDirect, &out)*/
+
+  LoggerI("ARGS: %s", args.serialize().c_str());
+
+  auto connect =
+    [this, args](const std::shared_ptr<picojson::value>& result) {
+    ScopeLogger("connect");
+
+    // Finding the service
+    ConvergenceRemoteAppControlService *service =
+      static_cast<ConvergenceRemoteAppControlService *>(
+        ConvergenceManager::GetInstance(this).GetService(args.get(kJSArgumentDeviceId).to_str().c_str(),
+          CONV_SERVICE_REMOTE_APP_CONTROL));
+    if (!service) {
+      LoggerE("Can not find the service type = 1, device_id = ",
+        args.get(kJSArgumentDeviceId).to_str().c_str());
+      //ReportSuccess(object); // TODO ReportError
+      return;
+    }
+
+    // Running the service connect procedure
+    service->Connect(static_cast<int>(args.get(kJSCurrentListenerId).get<double>()));
+
+    picojson::object& object = result->get<picojson::object>();
+    object[kJSCallbackId] = args.get(kJSCallbackId);
+    ReportSuccess(object);
+  };
+
+  auto connect_result =
+    [this, args](const std::shared_ptr<picojson::value>& result) {
+    ScopeLogger("connect_result");
+
+    result->get<picojson::object>()[kJSCallbackId] = args.get(kJSCallbackId);
+    Instance::PostMessage(this, result->serialize().c_str());
+  };
+
+  auto data =
+    std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}};
+
+  TaskQueue::GetInstance().Queue<picojson::value>(
+    connect,
+    connect_result,
+    data);
+
+  ReportSuccess(out);
+}
+
+void ConvergenceInstance::RemoteAppControlServiceDisconnect(
+  const picojson::value& args, picojson::object& out) {
+  ScopeLogger();
+
+  /*CHECK_PRIVILEGE_ACCESS(kPrivilegeInternet, &out)
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeBluetooth, &out)
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeWifiDirect, &out)*/
+
+  //LoggerI("ARGS: %s", args.serialize().c_str());
+
+  auto disconnect =
+    [this, args](const std::shared_ptr<picojson::value>& result) {
+    ScopeLogger("disconnect");
+
+    // Finding the service
+    ConvergenceRemoteAppControlService *service =
+      static_cast<ConvergenceRemoteAppControlService *>(
+        ConvergenceManager::GetInstance(this).GetService(args.get(kJSArgumentDeviceId).to_str().c_str(),
+          CONV_SERVICE_REMOTE_APP_CONTROL));
+    if (!service) {
+      //ReportSuccess(object); // TODO ReportError
+      LoggerE("Can not find the service type = 1, device_id = ",
+        args.get(kJSArgumentDeviceId).to_str().c_str());
+      return;
+    }
+
+    // Running the service disconnect procedure
+    service->Disconnect();
+
+    picojson::object& object = result->get<picojson::object>();
+    ReportSuccess(object);
+  };
+
+  auto data =
+    std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}};
+
+  TaskQueue::GetInstance().Async<picojson::value>(
+      disconnect,
+      data);
+
+  ReportSuccess(out);
+}
+
+void ConvergenceInstance::RemoteAppControlServiceLaunch(
+  const picojson::value& args, picojson::object& out) {
+  ScopeLogger();
+  CHECK_EXIST(args, "callbackId", out)
+
+  /*CHECK_PRIVILEGE_ACCESS(kPrivilegeInternet, &out)
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeBluetooth, &out)
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeWifiDirect, &out)*/
+
+  auto launch = [this, args](const std::shared_ptr<picojson::value>& result) {
+    ScopeLogger("send");
+
+    // Finding the service
+    ConvergenceRemoteAppControlService *service =
+      static_cast<ConvergenceRemoteAppControlService *>(
+        ConvergenceManager::GetInstance(this).GetService(args.get(kJSArgumentDeviceId).to_str().c_str(),
+          CONV_SERVICE_REMOTE_APP_CONTROL));
+    if (!service) {
+      //ReportSuccess(object); // TODO ReportError
+      LoggerE("Can not find the service type = 1, device_id = ",
+        args.get(kJSArgumentDeviceId).to_str().c_str());
+      return;
+    }
+
+    // Running the service app control procedure
+    service->Launch(
+      args.get(kJSArgumentAppId).to_str().c_str(),
+      static_cast<bool>(args.get(kJSArgumentReply).get<bool>()),
+      static_cast<int>(args.get(kJSCurrentListenerId).get<double>()));
+
+    picojson::object& object = result->get<picojson::object>();
+    object[kJSCallbackId] = args.get(kJSCallbackId);
+    ReportSuccess(object);
+  };
+
+  auto launch_result =
+    [this, args](const std::shared_ptr<picojson::value>& result) {
+    ScopeLogger("send_result");
+    result->get<picojson::object>()[kJSCallbackId] = args.get(kJSCallbackId);
+    Instance::PostMessage(this, result->serialize().c_str());
+  };
+
+  auto data =
+    std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}};
+
+  TaskQueue::GetInstance().Queue<picojson::value>(
+    launch,
+    launch_result,
+    data);
+
+  ReportSuccess(out);
+}
+
+void ConvergenceInstance::AppCommunicationServiceStart(
+  const picojson::value& args, picojson::object& out) {
+  ScopeLogger();
+  CHECK_EXIST(args, "callbackId", out)
+
+  /*CHECK_PRIVILEGE_ACCESS(kPrivilegeInternet, &out)
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeBluetooth, &out)
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeWifiDirect, &out)*/
+
+  auto start = [this, args](const std::shared_ptr<picojson::value>& result) {
+    ScopeLogger("start");
+
+    // Finding the service
+    ConvergenceAppCommunicationService *service =
+      static_cast<ConvergenceAppCommunicationService *>(
+        ConvergenceManager::GetInstance(this).GetService(args.get(kJSArgumentDeviceId).to_str().c_str(),
+          CONV_SERVICE_APP_TO_APP_COMMUNICATION));
+    if (!service) {
+      //ReportSuccess(object); // TODO ReportError
+      LoggerE("Can not find the service type = 0, device_id = ",
+        args.get(kJSArgumentDeviceId).to_str().c_str());
+      return;
+    }
+
+    // Running the service start procedure
+    service->Start(new ConvergenceChannel(args.get(kJSArgumentChannel)),
+      static_cast<int>(args.get(kJSCurrentListenerId).get<double>()));
+
+    picojson::object& object = result->get<picojson::object>();
+    object[kJSCallbackId] = args.get(kJSCallbackId);
+    ReportSuccess(object);
+  };
+
+  auto start_result =
+    [this, args](const std::shared_ptr<picojson::value>& result) {
+    ScopeLogger("start_result");
+    result->get<picojson::object>()[kJSCallbackId] = args.get(kJSCallbackId);
+    Instance::PostMessage(this, result->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}};
+
+  TaskQueue::GetInstance().Queue<picojson::value>(
+    start,
+    start_result,
+    data);
+
+  ReportSuccess(out);
+}
+
+void ConvergenceInstance::AppCommunicationServiceSend(
+  const picojson::value& args, picojson::object& out) {
+  ScopeLogger();
+  CHECK_EXIST(args, "callbackId", out)
+
+  /*CHECK_PRIVILEGE_ACCESS(kPrivilegeInternet, &out)
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeBluetooth, &out)
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeWifiDirect, &out)*/
+
+  auto send = [this, args](const std::shared_ptr<picojson::value>& result) {
+    ScopeLogger("send");
+
+    // Finding the service
+    ConvergenceAppCommunicationService *service =
+      static_cast<ConvergenceAppCommunicationService *>(
+        ConvergenceManager::GetInstance(this).GetService(args.get(kJSArgumentDeviceId).to_str().c_str(),
+          CONV_SERVICE_APP_TO_APP_COMMUNICATION));
+    if (!service) {
+      //ReportSuccess(object); // TODO ReportError
+      LoggerE("Can not find the service type = 0, device_id = ",
+        args.get(kJSArgumentDeviceId).to_str().c_str());
+      return;
+    }
+
+    // Running the service send procedure
+    service->Send(new ConvergenceChannel(args.get(kJSArgumentChannel)),
+      new ConvergencePayloadArray(args.get(kJSArgumentPayload)),
+      static_cast<int>(args.get(kJSCurrentListenerId).get<double>()));
+
+    picojson::object& object = result->get<picojson::object>();
+    object[kJSCallbackId] = args.get(kJSCallbackId);
+    ReportSuccess(object);
+  };
+
+  auto send_result =
+    [this, args](const std::shared_ptr<picojson::value>& result) {
+    ScopeLogger("send_result");
+    result->get<picojson::object>()[kJSCallbackId] = args.get(kJSCallbackId);
+    Instance::PostMessage(this, result->serialize().c_str());
+  };
+
+  auto data =
+    std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}};
+
+  TaskQueue::GetInstance().Queue<picojson::value>(
+    send,
+    send_result,
+    data);
+
+  ReportSuccess(out);
+}
+
+void ConvergenceInstance::AppCommunicationServiceStop(
+  const picojson::value& args, picojson::object& out) {
+  ScopeLogger();
+  CHECK_EXIST(args, "callbackId", out)
+
+  /*CHECK_PRIVILEGE_ACCESS(kPrivilegeInternet, &out)
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeBluetooth, &out)
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeWifiDirect, &out)*/
+
+  auto stop = [this, args](const std::shared_ptr<picojson::value>& result) {
+    ScopeLogger("stop");
+
+    // Finding the service
+    ConvergenceAppCommunicationService *service =
+      static_cast<ConvergenceAppCommunicationService *>(
+        ConvergenceManager::GetInstance(this).GetService(args.get(kJSArgumentDeviceId).to_str().c_str(),
+          CONV_SERVICE_APP_TO_APP_COMMUNICATION));
+    if (!service) {
+      //ReportSuccess(object); // TODO ReportError
+      LoggerE("Can not find the service type = 0, device_id = ",
+        args.get(kJSArgumentDeviceId).to_str().c_str());
+      return;
+    }
+
+    // Running the service stop procedure
+    service->Stop(new ConvergenceChannel(args.get(kJSArgumentChannel)),
+      static_cast<int>(args.get(kJSCurrentListenerId).get<double>()));
+
+    picojson::object& object = result->get<picojson::object>();
+    object[kJSCallbackId] = args.get(kJSCallbackId);
+    ReportSuccess(object);
+  };
+
+  auto stop_result =
+    [this, args](const std::shared_ptr<picojson::value>& result) {
+    ScopeLogger("stop_result");
+    result->get<picojson::object>()[kJSCallbackId] = args.get(kJSCallbackId);
+    Instance::PostMessage(this, result->serialize().c_str());
+  };
+
+  auto data =
+    std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}};
+
+  TaskQueue::GetInstance().Queue<picojson::value>(
+    stop,
+    stop_result,
+    data);
+
+  ReportSuccess(out);
+}
+
+void ConvergenceInstance::AppCommunicationServiceAddListener(
+  const picojson::value& args, picojson::object& out) {
+  ScopeLogger();
+
+  /*CHECK_PRIVILEGE_ACCESS(kPrivilegeInternet, &out)
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeBluetooth, &out)
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeWifiDirect, &out)*/
+
+  LoggerI("ARGS: %s", args.serialize().c_str());
+
+  // Finding the service
+  ConvergenceAppCommunicationService *service =
+    static_cast<ConvergenceAppCommunicationService *>(
+      ConvergenceManager::GetInstance(this).GetService(args.get(kJSArgumentDeviceId).to_str().c_str(),
+        CONV_SERVICE_APP_TO_APP_COMMUNICATION));
+  if (!service) {
+    //ReportSuccess(object); // TODO ReportError
+    LoggerE("Can not find the service type = 0, device_id = ",
+      args.get(kJSArgumentDeviceId).to_str().c_str());
+    return;
+  }
+
+  // Running the service stop procedure
+  service->SetListener(static_cast<int>(args.get(kJSCurrentListenerId).get<double>()));
+
+  ReportSuccess(out);
+}
+
+void ConvergenceInstance::AppCommunicationServiceRemoveListener(
+  const picojson::value& args, picojson::object& out) {
+  ScopeLogger();
+
+  /*CHECK_PRIVILEGE_ACCESS(kPrivilegeInternet, &out)
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeBluetooth, &out)
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeWifiDirect, &out)*/
+
+  // Finding the service
+  ConvergenceAppCommunicationService *service =
+    static_cast<ConvergenceAppCommunicationService *>(
+      ConvergenceManager::GetInstance(this).GetService(args.get(kJSArgumentDeviceId).to_str().c_str(),
+        CONV_SERVICE_APP_TO_APP_COMMUNICATION));
+  if (!service) {
+    //ReportSuccess(object); // TODO ReportError
+    LoggerE("Can not find the service type = 0, device_id = ",
+      args.get(kJSArgumentDeviceId).to_str().c_str());
+    return;
+  }
+
+  // Running the service stop procedure
+  service->RemoveListener();
+
+  ReportSuccess(out);
+}
+
+void ConvergenceInstance::AppCommunicationServerServiceConstructLocal(
+  const picojson::value& args, picojson::object& out) {
+  ScopeLogger();
+
+  // Finding the service
+  ConvergenceAppCommunicationClientService *service =
+    static_cast<ConvergenceAppCommunicationClientService *>(
+      ConvergenceManager::GetInstance(this).RegisterLocalService(args.get(kJSArgumentDeviceId).to_str().c_str(),
+        CONV_SERVICE_APP_TO_APP_COMMUNICATION));
+  if (!service) {
+    //ReportSuccess(object); // TODO ReportError
+    LoggerE("Can not find the service type = 1, device_id = ",
+      args.get(kJSArgumentDeviceId).to_str().c_str());
+    return;
+  }
+
+  ReportSuccess(out);
+}
+
+void ConvergenceInstance::AppCommunicationClientServiceConnect(
+  const picojson::value& args, picojson::object& out) {
+  ScopeLogger();
+  CHECK_EXIST(args, "callbackId", out)
+
+  /*CHECK_PRIVILEGE_ACCESS(kPrivilegeInternet, &out)
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeBluetooth, &out)
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeWifiDirect, &out)*/
+
+  LoggerI("ARGS: %s", args.serialize().c_str());
+
+  auto connect =
+    [this, args](const std::shared_ptr<picojson::value>& result) {
+    ScopeLogger("connect");
+
+    // Finding the service
+    ConvergenceAppCommunicationClientService *service =
+      static_cast<ConvergenceAppCommunicationClientService *>(
+        ConvergenceManager::GetInstance(this).GetService(args.get(kJSArgumentDeviceId).to_str().c_str(),
+          CONV_SERVICE_APP_TO_APP_COMMUNICATION));
+    if (!service) {
+      LoggerE("Can not find the service type = 1, device_id = ",
+        args.get(kJSArgumentDeviceId).to_str().c_str());
+      //ReportSuccess(object); // TODO ReportError
+      return;
+    }
+
+    // Running the service connect procedure
+    service->Connect(static_cast<int>(args.get(kJSCurrentListenerId).get<double>()));
+
+    picojson::object& object = result->get<picojson::object>();
+    object[kJSCallbackId] = args.get(kJSCallbackId);
+    ReportSuccess(object);
+  };
+
+  auto connect_result =
+    [this, args](const std::shared_ptr<picojson::value>& result) {
+    ScopeLogger("connect_result");
+
+    result->get<picojson::object>()[kJSCallbackId] = args.get(kJSCallbackId);
+    Instance::PostMessage(this, result->serialize().c_str());
+  };
+
+  auto data =
+    std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}};
+
+  TaskQueue::GetInstance().Queue<picojson::value>(
+    connect,
+    connect_result,
+    data);
+  ReportSuccess(out);
+}
+
+void ConvergenceInstance::AppCommunicationClientServiceDisconnect(
+  const picojson::value& args, picojson::object& out) {
+  ScopeLogger();
+  /*CHECK_PRIVILEGE_ACCESS(kPrivilegeInternet, &out)
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeBluetooth, &out)
+  CHECK_PRIVILEGE_ACCESS(kPrivilegeWifiDirect, &out)*/
+
+  //LoggerI("ARGS: %s", args.serialize().c_str());
+
+  auto disconnect =
+    [this, args](const std::shared_ptr<picojson::value>& result) {
+    ScopeLogger("disconnect");
+
+    // Finding the service
+    ConvergenceAppCommunicationClientService *service =
+      static_cast<ConvergenceAppCommunicationClientService *>(
+        ConvergenceManager::GetInstance(this).GetService(args.get(kJSArgumentDeviceId).to_str().c_str(),
+          CONV_SERVICE_APP_TO_APP_COMMUNICATION));
+    if (!service) {
+      //ReportSuccess(object); // TODO ReportError
+      LoggerE("Can not find the service type = 1, device_id = ",
+        args.get(kJSArgumentDeviceId).to_str().c_str());
+      return;
+    }
+
+    // Running the service disconnect procedure
+    service->Disconnect();
+
+    picojson::object& object = result->get<picojson::object>();
+    ReportSuccess(object);
+  };
+
+  auto data =
+    std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}};
+
+  TaskQueue::GetInstance().Async<picojson::value>(
+      disconnect,
+      data);
+  ReportSuccess(out);
+}
+
+
+#undef CHECK_EXIST
+
+} // namespace convergence
+} // namespace extension
diff --git a/src/convergence/convergence_instance.h b/src/convergence/convergence_instance.h
new file mode 100644 (file)
index 0000000..b38f631
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+
+#ifndef CONVERGENCE_CONVERGENCE_INSTANCE_H_
+#define CONVERGENCE_CONVERGENCE_INSTANCE_H_
+
+//#include "common/tizen_instance.h"
+#include "common/extension.h"
+
+namespace extension {
+namespace convergence {
+
+enum ConvergenceCallbacks {
+  // Convergence Manager Discovery
+  kConvergenceManagerDiscoveryCallback,
+
+  // Remote App Control
+  //kRemoteAppControlServiceConnectCallback,
+  kRemoteAppControlListenerCallback,
+
+  // App Communication
+  //kAppCommunicationSuccessCallback,
+  kAppCommunicationListenerCallback,
+
+
+  // App Communication Client
+  //kAppCommunicationClientServiceConnectCallback
+};
+
+
+// TODO:  inherit it by common::TizenInstance class
+//class ConvergenceInstance : public common::TizenInstance {
+
+class ConvergenceInstance : public common::ParsedInstance {
+ public:
+  ConvergenceInstance();
+  virtual ~ConvergenceInstance();
+ public:
+  void ReplyAsync(ConvergenceCallbacks cbfunc,
+    int curListenerId, bool isSuccess, picojson::object& param);
+
+ private:
+  // TODO: make all API functions return common::TizenResult
+
+  // Convergence Manager
+  void ConvergenceManagerStartDiscovery(const picojson::value& args,
+   picojson::object& out);
+  void ConvergenceManagerStopDiscovery(const picojson::value& args,
+   picojson::object& out);
+
+  // Remote App Control Service
+  void RemoteAppControlServiceConnect(const picojson::value& args, picojson::object& out);
+  void RemoteAppControlServiceDisconnect(const picojson::value& args, picojson::object& out);
+  void RemoteAppControlServiceLaunch(const picojson::value& args, picojson::object& out);
+
+  // App Communication Service
+  void AppCommunicationServiceStart(const picojson::value& args, picojson::object& out);
+  void AppCommunicationServiceStop(const picojson::value& args, picojson::object& out);
+  void AppCommunicationServiceSend(const picojson::value& args, picojson::object& out);
+  void AppCommunicationServiceAddListener(const picojson::value& args, picojson::object& out);
+  void AppCommunicationServiceRemoveListener(const picojson::value& args, picojson::object& out);
+
+  // App Communication Server Service
+  void AppCommunicationServerServiceConstructLocal(const picojson::value& args, picojson::object& out);
+
+  // App Communication Client Service
+  void AppCommunicationClientServiceConnect(const picojson::value& args, picojson::object& out);
+  void AppCommunicationClientServiceDisconnect(const picojson::value& args, picojson::object& out);
+};
+
+} // namespace convergence
+} // namespace extension
+
+#endif // CONVERGENCE_CONVERGENCE_INSTANCE_H_
diff --git a/src/convergence/convergence_manager.cc b/src/convergence/convergence_manager.cc
new file mode 100644 (file)
index 0000000..07b05b9
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+
+#include "convergence/convergence_manager.h"
+
+#include <glib.h>
+#include <d2d_conv_internal.h>
+
+#include "convergence/convergence_instance.h"
+#include "convergence/convergence_device.h"
+#include "convergence/convergence_service.h"
+#include "convergence/convergence_utils.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace convergence {
+
+using common::TizenResult;
+using common::TizenSuccess;
+
+
+// TODO check which fields are needed
+// TODO remove dublications, marked with //---
+namespace {
+// Commonly used key words
+static const std::string kId = "id"; //---
+static const std::string kName = "name"; //--
+static const std::string kKey = "key";
+static const std::string kValue = "value";
+
+// Channel data keys
+static const std::string kChannel = "channel";
+static const std::string kChannelDataChannelId = "channel_id";
+static const std::string kChannelDataChannelOption = "option";
+static const std::string kChannelDataChannelOptions = "options";
+
+// Payload data keys and some values
+static const std::string kPayload = "payload"; // ---
+static const std::string kPayloadDataType = "type"; // String, bytes or app control
+static const std::string kTypeString = "STRING";
+static const std::string kTypeRawBytes = "RAW_BYTES";
+static const std::string kTypeAppControl = "APP_CONTROL";
+static const std::string kPayloadDataAppControlAppId = "appI";
+static const std::string kPayloadDataAppControlOperation = "operation";
+static const std::string kPayloadDataAppControlUri = "uri";
+static const std::string kPayloadDataAppControlMime = "mime";
+static const std::string kPayloadDataAppControlLaunchMode = "launch_mode";
+static const std::string kPayloadDataAppControlCategory = "category";
+
+// Service keys
+static const std::string kServiceType = "serviceType"; //---
+static const std::string kServiceConnectionState = "connectionState"; //---
+static const std::string kServiceProperties = "properties";
+
+// Device keys
+static const std::string kDevice = "device";
+static const std::string kDeviceType = "profile"; //---
+static const std::string kDeviceServices = "services"; //---
+
+// Discovery keys
+static const std::string kDiscoveryStatus = "discovery_status";
+static const std::string kDiscoveryStatusDeviceFound = "device_found";
+static const std::string kDiscoveryStatusFinished = "discovery_finished";
+static const std::string kDiscoveryStatusError = "discovery_error";
+static const std::string kDiscoveryError = "discovery_error";
+
+// Service connection status keys
+static const std::string kServiceConnectionStatus = "connect_status"; //---
+static const std::string kServiceConnectionStatusConnected = "service_connected"; //---
+static const std::string kServiceConnectionStatusNotConnected = "service_not_connected"; //---
+
+// Service listener status keys
+static const std::string kServiceListenerStatus = "listener_status"; //---
+static const std::string kServiceListenerStatusOk = "listener_ok"; // ---
+static const std::string kServiceListenerStatusError = "listener_error"; //---
+static const std::string kServiceListenerError = "listener_error"; //---
+} // namespace
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+ConvergenceManager &ConvergenceManager::GetInstance(
+  ConvergenceInstance *owner) {
+  static ConvergenceManager instance;
+  instance.convergence_plugin_ = owner;
+  return instance;
+}
+
+ConvergenceManager::ConvergenceManager()
+ : convergence_plugin_(nullptr)
+ , convergence_manager_(nullptr) {
+  ScopeLogger();
+  const int error = conv_create(&convergence_manager_);
+  if (CONV_ERROR_NONE != error) {
+    // Handle error
+    trace_conv_error(error, __LINE__, "conv_create");
+  }
+}
+
+ConvergenceManager::~ConvergenceManager() {
+  ScopeLogger();
+
+  // Releasing all registered devices
+  for (auto it = registered_devices_.begin(); it != registered_devices_.end(); ++it) {
+      delete it->second;
+  }
+  registered_devices_.clear();
+
+  int error = conv_destroy(convergence_manager_);
+  if (CONV_ERROR_NONE != error) {
+    // Handle error
+    trace_conv_error(error, __LINE__, "conv_destroy");
+  }
+  convergence_manager_ = nullptr;
+}
+
+ConvergenceDevice *ConvergenceManager::SwapDevice(const char *device_id,
+  conv_device_h device_handle) {
+  ScopeLogger();
+  if (registered_devices_.count(device_id) <= 0) {
+    ConvergenceDevice *d = new ConvergenceDevice(device_handle, convergence_plugin_);
+    d->SetId(device_id);
+    registered_devices_[device_id] = d;
+    LoggerI("...registering the device [%s, %x]", device_id, device_handle);
+  }
+  return registered_devices_[device_id];
+}
+
+void ConvergenceManager::DiscoveryCb(conv_device_h device_handle,
+  conv_discovery_result_e result, void* user_data) {
+  ScopeLogger();
+
+  if (!user_data) {
+    LoggerE("ERROR! NULL user data in discovery callback");
+    return;
+  }
+
+  ConvergenceManager *owner = static_cast<ConvergenceManager *>(user_data);
+
+  switch(result) {
+  case CONV_DISCOVERY_RESULT_SUCCESS: {
+    LoggerI("...found a device");
+
+    char *id = nullptr;
+    int error = conv_device_get_property_string(device_handle, CONV_DEVICE_ID, &id);
+    if (CONV_ERROR_NONE != error) {
+      trace_conv_error(error, __LINE__, "conv_device_get_property_string ID");
+    }
+    if (!id) {
+      LoggerE("BAD ERROR: Device ID is NULL");
+      return; // TODO report error
+    }
+
+    conv_device_h clone_device = nullptr;
+    error = conv_device_clone(device_handle, &clone_device);
+    if (CONV_ERROR_NONE != error) {
+      trace_conv_error(error, __LINE__, "conv_device_clone");
+      break;
+    }
+    ConvergenceDevice *d = owner->SwapDevice(id, clone_device);
+    free(id);
+
+    if (!d) {
+      // Handle bad error
+      LoggerE("BAD ERROR: Cannot swap the device");
+      break;
+    }
+
+    d->Refresh();
+
+    picojson::object param;
+    param[kDiscoveryStatus] = picojson::value(kDiscoveryStatusDeviceFound);
+    param[kDevice] = d->ToJson();
+    owner->convergence_plugin_->ReplyAsync(kConvergenceManagerDiscoveryCallback,
+      -1,
+      true,
+      param);
+
+    break;
+  }
+  case CONV_DISCOVERY_RESULT_FINISHED: {
+    LoggerE("...discovery finished");
+
+    picojson::object param;
+    param[kDiscoveryStatus] = picojson::value(kDiscoveryStatusFinished);
+    owner->convergence_plugin_->ReplyAsync(kConvergenceManagerDiscoveryCallback,
+      -1,
+      true,
+      param);
+    break;
+  }
+  case CONV_DISCOVERY_RESULT_ERROR: {
+    LoggerE("Discovery Error");
+    picojson::object param;
+    param[kDiscoveryStatus] = picojson::value(kDiscoveryStatusError);
+    param[kDiscoveryError] = picojson::value(static_cast<double>(result));
+    owner->convergence_plugin_->ReplyAsync(kConvergenceManagerDiscoveryCallback,
+      -1,
+      false,
+      param);
+    break;
+  }
+  default: {
+    LoggerE("Unknown discovery result");
+    break;
+  }
+  }
+}
+
+TizenResult ConvergenceManager::StartDiscovery(long timeout) {
+  ScopeLogger();
+  const int error = conv_discovery_start(convergence_manager_,
+    (const int)timeout, DiscoveryCb, this);
+  if (CONV_ERROR_NONE != error) {
+    // TODO: Handle error
+    trace_conv_error(error, __LINE__, "conv_discovery_start");
+  }
+  return TizenSuccess();
+}
+
+TizenResult ConvergenceManager::StopDiscovery() {
+  ScopeLogger();
+  const int error = conv_discovery_stop(convergence_manager_);
+  if (CONV_ERROR_NONE != error) {
+    // TODO: Handle error
+    trace_conv_error(error, __LINE__, "conv_discovery_stop");
+  }
+  return TizenSuccess();
+}
+
+//-------------
+// TODO Implement the NULL Object pattern for Service,
+// so this function would return always  valid pointers
+//-------------
+ConvergenceService *ConvergenceManager::GetService(const char *device_id,
+  const int service_type) const {
+  ScopeLogger();
+
+  LoggerI("Getting the service object for id [%s], type [%d]", device_id, service_type);
+  if (registered_devices_.count(device_id) <= 0) {
+    LoggerE("Device ID not found");
+    return nullptr;
+  }
+
+  ConvergenceDevice *d = registered_devices_[device_id];
+  if (!d) {
+    LoggerE("Device object not found");
+    return nullptr;
+  }
+
+  return d->GetService(service_type);
+}
+
+ConvergenceService *ConvergenceManager::RegisterLocalService(const char *device_id,
+  const int service_type) {
+  ScopeLogger();
+
+  LoggerI("Registering local service [%d] for device id [%s]", service_type, device_id);
+
+  ConvergenceDevice *d = SwapDevice(device_id, nullptr);
+  if (!d) {
+    LoggerE("Device object not found");
+    return nullptr;
+  }
+
+  return d->RegisterLocalService(service_type);
+}
+
+} // namespace convergence
+}  // namespace extension
diff --git a/src/convergence/convergence_manager.h b/src/convergence/convergence_manager.h
new file mode 100644 (file)
index 0000000..4b61407
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+
+#ifndef CONVERGENCE_CONVERGENCE_MANAGER_H__
+#define CONVERGENCE_CONVERGENCE_MANAGER_H__
+
+#include <d2d_conv_manager.h>
+
+#include <string>
+#include <unordered_map>
+
+#include "common/tizen_result.h"
+
+namespace extension {
+namespace convergence {
+
+
+class ConvergenceDevice;
+class ConvergenceService;
+
+// TODO rename to Discovery Manager
+// TODO extract service start, stop, read, send to Service Manager class
+class ConvergenceManager {
+
+ public:
+   static ConvergenceManager &GetInstance(class ConvergenceInstance *owner);
+
+ public:
+  ConvergenceManager();
+  ~ConvergenceManager();
+  ConvergenceManager(const ConvergenceManager&) = delete;
+  ConvergenceManager(ConvergenceManager&&) = delete;
+  ConvergenceManager& operator=(const ConvergenceManager&) = delete;
+  ConvergenceManager& operator=(ConvergenceManager&&) = delete;
+
+ public:
+  common::TizenResult StartDiscovery(long timeout);
+  common::TizenResult StopDiscovery();
+
+ public:
+  ConvergenceService *GetService(const char *device_id,
+   const int service_type) const;
+  ConvergenceService *RegisterLocalService(const char *device_id,
+   const int service_type);
+
+ private:
+  static void DiscoveryCb(conv_device_h device_handle,
+   conv_discovery_result_e result, void* user_data);
+  ConvergenceDevice *SwapDevice(const char *device_id,
+   conv_device_h device_handle);
+
+ private:
+  class ConvergenceInstance *convergence_plugin_;
+  conv_h convergence_manager_;
+  mutable std::unordered_map<std::string, ConvergenceDevice *> registered_devices_; // TODO rename to discovered_devices_ or simply devices_
+};
+
+} // namespace convergence
+} // namespace extension
+
+#endif // CONVERGENCE_CONVERGENCE_MANAGER_H__
diff --git a/src/convergence/convergence_payload.cc b/src/convergence/convergence_payload.cc
new file mode 100644 (file)
index 0000000..aaefef3
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+
+// TODO check includes
+#include "convergence/convergence_payload.h"
+
+#include <glib.h>
+#include <d2d_conv_internal.h>
+
+#include "convergence/convergence_instance.h"
+#include "convergence/convergence_utils.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace convergence {
+
+namespace {
+// Payload data keys and some values
+static const std::string kKey = "key";
+static const std::string kValue = "value";
+static const std::string kPayloadDataType = "type"; // String, bytes
+static const std::string kTypeString = "STRING";
+static const std::string kTypeRawBytes = "RAW_BYTES";
+} // namespace
+
+ConvergencePayloadArray::ConvergencePayloadArray()
+  : payload_handle_(nullptr) {
+  ScopeLogger();
+}
+
+ConvergencePayloadArray::ConvergencePayloadArray(const picojson::value &payload_json)
+  : payload_handle_(nullptr) {
+  ScopeLogger();
+  FromJson(payload_json);
+}
+
+ConvergencePayloadArray::~ConvergencePayloadArray() {
+  ScopeLogger();
+
+  if (payload_handle_) {
+    conv_payload_destroy(payload_handle_);
+    payload_handle_ = nullptr;
+  }
+}
+
+conv_payload_h ConvergencePayloadArray::GetHandle() const {
+  ScopeLogger();
+  return payload_handle_;
+}
+
+
+void ConvergencePayloadArray::FromJson(const picojson::value &payload_json) {
+  ScopeLogger();
+  if (payload_json.is<picojson::null>()) {
+    LoggerE("ERROR: trying to convert NULL payload json value");
+    return;
+  }
+
+  if (payload_handle_) {
+    conv_payload_destroy(payload_handle_);
+    payload_handle_ = nullptr;
+  }
+
+  int error = conv_payload_create(&payload_handle_);
+  if ((CONV_ERROR_NONE != error) || !payload_handle_) {
+    trace_conv_error(error, __LINE__, "creating payload handle");
+    return;
+  }
+
+  if (!payload_json.is<picojson::array>()) {
+    LoggerE("ERROR: Payload json is not an array");
+    return;
+  }
+
+  const picojson::array &payload_items = payload_json.get<picojson::array>();
+  for (size_t i = 0; i < payload_items.size(); i++) {
+    picojson::value item = payload_items[i];
+    const std::string type = item.get(kPayloadDataType).to_str();
+    if (kTypeString == type) {
+      const std::string key = item.get(kKey).to_str();
+      const std::string value = item.get(kValue).to_str(); // TODO: check if it is an object
+      int error = conv_payload_set_string(payload_handle_, key.c_str(), value.c_str());
+      if (CONV_ERROR_NONE != error) {
+        trace_conv_error(error, __LINE__, "setting payload string");
+      }
+    } else if (kTypeRawBytes == type) {
+      // TODO
+      LoggerW("IMPLEMENT BYTE PAYLOAD!!!");
+    } else {
+      LoggerE("ERROR! Unknown type of payload [%s]", type.c_str());
+    }
+  }
+}
+
+picojson::value ConvergencePayloadArray::ToJson(conv_payload_h payload_handle) {
+  ScopeLogger();
+
+  picojson::array payloads; // Array of payloads to deliver to JS layer
+
+  do {
+    if (!payload_handle) {
+      LoggerE("ERROR: trying to convert NULL payload handle to json");
+      break;
+    }
+
+    picojson::value parsed_payload;
+    {
+      char *payload_json_str = nullptr;
+      int error = conv_payload_internal_export_to_string(payload_handle, &payload_json_str);
+      if ((CONV_ERROR_NONE != error) || !payload_json_str) {
+        trace_conv_error(error, __LINE__, "converting payload handle to json");
+        break;
+      }
+
+      std::string err;
+      picojson::parse(parsed_payload, payload_json_str,
+        payload_json_str + strlen(payload_json_str), &err);
+      free(payload_json_str);
+      if (!err.empty()) {
+        LoggerE("Error parsing payload json: %s", err.c_str());
+        break;
+      }
+    }
+
+    if (!parsed_payload.is<picojson::object>()) {
+      LoggerE("ERROR: Payload is not an object");
+      break;
+    }
+
+    const picojson::object &payload_items = parsed_payload.get<picojson::object>();
+    for (auto it = std::begin(payload_items); it != std::end(payload_items); ++it) {
+      const std::string item_name = it->first;
+      const picojson::value item_value = it->second;
+
+      picojson::object payload_object;
+      payload_object[kKey] = picojson::value(item_name);
+
+      // Recognizing type of the payload
+      if (item_value.is<picojson::array>()) { // Byte array payload
+        payload_object[kPayloadDataType] = picojson::value(kTypeRawBytes);
+        payload_object[kValue] = item_value;
+      } else { // String payload
+        payload_object[kPayloadDataType] = picojson::value(kTypeString);
+        payload_object[kValue] = item_value;
+      }
+
+      payloads.push_back(picojson::value(payload_object));
+    }
+  } while(false);
+
+  return picojson::value(payloads);
+}
+
+std::string ConvergencePayloadArray::ExtractPayloadString(conv_payload_h payload, const char *key) {
+  ScopeLogger();
+  char *value = nullptr;
+  const int error = conv_payload_get_string(payload, key, &value);
+  if (CONV_ERROR_NONE != error) {
+    trace_conv_error(error, __LINE__, "conv_payload_get_string");
+    return "";
+  }
+
+  if (value) {
+    const std::string result = std::string(value);
+    free(value);
+    return result;
+  }
+  return "";
+}
+} // namespace convergence
+}  // namespace extension
diff --git a/src/convergence/convergence_payload.h b/src/convergence/convergence_payload.h
new file mode 100644 (file)
index 0000000..fc439c7
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+
+#ifndef CONVERGENCE_CONVERGENCE_PAYLOAD_H__
+#define CONVERGENCE_CONVERGENCE_PAYLOAD_H__
+
+// TODO check includes
+#include <d2d_conv_manager.h>
+
+#include <string>
+#include <unordered_map>
+
+#include "common/tizen_result.h"
+
+namespace extension {
+namespace convergence {
+
+
+/*enum ConvergencePayloadType {
+  kUnknownPayload = -1,
+  kStringPayload,
+  kRawBytesPayload
+};*/
+
+
+// TODO rename to simply Payload
+class ConvergencePayloadArray {
+ public:
+  ConvergencePayloadArray();
+  ConvergencePayloadArray(const picojson::value &payload_json);
+  virtual ~ConvergencePayloadArray();
+  ConvergencePayloadArray(const ConvergencePayloadArray&) = delete;
+  ConvergencePayloadArray(ConvergencePayloadArray&&) = delete;
+  ConvergencePayloadArray& operator=(const ConvergencePayloadArray&) = delete;
+  ConvergencePayloadArray& operator=(ConvergencePayloadArray&&) = delete;
+
+ public:
+  conv_payload_h GetHandle() const;
+  void FromJson(const picojson::value &payload_json);
+
+ public:
+  static picojson::value ToJson(conv_payload_h payload_handle);
+  static std::string ExtractPayloadString(conv_payload_h payload, const char *key);
+
+ private:
+  conv_payload_h payload_handle_;
+};
+
+/*
+class ConvergencePayload {
+ public:
+  ConvergencePayload();
+  virtual ~ConvergencePayload();
+  ConvergencePayload(const ConvergencePayload&) = delete;
+  ConvergencePayload(ConvergencePayload&&) = delete;
+  ConvergencePayload& operator=(const ConvergencePayload&) = delete;
+  ConvergencePayload& operator=(ConvergencePayload&&) = delete;
+
+ public:
+  void FromJson(const picojson::value &payload_json);
+
+ protected:
+  std::string id_;
+  ConvergencePayloadType type_;
+};
+
+class ConvergencePayloadString : public ConvergencePayload {
+ public:
+  ConvergencePayloadString();
+  virtual ~ConvergencePayloadString();
+  ConvergencePayloadString(const ConvergencePayloadString&) = delete;
+  ConvergencePayloadString(ConvergencePayloadString&&) = delete;
+  ConvergencePayloadString& operator=(const ConvergencePayloadString&) = delete;
+  ConvergencePayloadString& operator=(ConvergencePayloadString&&) = delete;
+
+ public:
+  void FromJson(const picojson::value &payload_json);
+
+ private:
+  std::string string_value_;
+};
+
+class ConvergencePayloadRawBytes : public ConvergencePayload {
+ public:
+  ConvergencePayloadRawBytes();
+  virtual ~ConvergencePayloadRawBytes();
+  ConvergencePayloadRawBytes(const ConvergencePayloadRawBytes&) = delete;
+  ConvergencePayloadRawBytes(ConvergencePayloadRawBytes&&) = delete;
+  ConvergencePayloadRawBytes& operator=(const ConvergencePayloadRawBytes&) = delete;
+  ConvergencePayloadRawBytes& operator=(ConvergencePayloadRawBytes&&) = delete;
+
+ public:
+  void FromJson(const picojson::value &payload_json);
+
+ private:
+  std::vector<unsigned char> raw_bytes_value_;
+};
+*/
+
+} // namespace convergence
+} // namespace extension
+
+#endif // CONVERGENCE_CONVERGENCE_PAYLOAD_H__
diff --git a/src/convergence/convergence_remote_app_control_service.cc b/src/convergence/convergence_remote_app_control_service.cc
new file mode 100644 (file)
index 0000000..de3380b
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+
+// TODO check includes
+#include "convergence/convergence_remote_app_control_service.h"
+
+#include <glib.h>
+#include <d2d_conv_internal.h>
+
+#include "convergence/convergence_instance.h"
+#include "convergence/convergence_payload.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace convergence {
+
+using common::TizenResult;
+using common::TizenSuccess;
+
+namespace {
+// Payload data keys and some values
+static const std::string kPayload = "payload"; // ---
+
+// Service connection status keys
+static const std::string kServiceConnectionStatus = "connect_status"; // ---
+static const std::string kServiceConnectionStatusConnected = "service_connected";
+static const std::string kServiceConnectionStatusNotConnected = "service_not_connected";
+
+// Service listener status keys
+static const std::string kServiceListenerStatus = "listener_status"; //---
+static const std::string kServiceListenerStatusOk = "listener_ok"; // ---
+static const std::string kServiceListenerStatusError = "listener_error"; //---
+static const std::string kServiceListenerError = "listener_error"; //---
+} // namespace
+
+ConvergenceRemoteAppControlService::ConvergenceRemoteAppControlService()
+ : ConvergenceService()
+ , started_(false) {
+  ScopeLogger();
+}
+
+ConvergenceRemoteAppControlService::ConvergenceRemoteAppControlService(conv_device_h device, ConvergenceInstance *convergence_plugin)
+ : ConvergenceService(device, CONV_SERVICE_REMOTE_APP_CONTROL, convergence_plugin)
+ , started_(false) {
+  ScopeLogger();
+}
+
+ConvergenceRemoteAppControlService::~ConvergenceRemoteAppControlService() {
+  ScopeLogger();
+
+  // Release all memory, used by callback paramerers
+  for (size_t i = 0; i < callback_param_gc_.size(); i++) {
+    delete callback_param_gc_[i];
+  }
+  callback_param_gc_.clear();
+}
+
+void ConvergenceRemoteAppControlService::ServiceConnectedCb(conv_service_h service_handle,
+  conv_error_e error, conv_payload_h result, void* user_data) {
+  ScopeLogger();
+
+  CallbackParam *callbackParam = static_cast<CallbackParam *>(user_data);
+  if (!callbackParam) {
+    LoggerE("ERROR! NULL user data in Service Connect Callback");
+    return;
+  }
+
+  picojson::object param;
+  param["result_type"] = picojson::value("Connected");
+  //param[kPayload] = ConvergenceRemoteAppControlService::PayloadToJson(result);
+
+  if (CONV_ERROR_NONE == error) {
+    param[kServiceConnectionStatus] = picojson::value(kServiceConnectionStatusConnected);
+    callbackParam->plugin_->ReplyAsync(kRemoteAppControlListenerCallback,
+      callbackParam->callback_id_,
+      true,
+      param);
+  } else {
+    // Error occured during connection
+    param[kServiceConnectionStatus] = picojson::value(kServiceConnectionStatusNotConnected);
+    callbackParam->plugin_->ReplyAsync(kRemoteAppControlListenerCallback,
+      callbackParam->callback_id_,
+      false,
+      param);
+  }
+}
+
+common::TizenResult ConvergenceRemoteAppControlService::Connect(const int cur_listener_id) {
+  ScopeLogger();
+
+  conv_service_h service = FindServiceHandle();
+  if (!service) {
+    return LogAndCreateTizenError(NotFoundError,
+      "Service with specified type does not exist");
+  }
+
+  // TODO: make a garbage collection and release this memory when service is disconnected
+  // and when whole manager is destructed
+  CallbackParam *param = new CallbackParam(convergence_plugin_, cur_listener_id);
+  callback_param_gc_.push_back(param);
+
+  const int error = conv_service_connect(service, ServiceConnectedCb, param);
+  if (CONV_ERROR_NONE != error) {
+    // TODO: Handle error
+    trace_conv_error(error, __LINE__, "conv_service_connect");
+  }
+
+  return TizenSuccess();
+}
+
+common::TizenResult ConvergenceRemoteAppControlService::Disconnect() {
+  ScopeLogger();
+
+  conv_service_h service = FindServiceHandle();
+  if (!service)
+    return LogAndCreateTizenError(NotFoundError,
+      "Service with specified type does not exist");
+
+  const int error = conv_service_disconnect(service);
+  if (CONV_ERROR_NONE != error) {
+    // TODO: Handle error
+    trace_conv_error(error, __LINE__, "conv_service_disconnect");
+  }
+
+  return TizenSuccess();
+}
+
+void ConvergenceRemoteAppControlService::ServiceListenerCb(conv_service_h service_handle,
+  conv_channel_h channel_handle,
+  conv_error_e error, conv_payload_h result, void* user_data) {
+  ScopeLogger();
+
+  CallbackParam *callbackParam = static_cast<CallbackParam *>(user_data);
+  if (!callbackParam) {
+    LoggerE("ERROR! NULL user data in Service Listener Callback");
+    return;
+  }
+
+  picojson::object param;
+  param["payload"] = picojson::value("TODO");
+
+  // TODO parse the payload and fill the param
+
+  const std::string result_type = ConvergencePayloadArray::ExtractPayloadString(result, "result_type"); // TODO extract to constant kResultType = "result_type";
+  param["result_type"] = picojson::value(result_type);
+
+
+  if (CONV_ERROR_NONE == error) {
+    param[kServiceListenerStatus] = picojson::value(kServiceListenerStatusOk);
+    callbackParam->plugin_->ReplyAsync(kRemoteAppControlListenerCallback,
+      callbackParam->callback_id_,
+      true,
+      param);
+  } else {
+    // Error occured during connection
+    param[kServiceListenerStatus] = picojson::value(kServiceListenerStatusError);
+    param[kServiceListenerError] = picojson::value(static_cast<double>(error));
+    callbackParam->plugin_->ReplyAsync(kRemoteAppControlListenerCallback,
+      callbackParam->callback_id_,
+      false,
+      param);
+  }
+}
+
+void ConvergenceRemoteAppControlService::UpdateListener(const int cur_listener_id) {
+  ScopeLogger();
+  // TODO: make a garbage collection and release this memory when callback unset
+  // and when whole manager is destructed
+  CallbackParam *param = new CallbackParam(convergence_plugin_, cur_listener_id);
+  callback_param_gc_.push_back(param);
+
+  conv_service_h service_handle = FindServiceHandle();
+  if (!service_handle) {
+    LoggerE("AAAAAA!!! Service not found");
+    return;
+  }
+  const int error = conv_service_set_listener_cb(service_handle, ServiceListenerCb, param);
+  if (CONV_ERROR_NONE != error) {
+    // TODO: Handle error
+    trace_conv_error(error, __LINE__, "conv_service_set_listener_cb");
+  } else {
+    LoggerI("Listener is set correctly");
+  }
+}
+
+void ConvergenceRemoteAppControlService::EnsureStarted() {
+  ScopeLogger();
+  if (started_)
+    return;
+
+  conv_service_h service_handle = FindServiceHandle();
+  if (!service_handle) {
+    LoggerE("AAAAAA!!! Service not found");
+    return; // TODO handle error
+  }
+
+  const int error = conv_service_start(service_handle, nullptr, nullptr);
+  if (CONV_ERROR_NONE != error) {
+    // TODO: Handle error
+    trace_conv_error(error, __LINE__, "conv_service_publish START");
+  } else {
+    LoggerI("APP CONTROL SERVICE IS STARTED");
+    started_ = true;
+  }
+}
+
+common::TizenResult ConvergenceRemoteAppControlService::Launch(const char *appId, bool reply, const int cur_listener_id) {
+  ScopeLogger();
+
+  conv_service_h service_handle = FindServiceHandle();
+  if (!service_handle) {
+    LoggerE("AAAAAA!!! Service not found");
+    return LogAndCreateTizenError(NotFoundError,
+     "Service with specified type does not exist");
+  }
+
+  // Create app control payload with passed appId
+  conv_payload_h payload = CreateAppIdPayload(appId, reply);
+  if (!payload) {
+    // Handle error
+    return TizenSuccess(); // TODO TizenError
+  }
+
+  // Update listener: assign it if it is not yet assigned
+  if (reply)
+    UpdateListener(cur_listener_id);
+
+  // Ensure the service was started
+  EnsureStarted();
+
+  // Sending app control on the remote device
+  const int error = conv_service_publish(service_handle, nullptr, payload);
+  if (CONV_ERROR_NONE != error) {
+    // TODO: Handle error
+    trace_conv_error(error, __LINE__, "conv_service_publish LAUNCH");
+  } else {
+    LoggerI("---- SEEMS APP CONTROL WAS LAUNCHED ----");
+  }
+
+/*
+       conv_service_start(service_handle, NULL, NULL);
+       conv_payload_h payload_handle;
+       conv_payload_create(&payload_handle);
+       app_control_h app_control = NULL;
+       app_control_create(&app_control);
+       app_control_set_app_id(app_control, "org.example.d2d_test");
+       app_control_set_operation(app_control, APP_CONTROL_OPERATION_MAIN);
+       conv_payload_set_app_control(payload_handle, "app_control", app_control);
+       conv_payload_set_string(payload_handle, "reply", "0");
+       conv_service_publish(service_handle, NULL, payload_handle);
+*/
+
+  conv_payload_destroy(payload);
+  return TizenSuccess();
+}
+
+conv_payload_h ConvergenceRemoteAppControlService::CreateAppIdPayload(const char *appId, bool reply) const {
+  ScopeLogger();
+
+  conv_payload_h payload = nullptr;
+  int error = conv_payload_create(&payload);
+  if (CONV_ERROR_NONE != error) {
+    // Handle error
+  }
+
+  app_control_h app_control = nullptr;
+  error = app_control_create(&app_control);
+  if (APP_CONTROL_ERROR_NONE != error) {
+    LoggerE("ERROR! AppControl API error [%d]", error);
+  }
+
+  error = app_control_set_app_id(app_control, appId);
+  if (APP_CONTROL_ERROR_NONE != error) {
+    LoggerE("ERROR! AppControl API error [%d]", error);
+  }
+
+  error = app_control_set_operation(app_control, APP_CONTROL_OPERATION_MAIN);
+  if (CONV_ERROR_NONE != error) {
+    // Handle error
+  }
+
+  error = conv_payload_set_app_control(payload, "app_control", app_control);
+  if (APP_CONTROL_ERROR_NONE != error) {
+    // Handle error
+  }
+
+  if (reply) {
+    error = conv_payload_set_string(payload, "reply", "1");
+    if (CONV_ERROR_NONE != error) {
+      // Handle error
+    }
+  }
+
+  return payload;
+}
+
+picojson::value ConvergenceRemoteAppControlService::PayloadToJson(conv_payload_h payload) {
+  ScopeLogger();
+  picojson::value payload_json;
+
+  // TODO convert payload to array of ApplicationControlData
+
+  return payload_json;
+}
+
+} // namespace convergence
+}  // namespace extension
diff --git a/src/convergence/convergence_remote_app_control_service.h b/src/convergence/convergence_remote_app_control_service.h
new file mode 100644 (file)
index 0000000..2f416ae
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+
+#ifndef CONVERGENCE_CONVERGENCE_REMOTE_APP_CONTROL_SERVICE_H__
+#define CONVERGENCE_CONVERGENCE_REMOTE_APP_CONTROL_SERVICE_H__
+
+// TODO check includes
+#include <d2d_conv_manager.h>
+
+#include <string>
+#include <unordered_map>
+
+#include "convergence/convergence_service.h"
+#include "convergence/convergence_utils.h"
+#include "common/tizen_result.h"
+
+namespace extension {
+namespace convergence {
+
+class ConvergenceRemoteAppControlService : public ConvergenceService {
+
+ public:
+  ConvergenceRemoteAppControlService();
+  ConvergenceRemoteAppControlService(conv_device_h device, ConvergenceInstance *convergence_plugin);
+  virtual ~ConvergenceRemoteAppControlService();
+  ConvergenceRemoteAppControlService(const ConvergenceRemoteAppControlService&) = delete;
+  ConvergenceRemoteAppControlService(ConvergenceRemoteAppControlService&&) = delete;
+  ConvergenceRemoteAppControlService& operator=(const ConvergenceRemoteAppControlService&) = delete;
+  ConvergenceRemoteAppControlService& operator=(ConvergenceRemoteAppControlService&&) = delete;
+ public:
+  common::TizenResult Connect(const int cur_listener_id);
+  common::TizenResult Disconnect();
+  common::TizenResult Launch(const char *appId, bool reply, const int cur_listener_id);
+ private:
+  conv_payload_h CreateAppIdPayload(const char *appId, bool reply) const;
+  static picojson::value PayloadToJson(conv_payload_h payload);
+  void UpdateListener(const int cur_listener_id);
+  void EnsureStarted();
+  static void ServiceConnectedCb(conv_service_h service_handle,
+   conv_error_e error, conv_payload_h result, void* user_data);
+  static void ServiceListenerCb(conv_service_h service_handle,
+   conv_channel_h channel_handle,
+   conv_error_e error, conv_payload_h result, void* user_data);
+
+ private:
+  std::vector<CallbackParam *> callback_param_gc_;
+  bool started_;
+};
+
+} // namespace convergence
+} // namespace extension
+
+#endif // CONVERGENCE_CONVERGENCE_REMOTE_APP_CONTROL_SERVICE_H__
diff --git a/src/convergence/convergence_service.cc b/src/convergence/convergence_service.cc
new file mode 100644 (file)
index 0000000..035b51f
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+
+// TODO check includes
+#include "convergence/convergence_service.h"
+
+#include <glib.h>
+#include <d2d_conv_internal.h>
+
+#include "convergence/convergence_instance.h"
+#include "convergence/convergence_utils.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace convergence {
+
+namespace {
+// Service keys
+static const std::string kServiceType = "serviceType";
+static const std::string kServiceConnectionState = "connectionState";
+static const std::string kId = "id";
+static const std::string kVersion = "version";
+} // namespace
+
+ConvergenceService::ConvergenceService()
+ : convergence_plugin_(nullptr)
+ , device_(nullptr)
+ , type_(CONV_SERVICE_NONE)
+ , service_handle_(nullptr) {
+  ScopeLogger();
+}
+
+ConvergenceService::ConvergenceService(conv_device_h device, conv_service_e type, ConvergenceInstance *convergence_plugin)
+ : convergence_plugin_(convergence_plugin)
+ , device_(device)
+ , type_(type)
+ , service_handle_(nullptr) {
+  ScopeLogger();
+}
+
+ConvergenceService::~ConvergenceService() {
+  ScopeLogger();
+  LoggerI("DESTROYING SERVICE HANDLE [0x0%x] in ConvergenceService destr", service_handle_);
+  conv_service_destroy(service_handle_);
+}
+
+struct ServiceSearchQuery {
+  conv_service_h handle;
+  conv_service_e type;
+};
+
+void ConvergenceService::ForEachServiceCb(conv_service_h service_handle, void* user_data) {
+  ScopeLogger();
+  ServiceSearchQuery *query = static_cast<ServiceSearchQuery *>(user_data);
+  if (!query)
+    return;
+  if (query->handle)
+    return; // Already found a required service handle (no need to analyze something else)
+
+  conv_service_e type = CONV_SERVICE_NONE;
+  int error = conv_service_get_type(service_handle, &type);
+  if (error != CONV_ERROR_NONE) {
+    // TODO Handle error
+  }
+
+  if (type != query->type) {
+    return;
+  }
+  conv_service_h clone = nullptr;
+  error = conv_service_clone(service_handle, &clone);
+  if (error != CONV_ERROR_NONE) {
+    // TODO Handle error
+  }
+  query->handle = clone;
+}
+
+conv_service_h ConvergenceService::FindServiceHandle() const {
+  ScopeLogger();
+  if (!service_handle_) {
+
+    if (!device_) {
+      LoggerE("ERROR: Device handle is NULL, can not get device services");
+      return nullptr;
+    }
+
+    ServiceSearchQuery query = {nullptr, type_};
+    const int error = conv_device_foreach_service(device_, ForEachServiceCb, &query);
+    if (CONV_ERROR_NONE != error) {
+      // TODO Handle error
+      trace_conv_error(error, __LINE__, "conv_device_foreach_service");
+    }
+    service_handle_ = query.handle;
+  }
+  return service_handle_;
+}
+
+std::string ConvergenceService::ExtractServicePropery(conv_service_h service_handle,
+  const char *property) {
+  ScopeLogger();
+  char *value = nullptr;
+  const int error = conv_service_get_property_string(service_handle, property, &value);
+  if (CONV_ERROR_NONE != error) {
+    trace_conv_error(error, __LINE__, "conv_service_get_property_string");
+    return "";
+  }
+
+  if (value) {
+    const std::string result = std::string(value);
+    free(value);
+    return result;
+  }
+  return "";
+}
+
+void ConvergenceService::Refresh() {
+  ScopeLogger();
+  conv_service_h service_handle = FindServiceHandle();
+  if (!service_handle) {
+    LoggerE("AAAAAA!!! Service not found");
+    return;
+  }
+
+  conv_service_connection_state_e state = CONV_SERVICE_CONNECTION_STATE_NONE;
+  const int error = conv_service_get_connection_state(service_handle, &state);
+  if (CONV_ERROR_NONE != error) {
+    LoggerE("ERROR! D2D API Get Service Connection State error [%d]", error);
+    trace_conv_error(error, __LINE__, "conv_service_get_connection_state");
+  } else {
+    connection_state_ = state;
+  }
+
+  id_ = ExtractServicePropery(service_handle, CONV_SERVICE_ID);
+  version_ = ExtractServicePropery(service_handle, CONV_SERVICE_VERSION);
+
+  LoggerE("Refreshed service id [%s] version [%s] connection state [%d]",
+    id_.c_str(), version_.c_str(), connection_state_);
+
+  //conv_service_destroy(service_handle);
+  //LoggerI("DESTROYING SERVICE HANDLE [0x0%x] in ConvergenceService Refresh", service_handle_);
+}
+
+picojson::value ConvergenceService::ToJson() const {
+  ScopeLogger();
+  picojson::object service_json;
+
+  service_json[kServiceType] = picojson::value(static_cast<double>(type_));
+  service_json[kServiceConnectionState] = picojson::value(static_cast<double>(connection_state_));
+
+  // Following fields are not used in Web API layer now, but I parse it for
+  // future extensions
+  service_json[kId] = picojson::value(id_);
+  service_json[kVersion] = picojson::value(version_);
+
+  return picojson::value(service_json);
+}
+
+} // namespace convergence
+}  // namespace extension
diff --git a/src/convergence/convergence_service.h b/src/convergence/convergence_service.h
new file mode 100644 (file)
index 0000000..55fe741
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+
+#ifndef CONVERGENCE_CONVERGENCE_SERVICE_H__
+#define CONVERGENCE_CONVERGENCE_SERVICE_H__
+
+// TODO check includes
+#include <d2d_conv_manager.h>
+
+#include <string>
+#include <unordered_map>
+
+#include "common/tizen_result.h"
+
+namespace extension {
+namespace convergence {
+
+class ConvergenceInstance;
+
+class ConvergenceService {
+
+ public:
+  ConvergenceService();
+  ConvergenceService(conv_device_h device, conv_service_e type, ConvergenceInstance *convergence_plugin);
+  virtual ~ConvergenceService();
+  ConvergenceService(const ConvergenceService&) = delete;
+  ConvergenceService(ConvergenceService&&) = delete;
+  ConvergenceService& operator=(const ConvergenceService&) = delete;
+  ConvergenceService& operator=(ConvergenceService&&) = delete;
+
+ public:
+  void Refresh();
+
+ public:
+  //conv_service_e get_type() const { return type_; }
+  //conv_device_h get_device() const {return device_; }
+  picojson::value ToJson() const;
+
+ protected:
+  conv_service_h FindServiceHandle() const;
+  static void ForEachServiceCb(conv_service_h service_handle, void* user_data);
+  std::string ExtractServicePropery(conv_service_h service_handle,
+   const char *property);
+
+ protected:
+  ConvergenceInstance *convergence_plugin_;
+
+ //private:
+ protected: // TODO switch back to private:
+  conv_device_h device_; // TODO rename to device_handle_
+  conv_service_e type_;
+  mutable conv_service_h service_handle_;
+  friend class ConvergenceAppCommunicationServerService; // It is needed to register the local service
+ private:
+  conv_service_connection_state_e connection_state_;
+  std::string id_;
+  std::string version_;
+};
+
+} // namespace convergence
+} // namespace extension
+
+#endif // CONVERGENCE_CONVERGENCE_SERVICE_H__
diff --git a/src/convergence/convergence_utils.cc b/src/convergence/convergence_utils.cc
new file mode 100644 (file)
index 0000000..86e81c0
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    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.
+ */
+
+// TODO check includes
+#include "convergence/convergence_service.h"
+
+#include <glib.h>
+#include <d2d_conv_internal.h>
+
+#include "convergence/convergence_instance.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace convergence {
+
+
+
+
+void trace_conv_error(const int error, int line_number, const char *extra_text) {
+  std::string error_text;
+  switch (error) {
+  case CONV_ERROR_NONE:
+    error_text = "CONV_ERROR_NONE";
+    break;
+  case CONV_ERROR_INVALID_PARAMETER:
+    error_text = "CONV_ERROR_INVALID_PARAMETER";
+    break;
+  case CONV_ERROR_INVALID_OPERATION:
+    error_text = "CONV_ERROR_INVALID_OPERATION";
+    break;
+  case CONV_ERROR_OUT_OF_MEMORY:
+    error_text = "CONV_ERROR_OUT_OF_MEMORY";
+    break;
+  case CONV_ERROR_PERMISSION_DENIED:
+    error_text = "CONV_ERROR_PERMISSION_DENIED";
+    break;
+  case CONV_ERROR_NOT_SUPPORTED:
+    error_text = "CONV_ERROR_NOT_SUPPORTED";
+    break;
+  case CONV_ERROR_NO_DATA:
+    error_text = "CONV_ERROR_NO_DATA";
+    break;
+  default:
+    error_text = "UNSUPPORTED D2D ERROR CODE";
+    break;
+  }
+
+  if (extra_text) {
+    LoggerE("ERROR! D2D API error [%s], line %d: %s", error_text.c_str(), line_number, extra_text);
+  } else {
+    LoggerE("ERROR! D2D API error [%s], line %d", error_text.c_str(), line_number);
+  }
+}
+
+
+
+} // namespace convergence
+}  // namespace extension
similarity index 53%
rename from src/secureelement/secureelement_channel.h
rename to src/convergence/convergence_utils.h
index 4d62643..1afde74 100644 (file)
  *    limitations under the License.
  */
 
-#ifndef SECUREELEMENT_CHANNEL_H_
-#define SECUREELEMENT_CHANNEL_H_
+#ifndef CONVERGENCE_CONVERGENCE_UTILS_H__
+#define CONVERGENCE_CONVERGENCE_UTILS_H__
 
-#include <ClientChannel.h>
-#include "common/picojson.h"
+// TODO check includes
+#include <d2d_conv_manager.h>
+
+#include <string>
+#include <unordered_map>
+
+#include "common/tizen_result.h"
 
 namespace extension {
-namespace secureelement {
-
-class SEChannel {
-public:
-    SEChannel( smartcard_service_api::ClientChannel* channel_ptr) : m_channel_ptr(channel_ptr) {};
-    virtual ~SEChannel() {};
-    void close();
-    smartcard_service_api::ByteArray transmit(const picojson::array& v_command);
-    smartcard_service_api::ByteArray getSelectResponse();
-private:
-    smartcard_service_api::ClientChannel* m_channel_ptr;
+namespace convergence {
+
+class ConvergenceInstance;
+
+struct CallbackParam {
+ CallbackParam(ConvergenceInstance *plg,  int cbId)
+   : plugin_(plg), callback_id_(cbId) {}
+ ConvergenceInstance *plugin_;
+ int callback_id_;
 };
 
-} // secureelement
-} // extension
 
-#endif // SECUREELEMENT_CHANNEL_H_
+void trace_conv_error(const int error, int line_number, const char *extra_text);
+
+} // namespace convergence
+} // namespace extension
+
+#endif // CONVERGENCE_CONVERGENCE_UTILS_H__
index 55e19bb..10f5a54 100644 (file)
@@ -19,6 +19,7 @@ var validator = xwalk.utils.validator;
 var types = validator.Types;
 var T = xwalk.utils.type;
 var kIdKey = Symbol();
+var converter = xwalk.converter;
 
 function createListener(name, c) {
   var listenerName = name;
@@ -131,6 +132,7 @@ var ResponseResult = {
   ERROR: 'ERROR',
   RESOURCE_CREATED: 'RESOURCE_CREATED',
   RESOURCE_DELETED: 'RESOURCE_DELETED',
+  RESOURCE_CHANGED: 'RESOURCE_CHANGED',
   SLOW: 'SLOW',
   FORBIDDEN: 'FORBIDDEN',
 };
@@ -171,6 +173,20 @@ var QosLevel = {
   HIGH: 'HIGH'
 };
 
+var RequestType = {
+  UNKNOWN: 'UNKNOWN',
+  GET: 'GET',
+  PUT: 'PUT',
+  POST: 'POST',
+  DELETE: 'DELETE'
+};
+
+var ObserveType = {
+  NO_TYPE: 'NO_TYPE',
+  REGISTER: 'REGISTER',
+  DEREGISTER: 'DEREGISTER'
+};
+
 function DeviceInfo(data) {
   decorateWithData(data, this);
 }
@@ -237,12 +253,12 @@ function Representation(uriPath) {
       writable: true,
       enumerable: true
     },
-    states: {
+    attributes: {
       value: null,
       writable: true,
       enumerable: true
     },
-    representations: {
+    children: {
       value: null,
       writable: true,
       enumerable: true
@@ -252,7 +268,7 @@ function Representation(uriPath) {
 
 function createRepresentation(data) {
   var r = new tizen.Representation(data.uriPath);
-  var props = ['resourceTypes', 'resourceInterfaces', 'states'];
+  var props = ['resourceTypes', 'resourceInterfaces', 'attributes'];
 
   for (var p = 0; p < props.length; ++p) {
     if (data[props[p]]) {
@@ -260,10 +276,10 @@ function createRepresentation(data) {
     }
   }
 
-  if (data.representations) {
-    r.representations = [];
-    for (var i = 0; i < data.representations.length; ++i) {
-      r.representations.push(createRepresentation(data.representations[i]));
+  if (data.children) {
+    r.children = [];
+    for (var i = 0; i < data.children.length; ++i) {
+      r.children.push(createRepresentation(data.children[i]));
     }
   }
 
@@ -313,7 +329,7 @@ function Resource(data) {
   var internal = new InternalData(data);
   internal.decorate(this);
 
-  this.states = null;
+  this.attributes = null;
 }
 
 Resource.prototype.notify = function() {
@@ -329,20 +345,20 @@ Resource.prototype.notify = function() {
     nullable: true
   }]);
 
-  var states = {};
-  function getStates(r) {
-    states[r[kIdKey]] = r.states;
+  var attributes = {};
+  function getAttributes(r) {
+    attributes[r[kIdKey]] = r.attributes;
     for (var i = 0; i < r.resources.length; ++i) {
-      getStates(r.resources[i]);
+      getAttributes(r.resources[i]);
     }
   }
-  getStates(this);
+  getAttributes(this);
 
   var callArgs = {};
   callArgs.id = this[kIdKey];
   callArgs.qos = args.qos;
   callArgs.observerIds = args.observerIds;
-  callArgs.states = states;
+  callArgs.attributes = attributes;
 
   var result = native.callSync('IotconResource_notify', callArgs);
 
@@ -441,21 +457,37 @@ Resource.prototype.removeChildResource = function() {
   }
 };
 
-var resourceRequestListener = createListener('ResourceRequestListener', function(response) {
-  return new Request(response.data);
-});
-
-Resource.prototype.setRequestListener = function() {
-  var args = validator.validateMethod(arguments, [{
-    name: 'successCallback',
-    type: types.FUNCTION
-  }]);
+var resourceRequestListener = createListener('ResourceRequestListener');
 
+var _setRequestListener = function(id, listener) {
   var callArgs = {};
-  callArgs.id = this[kIdKey];
+  callArgs.id = id;
 
   var listener = function(result) {
-    args.successCallback(result);
+    var request = new Request(result.data.request);
+    switch (converter.toString(result.data.type, false)) {
+      case RequestType.GET:
+        native.callIfPossible(listener.onget, request);
+        break;
+
+      case RequestType.PUT:
+        native.callIfPossible(listener.onput, request);
+        break;
+
+      case RequestType.POST:
+        native.callIfPossible(listener.onpost, request);
+        break;
+
+      case RequestType.DELETE:
+        native.callIfPossible(listener.ondelete, request);
+        break;
+    }
+
+    var observeType = converter.toString(result.data.observeType, false);
+    var observerId = converter.toUnsignedLong(result.data.observerId, false);
+    if (observeType !== ObserveType.NO_TYPE && observerId) {
+      native.callIfPossible(listener.onobserving(request, observeType, observerId));
+    }
   };
 
   var result = native.callSync('IotconResource_setRequestListener', callArgs);
@@ -463,10 +495,20 @@ Resource.prototype.setRequestListener = function() {
   if (native.isFailure(result)) {
     throw native.getErrorObject(result);
   } else {
-    resourceRequestListener.addListener(this[kIdKey], listener);
+    resourceRequestListener.addListener(id, listener);
   }
 };
 
+Resource.prototype.setRequestListener = function() {
+  var args = validator.validateMethod(arguments, [{
+    name: 'listener',
+    type: types.LISTENER,
+    values: ['onget', 'onput', 'onpost', 'ondelete', 'onobserving']
+  }]);
+
+  _setRequestListener(this[kIdKey], args.listener);
+};
+
 Resource.prototype.unsetRequestListener = function() {
   var callArgs = {};
   callArgs.id = this[kIdKey];
@@ -480,7 +522,6 @@ Resource.prototype.unsetRequestListener = function() {
   }
 };
 
-
 function Response(request) {
   validator.isConstructorCall(this, tizen.Response);
 
@@ -509,17 +550,11 @@ function Response(request) {
 }
 
 Response.prototype.send = function() {
-  var args = validator.validateMethod(arguments, [{
-    name: 'iface',
-    type: types.STRING
-  }]);
-
   var callArgs = {};
   callArgs.id = this.request[kIdKey];
   callArgs.result = this.result;
   callArgs.representation = this.representation;
   callArgs.options = this.options;
-  callArgs.iface = args.iface;
 
   var result = native.callSync('IotconResponse_send', callArgs);
 
@@ -563,7 +598,7 @@ function State(key, state) {
   });
 }
 
-function prepareResourceInfo(that){
+function prepareResourceInfo(that, notIncludeOptions){
   var callArgs = {};
   callArgs.id = that[kIdKey];
   if (!callArgs.id) {
@@ -580,6 +615,9 @@ function prepareResourceInfo(that){
     callArgs.isExplicitDiscoverable = that.isExplicitDiscoverable;
     callArgs.resourceTypes = that.resourceTypes;
     callArgs.resourceInterfaces = that.resourceInterfaces;
+    if (!notIncludeOptions) {
+      callArgs.options = that.options;
+    }
   } else {
     console.log("Already stored in C++, all needed info is id");
   }
@@ -602,8 +640,7 @@ function RemoteResource(data) {
   Object.defineProperties(this, {
     cachedRepresentation: {
       get: function() {
-        var callArgs = {};
-        callArgs.id = this[kIdKey];
+        var callArgs = prepareResourceInfo(this);
         var result = native.callSync('IotconRemoteResource_getCachedRepresentation', callArgs);
         if (native.isSuccess(result)) {
           return createRepresentation(native.getResultObject(result));
@@ -615,8 +652,67 @@ function RemoteResource(data) {
       enumerable: true
     },
     options: {
-      value: null,
-      writable: true,
+      get: function() {
+        var options_ = null;
+        var callArgs = prepareResourceInfo(this, true);
+        var result = native.callSync('IotconRemoteResource_getOptions', callArgs);
+        if (native.isSuccess(result)) {
+          var data = native.getResultObject(result);
+          options_ = [];
+          for (var i = 0; i < data.length; ++i) {
+            options_.push(new IotconOption(data[i].id, data[i].data));
+          }
+        }
+        return options_;
+      }.bind(this),
+      set: function(val) {
+        // array or null are only acceptable values
+        if (!T.isArray(val) && null != val) {
+          return;
+        }
+        // check types of array values
+        if (T.isArray(val)) {
+          for (var i = 0; i < val.length; ++i) {
+            if (!(val[i] instanceof tizen.IotconOption)) {
+              return;
+            }
+          }
+        }
+
+        var callArgs = prepareResourceInfo(this, true);
+        callArgs['options'] = val;
+
+        var result = native.callSync('IotconRemoteResource_setOptions', callArgs);
+        if (native.isSuccess(result)) {
+          manageId(this, native.getResultObject(result));
+        }
+      }.bind(this),
+      enumerable: true
+    },
+    timeInterval: {
+      get: function() {
+        /* TODO Uncomment when the interface of the function iotcon_remote_resource_get_time_interval is changed
+        var callArgs = prepareResourceInfo(this, true);
+        */
+        var callArgs = {};
+
+        var result = native.callSync('IotconRemoteResource_getTimeInterval', callArgs);
+        if (native.isSuccess(result)) {
+          return native.getResultObject(result);
+        }
+        return null;
+      }.bind(this),
+      set: function(val) {
+        /* TODO Uncomment when the interface of the function iotcon_remote_resource_set_time_interval is changed
+        var callArgs = prepareResourceInfo(this, true);
+        callArgs[timeInterval] = converter.toLong(val);
+        */
+        var callArgs = {
+          timeInterval: converter.toLong(val)
+        };
+
+        native.callSync('IotconRemoteResource_setTimeInterval', callArgs);
+      }.bind(this),
       enumerable: true
     }
   });
@@ -631,12 +727,14 @@ function RemoteResource(data) {
 
 RemoteResource.prototype.methodGet = function() {
   var args = validator.validateMethod(arguments, [{
-    name: 'query',
-    type: types.DICTIONARY
-  }, {
     name: 'responseCallback',
     type: types.FUNCTION
   }, {
+    name: 'query',
+    type: types.DICTIONARY,
+    optional: true,
+    nullable: true
+  }, {
     name: 'errorCallback',
     type: types.FUNCTION,
     optional: true,
@@ -644,7 +742,9 @@ RemoteResource.prototype.methodGet = function() {
   }]);
 
   var callArgs = prepareResourceInfo(this);
-  callArgs.query = args.query;
+  if (args.query) {
+    callArgs.query = args.query;
+  }
 
   var callback = function(result) {
     result = native.getResultObject(result);
@@ -671,12 +771,14 @@ RemoteResource.prototype.methodPut = function() {
     type: types.PLATFORM_OBJECT,
     values: Representation
   }, {
-    name: 'query',
-    type: types.DICTIONARY
-  }, {
     name: 'responseCallback',
     type: types.FUNCTION
   }, {
+    name: 'query',
+    type: types.DICTIONARY,
+    optional: true,
+    nullable: true
+  }, {
     name: 'errorCallback',
     type: types.FUNCTION,
     optional: true,
@@ -685,7 +787,9 @@ RemoteResource.prototype.methodPut = function() {
 
   var callArgs = prepareResourceInfo(this);
   callArgs.representation = args.representation;
-  callArgs.query = args.query;
+  if (args.query) {
+    callArgs.query = args.query;
+  }
 
   var callback = function(result) {
     result = native.getResultObject(result);
@@ -712,12 +816,14 @@ RemoteResource.prototype.methodPost = function() {
     type: types.PLATFORM_OBJECT,
     values: Representation
   }, {
-    name: 'query',
-    type: types.DICTIONARY
-  }, {
     name: 'responseCallback',
     type: types.FUNCTION
   }, {
+    name: 'query',
+    type: types.DICTIONARY,
+    optional: true,
+    nullable: true
+  }, {
     name: 'errorCallback',
     type: types.FUNCTION,
     optional: true,
@@ -726,7 +832,9 @@ RemoteResource.prototype.methodPost = function() {
 
   var callArgs = prepareResourceInfo(this);
   callArgs.representation = args.representation;
-  callArgs.query = args.query;
+  if (args.query) {
+    callArgs.query = args.query;
+  }
 
   var callback = function(result) {
     result = native.getResultObject(result);
@@ -779,24 +887,28 @@ RemoteResource.prototype.methodDelete = function() {
   }
 };
 
-var stateChangeListener = createListener('RemoteResourceStateChangeListener');
+var resourceChangeListener = createListener('RemoteResourceChangeListener');
 
-RemoteResource.prototype.setStateChangeListener = function() {
+RemoteResource.prototype.startObserving = function() {
   var args = validator.validateMethod(arguments, [{
-    name: 'query',
-    type: types.DICTIONARY
-  }, {
     name: 'observePolicy',
     type: types.ENUM,
     values: T.getValues(ObservePolicy)
   }, {
     name: 'successCallback',
     type: types.FUNCTION
+  }, {
+    name: 'query',
+    type: types.DICTIONARY,
+    optional: true,
+    nullable: true
   }]);
 
   var callArgs = prepareResourceInfo(this);
-  callArgs.query = args.query;
   callArgs.observePolicy = args.observePolicy;
+  if (args.query) {
+    callArgs.query = args.query;
+  }
   var that = this;
 
   var listener = function(result) {
@@ -805,38 +917,52 @@ RemoteResource.prototype.setStateChangeListener = function() {
     args.successCallback(new RemoteResponse(result.data));
   };
 
-  var result = native.callSync('IotconRemoteResource_setStateChangeListener', callArgs);
+  var result = native.callSync('IotconRemoteResource_startObserving', callArgs);
 
   if (native.isFailure(result)) {
     throw native.getErrorObject(result);
   } else {
     manageId(this, native.getResultObject(result));
-    stateChangeListener.addListener(this[kIdKey], listener);
+    resourceChangeListener.addListener(this[kIdKey], listener);
   }
 };
 
-RemoteResource.prototype.unsetStateChangeListener = function() {
+RemoteResource.prototype.stopObserving = function() {
   var callArgs = prepareResourceInfo(this);
 
-  var result = native.callSync('IotconRemoteResource_unsetStateChangeListener', callArgs);
+  var result = native.callSync('IotconRemoteResource_stopObserving', callArgs);
 
   if (native.isFailure(result)) {
     throw native.getErrorObject(result);
   } else {
     manageId(this, native.getResultObject(result));
-    stateChangeListener.removeListener(this[kIdKey]);
+    resourceChangeListener.removeListener(this[kIdKey]);
   }
 };
 
+var cacheChangeListener = createListener('RemoteResourceCacheChangeListener');
+
 RemoteResource.prototype.startCaching = function() {
+  var args = validator.validateMethod(arguments, [{
+    name: 'successCallback',
+    type: types.FUNCTION,
+    optional: true,
+    nullable: true
+  }]);
+
   var callArgs = prepareResourceInfo(this);
 
+  var listener = function(result) {
+    native.callIfPossible(args.successCallback(createRepresentation(native.getResultObject(result.data))));
+  }
+
   var result = native.callSync('IotconRemoteResource_startCaching', callArgs);
 
   if (native.isFailure(result)) {
     throw native.getErrorObject(result);
   } else {
     manageId(this, native.getResultObject(result));
+    cacheChangeListener.addListener(this[kIdKey], listener);
   }
 };
 
@@ -849,12 +975,13 @@ RemoteResource.prototype.stopCaching = function() {
     throw native.getErrorObject(result);
   } else {
     manageId(this, native.getResultObject(result));
+    cacheChangeListener.removeListener(this[kIdKey]);
   }
 };
 
-var connectionChangeListener = createListener('RemoteResourceConnectionChangeListener');
+var resourceStateChangeListener = createListener('RemoteResourceStateChangeListener');
 
-RemoteResource.prototype.setConnectionChangeListener = function() {
+RemoteResource.prototype.setResourceStateChangeListener = function() {
   var args = validator.validateMethod(arguments, [{
     name: 'successCallback',
     type: types.FUNCTION
@@ -866,26 +993,26 @@ RemoteResource.prototype.setConnectionChangeListener = function() {
     args.successCallback(result.data);
   };
 
-  var result = native.callSync('IotconRemoteResource_setConnectionChangeListener', callArgs);
+  var result = native.callSync('IotconRemoteResource_setResourceStateChangeListener', callArgs);
 
   if (native.isFailure(result)) {
     throw native.getErrorObject(result);
   } else {
     manageId(this, native.getResultObject(result));
-    connectionChangeListener.addListener(this[kIdKey], listener);
+    resourceStateChangeListener.addListener(this[kIdKey], listener);
   }
 };
 
-RemoteResource.prototype.unsetConnectionChangeListener = function() {
+RemoteResource.prototype.unsetResourceStateChangeListener = function() {
   var callArgs = prepareResourceInfo(this);
 
-  var result = native.callSync('IotconRemoteResource_unsetConnectionChangeListener', callArgs);
+  var result = native.callSync('IotconRemoteResource_unsetResourceStateChangeListener', callArgs);
 
   if (native.isFailure(result)) {
     throw native.getErrorObject(result);
   } else {
     manageId(this, native.getResultObject(result));
-    connectionChangeListener.removeListener(this[kIdKey]);
+    resourceStateChangeListener.removeListener(this[kIdKey]);
   }
 };
 
@@ -901,8 +1028,8 @@ Client.prototype.findResource = function() {
     type: types.STRING,
     nullable: true
   }, {
-    name: 'resourceType',
-    type: types.STRING,
+    name: 'query',
+    type: types.DICTIONARY,
     nullable: true
   }, {
     name: 'connectivityType',
@@ -916,17 +1043,13 @@ Client.prototype.findResource = function() {
     type: types.FUNCTION,
     optional: true,
     nullable: true
-  }, {
-    name: 'isSecure',
-    type: types.BOOLEAN
   }]);
 
   var callArgs = {};
   callArgs.id = ++globalFindResourceId;
   callArgs.hostAddress = args.hostAddress;
-  callArgs.resourceType = args.resourceType;
+  callArgs.query = args.query;
   callArgs.connectivityType = args.connectivityType;
-  callArgs.isSecure = args.isSecure;
 
   var callback = function(result) {
     if (native.isFailure(result)) {
@@ -1001,10 +1124,15 @@ Client.prototype.removePresenceEventListener = function() {
   }
 };
 
-Client.prototype.getDeviceInfo = function() {
+Client.prototype.findDeviceInfo = function() {
   var args = validator.validateMethod(arguments, [{
     name: 'hostAddress',
-    type: types.STRING
+    type: types.STRING,
+    nullable: true
+  }, {
+    name: 'query',
+    type: types.DICTIONARY,
+    nullable: true
   }, {
     name: 'connectivityType',
     type: types.ENUM,
@@ -1020,7 +1148,9 @@ Client.prototype.getDeviceInfo = function() {
   }]);
 
   var callArgs = {};
+
   callArgs.hostAddress = args.hostAddress;
+  callArgs.query = args.query;
   callArgs.connectivityType = args.connectivityType;
 
   var callback = function(result) {
@@ -1031,17 +1161,22 @@ Client.prototype.getDeviceInfo = function() {
     }
   };
 
-  var result = native.call('IotconClient_getDeviceInfo', callArgs, callback);
+  var result = native.call('IotconClient_findDeviceInfo', callArgs, callback);
 
   if (native.isFailure(result)) {
     throw native.getErrorObject(result);
   }
 };
 
-Client.prototype.getPlatformInfo = function() {
+Client.prototype.findPlatformInfo = function() {
   var args = validator.validateMethod(arguments, [{
     name: 'hostAddress',
-    type: types.STRING
+    type: types.STRING,
+    nullable: true
+  }, {
+    name: 'query',
+    type: types.DICTIONARY,
+    nullable: true
   }, {
     name: 'connectivityType',
     type: types.ENUM,
@@ -1058,6 +1193,7 @@ Client.prototype.getPlatformInfo = function() {
 
   var callArgs = {};
   callArgs.hostAddress = args.hostAddress;
+  callArgs.query = args.query;
   callArgs.connectivityType = args.connectivityType;
 
   var callback = function(result) {
@@ -1068,7 +1204,7 @@ Client.prototype.getPlatformInfo = function() {
     }
   };
 
-  var result = native.call('IotconClient_getPlatformInfo', callArgs, callback);
+  var result = native.call('IotconClient_findPlatformInfo', callArgs, callback);
 
   if (native.isFailure(result)) {
     throw native.getErrorObject(result);
@@ -1076,6 +1212,31 @@ Client.prototype.getPlatformInfo = function() {
 };
 
 function Server() {
+  // TODO The variable _deviceName will be removed when the native function for getting device name is ready
+  var _deviceName = '';
+
+  Object.defineProperties(this, {
+    deviceName: {
+      get: function() {
+        return _deviceName;
+      },
+      set: function(v) {
+        if (v) {
+          var deviceName = converter.toString(v);
+
+          var callArgs = {
+            deviceName: deviceName
+          };
+
+          var result = native.callSync('IotconServer_setDeviceName', callArgs);
+          if (native.isSuccess(result)) {
+            _deviceName = deviceName;
+          }
+        }
+      },
+      enumerable: true
+    }
+  });
 }
 
 var serverResources = {};
@@ -1093,13 +1254,17 @@ Server.prototype.createResource = function() {
     type: types.ARRAY,
     values: types.STRING
   }, {
-    name: 'dictionary',
+    name: 'listener',
+    type: types.LISTENER,
+    values: ['onget', 'onput', 'onpost', 'ondelete', 'onobserving']
+  }, {
+    name: 'policy',
     type: types.DICTIONARY,
     optional: true,
     nullable: false
   }]);
 
-  var callArgs = args.dictionary || {};
+  var callArgs = args.policy || {};
   callArgs.uriPath = args.uriPath;
   callArgs.resourceTypes = args.resourceTypes;
   callArgs.resourceInterfaces = args.resourceInterfaces;
@@ -1111,6 +1276,9 @@ Server.prototype.createResource = function() {
   } else {
     var resource = new Resource(native.getResultObject(result));
     serverResources[resource[kIdKey]] = resource;
+
+    _setRequestListener(resource[kIdKey], args.listener);
+
     return resource;
   }
 };
@@ -1146,12 +1314,52 @@ Server.prototype.getResources = function() {
   return result;
 };
 
+Server.prototype.startPresence = function() {
+  var args = validator.validateMethod(arguments, [{
+    name: 'timeToLive',
+    type: types.UNSIGNED_LONG
+  }]);
+
+  var callArgs = {
+    timeToLive: args.timeToLive
+  };
+
+  var result = native.callSync('IotconServer_startPresence', callArgs);
+  if (native.isFailure(result)) {
+    throw native.getErrorObject(result);
+  }
+};
+
+Server.prototype.stopPresence = function() {
+  var result = native.callSync('IotconServer_stopPresence', {});
+  if (native.isFailure(result)) {
+    throw native.getErrorObject(result);
+  }
+};
+
 var client = new Client();
 var server = new Server();
 
 function Iotcon() {
 }
 
+Iotcon.prototype.initialize = function() {
+  var args = validator.validateMethod(arguments, [{
+    name: 'filePath',
+    type: types.STRING
+  }]);
+
+  var data = {
+    filePath: args.filePath
+  };
+
+  var result = native.callSync('Iotcon_initialize', data);
+
+  if (native.isFailure(result)) {
+    throw native.getErrorObject(result);
+  }
+};
+
 Iotcon.prototype.getClient = function() {
   return client;
 };
index 29af641..057c7a5 100644 (file)
@@ -30,7 +30,7 @@ namespace extension {
 namespace iotcon {
 
 namespace {
-const std::string kPrivilegeIotcon = "http://tizen.org/privilege/d2d.datasharing";
+const std::string kPrivilegeIotcon = "http://tizen.org/privilege/internet";
 
 struct CallbackData {
   common::PostCallback fun;
@@ -71,10 +71,12 @@ void RemoteResourceResponseCallback(iotcon_remote_resource_h resource,
 const common::ListenerToken kResourceRequestListenerToken{"ResourceRequestListener"};
 const common::ListenerToken kFindResourceListenerToken{"FindResourceListener"};
 const common::ListenerToken kPresenceEventListenerToken{"PresenceEventListener"};
-const common::ListenerToken kRemoteResourceConnectionChangeListener
-                                {"RemoteResourceConnectionChangeListener"};
 const common::ListenerToken kRemoteResourceStateChangeListener
                                 {"RemoteResourceStateChangeListener"};
+const common::ListenerToken kRemoteResourceChangeListener
+                                {"RemoteResourceChangeListener"};
+const common::ListenerToken kRemoteResourceCacheChangeListener
+                                {"RemoteResourceCacheChangeListener"};
 
 const std::string kObserverIds = "observerIds";
 const std::string kQos = "qos";
@@ -84,12 +86,16 @@ const std::string kInterface = "iface";
 const std::string kResult = "result";
 const std::string kTimeout = "timeout";
 const std::string kData = "data";
+const std::string kFilePath = "filePath";
+const std::string kTimeToLive = "timeToLive";
+
+const std::string kTimeInterval = "timeInterval";
 
 const std::string kVirtualResourcesHandlingPath = "/home/owner/share/tmp_file_iotcon.dat";
 
 }  // namespace
 
-IotconInstance::IotconInstance() {
+IotconInstance::IotconInstance() : initialized_(false), presence_started_(false) {
   ScopeLogger();
 
   using std::placeholders::_1;
@@ -108,18 +114,26 @@ IotconInstance::IotconInstance() {
   REGISTER_SYNC("IotconResource_unsetRequestListener", ResourceUnsetRequestListener);
   REGISTER_SYNC("IotconResponse_send", ResponseSend);
   REGISTER_SYNC("IotconRemoteResource_getCachedRepresentation", RemoteResourceGetCachedRepresentation);
-  REGISTER_SYNC("IotconRemoteResource_setStateChangeListener", RemoteResourceSetStateChangeListener);
-  REGISTER_SYNC("IotconRemoteResource_unsetStateChangeListener", RemoteResourceUnsetStateChangeListener);
+  REGISTER_SYNC("IotconRemoteResource_getOptions", RemoteResourceGetOptions);
+  REGISTER_SYNC("IotconRemoteResource_setOptions", RemoteResourceSetOptions);
+  REGISTER_SYNC("IotconRemoteResource_startObserving", RemoteResourceStartObserving);
+  REGISTER_SYNC("IotconRemoteResource_stopObserving", RemoteResourceStopObserving);
   REGISTER_SYNC("IotconRemoteResource_startCaching", RemoteResourceStartCaching);
   REGISTER_SYNC("IotconRemoteResource_stopCaching", RemoteResourceStopCaching);
-  REGISTER_SYNC("IotconRemoteResource_setConnectionChangeListener", RemoteResourceSetConnectionChangeListener);
-  REGISTER_SYNC("IotconRemoteResource_unsetConnectionChangeListener", RemoteResourceUnsetConnectionChangeListener);
+  REGISTER_SYNC("IotconRemoteResource_setResourceStateChangeListener", RemoteResourceSetResourceStateChangeListener);
+  REGISTER_SYNC("IotconRemoteResource_unsetResourceStateChangeListener", RemoteResourceUnsetResourceStateChangeListener);
+  REGISTER_SYNC("IotconRemoteResource_getTimeInterval", RemoteResourceGetTimeInterval);
+  REGISTER_SYNC("IotconRemoteResource_setTimeInterval", RemoteResourceSetTimeInterval);
   REGISTER_SYNC("IotconClient_addPresenceEventListener", ClientAddPresenceEventListener);
   REGISTER_SYNC("IotconClient_removePresenceEventListener", ClientRemovePresenceEventListener);
+  REGISTER_SYNC("Iotcon_initialize", Initialize);
   REGISTER_SYNC("Iotcon_getTimeout", GetTimeout);
   REGISTER_SYNC("Iotcon_setTimeout", SetTimeout);
   REGISTER_SYNC("IotconServer_createResource", ServerCreateResource);
   REGISTER_SYNC("IotconServer_removeResource", ServerRemoveResource);
+  REGISTER_SYNC("IotconServer_startPresence", ServerStartPresence);
+  REGISTER_SYNC("IotconServer_stopPresence", ServerStopPresence);
+  REGISTER_SYNC("IotconServer_setDeviceName", ServerSetDeviceName);
   REGISTER_SYNC("IotconClient_findResource", ClientFindResource);
 
 #undef REGISTER_SYNC
@@ -131,33 +145,26 @@ IotconInstance::IotconInstance() {
   REGISTER_ASYNC("IotconRemoteResource_methodPut", RemoteResourceMethodPut);
   REGISTER_ASYNC("IotconRemoteResource_methodPost", RemoteResourceMethodPost);
   REGISTER_ASYNC("IotconRemoteResource_methodDelete", RemoteResourceMethodDelete);
-  REGISTER_ASYNC("IotconClient_getDeviceInfo", ClientGetDeviceInfo);
-  REGISTER_ASYNC("IotconClient_getPlatformInfo", ClientGetPlatformInfo);
+  REGISTER_ASYNC("IotconClient_findDeviceInfo", ClientFindDeviceInfo);
+  REGISTER_ASYNC("IotconClient_findPlatformInfo", ClientFindPlatformInfo);
 
 #undef REGISTER_ASYNC
-
-  // initialize connection to iotcon service
-  int ret = iotcon_initialize(kVirtualResourcesHandlingPath.c_str());
-  if (IOTCON_ERROR_NONE != ret) {
-    LoggerE("Could not connnect to iotcon service: %s", get_error_message(ret));
-  } else {
-    LoggerD("Iotcon service connected");
-
-    ret = iotcon_start_presence(0);
-    if (IOTCON_ERROR_NONE != ret) {
-      LoggerE("Could not start presence: %s",
-                  get_error_message(ret));
-    } else {
-      LoggerD("Iotcon iotcon_start_presence");
-    }
-  }
 }
 
 IotconInstance::~IotconInstance() {
   ScopeLogger();
 
-  iotcon_stop_presence();
-  iotcon_deinitialize();
+  if (presence_started_) {
+    iotcon_stop_presence();
+    presence_started_ = false;
+    LoggerD("Iotcon service presence stopped");
+  }
+
+  if (initialized_) {
+    iotcon_deinitialize();
+    initialized_ = false;
+    LoggerD("Iotcon service deinitialized");
+  }
 }
 
 common::TizenResult IotconInstance::ResourceGetObserverIds(const picojson::object& args) {
@@ -189,7 +196,7 @@ common::TizenResult IotconInstance::ResourceNotify(const picojson::object& args)
 
   CHECK_EXIST(args, kId);
   CHECK_EXIST(args, kQos);
-  CHECK_EXIST(args, kStates);
+  CHECK_EXIST(args, kAttributes);
 
   ResourceInfoPtr resource;
   long long id = GetId(args);
@@ -242,10 +249,10 @@ common::TizenResult IotconInstance::ResourceNotify(const picojson::object& args)
     }
   }
 
-  // create representation from resource and states
+  // create representation from resource and attributes
   iotcon_representation_h representation = nullptr;
 
-  result = IotconUtils::RepresentationFromResource(resource, IotconUtils::GetArg(args, kStates), &representation);
+  result = IotconUtils::RepresentationFromResource(resource, IotconUtils::GetArg(args, kAttributes), &representation);
   if (!result) {
     LogAndReturnTizenError(result, ("RepresentationFromResource() failed"));
   }
@@ -279,9 +286,10 @@ common::TizenResult IotconInstance::ResourceAddResourceTypes(const picojson::obj
   const auto& types = IotconUtils::GetArg(args, kTypes).get<picojson::array>();
 
   for (const auto& type : types) {
-    result = IotconUtils::ConvertIotconError(iotcon_resource_bind_type(resource->handle, type.get<std::string>().c_str()));
-    if (!result) {
-      LogAndReturnTizenError(result, ("iotcon_resource_bind_type() failed"));
+    int ret = iotcon_resource_bind_type(resource->handle, type.get<std::string>().c_str());
+    if (IOTCON_ERROR_NONE != ret && IOTCON_ERROR_ALREADY != ret) {
+      LogAndReturnTizenError(
+          IotconUtils::ConvertIotconError(ret), ("iotcon_resource_bind_type() failed"));
     }
   }
 
@@ -302,9 +310,11 @@ common::TizenResult IotconInstance::ResourceAddResourceInterface(const picojson:
     LogAndReturnTizenError(result, ("GetResourceById() failed"));
   }
 
-  result = IotconUtils::ConvertIotconError(iotcon_resource_bind_interface(resource->handle, IotconUtils::GetArg(args, kInterface).get<std::string>().c_str()));
-  if (!result) {
-    LogAndReturnTizenError(result, ("iotcon_resource_bind_interface() failed"));
+  int ret = iotcon_resource_bind_interface(
+      resource->handle, IotconUtils::GetArg(args, kInterface).get<std::string>().c_str());
+  if (IOTCON_ERROR_NONE != ret && IOTCON_ERROR_ALREADY != ret) {
+    LogAndReturnTizenError(
+        IotconUtils::ConvertIotconError(ret), ("iotcon_resource_bind_interface() failed"));
   }
 
   return common::TizenSuccess();
@@ -332,9 +342,10 @@ common::TizenResult IotconInstance::ResourceAddChildResource(const picojson::obj
     LogAndReturnTizenError(result, ("GetResourceById() failed"));
   }
 
-  result = IotconUtils::ConvertIotconError(iotcon_resource_bind_child_resource(parent->handle, child->handle));
-  if (!result) {
-    LogAndReturnTizenError(result, ("iotcon_resource_bind_child_resource() failed"));
+  int ret = iotcon_resource_bind_child_resource(parent->handle, child->handle);
+  if (IOTCON_ERROR_NONE != ret && IOTCON_ERROR_ALREADY != ret) {
+    LogAndReturnTizenError(
+        IotconUtils::ConvertIotconError(ret), ("iotcon_resource_bind_child_resource() failed"));
   }
 
   parent->children.insert(child);
@@ -390,7 +401,8 @@ common::TizenResult IotconInstance::ResourceSetRequestListener(const picojson::o
   }
 
   if (!resource->request_listener) {
-    resource->request_listener = [this, id](const common::TizenResult&, const picojson::value& v) {
+    resource->request_listener = [this, id](const common::TizenResult&,
+                                            const picojson::value& v) {
       picojson::value response{picojson::object{}};
       auto& obj = response.get<picojson::object>();
 
@@ -428,7 +440,6 @@ common::TizenResult IotconInstance::ResponseSend(const picojson::object& args) {
   CHECK_EXIST(args, kResult);
   CHECK_EXIST(args, kRepresentation);
   CHECK_EXIST(args, kOptions);
-  CHECK_EXIST(args, kInterface);
 
   ResponsePtr response = nullptr;
   auto result = IotconServerManager::GetInstance().GetResponseById(GetId(args), &response);
@@ -523,7 +534,65 @@ common::TizenResult IotconInstance::RemoteResourceGetCachedRepresentation(const
     }
     return common::TizenSuccess{repr_json};
   }
-  return common::UnknownError("Failed to gather cached representation");
+  return common::AbortError("Failed to gather cached representation");
+}
+
+common::TizenResult IotconInstance::RemoteResourceGetOptions(const picojson::object& args) {
+  ScopeLogger();
+
+  FoundRemoteInfoPtr ptr;
+  auto res = IotconUtils::RemoteResourceFromJson(args, &ptr);
+  if (!res) {
+    LogAndReturnTizenError(res, ("Failed to build resource using json data"));
+  }
+
+  iotcon_options_h options = nullptr;
+  res = IotconUtils::ConvertIotconError(
+      iotcon_remote_resource_get_options(ptr->handle, &options));
+  if (!res) {
+    LogAndReturnTizenError(res, ("Gathering options failed"));
+  }
+
+  if (options) {
+    picojson::array options_array;
+    res = IotconUtils::OptionsToJson(options, &options_array);
+    if (!res) {
+      LogAndReturnTizenError(res, ("OptionsToJson() failed"));
+    }
+    return common::TizenSuccess{picojson::value(options_array)};
+  }
+
+  return common::AbortError("Failed to gather options");
+}
+
+common::TizenResult IotconInstance::RemoteResourceSetOptions(const picojson::object& args) {
+  ScopeLogger();
+  CHECK_EXIST(args, kOptions);
+
+  FoundRemoteInfoPtr ptr;
+  auto res = IotconUtils::RemoteResourceFromJson(args, &ptr);
+  if (!res) {
+    LogAndReturnTizenError(res, ("Failed to build resource using json data"));
+  }
+
+  // default value would be null (if provided value is not an array)
+  iotcon_options_h options = nullptr;
+  const auto& options_it = args.find(kOptions);
+  if (options_it->second.is<picojson::array>()) {
+    // if it is an array use provided values
+    const auto& options_array = options_it->second.get<picojson::array>();
+    res = IotconUtils::OptionsFromJson(options_array, &options);
+    if (!res) {
+      return res;
+    }
+  }
+
+  res = IotconUtils::ConvertIotconError(iotcon_remote_resource_set_options(ptr->handle, options));
+  if (!res) {
+    LogAndReturnTizenError(res, ("iotcon_response_set_options() failed"));
+  }
+
+  return common::TizenSuccess{IotconClientManager::GetInstance().StoreRemoteResource(ptr)};
 }
 
 common::TizenResult IotconInstance::RemoteResourceMethodGet(const picojson::object& args,
@@ -532,8 +601,6 @@ common::TizenResult IotconInstance::RemoteResourceMethodGet(const picojson::obje
 
   CHECK_PRIVILEGE(kPrivilegeIotcon);
 
-  CHECK_EXIST(args, kQuery);
-
   FoundRemoteInfoPtr resource;
   auto result = IotconUtils::RemoteResourceFromJson(args, &resource);
   if (!result) {
@@ -541,12 +608,17 @@ common::TizenResult IotconInstance::RemoteResourceMethodGet(const picojson::obje
   }
 
   iotcon_query_h query = nullptr;
-  result = IotconUtils::QueryFromJson(IotconUtils::GetArg(args, kQuery).get<picojson::object>(), &query);
-  if (!result) {
-    LogAndReturnTizenError(result, ("QueryFromJson() failed"));
+  const auto& query_it = args.find(kQuery);
+  if (args.end() != query_it) {
+    result = IotconUtils::QueryFromJson(query_it->second.get<picojson::object>(), &query);
+    if (!result) {
+      LogAndReturnTizenError(result, ("QueryFromJson() failed"));
+    }
   }
   SCOPE_EXIT {
-    iotcon_query_destroy(query);
+    if (query) {
+      iotcon_query_destroy(query);
+    }
   };
 
   std::unique_ptr<CallbackData> data{new CallbackData{PostForMethodCall(token, resource)}};
@@ -589,7 +661,6 @@ common::TizenResult IotconInstance::RemoteResourceMethodPut(const picojson::obje
   CHECK_PRIVILEGE(kPrivilegeIotcon);
 
   CHECK_EXIST(args, kRepresentation);
-  CHECK_EXIST(args, kQuery);
 
   FoundRemoteInfoPtr resource;
   auto result = IotconUtils::RemoteResourceFromJson(args, &resource);
@@ -607,12 +678,17 @@ common::TizenResult IotconInstance::RemoteResourceMethodPut(const picojson::obje
   };
 
   iotcon_query_h query = nullptr;
-  result = IotconUtils::QueryFromJson(IotconUtils::GetArg(args, kQuery).get<picojson::object>(), &query);
-  if (!result) {
-    LogAndReturnTizenError(result, ("QueryFromJson() failed"));
+  const auto& query_it = args.find(kQuery);
+  if (args.end() != query_it) {
+    result = IotconUtils::QueryFromJson(query_it->second.get<picojson::object>(), &query);
+    if (!result) {
+      LogAndReturnTizenError(result, ("QueryFromJson() failed"));
+    }
   }
   SCOPE_EXIT {
-    iotcon_query_destroy(query);
+    if (query) {
+      iotcon_query_destroy(query);
+    }
   };
 
   std::unique_ptr<CallbackData> data{new CallbackData{PostForMethodCall(token, resource)}};
@@ -655,7 +731,6 @@ common::TizenResult IotconInstance::RemoteResourceMethodPost(const picojson::obj
   CHECK_PRIVILEGE(kPrivilegeIotcon);
 
   CHECK_EXIST(args, kRepresentation);
-  CHECK_EXIST(args, kQuery);
 
   FoundRemoteInfoPtr resource;
   auto result = IotconUtils::RemoteResourceFromJson(args, &resource);
@@ -673,12 +748,17 @@ common::TizenResult IotconInstance::RemoteResourceMethodPost(const picojson::obj
   };
 
   iotcon_query_h query = nullptr;
-  result = IotconUtils::QueryFromJson(IotconUtils::GetArg(args, kQuery).get<picojson::object>(), &query);
-  if (!result) {
-    LogAndReturnTizenError(result, ("QueryFromJson() failed"));
+  const auto& query_it = args.find(kQuery);
+  if (args.end() != query_it) {
+    result = IotconUtils::QueryFromJson(query_it->second.get<picojson::object>(), &query);
+    if (!result) {
+      LogAndReturnTizenError(result, ("QueryFromJson() failed"));
+    }
   }
   SCOPE_EXIT {
-    iotcon_query_destroy(query);
+    if (query) {
+      iotcon_query_destroy(query);
+    }
   };
 
   std::unique_ptr<CallbackData> data{new CallbackData{PostForMethodCall(token, resource)}};
@@ -763,6 +843,11 @@ static void ObserveCallback(iotcon_remote_resource_h resource, iotcon_error_e er
                             int sequence_number, iotcon_response_h response, void *user_data) {
   ScopeLogger();
   FoundRemoteInfo* ptr = static_cast<FoundRemoteInfo*>(user_data);
+  if (nullptr == ptr) {
+    LoggerE("ObserveCallback() failed.  Ignoring callback");
+    return;
+  }
+
   if (ptr->observe_listener) {
     picojson::value json_result = picojson::value(picojson::object());
 
@@ -775,12 +860,11 @@ static void ObserveCallback(iotcon_remote_resource_h resource, iotcon_error_e er
   }
 }
 
-common::TizenResult IotconInstance::RemoteResourceSetStateChangeListener(const picojson::object& args) {
+common::TizenResult IotconInstance::RemoteResourceStartObserving(const picojson::object& args) {
   ScopeLogger();
 
   CHECK_PRIVILEGE(kPrivilegeIotcon);
 
-  CHECK_EXIST(args, kQuery);
   CHECK_EXIST(args, kObservePolicy);
   FoundRemoteInfoPtr ptr;
   auto result = IotconUtils::RemoteResourceFromJson(args, &ptr);
@@ -789,13 +873,17 @@ common::TizenResult IotconInstance::RemoteResourceSetStateChangeListener(const p
   }
 
   iotcon_query_h query = nullptr;
-  auto query_obj = args.find(kQuery)->second.get<picojson::object>();
-  result = IotconUtils::QueryFromJson(query_obj, &query);
-  if (!result){
-    return result;
+  const auto& query_it = args.find(kQuery);
+  if (args.end() != query_it) {
+    result = IotconUtils::QueryFromJson(query_it->second.get<picojson::object>(), &query);
+    if (!result){
+      return result;
+    }
   }
   SCOPE_EXIT {
-    iotcon_query_destroy(query);
+    if (query) {
+      iotcon_query_destroy(query);
+    }
   };
 
   iotcon_observe_policy_e observe_policy = IotconUtils::ToObservePolicy(
@@ -808,7 +896,7 @@ common::TizenResult IotconInstance::RemoteResourceSetStateChangeListener(const p
     obj.insert(std::make_pair(kId, picojson::value{static_cast<double>(ptr->id)}));
     obj.insert(std::make_pair(kData, v));
 
-    Post(kRemoteResourceStateChangeListener, common::TizenSuccess{response});
+    Post(kRemoteResourceChangeListener, common::TizenSuccess{response});
   };
 
   // set options to the remote resource
@@ -840,7 +928,7 @@ common::TizenResult IotconInstance::RemoteResourceSetStateChangeListener(const p
   return common::TizenSuccess{IotconClientManager::GetInstance().StoreRemoteResource(ptr)};
 }
 
-common::TizenResult IotconInstance::RemoteResourceUnsetStateChangeListener(const picojson::object& args) {
+common::TizenResult IotconInstance::RemoteResourceStopObserving(const picojson::object& args) {
   ScopeLogger();
 
   CHECK_PRIVILEGE(kPrivilegeIotcon);
@@ -882,8 +970,24 @@ common::TizenResult IotconInstance::RemoteResourceUnsetStateChangeListener(const
 static void RepresentationChangedCallback(iotcon_remote_resource_h resource,
                                           iotcon_representation_h representation,
                                           void *user_data) {
-  LoggerD("Entered");
-  //TODO probably should be handled
+  ScopeLogger();
+  FoundRemoteInfo* ptr = static_cast<FoundRemoteInfo*>(user_data);
+  if (nullptr == ptr) {
+    LoggerE("RepresentationChangeCallback() failed.  Ignoring callback");
+    return;
+  }
+
+  if (ptr->cache_change_listener) {
+    picojson::value json_result = picojson::value(picojson::object());
+
+    auto result = IotconUtils::RepresentationToJson(representation, &json_result.get<picojson::object>());
+    if (result) {
+      ptr->cache_change_listener(common::TizenSuccess(), json_result);
+    } else {
+      LoggerE("RepresentationToJson() failed.  Ignoring callback");
+      return;
+    }
+  }
 }
 
 common::TizenResult IotconInstance::RemoteResourceStartCaching(const picojson::object& args) {
@@ -896,11 +1000,23 @@ common::TizenResult IotconInstance::RemoteResourceStartCaching(const picojson::o
   if (!result) {
     LogAndReturnTizenError(result, ("Failed to create remote resource handle"));
   }
+
+  ptr->cache_change_listener = [this, ptr](const common::TizenResult& res, const picojson::value& v) {
+    picojson::value response{picojson::object{}};
+    auto& obj = response.get<picojson::object>();
+
+    obj.insert(std::make_pair(kId, picojson::value{static_cast<double>(ptr->id)}));
+    obj.insert(std::make_pair(kData, v));
+
+    Post(kRemoteResourceCacheChangeListener, common::TizenSuccess{response});
+  };
+
   result = IotconUtils::ConvertIotconError(
-      iotcon_remote_resource_start_caching(ptr->handle, RepresentationChangedCallback, nullptr));
+      iotcon_remote_resource_start_caching(ptr->handle, RepresentationChangedCallback, ptr.get()));
   if (!result) {
     return result;
   }
+
   return common::TizenSuccess{IotconClientManager::GetInstance().StoreRemoteResource(ptr)};
 }
 
@@ -914,11 +1030,13 @@ common::TizenResult IotconInstance::RemoteResourceStopCaching(const picojson::ob
   if (!result) {
     LogAndReturnTizenError(result, ("Failed to create remote resource handle"));
   }
+
   result = IotconUtils::ConvertIotconError(
       iotcon_remote_resource_stop_caching(ptr->handle));
   if (!result) {
     return result;
   }
+  ptr->cache_change_listener = nullptr;
   return common::TizenSuccess{IotconClientManager::GetInstance().RemoveRemoteResource(ptr)};
 }
 
@@ -926,43 +1044,50 @@ static void MonitoringCallback(iotcon_remote_resource_h resource,
                                  iotcon_remote_resource_state_e state, void *user_data) {
   ScopeLogger();
   FoundRemoteInfo* ptr = static_cast<FoundRemoteInfo*>(user_data);
-  if (ptr->connection_listener) {
+  if (nullptr == ptr) {
+    LoggerE("MonitoringCallback() failed.  Ignoring callback");
+    return;
+  }
+
+  if (ptr->state_listener) {
     picojson::value json_result = picojson::value(IOTCON_REMOTE_RESOURCE_ALIVE == state);
-    ptr->connection_listener(common::TizenSuccess(), json_result);
+    ptr->state_listener(common::TizenSuccess(), json_result);
   } else {
     LoggerD("Post function not present, just ignoring");
   }
 }
 
-common::TizenResult IotconInstance::RemoteResourceSetConnectionChangeListener(const picojson::object& args) {
+common::TizenResult IotconInstance::RemoteResourceSetResourceStateChangeListener(const picojson::object& args) {
   ScopeLogger();
 
   CHECK_PRIVILEGE(kPrivilegeIotcon);
 
+
   FoundRemoteInfoPtr ptr;
   auto result = IotconUtils::RemoteResourceFromJson(args, &ptr);
   if (!result) {
     LogAndReturnTizenError(result, ("Failed to create remote resource handle"));
   }
-  result = IotconUtils::ConvertIotconError(
-      iotcon_remote_resource_start_monitoring(ptr->handle, MonitoringCallback, ptr.get()));
-  if (!result) {
-    return result;
-  }
-  ptr->connection_listener = [this, ptr](const common::TizenResult& res, const picojson::value& v) {
+
+  ptr->state_listener = [this, ptr](const common::TizenResult& res, const picojson::value& v) {
     picojson::value response{picojson::object{}};
     auto& obj = response.get<picojson::object>();
 
     obj.insert(std::make_pair(kId, picojson::value{static_cast<double>(ptr->id)}));
     obj.insert(std::make_pair(kData, v));
 
-    Post(kRemoteResourceConnectionChangeListener, common::TizenSuccess{response});
+    Post(kRemoteResourceStateChangeListener, common::TizenSuccess{response});
   };
 
+  result = IotconUtils::ConvertIotconError(
+      iotcon_remote_resource_start_monitoring(ptr->handle, MonitoringCallback, ptr.get()));
+  if (!result) {
+    return result;
+  }
   return common::TizenSuccess{IotconClientManager::GetInstance().StoreRemoteResource(ptr)};
 }
 
-common::TizenResult IotconInstance::RemoteResourceUnsetConnectionChangeListener(const picojson::object& args) {
+common::TizenResult IotconInstance::RemoteResourceUnsetResourceStateChangeListener(const picojson::object& args) {
   ScopeLogger();
 
   CHECK_PRIVILEGE(kPrivilegeIotcon);
@@ -976,14 +1101,68 @@ common::TizenResult IotconInstance::RemoteResourceUnsetConnectionChangeListener(
   if (!result) {
     return result;
   }
-  ptr->connection_listener = nullptr;
+  ptr->state_listener = nullptr;
   return common::TizenSuccess{IotconClientManager::GetInstance().RemoveRemoteResource(ptr)};
 }
 
+common::TizenResult IotconInstance::RemoteResourceGetTimeInterval(const picojson::object& args) {
+  ScopeLogger();
+
+  CHECK_PRIVILEGE(kPrivilegeIotcon);
+
+/* TODO Uncomment when the interface of the function iotcon_remote_resource_get_time_interval is changed
+  FoundRemoteInfoPtr ptr;
+  auto res = IotconUtils::RemoteResourceFromJson(args, &ptr);
+  if (!res) {
+    LogAndReturnTizenError(res, ("Failed to build resource using json data"));
+  }
+*/
+  int time_interval = 0;
+
+  auto res = IotconUtils::ConvertIotconError(iotcon_remote_resource_get_time_interval(&time_interval));
+  if (!res) {
+    LogAndReturnTizenError(res, ("iotcon_remote_resource_set_time_interval() failed"));
+  }
+
+  return common::TizenSuccess{picojson::value(static_cast<double>(time_interval))};
+}
+
+common::TizenResult IotconInstance::RemoteResourceSetTimeInterval(const picojson::object& args) {
+  ScopeLogger();
+
+  CHECK_PRIVILEGE(kPrivilegeIotcon);
+  CHECK_EXIST(args, kTimeInterval);
+
+  int time_interval = static_cast<int>(IotconUtils::GetArg(args, kTimeInterval).get<double>());
+
+/* TODO Uncomment when the interface of the function iotcon_remote_resource_set_time_interval is changed
+  FoundRemoteInfoPtr ptr;
+  auto res = IotconUtils::RemoteResourceFromJson(args, &ptr);
+  if (!res) {
+    LogAndReturnTizenError(res, ("Failed to build resource using json data"));
+  }
+*/
+
+  auto res = IotconUtils::ConvertIotconError(iotcon_remote_resource_set_time_interval(time_interval));
+  if (!res) {
+    LogAndReturnTizenError(res, ("iotcon_remote_resource_set_time_interval() failed"));
+  }
+
+  // TODO Uncomment when the interface of the function iotcon_remote_resource_set_time_interval is changed
+  // return common::TizenSuccess{IotconClientManager::GetInstance().StoreRemoteResource(ptr)};
+
+  return common::TizenSuccess{};
+}
+
 bool IotconInstance::ResourceFoundCallback(iotcon_remote_resource_h resource,
                                            iotcon_error_e result, void *user_data) {
   ScopeLogger();
   CallbackData* data = static_cast<CallbackData*>(user_data);
+  if (nullptr == data) {
+    LoggerE("ResourceFoundCallback() failed.  Ignoring callback");
+    return IOTCON_FUNC_STOP;
+  }
+
   auto ret = IotconUtils::ConvertIotconError(result);
   if (!ret) {
     data->fun(ret, picojson::value{});
@@ -999,7 +1178,7 @@ bool IotconInstance::ResourceFoundCallback(iotcon_remote_resource_h resource,
   }
   data->fun(ret, json_result);
 
-  return IOTCON_FUNC_STOP;
+  return IOTCON_FUNC_CONTINUE;
 }
 
 common::TizenResult IotconInstance::ClientFindResource(const picojson::object& args) {
@@ -1011,19 +1190,28 @@ common::TizenResult IotconInstance::ClientFindResource(const picojson::object& a
   char* host_address = nullptr;
   if (args.find(kHostAddress)->second.is<std::string>()) {
     host_address = const_cast<char*>(args.find(kHostAddress)->second.get<std::string>().c_str());
+  } else {
+    host_address = IOTCON_MULTICAST_ADDRESS;
   }
 
-  CHECK_EXIST(args, kResourceType);
-  char* resource_type = nullptr;
-  if (args.find(kResourceType)->second.is<std::string>()) {
-    resource_type = const_cast<char*>(args.find(kResourceType)->second.get<std::string>().c_str());
+  CHECK_EXIST(args, kQuery);
+  iotcon_query_h query = nullptr;
+  const auto& query_obj = args.find(kQuery)->second;
+  if (query_obj.is<picojson::object>()) {
+    auto result = IotconUtils::QueryFromJson(query_obj.get<picojson::object>(), &query);
+    if (!result) {
+      LogAndReturnTizenError(result, ("QueryFromJson() failed"));
+    }
   }
+  SCOPE_EXIT {
+    if (query) {
+      iotcon_query_destroy(query);
+    }
+  };
 
   CHECK_EXIST(args, kConnectivityType);
   iotcon_connectivity_type_e connectivity_type = IotconUtils::ToConnectivityType(
       args.find(kConnectivityType)->second.get<std::string>());
-  CHECK_EXIST(args, kIsSecure);
-  bool is_secure = args.find(kIsSecure)->second.get<bool>();
 
   long long id = GetId(args);
   auto response = [this, id](const common::TizenResult& res, const picojson::value& v) {
@@ -1041,11 +1229,11 @@ common::TizenResult IotconInstance::ClientFindResource(const picojson::object& a
   };
   CallbackData* data = new CallbackData{response};
 
-  LoggerD("Running find with:\nhost_address: %s,\nconnectivity_type: %d,\nresource_type: %s,\nis_secure: %d",
-          host_address, connectivity_type, resource_type, is_secure);
+  LoggerD("Running find with:\nhost_address: %s,\nconnectivity_type: %d",
+          host_address, connectivity_type);
   auto result = IotconUtils::ConvertIotconError(
-      iotcon_find_resource(host_address, connectivity_type, resource_type,
-                           is_secure, ResourceFoundCallback, data));
+      iotcon_find_resource(host_address, connectivity_type, query,
+                           ResourceFoundCallback, data));
   if (!result) {
     delete data;
     LogAndReturnTizenError(result);
@@ -1137,6 +1325,11 @@ bool IotconDeviceInfoCb(iotcon_device_info_h device_info,
   ScopeLogger();
 
   CallbackData* data = static_cast<CallbackData*>(user_data);
+  if (nullptr == data) {
+    LoggerE("IotconDeviceInfoCb() failed.  Ignoring callback");
+    return IOTCON_FUNC_STOP;
+  }
+
   picojson::value v{picojson::object{}};
   common::TizenResult ret = common::TizenSuccess();
 
@@ -1149,27 +1342,46 @@ bool IotconDeviceInfoCb(iotcon_device_info_h device_info,
   data->fun(ret, v);
   delete data;
 
-  return IOTCON_FUNC_STOP;
+  return IOTCON_FUNC_CONTINUE;
 }
 
-common::TizenResult IotconInstance::ClientGetDeviceInfo(const picojson::object& args,
-                                                        const common::AsyncToken& token) {
+common::TizenResult IotconInstance::ClientFindDeviceInfo(const picojson::object& args,
+                                                         const common::AsyncToken& token) {
   ScopeLogger();
 
   CHECK_PRIVILEGE(kPrivilegeIotcon);
 
   CHECK_EXIST(args, kHostAddress);
-  CHECK_EXIST(args, kConnectivityType);
+  char* host_address = nullptr;
+  if (args.find(kHostAddress)->second.is<std::string>()) {
+    host_address = const_cast<char*>(args.find(kHostAddress)->second.get<std::string>().c_str());
+  } else {
+    host_address = IOTCON_MULTICAST_ADDRESS;
+  }
+
+  CHECK_EXIST(args, kQuery);
+  iotcon_query_h query = nullptr;
+  const auto& query_obj = args.find(kQuery)->second;
+  if (query_obj.is<picojson::object>()) {
+    auto result = IotconUtils::QueryFromJson(query_obj.get<picojson::object>(), &query);
+    if (!result) {
+      LogAndReturnTizenError(result, ("QueryFromJson() failed"));
+    }
+  }
+  SCOPE_EXIT {
+    if (query) {
+      iotcon_query_destroy(query);
+    }
+  };
 
-  std::string host = args.find(kHostAddress)->second.get<std::string>();
+  CHECK_EXIST(args, kConnectivityType);
   std::string con_type = args.find(kConnectivityType)->second.get<std::string>();
   iotcon_connectivity_type_e con_type_e = IotconUtils::ToConnectivityType(con_type);
 
   CallbackData* data = new CallbackData{SimplePost(token)};
 
   auto result = IotconUtils::ConvertIotconError(
-       iotcon_find_device_info(host.c_str(), con_type_e, IotconDeviceInfoCb,
-                                data));
+       iotcon_find_device_info(host_address, con_type_e, query, IotconDeviceInfoCb, data));
 
   if (!result) {
     delete data;
@@ -1184,6 +1396,11 @@ bool IotconPlatformInfoCb(iotcon_platform_info_h platform_info,
   ScopeLogger();
 
   CallbackData* data = static_cast<CallbackData*>(user_data);
+  if (nullptr == data) {
+    LoggerE("IotconPlatformInfoCb() failed.  Ignoring callback");
+    return IOTCON_FUNC_STOP;
+  }
+
   picojson::value v{picojson::object{}};
   common::TizenResult ret = common::TizenSuccess();
 
@@ -1196,27 +1413,46 @@ bool IotconPlatformInfoCb(iotcon_platform_info_h platform_info,
   data->fun(ret, v);
   delete data;
 
-  return IOTCON_FUNC_STOP;
+  return IOTCON_FUNC_CONTINUE;
 }
 
-common::TizenResult IotconInstance::ClientGetPlatformInfo(const picojson::object& args,
-                                                          const common::AsyncToken& token) {
+common::TizenResult IotconInstance::ClientFindPlatformInfo(const picojson::object& args,
+                                                           const common::AsyncToken& token) {
   ScopeLogger();
 
   CHECK_PRIVILEGE(kPrivilegeIotcon);
 
   CHECK_EXIST(args, kHostAddress);
-  CHECK_EXIST(args, kConnectivityType);
+  char* host_address = nullptr;
+  if (args.find(kHostAddress)->second.is<std::string>()) {
+    host_address = const_cast<char*>(args.find(kHostAddress)->second.get<std::string>().c_str());
+  } else {
+    host_address = IOTCON_MULTICAST_ADDRESS;
+  }
+
+  CHECK_EXIST(args, kQuery);
+  iotcon_query_h query = nullptr;
+  const auto& query_obj = args.find(kQuery)->second;
+  if (query_obj.is<picojson::object>()) {
+    auto result = IotconUtils::QueryFromJson(query_obj.get<picojson::object>(), &query);
+    if (!result) {
+      LogAndReturnTizenError(result, ("QueryFromJson() failed"));
+    }
+  }
+  SCOPE_EXIT {
+    if (query) {
+      iotcon_query_destroy(query);
+    }
+  };
 
-  std::string host = args.find(kHostAddress)->second.get<std::string>();
+  CHECK_EXIST(args, kConnectivityType);
   std::string con_type = args.find(kConnectivityType)->second.get<std::string>();
   iotcon_connectivity_type_e con_type_e = IotconUtils::ToConnectivityType(con_type);
 
   CallbackData* data = new CallbackData{SimplePost(token)};
 
   auto result = IotconUtils::ConvertIotconError(
-       iotcon_find_platform_info(host.c_str(), con_type_e, IotconPlatformInfoCb,
-                                data));
+       iotcon_find_platform_info(host_address, con_type_e, query, IotconPlatformInfoCb, data));
 
   if (!result) {
     delete data;
@@ -1232,15 +1468,17 @@ common::TizenResult IotconInstance::ServerCreateResource(const picojson::object&
   CHECK_PRIVILEGE(kPrivilegeIotcon);
 
   CHECK_EXIST(args, kUriPath);
+  CHECK_EXIST(args, kResourceTypes);
+  CHECK_EXIST(args, kResourceInterfaces);
 
   const std::string& uri_path = args.find(kUriPath)->second.get<std::string>();
 
-  const auto& interfaces = IotconUtils::GetArg(args, kResourceInterfaces);
-  const auto& resource_interfaces = interfaces.is<picojson::array>() ? interfaces.get<picojson::array>() : picojson::array();
-
   const auto& types = IotconUtils::GetArg(args, kResourceTypes);
   const auto& resource_types = types.is<picojson::array>() ? types.get<picojson::array>() : picojson::array();
 
+  const auto& interfaces = IotconUtils::GetArg(args, kResourceInterfaces);
+  const auto& resource_interfaces = interfaces.is<picojson::array>() ? interfaces.get<picojson::array>() : picojson::array();
+
   int properties = IotconUtils::GetProperties(args);
 
   ResourceInfoPtr resource{new ResourceInfo()};
@@ -1271,6 +1509,97 @@ common::TizenResult IotconInstance::ServerRemoveResource(const picojson::object&
   return IotconServerManager::GetInstance().DestroyResource(GetId(args));
 }
 
+common::TizenResult IotconInstance::ServerStartPresence(const picojson::object& args) {
+  ScopeLogger();
+
+  CHECK_PRIVILEGE(kPrivilegeIotcon);
+  CHECK_EXIST(args, kTimeToLive);
+
+  if (!initialized_) {
+    return LogAndCreateTizenError(AbortError, "Iotcon service not initialized");
+  }
+
+  if (presence_started_) {
+    LoggerD("Iotcon service presence has been already started");
+    return common::TizenSuccess();
+  }
+
+  unsigned int timeToLive = static_cast<unsigned int>(IotconUtils::GetArg(args, kTimeToLive).get<double>());
+
+  auto result = IotconUtils::ConvertIotconError(iotcon_start_presence(timeToLive));
+  if (!result) {
+    LogAndReturnTizenError(result);
+  }
+
+  presence_started_ = true;
+  LoggerD("Iotcon service presence started");
+
+  return result;
+}
+
+common::TizenResult IotconInstance::ServerStopPresence(const picojson::object& args) {
+  ScopeLogger();
+
+  CHECK_PRIVILEGE(kPrivilegeIotcon);
+
+  if (!presence_started_) {
+    LoggerD("Iotcon service presence not started before");
+    return common::TizenSuccess();
+  }
+
+  auto result = IotconUtils::ConvertIotconError(iotcon_stop_presence());
+  if (!result) {
+    LogAndReturnTizenError(result);
+  }
+
+  presence_started_ = false;
+  LoggerD("Iotcon service presence stopped");
+
+  return result;
+}
+
+common::TizenResult IotconInstance::ServerSetDeviceName(const picojson::object& args) {
+  ScopeLogger();
+
+  CHECK_PRIVILEGE(kPrivilegeIotcon);
+  CHECK_EXIST(args, kDeviceName);
+
+  if (!initialized_) {
+    return LogAndCreateTizenError(AbortError, "Iotcon service not initialized");
+  }
+
+  const std::string& name = IotconUtils::GetArg(args, kDeviceName).get<std::string>();
+
+  auto result = IotconUtils::ConvertIotconError(iotcon_set_device_name(name.c_str()));
+  if (!result) {
+    LogAndReturnTizenError(result);
+  }
+
+  LoggerD("Iotcon service device name set");
+
+  return result;
+}
+
+common::TizenResult IotconInstance::Initialize(const picojson::object& args) {
+  ScopeLogger();
+
+  CHECK_PRIVILEGE(kPrivilegeIotcon);
+
+  CHECK_EXIST(args, kFilePath);
+  const auto& filePath = IotconUtils::GetArg(args, kFilePath);
+
+  auto result = IotconUtils::ConvertIotconError(
+                  iotcon_initialize(filePath.get<std::string>().c_str()));
+  if (!result) {
+    LogAndReturnTizenError(result);
+  }
+
+  initialized_ = true;
+  LoggerD("Iotcon service initialized");
+
+  return result;
+}
+
 common::TizenResult IotconInstance::GetTimeout(const picojson::object& args) {
   ScopeLogger();
 
index 5af4f6f..7e2070c 100644 (file)
@@ -45,6 +45,8 @@ class IotconInstance : public common::TizenInstance {
   common::TizenResult ResourceUnsetRequestListener(const picojson::object& args);
   common::TizenResult ResponseSend(const picojson::object& args);
   common::TizenResult RemoteResourceGetCachedRepresentation(const picojson::object& args);
+  common::TizenResult RemoteResourceGetOptions(const picojson::object& args);
+  common::TizenResult RemoteResourceSetOptions(const picojson::object& args);
   common::TizenResult RemoteResourceMethodGet(const picojson::object& args,
                                               const common::AsyncToken& token);
   common::TizenResult RemoteResourceMethodPut(const picojson::object& args,
@@ -53,25 +55,35 @@ class IotconInstance : public common::TizenInstance {
                                                const common::AsyncToken& token);
   common::TizenResult RemoteResourceMethodDelete(const picojson::object& args,
                                                  const common::AsyncToken& token);
-  common::TizenResult RemoteResourceSetStateChangeListener(const picojson::object& args);
-  common::TizenResult RemoteResourceUnsetStateChangeListener(const picojson::object& args);
+  common::TizenResult RemoteResourceStartObserving(const picojson::object& args);
+  common::TizenResult RemoteResourceStopObserving(const picojson::object& args);
   common::TizenResult RemoteResourceStartCaching(const picojson::object& args);
   common::TizenResult RemoteResourceStopCaching(const picojson::object& args);
-  common::TizenResult RemoteResourceSetConnectionChangeListener(const picojson::object& args);
-  common::TizenResult RemoteResourceUnsetConnectionChangeListener(const picojson::object& args);
+  common::TizenResult RemoteResourceSetResourceStateChangeListener(const picojson::object& args);
+  common::TizenResult RemoteResourceUnsetResourceStateChangeListener(const picojson::object& args);
+  common::TizenResult RemoteResourceGetTimeInterval(const picojson::object& args);
+  common::TizenResult RemoteResourceSetTimeInterval(const picojson::object& args);
   common::TizenResult ClientFindResource(const picojson::object& args);
   common::TizenResult ClientAddPresenceEventListener(const picojson::object& args);
   common::TizenResult ClientRemovePresenceEventListener(const picojson::object& args);
-  common::TizenResult ClientGetDeviceInfo(const picojson::object& args,
-                                          const common::AsyncToken& token);
-  common::TizenResult ClientGetPlatformInfo(const picojson::object& args,
-                                            const common::AsyncToken& token);
+  common::TizenResult ClientFindDeviceInfo(const picojson::object& args,
+                                           const common::AsyncToken& token);
+  common::TizenResult ClientFindPlatformInfo(const picojson::object& args,
+                                             const common::AsyncToken& token);
   common::TizenResult ServerCreateResource(const picojson::object& args);
   common::TizenResult ServerRemoveResource(const picojson::object& args);
+  common::TizenResult ServerStartPresence(const picojson::object& args);
+  common::TizenResult ServerStopPresence(const picojson::object& args);
+  common::TizenResult ServerSetDeviceName(const picojson::object& args);
+  common::TizenResult Initialize(const picojson::object& args);
   common::TizenResult GetTimeout(const picojson::object& args);
   common::TizenResult SetTimeout(const picojson::object& args);
 
   common::PostCallback PostForMethodCall(const common::AsyncToken& token, const FoundRemoteInfoPtr& resource);
+
+ private:
+  bool initialized_;
+  bool presence_started_;
 };
 
 }  // namespace iotcon
index 277e52e..be41a71 100644 (file)
@@ -55,8 +55,8 @@ void IotconServerManager::RequestHandler(iotcon_resource_h resource,
   }
 
   // handle observer changes
-  iotcon_observe_type_e type = IOTCON_OBSERVE_NO_TYPE;
-  result = IotconUtils::ConvertIotconError(iotcon_request_get_observe_type(request, &type));
+  iotcon_observe_type_e observe_type = IOTCON_OBSERVE_NO_TYPE;
+  result = IotconUtils::ConvertIotconError(iotcon_request_get_observe_type(request, &observe_type));
 
   if (!result) {
     LoggerE("iotcon_request_get_observe_type() failed");
@@ -71,7 +71,7 @@ void IotconServerManager::RequestHandler(iotcon_resource_h resource,
     return;
   }
 
-  switch (type) {
+  switch (observe_type) {
     case IOTCON_OBSERVE_NO_TYPE:
       LoggerD("observer did not change");
       break;
@@ -92,13 +92,29 @@ void IotconServerManager::RequestHandler(iotcon_resource_h resource,
     picojson::value value{picojson::object{}};
     auto& obj = value.get<picojson::object>();
 
-    result = IotconUtils::RequestToJson(request, &obj);
-
+    iotcon_request_type_e request_type = IOTCON_REQUEST_UNKNOWN;
+    auto result = IotconUtils::ConvertIotconError(iotcon_request_get_request_type(request, &request_type));
+    if (!result) {
+      LoggerE("iotcon_request_get_request_type() failed");
+      return;
+    }
+    picojson::value request_type_val{IotconUtils::FromRequestType(request_type)};
+    obj.insert(std::make_pair(kRequestType, request_type_val));
+    picojson::value observe_type_val{IotconUtils::FromObserveType(observe_type)};
+    obj.insert(std::make_pair(kObserveType, observe_type_val));
+    picojson::value observe_id_val{static_cast<double>(observer_id)};
+    obj.insert(std::make_pair(kObserverId, observe_id_val));
+
+    picojson::value request_val{picojson::object{}};
+    auto& request_obj = request_val.get<picojson::object>();
+    result = IotconUtils::RequestToJson(request, &request_obj);
     if (!result) {
       LoggerE("RequestToJson() failed");
       return;
     }
 
+    obj.insert(std::make_pair(kRequest, request_val));
+
     // create response
     iotcon_response_h response = nullptr;
     result = IotconUtils::ConvertIotconError(iotcon_response_create(request, &response));
index c167418..1436236 100644 (file)
@@ -71,6 +71,7 @@ namespace {
   X(IOTCON_RESPONSE_ERROR, "ERROR") \
   X(IOTCON_RESPONSE_RESOURCE_CREATED, "RESOURCE_CREATED") \
   X(IOTCON_RESPONSE_RESOURCE_DELETED, "RESOURCE_DELETED") \
+  X(IOTCON_RESPONSE_RESOURCE_CHANGED, "RESOURCE_CHANGED") \
   X(IOTCON_RESPONSE_SLOW, "SLOW") \
   X(IOTCON_RESPONSE_FORBIDDEN, "FORBIDDEN") \
   XD(IOTCON_RESPONSE_ERROR, "unknown")
@@ -92,17 +93,19 @@ const std::string kResourceTypes = "resourceTypes";
 const std::string kResourceInterfaces = "resourceInterfaces";
 const std::string kResourceChildren = "resources";
 const std::string kUriPath = "uriPath";
-const std::string kStates = "states";
+const std::string kAttributes = "attributes";
 const std::string kId = "id";
 const std::string kKeepId = "keepId";
 const std::string kDeviceId = "deviceId";
+const std::string kDeviceName = "deviceName";
 const std::string kHostAddress = "hostAddress";
 const std::string kConnectivityType = "connectivityType";
 const std::string kObservePolicy = "observePolicy";
 
 const std::string kRepresentation = "representation";
-const std::string kRepresentations = "representations";
+const std::string kChildren = "children";
 const std::string kRequestType = "type";
+const std::string kRequest = "request";
 const std::string kOptions = "options";
 const std::string kQuery = "query";
 const std::string kObserverId = "observerId";
@@ -129,7 +132,6 @@ const std::string kFirmwareVersion = "firmwareVersion";
 const std::string kSupportUrl = "supportUrl";
 const std::string kSystemTime = "systemTime";
 
-const std::string kDeviceName = "deviceName";
 const std::string kSpecVersion = "specVersion";
 const std::string kOicDeviceId = "oicDeviceId";
 const std::string kDataModelVersion = "dataModelVersion";
@@ -139,6 +141,8 @@ const std::string kTriggerType = "triggerType";
 
 const std::string kResult = "result";
 
+const int defRemoteResTimeInterval = 10;
+
 using common::TizenResult;
 using common::TizenSuccess;
 
@@ -202,7 +206,7 @@ TizenResult IotconUtils::ArrayToInterfaces(const picojson::array& i, iotcon_reso
     LogAndReturnTizenError(result, ("iotcon_resource_interfaces_create() failed"));
   }
 
-  std::unique_ptr<std::remove_pointer<iotcon_resource_interfaces_h>::type, void(*)(iotcon_resource_interfaces_h)> ptr{interfaces, &iotcon_resource_interfaces_destroy};
+  std::unique_ptr<std::remove_pointer<iotcon_resource_interfaces_h>::type, int(*)(iotcon_resource_interfaces_h)> ptr{interfaces, &iotcon_resource_interfaces_destroy};
 
   for (const auto& iter : i) {
     if (!iter.is<std::string>()) {
@@ -252,7 +256,7 @@ TizenResult IotconUtils::ArrayToTypes(const picojson::array& types, iotcon_resou
     LogAndReturnTizenError(result, ("iotcon_resource_types_create() failed"));
   }
 
-  std::unique_ptr<std::remove_pointer<iotcon_resource_types_h>::type, void(*)(iotcon_resource_types_h)> ptr{resource_types, &iotcon_resource_types_destroy};
+  std::unique_ptr<std::remove_pointer<iotcon_resource_types_h>::type, int(*)(iotcon_resource_types_h)> ptr{resource_types, &iotcon_resource_types_destroy};
 
   for (const auto& iter : types) {
     if (!iter.is<std::string>()) {
@@ -377,7 +381,13 @@ TizenResult IotconUtils::ExtractFromRemoteResource(RemoteResourceInfo* resource)
   result = ConvertIotconError(
       iotcon_remote_resource_get_device_id(resource->resource, &resource->device_id));
   if (!result) {
-    LogAndReturnTizenError(result, ("Gathering host address failed"));
+    LogAndReturnTizenError(result, ("Gathering device id failed"));
+  }
+
+  result = ConvertIotconError(
+      iotcon_remote_resource_get_device_name(resource->resource, &resource->device_name));
+  if (!result) {
+    LogAndReturnTizenError(result, ("Gathering device name failed"));
   }
 
   result = ConvertIotconError(
@@ -406,6 +416,12 @@ TizenResult IotconUtils::ExtractFromRemoteResource(RemoteResourceInfo* resource)
     //LogAndReturnTizenError(result, ("Gathering cached representation failed"));
   }
 
+  result = ConvertIotconError(
+      iotcon_remote_resource_get_options(resource->resource, &resource->options));
+  if (!result) {
+    LogAndReturnTizenError(result, ("Gathering options failed"));
+  }
+
   return TizenSuccess();
 }
 
@@ -424,6 +440,7 @@ TizenResult IotconUtils::RemoteResourceToJson(iotcon_remote_resource_h handle,
       FromConnectivityType(remote_res.connectivity_type))));
   res->insert(std::make_pair(kHostAddress, picojson::value(remote_res.host_address)));
   res->insert(std::make_pair(kDeviceId, picojson::value(remote_res.device_id)));
+  res->insert(std::make_pair(kDeviceName, picojson::value(remote_res.device_name)));
 
   if (remote_res.types) {
     picojson::array types;
@@ -451,6 +468,15 @@ TizenResult IotconUtils::RemoteResourceToJson(iotcon_remote_resource_h handle,
     res->insert(std::make_pair(kRepresentation, repr_json));
   }
 
+  if (remote_res.options) {
+    picojson::array options;
+    result = OptionsToJson(remote_res.options, &options);
+    if (!result) {
+      LogAndReturnTizenError(result, ("OptionsToJson() failed"));
+    }
+    res->insert(std::make_pair(kOptions, picojson::value(options)));
+  }
+
   return TizenSuccess();
 }
 
@@ -517,6 +543,21 @@ common::TizenResult IotconUtils::RemoteResourceFromJson(const picojson::object&
     LogAndReturnTizenError(res, ("creating handle failed"));
   }
 
+  // options is optional nullable. if it's not present, just ignore it
+  auto options_it = source.find(kOptions);
+  if (source.end() != options_it) {
+    const auto& options_array = options_it->second.get<picojson::array>();
+    iotcon_options_h options = nullptr;
+    res = IotconUtils::OptionsFromJson(options_array, &options);
+    if (!res) {
+      return res;
+    }
+    res = IotconUtils::ConvertIotconError(iotcon_remote_resource_set_options((*ptr)->handle, options));
+    if (!res) {
+      LogAndReturnTizenError(res, ("iotcon_response_set_options() failed"));
+    }
+  }
+
   return TizenSuccess();
 }
 
@@ -565,16 +606,6 @@ common::TizenResult IotconUtils::RequestToJson(iotcon_request_h request,
     }
 
     {
-      // requestType
-      iotcon_request_type_e request_type = IOTCON_REQUEST_UNKNOWN;
-      auto result = ConvertIotconError(iotcon_request_get_request_type(request, &request_type));
-      if (!result) {
-        LogAndReturnTizenError(result, ("iotcon_request_get_request_type() failed"));
-      }
-      out->insert(std::make_pair(kRequestType, picojson::value{FromRequestType(request_type)}));
-    }
-
-    {
       // options
       iotcon_options_h options = nullptr;
       auto result = ConvertIotconError(iotcon_request_get_options(request, &options));
@@ -603,26 +634,6 @@ common::TizenResult IotconUtils::RequestToJson(iotcon_request_h request,
       }
       out->insert(std::make_pair(kQuery, v));
     }
-
-    {
-      // observerId
-      int observer_id = -1;
-      auto result = ConvertIotconError(iotcon_request_get_observe_id(request, &observer_id));
-      if (!result) {
-        LogAndReturnTizenError(result, ("iotcon_request_get_observe_id() failed"));
-      }
-      out->insert(std::make_pair(kObserverId, picojson::value{static_cast<double>(observer_id)}));
-    }
-
-    {
-      // observeType
-      iotcon_observe_type_e observe_type = IOTCON_OBSERVE_NO_TYPE;
-      auto result = ConvertIotconError(iotcon_request_get_observe_type(request, &observe_type));
-      if (!result) {
-        LogAndReturnTizenError(result, ("iotcon_request_get_observe_type() failed"));
-      }
-      out->insert(std::make_pair(kObserveType, picojson::value{FromObserveType(observe_type)}));
-    }
   } else {
     LoggerW("Request handle is null, ignoring");
   }
@@ -672,7 +683,7 @@ common::TizenResult IotconUtils::RepresentationToJson(iotcon_representation_h re
     }
 
     {
-      // states
+      // attributes
       iotcon_attributes_h attributes = nullptr;
       auto result = ConvertIotconError(iotcon_representation_get_attributes(representation, &attributes));
       if (!result) {
@@ -683,11 +694,11 @@ common::TizenResult IotconUtils::RepresentationToJson(iotcon_representation_h re
       if (!result) {
         LogAndReturnTizenError(result, ("AttributesToJson() failed"));
       }
-      out->insert(std::make_pair(kStates, v));
+      out->insert(std::make_pair(kAttributes, v));
     }
 
     {
-      // representations
+      // children
       picojson::value v{picojson::array{}};
       auto result = ConvertIotconError(iotcon_representation_foreach_children(representation, [](iotcon_representation_h child, void* user_data) -> bool {
         auto arr = static_cast<picojson::array*>(user_data);
@@ -702,7 +713,7 @@ common::TizenResult IotconUtils::RepresentationToJson(iotcon_representation_h re
       if (!result) {
         LogAndReturnTizenError(result, ("iotcon_representation_foreach_children() failed"));
       }
-      out->insert(std::make_pair(kRepresentations, v));
+      out->insert(std::make_pair(kChildren, v));
     }
   } else {
     LoggerW("Representation handle is null, ignoring");
@@ -1067,7 +1078,7 @@ common::TizenResult IotconUtils::QueryFromJson(const picojson::object& source, i
   if (!result) {
     LogAndReturnTizenError(result, ("iotcon_query_create() failed"));
   }
-  std::unique_ptr<std::remove_pointer<iotcon_query_h>::type, void(*)(iotcon_query_h)>
+  std::unique_ptr<std::remove_pointer<iotcon_query_h>::type, int(*)(iotcon_query_h)>
   query_ptr(query, &iotcon_query_destroy); // automatically release the memory
   {
     // resourceType
@@ -1189,7 +1200,7 @@ common::TizenResult IotconUtils::RepresentationFromResource(const ResourceInfoPt
     LogAndReturnTizenError(result, ("iotcon_representation_create() failed"));
   }
 
-  std::unique_ptr<std::remove_pointer<iotcon_representation_h>::type, void(*)(iotcon_representation_h)> ptr{representation, &iotcon_representation_destroy};
+  std::unique_ptr<std::remove_pointer<iotcon_representation_h>::type, int(*)(iotcon_representation_h)> ptr{representation, &iotcon_representation_destroy};
 
   {
     char* uri_path = nullptr;
@@ -1295,7 +1306,7 @@ common::TizenResult IotconUtils::AttributesFromJson(const picojson::object& s,
     LogAndReturnTizenError(result, ("iotcon_attributes_create() failed"));
   }
 
-  std::unique_ptr<std::remove_pointer<iotcon_attributes_h>::type, void(*)(iotcon_attributes_h)> ptr{attributes, &iotcon_attributes_destroy};
+  std::unique_ptr<std::remove_pointer<iotcon_attributes_h>::type, int(*)(iotcon_attributes_h)> ptr{attributes, &iotcon_attributes_destroy};
 
   for (const auto& property : s) {
     const auto& key = property.first;
@@ -1405,7 +1416,7 @@ common::TizenResult IotconUtils::StateListFromJson(const picojson::array& l,
     LogAndReturnTizenError(result, ("iotcon_list_create() failed"));
   }
 
-  std::unique_ptr<std::remove_pointer<iotcon_list_h>::type, void(*)(iotcon_list_h)> ptr{list, &iotcon_list_destroy};
+  std::unique_ptr<std::remove_pointer<iotcon_list_h>::type, int(*)(iotcon_list_h)> ptr{list, &iotcon_list_destroy};
 
   int position = 0;
 
@@ -1493,7 +1504,7 @@ common::TizenResult IotconUtils::StateListFromJson(const picojson::array& l,
       default:
         // should not happen
         LoggerE("Unexpected type: %d", type);
-        return common::UnknownError("Unexpected list type");
+        return common::AbortError("Unexpected list type");
     }
   }
 
@@ -1617,7 +1628,7 @@ common::TizenResult IotconUtils::OptionsFromJson(const picojson::array& o,
     LogAndReturnTizenError(result, ("iotcon_options_create() failed"));
   }
 
-  std::unique_ptr<std::remove_pointer<iotcon_options_h>::type, void(*)(iotcon_options_h)> ptr{options, &iotcon_options_destroy};
+  std::unique_ptr<std::remove_pointer<iotcon_options_h>::type, int(*)(iotcon_options_h)> ptr{options, &iotcon_options_destroy};
 
   // we ignore values with incorrect types
   // TODO: should we convert them in JS?
@@ -1650,7 +1661,7 @@ common::TizenResult IotconUtils::RepresentationFromJson(const picojson::object&
     LogAndReturnTizenError(result, ("iotcon_representation_create() failed"));
   }
 
-  std::unique_ptr<std::remove_pointer<iotcon_representation_h>::type, void(*)(iotcon_representation_h)> ptr{representation, &iotcon_representation_destroy};
+  std::unique_ptr<std::remove_pointer<iotcon_representation_h>::type, int(*)(iotcon_representation_h)> ptr{representation, &iotcon_representation_destroy};
 
   {
     const auto& uri_path = r.find(kUriPath);
@@ -1708,7 +1719,7 @@ common::TizenResult IotconUtils::RepresentationFromJson(const picojson::object&
   }
 
   {
-    const auto& states = r.find(kStates);
+    const auto& states = r.find(kAttributes);
     if (r.end() != states && states->second.is<picojson::object>()) {
       iotcon_attributes_h s = nullptr;
 
@@ -1728,9 +1739,9 @@ common::TizenResult IotconUtils::RepresentationFromJson(const picojson::object&
   }
 
   {
-    const auto& representations = r.find(kRepresentations);
-    if (r.end() != representations && representations->second.is<picojson::array>()) {
-      for (const auto& js_child : representations->second.get<picojson::array>()) {
+    const auto& children = r.find(kChildren);
+    if (r.end() != children && children->second.is<picojson::array>()) {
+      for (const auto& js_child : children->second.get<picojson::array>()) {
         if (js_child.is<picojson::object>()) {
           iotcon_representation_h child = nullptr;
 
@@ -1747,7 +1758,7 @@ common::TizenResult IotconUtils::RepresentationFromJson(const picojson::object&
             LogAndReturnTizenError(result, ("iotcon_representation_add_child() failed"));
           }
         } else {
-          return LogAndCreateTizenError(TypeMismatchError, "The Representation.representations attribute needs to be an array of Representation objects.");
+          return LogAndCreateTizenError(TypeMismatchError, "The Representation.children attribute needs to be an array of Representation objects.");
         }
       }
     }
@@ -1958,12 +1969,10 @@ common::TizenResult IotconUtils::ConvertIotconError(int error) {
     case IOTCON_ERROR_NOT_SUPPORTED:
       return common::NotSupportedError(error);
 
+    case IOTCON_ERROR_NO_DATA:
     case IOTCON_ERROR_INVALID_PARAMETER:
       return common::InvalidValuesError(error);
 
-    case IOTCON_ERROR_NO_DATA:
-      return common::NotFoundError(error);
-
     case IOTCON_ERROR_TIMEOUT:
       return common::TimeoutError(error);
 
index f946419..e6a1505 100644 (file)
@@ -49,10 +49,11 @@ extern const std::string kResourceType;
 extern const std::string kResourceInterfaces;
 extern const std::string kResourceChildren;
 extern const std::string kUriPath;
-extern const std::string kStates;
+extern const std::string kAttributes;
 extern const std::string kId;
 extern const std::string kKeepId;
 extern const std::string kDeviceId;
+extern const std::string kDeviceName;
 extern const std::string kHostAddress;
 extern const std::string kConnectivityType;
 extern const std::string kResourceType;
@@ -60,6 +61,12 @@ extern const std::string kRepresentation;
 extern const std::string kOptions;
 extern const std::string kQuery;
 extern const std::string kObservePolicy;
+extern const std::string kRequestType;
+extern const std::string kRequest;
+extern const std::string kObserveType;
+extern const std::string kObserverId;
+
+extern const int defRemoteResTimeInterval;
 
 class ResourceInfo;
 class PresenceEvent;
@@ -96,6 +103,7 @@ struct RemoteResourceInfo {
   iotcon_connectivity_type_e connectivity_type;
   char* host_address;
   char* device_id;
+  char* device_name;
   iotcon_resource_types_h types;
   iotcon_resource_interfaces_h ifaces;
   uint8_t properties;  // to check if observable
@@ -104,7 +112,7 @@ struct RemoteResourceInfo {
   RemoteResourceInfo() :
     resource(nullptr), uri_path(nullptr),
     connectivity_type(IOTCON_CONNECTIVITY_ALL), host_address(nullptr),
-    device_id(nullptr), types(nullptr), ifaces(0),
+    device_id(nullptr), device_name(nullptr), types(nullptr), ifaces(0),
     properties(0), options(nullptr), representation(nullptr) {}
   ~RemoteResourceInfo() {
     //according to native description, must not release any handles
@@ -116,8 +124,9 @@ struct FoundRemoteInfo {
   iotcon_remote_resource_h handle;
   short ref_count; // counter for registered listeners for this handle
   //TODO add listeners for each type
-  common::PostCallback connection_listener;
+  common::PostCallback state_listener;
   common::PostCallback observe_listener;
+  common::PostCallback cache_change_listener;
   FoundRemoteInfo() :
     id(0), handle(nullptr), ref_count(1) {} //initialize with 1 (struct is created, so it
                                             //mean that some listener would be created)
index 74a0b46..55f7da2 100755 (executable)
@@ -206,7 +206,7 @@ msg_error_t MessagingDatabaseManager::connect()
 
         memset(strDBName, 0x00, sizeof(strDBName));
         snprintf(strDBName, sizeof(strDBName), "%s/%s",
-                 tzplatform_getenv(TZ_SYS_DB), MSG_DB_NAME);
+                 tzplatform_getenv(TZ_SYS_GLOBALUSER_DB), MSG_DB_NAME);
 
         // this should match MSGFW_DB_NAME defined in msg-service/include/utils/MsgSqliteWrapper.h
         SLoggerD("Using database: [%s]", strDBName);
index a302c6a..9c9bf00 100644 (file)
         'secureelement_extension.h',
         'secureelement_instance.cc',
         'secureelement_instance.h',
-        'secureelement_seservice.cc',
-        'secureelement_seservice.h',
-        'secureelement_reader.cc',
-        'secureelement_reader.h',
-        'secureelement_session.cc',
-        'secureelement_session.h',
-        'secureelement_channel.cc',
-        'secureelement_channel.h',
       ],
       'includes': [
         '../common/pkg-config.gypi',
       ],
       'conditions': [
         [ 'tizen == 1', {
-            'variables': { 'packages': ['smartcard-service', 'smartcard-service-common'] },
+            'variables': { 'packages': ['capi-network-smartcard'] },
         }],
       ],
     },
index ccbcde2..4ff5bd2 100644 (file)
@@ -184,7 +184,7 @@ function Reader(reader_handle) {
                               console.log('SEReader_isPresent error: ' + native_.getErrorObject(result));
                               return false;
                             } else {
-                              return native_.getResultObject(result).isPresent;
+                              return native_.getResultObject(result);
                             }
                         }},
         _handle:    {   configurable: false,
@@ -202,7 +202,7 @@ Reader.prototype.getName = function() {
         throw native_.getErrorObject(result);
     }
 
-    return native_.getResultObject(result).name;
+    return native_.getResultObject(result);
 };
 
 Reader.prototype.openSession = function() {
@@ -306,7 +306,7 @@ function Session(session_handle) {
                           console.log('SESession_isClosed error: ' + native_.getErrorObject(result));
                           return true;
                         } else {
-                          return native_.getResultObject(result).isClosed;
+                          return native_.getResultObject(result);
                         }
                       }
                     },
diff --git a/src/secureelement/secureelement_channel.cc b/src/secureelement/secureelement_channel.cc
deleted file mode 100644 (file)
index e7355d3..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
- *
- *    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.
- */
-
-#include "common/picojson.h"
-#include "common/logger.h"
-#include "secureelement_channel.h"
-
-using namespace smartcard_service_api;
-
-namespace extension {
-namespace secureelement {
-
-void SEChannel::close() {
-    LoggerD("Entered");
-    if (m_channel_ptr && !m_channel_ptr->isClosed()) {
-        m_channel_ptr->closeSync();
-    }
-}
-
-
-ByteArray SEChannel::transmit(const picojson::array& v_command) {
-    LoggerD("Entered");
-    ByteArray response;
-    if ( m_channel_ptr) {
-        size_t v_command_size = v_command.size();
-        uint8_t* command = new uint8_t[v_command_size];
-        for (size_t i = 0; i < v_command_size; i++) {
-            command[i] = (uint8_t) static_cast<long>(v_command[i].get<double>());
-        }
-        ByteArray ba_command(command, v_command.size());
-        delete [] command;
-        m_channel_ptr->transmitSync( ba_command, response);
-    }
-    return response;
-}
-
-
-ByteArray SEChannel::getSelectResponse() {
-    LoggerD("Entered");
-    ByteArray response;
-    if ( m_channel_ptr) {
-        response = m_channel_ptr->getSelectResponse();
-    }
-    return response;
-}
-
-} // secureelement
-} // extension
index 3b78716..ea01bee 100644 (file)
 
 #include "secureelement/secureelement_instance.h"
 
-#include <SEService.h>
-#include <Reader.h>
-#include "common/picojson.h"
-#include "common/logger.h"
-#include "common/task-queue.h"
-#include "common/tools.h"
+#include <thread>
+#include <smartcard.h>
 
-#include "secureelement_reader.h"
-#include "secureelement_session.h"
-#include "secureelement_channel.h"
+#include "common/tools.h"
+#include "common/scope_exit.h"
 
 namespace extension {
 namespace secureelement {
 
-using namespace common;
-using namespace smartcard_service_api;
+using common::TizenResult;
+using common::TizenSuccess;
 
 namespace {
 const std::string kPrivilegeSecureElement = "http://tizen.org/privilege/secureelement";
+
+const std::string kHandle = "handle";
+const std::string kIsBasicChannel = "isBasicChannel";
+const std::string kAid = "aid";
+const std::string kAction = "action";
+const std::string kCommand = "command";
+const std::string kListenerId = "listenerId";
+const std::string kListener = "SecureElementChangeListener";
+const std::string kReady = "onSEReady";
+const std::string kNotReady = "onSENotReady";
+
+TizenResult ConvertErrorCode(int error) {
+  switch (error) {
+    case SMARTCARD_ERROR_NONE:
+      return TizenSuccess();
+    case SMARTCARD_ERROR_INVALID_PARAMETER:
+      return common::InvalidValuesError(error);
+    case SMARTCARD_ERROR_IO_ERROR:
+      return common::IoError(error);
+    case SMARTCARD_ERROR_ILLEGAL_STATE:
+    case SMARTCARD_ERROR_CHANNEL_NOT_AVAILABLE:
+      return common::InvalidStateError(error);
+    case SMARTCARD_ERROR_NO_SUCH_ELEMENT:
+      return common::NotFoundError(error);
+    case SMARTCARD_ERROR_GENERAL:
+    case SMARTCARD_ERROR_ILLEGAL_REFERENCE:
+    case SMARTCARD_ERROR_OPERATION_NOT_SUPPORTED:
+    case SMARTCARD_ERROR_PERMISSION_DENIED:
+    case SMARTCARD_ERROR_NOT_INITIALIZED:
+    case SMARTCARD_ERROR_NOT_SUPPORTED:
+    default:
+      return common::UnknownError(error);
+  }
 }
 
-SecureElementInstance::SecureElementInstance()
-    : service_(*this) {
-    LoggerD("Entered");
+void SecureElementEventCb(int reader, smartcard_reader_event_type_e event_type, void *user_data) {
+  ScopeLogger();
+
+  //TODO What action should be performed in case of SMARTCARD_READER_EVENT_TYPE_IO_ERROR event
+  if (SMARTCARD_READER_EVENT_TYPE_INSERTED != event_type &&
+      SMARTCARD_READER_EVENT_TYPE_REMOVED != event_type) {
+    LoggerD("Incorrect event type");
+    return;
+  }
+
+  SecureElementInstance* instance = static_cast<SecureElementInstance*>(user_data);
+  if (!instance) {
+    LoggerD("user data is null");
+    return;
+  }
+
+  picojson::value result{picojson::object{}};
+  auto& obj = result.get<picojson::object>();
 
-    using std::placeholders::_1;
-    using std::placeholders::_2;
+  std::string action = SMARTCARD_READER_EVENT_TYPE_INSERTED == event_type ? kReady : kNotReady;
+
+  obj.insert(std::make_pair(kAction, picojson::value(action)));
+  obj.insert(std::make_pair(kHandle, picojson::value(static_cast<double>(reader))));
+  obj.insert(std::make_pair(kListenerId, picojson::value(kListener)));
+
+  instance->Instance::PostMessage(instance, result.serialize().c_str());
+}
+
+} //namespace
+
+SecureElementInstance::SecureElementInstance() :
+  is_initialized_(false),
+  is_listener_set_(false) {
+  ScopeLogger();
+
+  using std::placeholders::_1;
+  using std::placeholders::_2;
 
 #define REGISTER_SYNC(c,x) \
-    RegisterSyncHandler(c, std::bind(&SecureElementInstance::x, this, _1, _2));
-
-    REGISTER_SYNC("SEService_registerSEListener", RegisterSEListener);
-    REGISTER_SYNC("SEService_unregisterSEListener", UnregisterSEListener);
-    REGISTER_SYNC("SEService_shutdown", Shutdown);
-    REGISTER_SYNC("SEReader_getName", GetName);
-    REGISTER_SYNC("SEReader_isPresent", IsPresent);
-    REGISTER_SYNC("SEReader_closeSessions", CloseSessions);
-    REGISTER_SYNC("SESession_getATR", GetATR);
-    REGISTER_SYNC("SESession_isClosed", IsSessionClosed);
-    REGISTER_SYNC("SESession_close", CloseSession);
-    REGISTER_SYNC("SESession_closeChannels", CloseChannels);
-    REGISTER_SYNC("SEChannel_close", CloseChannel);
-    REGISTER_SYNC("SEChannel_getSelectResponse", GetSelectResponse);
+  RegisterSyncHandler(c, std::bind(&SecureElementInstance::x, this, _1));
+
+  REGISTER_SYNC("SEService_registerSEListener", RegisterSEListener);
+  REGISTER_SYNC("SEService_unregisterSEListener", UnregisterSEListener);
+  REGISTER_SYNC("SEService_shutdown", Shutdown);
+  REGISTER_SYNC("SEReader_getName", GetName);
+  REGISTER_SYNC("SEReader_isPresent", IsPresent);
+  REGISTER_SYNC("SEReader_closeSessions", CloseSessions);
+  REGISTER_SYNC("SESession_getATR", GetATR);
+  REGISTER_SYNC("SESession_isClosed", IsSessionClosed);
+  REGISTER_SYNC("SESession_close", CloseSession);
+  REGISTER_SYNC("SESession_closeChannels", CloseChannels);
+  REGISTER_SYNC("SEChannel_close", CloseChannel);
+  REGISTER_SYNC("SEChannel_getSelectResponse", GetSelectResponse);
 #undef REGISTER_SYNC
 
 #define REGISTER(c,x) \
-    RegisterSyncHandler(c, std::bind(&SecureElementInstance::x, this, _1, _2));
+  RegisterHandler(c, std::bind(&SecureElementInstance::x, this, _1, _2));
 
-    REGISTER("SEService_getReaders", GetReaders);
-    REGISTER("SEReader_openSession", OpenSession);
-    REGISTER("SESession_openBasicChannel", OpenBasicChannel);
-    REGISTER("SESession_openLogicalChannel", OpenLogicalChannel);
-    REGISTER("SEChannel_transmit", Transmit);
+  REGISTER("SEService_getReaders", GetReaders);
+  REGISTER("SEReader_openSession", OpenSession);
+  REGISTER("SESession_openBasicChannel", OpenBasicChannel);
+  REGISTER("SESession_openLogicalChannel", OpenLogicalChannel);
+  REGISTER("SEChannel_transmit", Transmit);
 #undef REGISTER
+
+  if (SMARTCARD_ERROR_NONE == smartcard_initialize()) {
+    is_initialized_ = true;
+  }
 }
 
 SecureElementInstance::~SecureElementInstance() {
+  ScopeLogger();
+
+  UnregisterListener();
+  Deinitialize();
 }
 
-void SecureElementInstance::GetReaders(const picojson::value& args, picojson::object& out) {
-  LoggerD("Entered");
+// Service methods
+TizenResult SecureElementInstance::GetReaders(picojson::object const& args, const common::AsyncToken& token) {
+  ScopeLogger();
 
-  CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
+  CHECK_PRIVILEGE(kPrivilegeSecureElement);
 
-  double callback_id = 0.0;
-  if (args.contains("callbackId")) {
-    callback_id = args.get("callbackId").get<double>();
-  }
+  auto get_readers = [this](const common::AsyncToken& token) -> void {
+    TizenResult result = TizenSuccess();
+
+    int* readers = nullptr;
+    int count = 0;
+
+    int ret = smartcard_get_readers(&readers, &count);
+    SCOPE_EXIT {
+      free(readers);
+    };
+
+    if (SMARTCARD_ERROR_NONE != ret) {
+      LoggerE("smartcard_get_readers() failed");
+      result = ConvertErrorCode(ret);
+    } else {
+      picojson::value response{picojson::array{}};
+      auto& array = response.get<picojson::array>();
+      bool is_present = false;
+
+      for (int i = 0; i < count; i++) {
+        ret = smartcard_reader_is_secure_element_present(readers[i], &is_present);
+        if (SMARTCARD_ERROR_NONE == ret && is_present) {
+            array.push_back(picojson::value(static_cast<double>(readers[i])));
+        }
+      }
+
+      result = TizenSuccess(response);
+    }
+
+    this->Post(token, result);
+  };
 
-  service_.GetReaders(callback_id);
-  ReportSuccess(out);
+  std::thread(get_readers, token).detach();
+
+  return TizenSuccess();
 }
 
-void SecureElementInstance::RegisterSEListener(const picojson::value& args, picojson::object& out) {
-  LoggerD("Entered");
+TizenResult SecureElementInstance::RegisterSEListener(picojson::object const& args) {
+  ScopeLogger();
+
+  CHECK_PRIVILEGE(kPrivilegeSecureElement);
 
-  CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
+  int ret = smartcard_reader_set_event_cb(SecureElementEventCb, this);
+  if (SMARTCARD_ERROR_NONE != ret) {
+    LogAndReturnTizenError(ConvertErrorCode(ret), ("smartcard_reader_set_event_cb() failed"));
+  }
+
+  is_listener_set_ = true;
 
-  service_.RegisterSEListener();
-  ReportSuccess(out);
+  return TizenSuccess();
 }
 
-void SecureElementInstance::UnregisterSEListener(
-    const picojson::value& args, picojson::object& out) {
-  LoggerD("Entered");
+TizenResult SecureElementInstance::UnregisterListener() {
+  ScopeLogger();
 
-  CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
+  CHECK_PRIVILEGE(kPrivilegeSecureElement);
+
+  if (is_listener_set_) {
+    int ret = smartcard_reader_unset_event_cb();
+    if (SMARTCARD_ERROR_NONE != ret) {
+      LogAndReturnTizenError(ConvertErrorCode(ret), ("smartcard_reader_unset_event_cb() failed"));
+    }
 
-  service_.UnregisterSEListener();
-  ReportSuccess(out);
+    is_listener_set_ = false;
+  }
+
+  return TizenSuccess();
 }
 
-void SecureElementInstance::Shutdown(const picojson::value& args, picojson::object& out) {
-  LoggerD("Entered");
+TizenResult SecureElementInstance::UnregisterSEListener(picojson::object const& args) {
+  ScopeLogger();
 
-  CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
+  CHECK_PRIVILEGE(kPrivilegeSecureElement);
 
-  service_.Shutdown();
-  ReportSuccess(out);
+  return UnregisterListener();
 }
 
-void SecureElementInstance::GetName(
-        const picojson::value& args, picojson::object& out) {
-    LoggerD("Entered");
+TizenResult SecureElementInstance::Deinitialize() {
+  ScopeLogger();
+
+  CHECK_PRIVILEGE(kPrivilegeSecureElement);
+
+  if (is_initialized_) {
+    int ret = smartcard_deinitialize();
+    if (SMARTCARD_ERROR_NONE != ret) {
+      LogAndReturnTizenError(ConvertErrorCode(ret), ("smartcard_deinitialize() failed"));
+    }
 
-    CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
+    is_initialized_ = false;
+  }
 
-    Reader* reader_ptr = (Reader*) static_cast<long>(args.get("handle").get<double>());
-    SEReader seReader(reader_ptr);
-    picojson::value result = seReader.getName();
-    ReportSuccess(result, out);
+  return TizenSuccess();
 }
 
-void SecureElementInstance::IsPresent(
-        const picojson::value& args, picojson::object& out) {
-    LoggerD("Entered");
+TizenResult SecureElementInstance::Shutdown(picojson::object const& args) {
+  ScopeLogger();
 
-    Reader* reader_ptr = (Reader*) static_cast<long>(args.get("handle").get<double>());
-    SEReader seReader(reader_ptr);
-    picojson::value result = seReader.isPresent();
-    ReportSuccess(result, out);
+  UnregisterListener();
+  return Deinitialize();
 }
 
-void SecureElementInstance::CloseSessions(
-        const picojson::value& args, picojson::object& out) {
-    LoggerD("Entered");
+// Reader methods
+TizenResult SecureElementInstance::GetName(picojson::object const& args) {
+  ScopeLogger();
+
+  CHECK_PRIVILEGE(kPrivilegeSecureElement);
+
+  int reader = static_cast<int>(args.find(kHandle)->second.get<double>());
+  char* name = nullptr;
 
-    CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
+  int ret = smartcard_reader_get_name(reader, &name);
+  SCOPE_EXIT {
+    free(name);
+  };
 
-    Reader* reader_ptr = (Reader*) static_cast<long>(args.get("handle").get<double>());
-    SEReader seReader(reader_ptr);
-    seReader.closeSessions();
-    ReportSuccess(out);
+  if (SMARTCARD_ERROR_NONE != ret) {
+    LogAndReturnTizenError(ConvertErrorCode(ret), ("smartcard_reader_get_name() failed"));
+  }
+
+  return TizenSuccess(picojson::value(name));
 }
 
-void SecureElementInstance::CloseChannel( const picojson::value& args, picojson::object& out) {
-    LoggerD("Entered");
-    CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
+TizenResult SecureElementInstance::IsPresent(picojson::object const& args) {
+  ScopeLogger();
+
+  int reader = static_cast<int>(args.find(kHandle)->second.get<double>());
+  bool is_present = false;
+
+  int ret = smartcard_reader_is_secure_element_present(reader, &is_present);
+  if (SMARTCARD_ERROR_NONE != ret) {
+    LogAndReturnTizenError(ConvertErrorCode(ret),
+                           ("smartcard_reader_is_secure_element_present() failed"));
+  }
 
-    ClientChannel* channel_ptr = (ClientChannel*) static_cast<long>(args.get("handle").get<double>());
-    SEChannel seChannel(channel_ptr);
-    seChannel.close();
-    ReportSuccess(out);
+  return TizenSuccess(picojson::value(is_present));
 }
 
-void SecureElementInstance::GetSelectResponse( const picojson::value& args, picojson::object& out) {
-    LoggerD("Entered");
-    CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
+TizenResult SecureElementInstance::OpenSession(picojson::object const& args, const common::AsyncToken& token) {
+  ScopeLogger();
+
+  CHECK_PRIVILEGE(kPrivilegeSecureElement);
+
+  int reader = static_cast<int>(args.find(kHandle)->second.get<double>());
+
+  auto open_session = [this, reader](const common::AsyncToken& token) -> void {
+    TizenResult result = TizenSuccess();
+    int session = 0;
 
-    ClientChannel* channel_ptr = (ClientChannel*) static_cast<long>(args.get("handle").get<double>());
-    SEChannel seChannel(channel_ptr);
+    int ret = smartcard_reader_open_session(reader, &session);
+    if (SMARTCARD_ERROR_NONE != ret) {
+      LoggerE("smartcard_reader_open_session() failed");
+      result = ConvertErrorCode(ret);
+    } else {
+      picojson::value response{picojson::object{}};
+      auto& obj = response.get<picojson::object>();
 
-    ByteArray select_response = seChannel.getSelectResponse();
-    picojson::value result = picojson::value(picojson::array());
-    picojson::array& arr = result.get<picojson::array>();
-    size_t select_response_size = select_response.size();
-    for (size_t i = 0; i < select_response_size; i++) {
-        arr.push_back(picojson::value(static_cast<double>(select_response[i])));
+      obj.insert(std::make_pair(kHandle, picojson::value(static_cast<double>(session))));
+      result = TizenSuccess(response);
     }
-    ReportSuccess( result, out);
+
+    this->Post(token, result);
+  };
+
+  std::thread(open_session, token).detach();
+
+  return TizenSuccess();
 }
 
-void SecureElementInstance::OpenSession(
-        const picojson::value& args, picojson::object& out) {
-    LoggerD("Entered");
-    CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
-
-    const double callback_id = args.get("callbackId").get<double>();
-    Reader* reader_ptr = (Reader*) static_cast<long>(args.get("handle").get<double>());
-
-    auto open_session = [this, reader_ptr](const std::shared_ptr<picojson::value>& response) -> void {
-        LoggerD("Opening session");
-        try {
-            SEReader seReader(reader_ptr);
-            picojson::value result = seReader.openSession();
-            ReportSuccess(result, response->get<picojson::object>());
-        } catch (const ErrorIO& err) {
-            LogAndReportError(PlatformResult(ErrorCode::IO_ERR), &response->get<picojson::object>());
-        } catch (const ErrorIllegalState& err) {
-            LogAndReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR), &response->get<picojson::object>());
-        } catch (const ErrorIllegalParameter& err) {
-            LogAndReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR), &response->get<picojson::object>());
-        } catch (const ErrorSecurity& err) {
-            LogAndReportError(PlatformResult(ErrorCode::SECURITY_ERR), &response->get<picojson::object>());
-        } catch (const ExceptionBase& err) {
-            LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR), &response->get<picojson::object>());
-        }
-    };
+TizenResult SecureElementInstance::CloseSessions(picojson::object const& args) {
+  ScopeLogger();
 
-    auto open_session_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
-        LoggerD("Getting response");
+  CHECK_PRIVILEGE(kPrivilegeSecureElement);
 
-        picojson::object& obj = response->get<picojson::object>();
-        obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
-        Instance::PostMessage(this, response->serialize().c_str());
-    };
+  int reader = static_cast<int>(args.find(kHandle)->second.get<double>());
 
-    auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+  int ret = smartcard_reader_close_sessions(reader);
+  if (SMARTCARD_ERROR_NONE != ret) {
+    LogAndReturnTizenError(ConvertErrorCode(ret), ("smartcard_reader_close_sessions() failed"));
+  }
 
-    TaskQueue::GetInstance().Queue<picojson::value>(
-            open_session,
-            open_session_response,
-            data);
+  return TizenSuccess();
 }
 
 // Session functions
 
-void SecureElementInstance::OpenBasicChannel( const picojson::value& args, picojson::object& out) {
-    LoggerD("Enter");
-    CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
-
-    const double callback_id = args.get("callbackId").get<double>();
-    const picojson::array v_aid = args.get("aid").get<picojson::value::array>();
-    Session* session_ptr = (Session*) static_cast<long>(args.get("handle").get<double>());
-
-    auto open = [this, v_aid, session_ptr](const std::shared_ptr<picojson::value>& response) -> void {
-        LoggerD("Opening basic channel");
-        try {
-            SESession seSession(session_ptr);
-            picojson::value result = seSession.openBasicChannel(v_aid);
-            ReportSuccess(result, response->get<picojson::object>());
-        } catch (const ErrorIO& err) {
-            LogAndReportError(PlatformResult(ErrorCode::IO_ERR), &response->get<picojson::object>());
-        } catch (const ErrorIllegalState& err) {
-            LogAndReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR), &response->get<picojson::object>());
-        } catch (const ErrorIllegalParameter& err) {
-            LogAndReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR), &response->get<picojson::object>());
-        } catch (const ErrorSecurity& err) {
-            LogAndReportError(PlatformResult(ErrorCode::SECURITY_ERR), &response->get<picojson::object>());
-        } catch (const ExceptionBase& err) {
-            LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR), &response->get<picojson::object>());
-        }
-    };
+TizenResult SecureElementInstance::IsBasicChannel(int channel, picojson::value& val) {
+  ScopeLogger();
 
-    auto get_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
-        LoggerD("Getting response");
-        picojson::object& obj = response->get<picojson::object>();
-        obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
-        Instance::PostMessage(this, response->serialize().c_str());
-    };
+  bool is_basic = false;
+  int ret = smartcard_channel_is_basic_channel(channel, &is_basic);
+  if (SMARTCARD_ERROR_NONE != ret) {
+    LogAndReturnTizenError(ConvertErrorCode(ret), ("smartcard_channel_is_basic_channel() failed"));
+  }
 
-    auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+  auto& obj = val.get<picojson::object>();
+  obj.insert(std::make_pair(kIsBasicChannel, picojson::value(is_basic)));
 
-    TaskQueue::GetInstance().Queue<picojson::value>(open, get_response, data);
+  return TizenSuccess(val);
 }
 
+TizenResult SecureElementInstance::OpenBasicChannel(picojson::object const& args, const common::AsyncToken& token) {
+  ScopeLogger();
 
-void SecureElementInstance::OpenLogicalChannel( const picojson::value& args, picojson::object& out) {
-    LoggerD("Enter");
-    CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
-
-    const double callback_id = args.get("callbackId").get<double>();
-    const picojson::array v_aid = args.get("aid").get<picojson::value::array>();
-    Session* session_ptr = (Session*) static_cast<long>(args.get("handle").get<double>());
-
-    auto open = [this, v_aid, session_ptr](const std::shared_ptr<picojson::value>& response) -> void {
-        LoggerD("Opening basic channel");
-        try {
-            SESession seSession(session_ptr);
-            picojson::value result = seSession.openLogicalChannel(v_aid);
-            ReportSuccess(result, response->get<picojson::object>());
-        } catch (const ErrorIO& err) {
-            LogAndReportError(PlatformResult(ErrorCode::IO_ERR), &response->get<picojson::object>());
-        } catch (const ErrorIllegalState& err) {
-            LogAndReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR), &response->get<picojson::object>());
-        } catch (const ErrorIllegalParameter& err) {
-            LogAndReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR), &response->get<picojson::object>());
-        } catch (const ErrorSecurity& err) {
-            LogAndReportError(PlatformResult(ErrorCode::SECURITY_ERR), &response->get<picojson::object>());
-        } catch (const ExceptionBase& err) {
-            LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR), &response->get<picojson::object>());
-        }
-    };
+  CHECK_PRIVILEGE(kPrivilegeSecureElement);
+
+  int session = static_cast<int>(args.find(kHandle)->second.get<double>());
+  const picojson::array v_aid = args.find(kAid)->second.get<picojson::array>();
 
-    auto get_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
-        LoggerD("Getting response");
-        picojson::object& obj = response->get<picojson::object>();
-        obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
-        Instance::PostMessage(this, response->serialize().c_str());
+  auto open_basic_channel = [this, session, v_aid](const common::AsyncToken& token) -> void {
+    TizenResult result = TizenSuccess();
+    int channel = 0;
+    unsigned char P2 = 0;
+
+    size_t v_aid_size = v_aid.size();
+    unsigned char* aid = new unsigned char[v_aid_size];
+    SCOPE_EXIT {
+      delete [] aid;
     };
 
-    auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+    for (size_t i = 0; i < v_aid_size; i++) {
+      aid[i] = static_cast<unsigned char>(v_aid[i].get<double>());
+    }
+
+    int ret = smartcard_session_open_basic_channel(session, aid, v_aid_size, P2, &channel);
+    if (SMARTCARD_ERROR_NONE != ret) {
+      LoggerE("smartcard_session_open_basic_channel() failed");
+      result = ConvertErrorCode(ret);
+    } else {
+      picojson::value response{picojson::object{}};
+      auto& obj = response.get<picojson::object>();
+
+      obj.insert(std::make_pair(kHandle, picojson::value(static_cast<double>(channel))));
+      result = IsBasicChannel(channel, response);
+    }
+
+    this->Post(token, result);
+  };
+
+  std::thread(open_basic_channel, token).detach();
 
-    TaskQueue::GetInstance().Queue<picojson::value>(open, get_response, data);
+  return TizenSuccess();
 }
 
+TizenResult SecureElementInstance::OpenLogicalChannel(picojson::object const& args, const common::AsyncToken& token) {
+  ScopeLogger();
 
-void SecureElementInstance::GetATR( const picojson::value& args, picojson::object& out) {
-    LoggerD("Enter");
-    CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
+  CHECK_PRIVILEGE(kPrivilegeSecureElement);
 
-    Session* session_ptr = (Session*) static_cast<long>(args.get("handle").get<double>());
-    SESession seSession(session_ptr);
+  int session = static_cast<int>(args.find(kHandle)->second.get<double>());
+  const picojson::array v_aid = args.find(kAid)->second.get<picojson::array>();
 
-    ByteArray atr_result = seSession.getATR();
-    picojson::value result = picojson::value(picojson::array());
-    picojson::array& arr = result.get<picojson::array>();
-    size_t atr_result_size = atr_result.size();
-    for (size_t i = 0; i < atr_result_size; i++) {
-        arr.push_back(picojson::value(static_cast<double>(atr_result[i])));
+  auto open_basic_logical = [this, session, v_aid](const common::AsyncToken& token) -> void {
+    TizenResult result = TizenSuccess();
+    int channel = 0;
+    unsigned char P2 = 0;
+
+    size_t v_aid_size = v_aid.size();
+    unsigned char* aid = new unsigned char[v_aid_size];
+    SCOPE_EXIT {
+      delete [] aid;
+    };
+
+    for (size_t i = 0; i < v_aid_size; i++) {
+      aid[i] = static_cast<unsigned char>(v_aid[i].get<double>());
     }
-    ReportSuccess( result, out);
+
+    int ret = smartcard_session_open_logical_channel(session, aid, v_aid_size, P2, &channel);
+    if (SMARTCARD_ERROR_NONE != ret) {
+      LoggerE("smartcard_session_open_logical_channel() failed");
+      result = ConvertErrorCode(ret);
+    } else {
+      picojson::value response{picojson::object{}};
+      auto& obj = response.get<picojson::object>();
+
+      obj.insert(std::make_pair(kHandle, picojson::value(static_cast<double>(channel))));
+      result = IsBasicChannel(channel, response);
+    }
+
+    this->Post(token, result);
+  };
+
+  std::thread(open_basic_logical, token).detach();
+
+  return TizenSuccess();
 }
 
+TizenResult SecureElementInstance::GetATR(picojson::object const& args) {
+  ScopeLogger();
+
+  CHECK_PRIVILEGE(kPrivilegeSecureElement);
+
+  int session = static_cast<int>(args.find(kHandle)->second.get<double>());
+  int length = 0;
+  unsigned char* atr = nullptr;
+
+  int ret = smartcard_session_get_atr(session, &atr, &length);
+  SCOPE_EXIT {
+    free(atr);
+  };
 
-void SecureElementInstance::IsSessionClosed( const picojson::value& args, picojson::object& out) {
-    LoggerD("Enter");
-    Session* session_ptr = (Session*) static_cast<long>(args.get("handle").get<double>());
-    SESession seSession(session_ptr);
-    picojson::value result = seSession.isClosed();
-    ReportSuccess( result, out);
+  if (SMARTCARD_ERROR_NONE != ret) {
+    LogAndReturnTizenError(ConvertErrorCode(ret), ("smartcard_session_get_atr() failed"));
+  }
+
+  picojson::value response{picojson::array{}};
+  auto& array = response.get<picojson::array>();
+
+  for (int i = 0; i < length; i++) {
+    array.push_back(picojson::value(static_cast<double>(atr[i])));
+  }
+
+  return TizenSuccess(response);
 }
 
+TizenResult SecureElementInstance::IsSessionClosed(picojson::object const& args) {
+  ScopeLogger();
+
+  int session = static_cast<int>(args.find(kHandle)->second.get<double>());
+  bool is_closed = false;
 
-void SecureElementInstance::CloseSession( const picojson::value& args, picojson::object& out) {
-    LoggerD("Enter");
-    CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
+  int ret = smartcard_session_is_closed(session, &is_closed);
+  if (SMARTCARD_ERROR_NONE != ret) {
+    LogAndReturnTizenError(ConvertErrorCode(ret), ("smartcard_session_is_closed() failed"));
+  }
 
-    Session* session_ptr = (Session*) static_cast<long>(args.get("handle").get<double>());
-    SESession seSession(session_ptr);
-    seSession.close();
-    ReportSuccess(out);
+  return TizenSuccess(picojson::value(is_closed));
 }
 
+TizenResult SecureElementInstance::CloseSession(picojson::object const& args) {
+  ScopeLogger();
+
+  CHECK_PRIVILEGE(kPrivilegeSecureElement);
 
-void SecureElementInstance::CloseChannels( const picojson::value& args, picojson::object& out) {
-    LoggerD("Enter");
-    CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
+  int session = static_cast<int>(args.find(kHandle)->second.get<double>());
 
-    Session* session_ptr = (Session*) static_cast<long>(args.get("handle").get<double>());
-    SESession seSession(session_ptr);
-    seSession.closeChannels();
-    ReportSuccess(out);
+  int ret = smartcard_session_close(session);
+  if (SMARTCARD_ERROR_NONE != ret) {
+    LogAndReturnTizenError(ConvertErrorCode(ret), ("smartcard_session_close() failed"));
+  }
+
+  return TizenSuccess();
 }
 
-void SecureElementInstance::Transmit( const picojson::value& args, picojson::object& out) {
-    LoggerD("Enter");
-    CHECK_PRIVILEGE_ACCESS(kPrivilegeSecureElement, &out);
-
-    const double callback_id = args.get("callbackId").get<double>();
-    const picojson::array v_command = args.get("command").get<picojson::value::array>();
-    ClientChannel* channel_ptr = (ClientChannel*) static_cast<long>(args.get("handle").get<double>());
-
-    auto open = [this, v_command, channel_ptr](const std::shared_ptr<picojson::value>& response) -> void {
-        LoggerD("Transmit APDDU command to secure element");
-        try {
-            SEChannel seChannel(channel_ptr);
-            ByteArray transmit_response = seChannel.transmit(v_command);
-            picojson::value result = picojson::value(picojson::array());
-            picojson::array& arr = result.get<picojson::array>();
-            size_t transmit_response_size = transmit_response.size();
-            for (size_t i = 0; i < transmit_response_size; i++) {
-                arr.push_back(picojson::value(static_cast<double>(transmit_response[i])));
-            }
-            ReportSuccess( result, response->get<picojson::object>());
-        } catch (const ErrorIO& err) {
-            LogAndReportError(PlatformResult(ErrorCode::IO_ERR, "Failed to transmit command."), &response->get<picojson::object>());
-        } catch (const ErrorIllegalState& err) {
-            LogAndReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR, "Failed to transmit command."), &response->get<picojson::object>());
-        } catch (const ErrorIllegalParameter& err) {
-            LogAndReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Failed to transmit command."), &response->get<picojson::object>());
-        } catch (const ErrorSecurity& err) {
-            LogAndReportError(PlatformResult(ErrorCode::SECURITY_ERR, "Failed to transmit command."), &response->get<picojson::object>());
-        } catch (const ExceptionBase& err) {
-            LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to transmit command."), &response->get<picojson::object>());
-        }
+TizenResult SecureElementInstance::CloseChannels(picojson::object const& args) {
+  ScopeLogger();
+
+  CHECK_PRIVILEGE(kPrivilegeSecureElement);
+
+  int session = static_cast<int>(args.find(kHandle)->second.get<double>());
+
+  int ret = smartcard_session_close_channels(session);
+  if (SMARTCARD_ERROR_NONE != ret) {
+    LogAndReturnTizenError(ConvertErrorCode(ret), ("smartcard_session_close_channels() failed"));
+  }
+
+  return TizenSuccess();
+}
+
+// Channel methods
+TizenResult SecureElementInstance::CloseChannel(picojson::object const& args) {
+  ScopeLogger();
+
+  CHECK_PRIVILEGE(kPrivilegeSecureElement);
+
+  int channel = static_cast<int>(args.find(kHandle)->second.get<double>());
+
+  int ret = smartcard_channel_close(channel);
+  if (SMARTCARD_ERROR_NONE != ret) {
+    LogAndReturnTizenError(ConvertErrorCode(ret), ("smartcard_channel_close() failed"));
+  }
+
+  return TizenSuccess();
+}
+
+TizenResult SecureElementInstance::Transmit(picojson::object const& args, const common::AsyncToken& token) {
+  ScopeLogger();
+
+  CHECK_PRIVILEGE(kPrivilegeSecureElement);
+
+  int channel = static_cast<int>(args.find(kHandle)->second.get<double>());
+  const auto& v_cmd = args.find(kCommand)->second.get<picojson::array>();
+
+  auto transmit = [this, channel, v_cmd](const common::AsyncToken& token) -> void {
+    TizenResult result = TizenSuccess();
+
+    size_t v_cmd_size = v_cmd.size();
+    unsigned char* cmd = new unsigned char[v_cmd_size];
+    SCOPE_EXIT {
+      delete [] cmd;
     };
 
-    auto get_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
-        LoggerD("Getting response");
-        picojson::object& obj = response->get<picojson::object>();
-        obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
-        Instance::PostMessage(this, response->serialize().c_str());
+    for (size_t i = 0; i < v_cmd_size; i++) {
+      cmd[i] = static_cast<unsigned char>(v_cmd[i].get<double>());
+    }
+
+    int length = 0;
+    unsigned char* response = nullptr;
+
+    int ret = smartcard_channel_transmit(channel, cmd, v_cmd_size, &response, &length);
+    SCOPE_EXIT {
+      free(response);
     };
 
-    auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+    if (SMARTCARD_ERROR_NONE != ret) {
+      LoggerE("smartcard_channel_transmit() failed");
+      result = ConvertErrorCode(ret);
+    } else {
+      picojson::value response_v{picojson::array{}};
+      auto& array = response_v.get<picojson::array>();
+
+      for (int i = 0; i < length; i++) {
+        array.push_back(picojson::value(static_cast<double>(response[i])));
+      }
+
+      result = TizenSuccess(response_v);
+    }
+
+    this->Post(token, result);
+  };
+
+  std::thread(transmit, token).detach();
+
+  return TizenSuccess();
+}
+
+TizenResult SecureElementInstance::GetSelectResponse(picojson::object const& args) {
+  ScopeLogger();
+
+  CHECK_PRIVILEGE(kPrivilegeSecureElement);
+
+  int channel = static_cast<int>(args.find(kHandle)->second.get<double>());
+  int length = 0;
+  unsigned char* select_response = nullptr;
+
+  int ret = smartcard_channel_get_select_response(channel, &select_response, &length);
+  SCOPE_EXIT {
+    free(select_response);
+  };
+
+  if (SMARTCARD_ERROR_NONE != ret) {
+    LogAndReturnTizenError(ConvertErrorCode(ret),
+                           ("smartcard_channel_get_select_response() failed"));
+  }
+
+  picojson::value response{picojson::array{}};
+  auto& array = response.get<picojson::array>();
+
+  for (int i = 0; i < length; i++) {
+    array.push_back(picojson::value(static_cast<double>(select_response[i])));
+  }
 
-    TaskQueue::GetInstance().Queue<picojson::value>(open, get_response, data);
+  return TizenSuccess(response);
 }
 
 } // namespace secureelement
index 1f0ff9c..d4e1295 100644 (file)
 #ifndef SECUREELEMENT_SECUREELEMENT_INSTANCE_H_
 #define SECUREELEMENT_SECUREELEMENT_INSTANCE_H_
 
-#include "common/extension.h"
-#include "secureelement_seservice.h"
+#include "common/tizen_instance.h"
 
 namespace extension {
 namespace secureelement {
 
-class SecureElementInstance: public common::ParsedInstance {
+class SecureElementInstance: public common::TizenInstance {
 public:
     SecureElementInstance();
     virtual ~SecureElementInstance();
 
 private:
-    /* SEService methods */
-    void GetReaders(const picojson::value& args, picojson::object& out);
-    void RegisterSEListener(const picojson::value& args, picojson::object& out);
-    void UnregisterSEListener(const picojson::value& args, picojson::object& out);
-    void Shutdown(const picojson::value& args, picojson::object& out);
+    /* Service methods */
+    common::TizenResult GetReaders(picojson::object const& args, const common::AsyncToken& token);
+    common::TizenResult RegisterSEListener(picojson::object const& args);
+    common::TizenResult UnregisterSEListener(picojson::object const& args);
+    common::TizenResult Shutdown(picojson::object const& args);
 
     /* Reader methods */
-    void GetName(const picojson::value& args, picojson::object& out);
-    void IsPresent(const picojson::value& args, picojson::object& out);
-    void OpenSession(const picojson::value& args, picojson::object& out);
-    void CloseSessions(const picojson::value& args, picojson::object& out);
+    common::TizenResult GetName(picojson::object const& args);
+    common::TizenResult IsPresent(picojson::object const& args);
+    common::TizenResult OpenSession(picojson::object const& args, const common::AsyncToken& token);
+    common::TizenResult CloseSessions(picojson::object const& args);
 
     /* Session methods */
-    void OpenBasicChannel(const picojson::value& args, picojson::object& out);
-    void OpenLogicalChannel(const picojson::value& args, picojson::object& out);
-    void GetATR(const picojson::value& args, picojson::object& out);
-    void IsSessionClosed(const picojson::value& args, picojson::object& out);
-    void CloseSession(const picojson::value& args, picojson::object& out);
-    void CloseChannels(const picojson::value& args, picojson::object& out);
+    common::TizenResult IsBasicChannel(int channel, picojson::value& val);
+    common::TizenResult OpenBasicChannel(picojson::object const& args, const common::AsyncToken& token);
+    common::TizenResult OpenLogicalChannel(picojson::object const& args, const common::AsyncToken& token);
+    common::TizenResult GetATR(picojson::object const& args);
+    common::TizenResult IsSessionClosed(picojson::object const& args);
+    common::TizenResult CloseSession(picojson::object const& args);
+    common::TizenResult CloseChannels(picojson::object const& args);
 
     /* Channel methods */
-    void CloseChannel(const picojson::value& args, picojson::object& out);
-    void Transmit(const picojson::value& args, picojson::object& out);
-    void GetSelectResponse(const picojson::value& args, picojson::object& out);
+    common::TizenResult CloseChannel(picojson::object const& args);
+    common::TizenResult Transmit(picojson::object const& args, const common::AsyncToken& token);
+    common::TizenResult GetSelectResponse(picojson::object const& args);
 
-    SEService service_;
+    common::TizenResult Deinitialize();
+    common::TizenResult UnregisterListener();
+
+    bool is_initialized_;
+    bool is_listener_set_;
 };
 
 } // namespace secureelement
diff --git a/src/secureelement/secureelement_reader.cc b/src/secureelement/secureelement_reader.cc
deleted file mode 100644 (file)
index 3ad2845..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
- *
- *    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.
- */
-
-#include "secureelement_reader.h"
-
-#include <Session.h>
-#include <Reader.h>
-#include "common/picojson.h"
-#include "common/logger.h"
-
-using namespace smartcard_service_api;
-using namespace std;
-
-namespace extension {
-namespace secureelement {
-
-
-picojson::value SEReader::getName() {
-    LoggerD("Entered");
-
-    picojson::value result = picojson::value(picojson::object());
-    picojson::object& obj = result.get<picojson::object>();
-
-    if(m_reader) {
-        obj.insert(std::make_pair("name", picojson::value(m_reader->getName())));
-    }
-
-    return result;
-}
-
-picojson::value SEReader::isPresent() {
-    LoggerD("Entered");
-
-    picojson::value result = picojson::value(picojson::object());
-    picojson::object& obj = result.get<picojson::object>();
-
-    if(m_reader) {
-        obj.insert(std::make_pair("isPresent", picojson::value(m_reader->isSecureElementPresent())));
-    }
-
-    return result;
-}
-
-picojson::value SEReader::openSession() {
-    LoggerD("Entered");
-
-    picojson::value result = picojson::value(picojson::object());
-    picojson::object& obj = result.get<picojson::object>();
-
-    if(m_reader) {
-        Session *session_ptr = static_cast<Session*>(m_reader->openSessionSync());
-
-        obj.insert(std::make_pair("handle", picojson::value((double) (long) session_ptr)));
-        obj.insert(std::make_pair("isClosed", picojson::value(session_ptr->isClosed())));
-    }
-
-    return result;
-}
-
-void SEReader::closeSessions() {
-    LoggerD("Entered");
-
-    if(m_reader) {
-        m_reader->closeSessions();
-    }
-}
-
-}// secureelement
-}// extension
diff --git a/src/secureelement/secureelement_seservice.cc b/src/secureelement/secureelement_seservice.cc
deleted file mode 100644 (file)
index 15fe491..0000000
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
- *
- *    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.
- */
-
-#include "secureelement/secureelement_seservice.h"
-
-#include "common/logger.h"
-#include "common/platform_result.h"
-#include "common/task-queue.h"
-#include "common/tools.h"
-
-
-#include "secureelement/secureelement_instance.h"
-
-using namespace smartcard_service_api;
-using namespace common;
-using namespace tools;
-
-namespace extension {
-namespace secureelement {
-
-namespace {
-const int SE_INSERTED = 1;
-const int SE_REMOVED = 2;
-}
-
-class SEServiceEventHandler : public SEServiceListener {
-  void serviceConnected(SEServiceHelper *service, void *context) {
-    LoggerD("Entered");
-    if (context) {
-      (static_cast<SEService*>(context))->ServiceConnected();
-    } else {
-      LoggerE("Context is null");
-    }
-  }
-
-  void eventHandler(SEServiceHelper *service, char *se_name, int event, void *context) {
-    LoggerD("Entered");
-    if (context) {
-      (static_cast<SEService*>(context))->EventHandler(se_name, event);
-    } else {
-      LoggerE("Context is null");
-    }
-  }
-
-  void errorHandler(SEServiceHelper *service, int error, void *context) {
-    LoggerE("Error handler called, code: %d", error);
-    if (context) {
-      (static_cast<SEService*>(context))->ErrorHandler(error);
-    } else {
-      LoggerE("Context is null");
-    }
-  }
-};
-
-static SEServiceEventHandler se_event_handler;
-
-SEService::SEService(SecureElementInstance& instance)
-    : is_initialized_(false),
-      is_listener_set_(false),
-      is_error_(false),
-      instance_(instance) {
-  LoggerD("Entered");
-
-  se_service_ = new smartcard_service_api::SEService((void *)this, &se_event_handler);
-}
-
-SEService::~SEService() {
-  LoggerD("Entered");
-
-  if (is_initialized_) {
-    se_service_->shutdownSync();
-    is_initialized_ = false;
-  }
-
-  delete se_service_;
-  se_service_ = nullptr;
-}
-
-void SEService::GetReaders(double callback_id) {
-  LoggerD("Entered");
-
-  auto get_readers = [this](
-      const std::shared_ptr<picojson::value>& response) -> void {
-    picojson::value result = picojson::value(picojson::array());
-    picojson::array& result_array = result.get<picojson::array>();
-
-    std::vector<smartcard_service_api::ReaderHelper *> readers = se_service_->getReaders();
-    for (std::size_t i = 0; i < readers.size(); i++) {
-      if (readers[i]->isSecureElementPresent()) {
-        result_array.push_back(picojson::value((double) (long) readers[i]));
-      }
-    }
-
-    ReportSuccess(result, response->get<picojson::object>());
-  };
-
-  auto get_readers_response = [this, callback_id](
-      const std::shared_ptr<picojson::value>& response) -> void {
-    picojson::object& obj = response->get<picojson::object>();
-    obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
-    Instance::PostMessage(&instance_, response->serialize().c_str());
-  };
-
-  if (is_error_) {
-    // there has been an error, report it asynchronously
-    std::shared_ptr<picojson::value> response{new picojson::value{picojson::object{}}};
-    LogAndReportError(
-        PlatformResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR,
-                       "Unable to connect to service."),
-        &response->get<picojson::object>(),
-        ("Failed: is_error_"));
-    TaskQueue::GetInstance().Async<picojson::value>(get_readers_response, response);
-    return;
-  }
-
-  if (!is_initialized_) {
-    // not yet ready, wait for the platform callback, send the response then
-    get_readers_callbacks_.push_back(callback_id);
-    return;
-  }
-
-  auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
-
-  // everything's fine, get the readers, send the response
-  TaskQueue::GetInstance().Queue<picojson::value>(
-      get_readers,
-      get_readers_response,
-      data);
-}
-
-void SEService::RegisterSEListener() {
-  LoggerD("Entered");
-
-  is_listener_set_ = true;
-}
-
-void SEService::UnregisterSEListener() {
-  LoggerD("Entered");
-
-  is_listener_set_ = false;
-}
-
-void SEService::Shutdown() {
-  LoggerD("Entered");
-
-  if (is_initialized_) {
-      se_service_->shutdownSync();
-      is_initialized_ = false;
-  }
-}
-
-void SEService::ServiceConnected() {
-  LoggerD("Entered");
-
-  is_initialized_ = true;
-
-  // send the response to pending GetReaders callbacks
-  for (const auto& callback_id : get_readers_callbacks_) {
-    GetReaders(callback_id);
-  }
-  get_readers_callbacks_.clear();
-
-  // notify the listeners
-  if (!is_listener_set_) {
-    LoggerE("SE listener is not set.");
-    return;
-  }
-
-  std::vector<smartcard_service_api::ReaderHelper *> readers = se_service_->getReaders();
-  for (std::size_t i = 0; i < readers.size(); i++) {
-    if (readers[i]->isSecureElementPresent()) {
-      picojson::value result = picojson::value(picojson::object());
-      picojson::object& obj = result.get<picojson::object>();
-
-      obj.insert(std::make_pair("action", picojson::value("onSEReady")));
-      obj.insert(std::make_pair("handle", picojson::value((double) (long) readers[i])));
-
-      Instance::PostMessage(&instance_, result.serialize().c_str());
-    }
-  }
-}
-
-void SEService::EventHandler(char *se_name, int event) {
-  LoggerD("Entered");
-
-  if (SE_INSERTED != event && SE_REMOVED != event) {
-    LoggerD("Incorrect event type");
-    return;
-  }
-
-  if (is_initialized_ && is_listener_set_) {
-    bool is_present = event == SE_INSERTED;
-
-    std::vector<smartcard_service_api::ReaderHelper *> readers = se_service_->getReaders();
-    for (std::size_t i = 0; i < readers.size(); i++) {
-      if (!strcmp(se_name, readers[i]->getName()) &&
-          readers[i]->isSecureElementPresent() != is_present) {
-        picojson::value result = picojson::value(picojson::object());
-        picojson::object& obj = result.get<picojson::object>();
-
-        if (is_present) {
-          obj.insert(std::make_pair("action", picojson::value("onSEReady")));
-        } else {
-          obj.insert(std::make_pair("action", picojson::value("onSENotReady")));
-        }
-
-        obj.insert(std::make_pair("handle", picojson::value((double) (long) readers[i])));
-        Instance::PostMessage(&instance_, result.serialize().c_str());
-        return;
-      }
-    }
-  }
-}
-
-void SEService::ErrorHandler(int error) {
-  LoggerD("Entered");
-  is_error_ = true;
-
-  for (const auto& callback_id : get_readers_callbacks_) {
-    GetReaders(callback_id);
-  }
-  get_readers_callbacks_.clear();
-}
-
-} // secureelement
-} // extension
diff --git a/src/secureelement/secureelement_seservice.h b/src/secureelement/secureelement_seservice.h
deleted file mode 100644 (file)
index 5ac4067..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
- *
- *    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.
- */
-
-#ifndef SECUREELEMENT_SESERVICE_H_
-#define SECUREELEMENT_SESERVICE_H_
-
-#include <SEService.h>
-#include <SEServiceHelper.h>
-
-namespace extension {
-namespace secureelement {
-
-class SecureElementInstance;
-
-class SEService {
- public:
-  explicit SEService(SecureElementInstance& instance);
-  ~SEService();
-
-  void GetReaders(double callback_id);
-  void RegisterSEListener();
-  void UnregisterSEListener();
-  void Shutdown();
-
-  void ServiceConnected();
-  void EventHandler(char *se_name, int event);
-  void ErrorHandler(int error);
- private:
-  SEService(const SEService&) = delete;
-  SEService& operator=(const SEService&) = delete;
-
-  smartcard_service_api::SEService *se_service_;
-  bool is_initialized_;
-  bool is_listener_set_;
-  bool is_error_;
-  std::vector<double> get_readers_callbacks_;
-  SecureElementInstance& instance_;
-};
-
-} // secureelement
-} // extension
-
-#endif // SECUREELEMENT_SESERVICE_H_
diff --git a/src/secureelement/secureelement_session.cc b/src/secureelement/secureelement_session.cc
deleted file mode 100644 (file)
index 35fee11..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
- *
- *    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.
- */
-
-#include <Session.h>
-#include <ClientChannel.h>
-#include "common/picojson.h"
-#include "common/logger.h"
-#include "secureelement_session.h"
-
-using namespace smartcard_service_api;
-
-namespace extension {
-namespace secureelement {
-
-picojson::value SESession::openBasicChannel(const picojson::array& v_aid) {
-    LoggerD("Entered");
-
-    size_t v_aid_size = v_aid.size();
-    unsigned char* aid = new unsigned char[v_aid_size];
-    for (size_t i = 0; i < v_aid_size; i++) {
-        aid[i] = static_cast<unsigned char>(v_aid[i].get<double>());
-    }
-    ByteArray aid_byte_array( aid, (unsigned int) v_aid.size());
-    ClientChannel* channel_ptr = static_cast<ClientChannel*>(m_session_ptr->openBasicChannelSync( aid_byte_array));
-    delete [] aid;
-
-    picojson::value result = picojson::value(picojson::object());
-    picojson::object& obj = result.get<picojson::object>();
-    obj.insert(std::make_pair("handle", picojson::value((double) (long) channel_ptr)));
-    obj.insert(std::make_pair("isBasicChannel", picojson::value(channel_ptr->isBasicChannel())));
-
-    return result;
-}
-
-
-picojson::value SESession::openLogicalChannel(const picojson::array& v_aid) {
-    LoggerD("Entered");
-
-    size_t v_aid_size = v_aid.size();
-    unsigned char* aid = new unsigned char[v_aid_size];
-    for (size_t i = 0; i < v_aid_size; i++) {
-        aid[i] = static_cast<unsigned char>(v_aid[i].get<double>());
-    }
-    ByteArray aid_byte_array( aid, (unsigned int) v_aid.size());
-    ClientChannel* channel_ptr = static_cast<ClientChannel*>(m_session_ptr->openLogicalChannelSync( aid_byte_array));
-    delete [] aid;
-
-    picojson::value result = picojson::value(picojson::object());
-    picojson::object& obj = result.get<picojson::object>();
-    obj.insert(std::make_pair("handle", picojson::value((double) (long) channel_ptr)));
-    obj.insert(std::make_pair("isBasicChannel", picojson::value(channel_ptr->isBasicChannel())));
-
-    return result;
-}
-
-
-picojson::value SESession::isClosed() {
-    LoggerD("Entered");
-    bool is_closed = m_session_ptr->isClosed();
-    picojson::value result = picojson::value(picojson::object());
-    picojson::object& obj = result.get<picojson::object>();
-    obj.insert(std::make_pair("isClosed", picojson::value(is_closed)));
-    return result;
-}
-
-
-void SESession::close() {
-    LoggerD("Entered");
-    if ( m_session_ptr) {
-        m_session_ptr->closeSync();
-    }
-}
-
-
-ByteArray SESession::getATR() {
-    LoggerD("Entered");
-    ByteArray response;
-    if ( m_session_ptr) {
-        response = m_session_ptr->getATRSync();
-    }
-    return response;
-}
-
-
-void SESession::closeChannels() {
-    LoggerD("Entered");
-    if ( m_session_ptr) {
-        m_session_ptr->closeChannels();
-    }
-}
-
-
-} // secureelement
-} // extension
diff --git a/src/secureelement/secureelement_session.h b/src/secureelement/secureelement_session.h
deleted file mode 100644 (file)
index 891380c..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
- *
- *    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.
- */
-
-#ifndef SECUREELEMENT_SESSION_H_
-#define SECUREELEMENT_SESSION_H_
-
-#include <Session.h>
-#include "common/picojson.h"
-#include "common/logger.h"
-
-namespace extension {
-namespace secureelement {
-
-class SESession {
-public:
-    SESession(smartcard_service_api::Session* session_ptr)
-        : m_session_ptr(session_ptr) {
-    }
-
-    ~SESession() {};
-    picojson::value openBasicChannel( const picojson::array& v_aid);
-    picojson::value openLogicalChannel( const picojson::array& v_aid);
-    picojson::value isClosed();
-    void close();
-    smartcard_service_api::ByteArray getATR();
-    void closeChannels();
-private:
-    smartcard_service_api::Session* m_session_ptr;
-};
-
-} // secureelement
-} // extension
-
-#endif // SECUREELEMENT_SESSION_H_
index 939e691..7cc8a10 100755 (executable)
             ],
           },
         ],
+        [
+          'tizen_feature_convergence_support==1', {
+            'dependencies': [
+              'convergence/convergence.gyp:*',
+            ],
+          },
+        ],
       ], # end conditions
     },
   ], # end targets
index c93f5db..0583aa7 100644 (file)
@@ -7,6 +7,8 @@
 #include <dlfcn.h>
 #include <dirent.h>
 #include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
 
 #include <common/extension.h>
 
@@ -163,12 +165,11 @@ int main(int argc, char* argv[]) {
     return -1;
   }
 
-  DIR * dir;
-  struct dirent ent = {0};
-  struct dirent* result = nullptr;
-  if ((dir = opendir(tec_path.c_str())) != NULL) {
-    while ((0 == (readdir_r(dir, &ent, &result))) && result) {
-      std::string fname = ent.d_name;
+  struct dirent** namelist;
+  int num_entries = scandir(tec_path.c_str(), &namelist, NULL, alphasort);
+  if( num_entries >= 0 ) {
+    for( int i = 0; i < num_entries; ++i ) {
+      std::string fname = namelist[i]->d_name;
 
       if (fname.size() >= prefix_.size() + postfix_.size() &&
           !fname.compare(0, prefix_.size(), prefix_) &&
@@ -206,12 +207,14 @@ int main(int argc, char* argv[]) {
         //
         // dlclose(handle);
       }
+      free(namelist[i]);
     }
-    closedir(dir);
-
+    free(namelist);
     print_json();
   } else {
-    std::cerr << "path not exist : " << tec_path << std::endl;
+    perror("scandir");
+    if( errno == ENOENT )
+      std::cerr << "path not exist : " << tec_path << std::endl;
     return -1;
   }