Add store/load editable context feature 32/173232/18
authorhyunho <hhstark.kang@samsung.com>
Tue, 20 Mar 2018 06:06:04 +0000 (15:06 +0900)
committerHyunho Kang <hhstark.kang@samsung.com>
Thu, 29 Mar 2018 07:05:28 +0000 (07:05 +0000)
Change-Id: I0af4ccdbad71e0b3ec23046af1ba131a84ace0c3
Signed-off-by: hyunho <hhstark.kang@samsung.com>
34 files changed:
CMakeLists.txt
packaging/libwatchface-complication.spec
unittest/CMakeLists.txt
unittest/src/test_complication.cc
watchface-complication-provider/CMakeLists.txt
watchface-complication-provider/complication-provider.cc
watchface-complication-provider/include/watchface-complication-provider.h
watchface-complication-provider/watchface-complication-provider.cc
watchface-complication/complication-connector.cc
watchface-complication/complication-connector.h
watchface-complication/complication-implementation.h
watchface-complication/complication.cc
watchface-complication/complication.h
watchface-complication/design-element-implementation.h
watchface-complication/design-element.cc
watchface-complication/design-element.h
watchface-complication/editable-interface.h
watchface-complication/editables-container-event-interface.h
watchface-complication/editables-container-implementation.h
watchface-complication/editables-container.cc
watchface-complication/editables-container.h
watchface-complication/editables-manager-implementation.h
watchface-complication/editables-manager.cc
watchface-complication/editables-manager.h
watchface-complication/include/watchface-complication-internal.h
watchface-complication/received-editable-implementation.h
watchface-complication/received-editable.cc
watchface-complication/received-editable.h
watchface-complication/watchface-complication.cc
watchface-editor/CMakeLists.txt
watchface-editor/editables-editor.cc
watchface-editor/editables-editor.h
watchface-editor/include/watchface-editor.h
watchface-editor/watchface-editor.cc

index 78bf7b5..9796bab 100644 (file)
@@ -9,3 +9,4 @@ ADD_SUBDIRECTORY(unittest)
 ADD_DEPENDENCIES(watchface-editor watchface-complication)
 ADD_DEPENDENCIES(watchface-complication-provider watchface-complication)
 ADD_DEPENDENCIES(complication-parser watchface-complication)
+ADD_DEPENDENCIES(gtest-watchface-complication watchface-complication-provider)
index 6e48754..9a7fabd 100755 (executable)
@@ -23,6 +23,7 @@ BuildRequires: pkgconfig(capi-appfw-app-common)
 BuildRequires: pkgconfig(libtzplatform-config)
 BuildRequires: pkgconfig(pkgmgr-info)
 BuildRequires: pkgconfig(pkgmgr-installer)
+BuildRequires: pkgconfig(capi-appfw-app-control)
 %if 0%{?gcov:1}
 BuildRequires: lcov
 %endif
index bc63c3e..79218f1 100755 (executable)
@@ -6,6 +6,7 @@ pkg_check_modules(gtest-watchface-complication REQUIRED
     glib-2.0
     dlog
     gmock
+    capi-appfw-app-control
 )
 
 FOREACH(flag ${gtest-watchface-complication_CFLAGS})
index 678d40e..5c92468 100755 (executable)
@@ -55,7 +55,7 @@ class WC : public ::testing::Test {
   string providerId = "sample_provider";
 
   virtual void SetUp() {
-    complication = new WatchComplication(0, 1, providerId.c_str(), ShortText,
+    complication = new WatchComplication(0, ShortText, providerId.c_str(), ShortText,
       std::shared_ptr<IEditable::Geometry>(new IEditable::Geometry(0, 0, 100, 100)));
   }
   virtual void TearDown() {
@@ -96,7 +96,7 @@ TEST_F(WC, GetData)
   EXPECT_NE(curData.GetRaw(), nullptr);
   EXPECT_NE(nthData.GetRaw(), nullptr);
 
-  EXPECT_EQ(WC::complication->GetType(curData), 1);
+  EXPECT_EQ(WC::complication->GetType(curData), ShortText);
 }
 
 TEST_F(WC, DataIdx)
index 30e836e..61ab633 100755 (executable)
@@ -14,6 +14,7 @@ pkg_check_modules(watchface-complication-provider REQUIRED
        gio-2.0
        dlog
        aul
+       capi-appfw-app-control
 )
 
 FOREACH(flag ${watchface-complication-provider_CFLAGS})
index 00a8606..c4b2563 100644 (file)
@@ -38,7 +38,7 @@ ComplicationProvider::Impl::Impl(ComplicationProvider* parent,
                                  int support_types)
   : parent_(parent), provider_id_(provider_id), support_types_(support_types) {
   subscribe_id_ = ComplicationConnector::GetInst().SubscribeSignal(
-    ComplicationConnector::Complication, provider_id_, 0, this);
+    ComplicationConnector::Complication, provider_id_, -1, this);
   LOGI("subscribe signal %d", subscribe_id_);
 }
 
index d5936c5..c4b465f 100644 (file)
@@ -18,6 +18,7 @@
 #define WATCHFACE_COMPLICATION_PROVIDER_INCLUDE_WATCHFACE_COMPLICATION_PROVIDER_H_
 
 #include <tizen.h>
+#include <app_control.h>
 #include "watchface-complication/include/watchface-complication.h"
 
 #ifdef __cplusplus
@@ -45,8 +46,93 @@ int complication_provider_get_support_types(const char *provider_id,
     int *types);
 int complication_provider_notify_update(const char *provider_id);
 
+/**
+ * @brief Sends reply to the editor.
+ * @details Using this API, setup app can sends new context data to the editor
+ * @since_tizen 5.0
+ * @param[in] handle The editable handle
+ * @param[in] context The new context data of complication provider.
+ * @see #complication_provider_setup_get_context
+ * @return #COMPLICATION_ERROR_NONE on success,
+ *         otherwise an error code (see COMPLICATION_ERROR_XXX) on failure
+ * @retval #COMPLICATION_ERROR_NONE Successful
+ * @retval #COMPLICATION_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #COMPLICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par Sample code:
+ * @code
+#include <watchface-complication-provider.h>
+
+{
+  bundle *b = bundle_create();
+  bundle_add_str(b, "REGION_DATA", "KR");
+  complication_provider_setup_reply_to_editor(handle, b);
+  bundle_free(b);
+}
+ * @endcode
+ */
+int complication_provider_setup_reply_to_editor(app_control_h h, bundle *context);
+
+/**
+ * @brief Check whether watch app request editing or not.
+ * @details Using this API, setup app can tell what kind of UI should be displayed
+ *
+ * @since_tizen 5.0
+ * @param[in] handle The editable handle
+ * @param[out] is_editing The value that tell it's editing mode.
+ * @see #complication_provider_setup_reply_to_editor
+ * @return #COMPLICATION_ERROR_NONE on success,
+ *         otherwise an error code (see COMPLICATION_ERROR_XXX) on failure
+ * @retval #COMPLICATION_ERROR_NONE Successful
+ * @retval #COMPLICATION_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #COMPLICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par Sample code:
+ * @code
+#include <watchface-complication-provider.h>
+void app_control(app_control_h app_control, void *data)
+{
+  bool is_editing;
+
+  complication_provider_setup_is_editing(handle, &is_editing);
+  if (is_editing) {
+        complication_provider_setup_get_context(handle, &b);
+        // Draw complication provider app's current setting state.
+  }
+}
+ * @endcode
+ */
+int complication_provider_setup_is_editing(
+    app_control_h handle, bool *id_editing);
+
+/**
+ * @brief Get provider app's setup context data.
+ * @details Context data will be passed to the complication provider application
+ *          through the app_control event callaback's app_control_h handle parameter
+ * @since_tizen 5.0
+ * @param[in] handle The editable handle
+ * @param[out] context
+ * @see #complication_provider_setup_reply_to_editor
+ * @return #COMPLICATION_ERROR_NONE on success,
+ *         otherwise an error code (see COMPLICATION_ERROR_XXX) on failure
+ * @retval #COMPLICATION_ERROR_NONE Successful
+ * @retval #COMPLICATION_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #COMPLICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par Sample code:
+ * @code
+#include <watchface-complication-provider.h>
+void app_control(app_control_h app_control, void *data)
+{
+  bundle *b;
+
+  complication_provider_setup_get_context(handle, &b);
+  // Draw complication provider app's current setting state.
+}
+ * @endcode
+ */
+int complication_provider_setup_get_context(app_control_h handle, bundle **context);
+
 #ifdef __cplusplus
 }
+
 #endif
 
 #endif  // WATCHFACE_COMPLICATION_PROVIDER_INCLUDE_WATCHFACE_COMPLICATION_PROVIDER_H_
index 6f4e780..4d841bd 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "watchface-complication-provider/complication-provider.h"
 #include "watchface-complication-provider/include/watchface-complication-provider.h"
+#include "watchface-complication/include/watchface-complication-internal.h"
 
 #ifdef LOG_TAG
 #undef LOG_TAG
@@ -153,3 +154,106 @@ extern "C" EXPORT_API int complication_provider_notify_update(
 
   return 0;
 }
+
+extern "C" EXPORT_API int complication_provider_setup_reply_to_editor(
+  app_control_h handle, bundle* context)
+{
+  char* editor_appid = NULL;
+  char* editable_id = NULL;
+  int ret;
+  int str_len = 0;
+  bundle_raw* raw_data = NULL;
+
+  ret = app_control_get_extra_data(handle, SETUP_EDITOR_APPID_KEY, &editor_appid);
+  if (ret != 0) {
+    LOGE("Fail to get editor appid");
+    return COMPLICATION_ERROR_INVALID_PARAMETER;
+  }
+
+  ret = app_control_get_extra_data(handle, SETUP_EDITABLE_ID_KEY, &editable_id);
+  if (ret != APP_CONTROL_ERROR_NONE) {
+    if (ret == APP_CONTROL_ERROR_OUT_OF_MEMORY) {
+      LOGE("Fail to get context data");
+      return COMPLICATION_ERROR_OUT_OF_MEMORY;
+    }
+    LOGE("Fail to get context data");
+    return COMPLICATION_ERROR_INVALID_PARAMETER;
+  }
+
+  if (context != NULL) {
+    ret = bundle_encode(context, &raw_data, &str_len);
+    if (ret != 0) {
+      LOGE("Fail to encode data");
+      free(editable_id);
+      free(editor_appid);
+      return COMPLICATION_ERROR_INVALID_PARAMETER;
+    }
+  }
+
+  ComplicationConnector::GetInst().EmitSignal(
+      ComplicationConnector::Editable,
+      std::string(editor_appid),
+      std::string(editor_appid), -1,
+      ComplicationConnector::GetInst().GetCmdStr(
+          ComplicationConnector::SetupReply),
+      g_variant_new("(is)", atoi(editable_id),
+                    raw_data == NULL ? "" : reinterpret_cast<char*>(raw_data)));
+
+  free(editor_appid);
+  free(editable_id);
+  free(raw_data);
+
+  return COMPLICATION_ERROR_NONE;
+}
+
+extern "C" EXPORT_API int complication_provider_setup_is_editing(
+  app_control_h handle, bool* is_editing)
+{
+  char* value = NULL;
+  int ret;
+
+  if (handle == NULL) {
+    LOGE("handle is null");
+    return COMPLICATION_ERROR_INVALID_PARAMETER;
+  }
+
+  ret = app_control_get_extra_data(handle, SETUP_EDITOR_APPID_KEY, &value);
+  if (ret != APP_CONTROL_ERROR_NONE) {
+    if (ret == APP_CONTROL_ERROR_OUT_OF_MEMORY) {
+      LOGE("Fail to get context data");
+      return COMPLICATION_ERROR_OUT_OF_MEMORY;
+    }
+    LOGE("Fail to get context data");
+    return COMPLICATION_ERROR_INVALID_PARAMETER;
+  }
+
+  *is_editing = true;
+  free(value);
+
+  return COMPLICATION_ERROR_NONE;
+}
+
+extern "C" EXPORT_API int complication_provider_setup_get_context(
+  app_control_h handle, bundle** context)
+{
+  char* value = NULL;
+  bundle* data = NULL;
+  int ret;
+
+  ret = app_control_get_extra_data(handle, SETUP_CONTEXT_DATA_KEY, &value);
+  if (ret != APP_CONTROL_ERROR_NONE) {
+    if (ret == APP_CONTROL_ERROR_OUT_OF_MEMORY) {
+      LOGE("Fail to get context data");
+      return COMPLICATION_ERROR_OUT_OF_MEMORY;
+    }
+    LOGE("Fail to get context data");
+    return COMPLICATION_ERROR_INVALID_PARAMETER;
+  }
+
+  data = bundle_decode(reinterpret_cast<const bundle_raw*>(value),
+    strlen(value));
+  *context = data;
+  free(value);
+
+  return COMPLICATION_ERROR_NONE;
+}
index 4c4347c..f6ef2f0 100644 (file)
@@ -236,6 +236,9 @@ std::string ComplicationConnector::GetCmdStr(CmdType type) {
   case EditableEditReady :
     ret = "__EDITABLE_EDIT_READY__";
     break;
+  case SetupReply :
+    ret = "__SETUP_REPLY__";
+    break;
   default :
     break;
   }
index cf65453..203cdb4 100644 (file)
@@ -40,7 +40,8 @@ class EXPORT_API ComplicationConnector {
     EditableEditComplete,
     EditableEditPreview,
     EditableEditCancel,
-    EditableEditReady
+    EditableEditReady,
+    SetupReply
   };
 
   class IEventListener {
index b208ed1..2d45a4a 100644 (file)
@@ -72,6 +72,7 @@ class Complication::Impl : ComplicationConnector::IEventListener {
   std::list<std::unique_ptr<Bundle>> candidates_list_;
   int cur_data_idx_;
   std::unique_ptr<Bundle> context_data_ = nullptr;
+  std::unique_ptr<Bundle> last_context_data_ = nullptr;
   std::unique_ptr<Bundle> last_data_ = nullptr;
   int last_data_idx_;
   EditableShapeType shape_type_;
index 956b6a4..b6246e5 100755 (executable)
@@ -181,6 +181,17 @@ void Complication::Impl::RestoreStateOrSetDefault() {
 
   /* Initialize last_data_idx_ */
   last_data_idx_ = cur_data_idx_;
+  if (candidates_list_.size() > 0) {
+    std::list<std::unique_ptr<Bundle>>::iterator it
+                                    = candidates_list_.begin();
+    auto nx = std::next(it, last_data_idx_);
+    last_data_.reset(new Bundle((*nx).get()->GetRaw()));
+  }
+
+  context_data_ = EditablesManager::GetInst().LoadContext(complication_id_,
+      cur_provider_id_.c_str());
+  if (context_data_ != nullptr)
+    last_context_data_.reset(new Bundle(context_data_.get()->GetRaw()));
 }
 
 int Complication::Impl::StoreSetting(int comp_id, std::string& provider_id,
@@ -452,7 +463,7 @@ int Complication::SendDataUpdateRequest() {
     ComplicationConnector::Complication,
     provider_appid,
     impl_->cur_provider_id_,
-    0,
+    -1,
     ComplicationConnector::GetInst().GetCmdStr(
         ComplicationConnector::CompUpdateRequest),
     g_variant_new("(siis)",
@@ -480,4 +491,39 @@ IEditable::EditableState Complication::GetState() {
   return impl_->ed_state_;
 }
 
+const std::string Complication::GetSetupAppId() {
+  // TODO(?): from db
+  return "org.tizen.comp_setting";
+}
+
+int Complication::SetContext(std::unique_ptr<Bundle> context) {
+  impl_->context_data_.reset();
+  impl_->context_data_ = std::move(context);
+  return COMPLICATION_ERROR_NONE;
+}
+
+std::unique_ptr<Bundle>& Complication::GetContext() const {
+  return impl_->context_data_;
+}
+
+int Complication::UpdateLastContext() {
+  if (impl_->context_data_.get() == NULL) {
+    LOGI("Empty context");
+    return COMPLICATION_ERROR_NONE;
+  }
+
+  int ret = EditablesManager::GetInst().StoreContext(impl_->complication_id_,
+      impl_->cur_provider_id_.c_str(), *impl_->context_data_.get());
+  if (ret != COMPLICATION_ERROR_NONE)
+    return ret;
+
+  impl_->last_context_data_.reset(new Bundle((impl_->context_data_.get())->GetRaw()));
+  return COMPLICATION_ERROR_NONE;
+}
+
+std::unique_ptr<Bundle>& Complication::GetLastContext() const {
+  return impl_->last_context_data_;
+}
+
+
 }  // namespace watchface_complication
index b3aae16..9a2d215 100755 (executable)
@@ -60,6 +60,11 @@ class EXPORT_API Complication : public IEditable
   void SetName(const std::string& name) override;
   void SetState(IEditable::EditableState state) override;
   IEditable::EditableState GetState() override;
+  int SetContext(std::unique_ptr<Bundle> context) override;
+  std::unique_ptr<Bundle>& GetContext() const override;
+  int UpdateLastContext() override;
+  std::unique_ptr<Bundle>& GetLastContext() const override;
+  const std::string GetSetupAppId() override;
   int SendDataUpdateRequest();
   void SetShapeType(IEditable::EditableShapeType shape_type);
   std::list<std::string> GetProviderList(
index 779da4e..6f3b887 100644 (file)
@@ -55,6 +55,8 @@ class DesignElement::Impl {
   EditableShapeType shape_type_;
   std::string name_;
   IEditable::EditableState ed_state_;
+  std::unique_ptr<Bundle> context_data_;
+  std::unique_ptr<Bundle> last_context_data_ = nullptr;
 };
 
 }  // namespace watchface_complication
index 87f65a8..2f46241 100644 (file)
@@ -172,4 +172,33 @@ IEditable::EditableState DesignElement::GetState() {
   return impl_->ed_state_;
 }
 
+const std::string DesignElement::GetSetupAppId() {
+  std::string setup_appid = "org.tizen.comp_setting";
+  // TODO(?) : from DB
+  return setup_appid;
+}
+
+int DesignElement::SetContext(std::unique_ptr<Bundle> context) {
+  impl_->context_data_.reset();
+  impl_->context_data_ = std::move(context);
+  return COMPLICATION_ERROR_NONE;
+}
+
+std::unique_ptr<Bundle>& DesignElement::GetContext() const {
+  return impl_->context_data_;
+}
+
+int DesignElement::UpdateLastContext() {
+  if (impl_->context_data_.get() == NULL) {
+    LOGI("Empty context");
+    return COMPLICATION_ERROR_NONE;
+  }
+  impl_->last_context_data_.reset(new Bundle((impl_->context_data_.get())->GetRaw()));
+  return COMPLICATION_ERROR_NONE;
+}
+
+std::unique_ptr<Bundle>& DesignElement::GetLastContext() const {
+  return impl_->last_context_data_;
+}
+
 }  // namespace watchface_complication
index 71f825a..9d94a19 100644 (file)
@@ -55,6 +55,11 @@ class EXPORT_API DesignElement : public IEditable {
   void SetName(const std::string& name) override;
   void SetState(IEditable::EditableState state) override;
   IEditable::EditableState GetState() override;
+  int SetContext(std::unique_ptr<Bundle> context) override;
+  std::unique_ptr<Bundle>& GetContext() const override;
+  int UpdateLastContext() override;
+  std::unique_ptr<Bundle>& GetLastContext() const override;
+  const std::string GetSetupAppId() override;
   void SetShapeType(IEditable::EditableShapeType shape_type);
 
  private:
index e2997fc..78ebcc6 100644 (file)
@@ -80,6 +80,11 @@ class IEditable {
   virtual void OnEditableUpdated(int selected_idx, EditableState state) = 0;
   virtual void SetState(EditableState state) = 0;
   virtual EditableState GetState() = 0;
+  virtual const std::string GetSetupAppId() = 0;
+  virtual int SetContext(std::unique_ptr<Bundle> context) = 0;
+  virtual std::unique_ptr<Bundle>& GetContext() const = 0;
+  virtual int UpdateLastContext() = 0;
+  virtual std::unique_ptr<Bundle>& GetLastContext() const = 0;
 };
 
 }  // namespace watchface_complication
index 2e18df6..43c6313 100644 (file)
@@ -30,6 +30,7 @@ class EXPORT_API IEditablesContainerEvent {
  public:
   virtual void OnRequestEdit(const std::string& appid,
                              std::list<std::unique_ptr<IEditable>> e_list) = 0;
+  virtual void OnSetupReply(int editable_id, std::unique_ptr<Bundle> context) = 0;
 };
 
 }  // namespace watchface_complication
index e64de7a..0695867 100644 (file)
@@ -42,6 +42,7 @@ class EditablesContainer::Impl : ComplicationConnector::IEventListener {
                 GVariant* parameters) override;
   void OnVanish(const std::string& name) override;
   void OnAppear(const std::string& name, const std::string& name_owner) override;
+  void CancelEditing();
   explicit Impl(EditablesContainer* parent);
   Impl(Impl const& other) = default;
   Impl(Impl && other) = default;
index 594b8e5..41f2429 100644 (file)
@@ -41,7 +41,7 @@ EditablesContainer::Impl::Impl(EditablesContainer* parent)
   : parent_(parent) {
   subscribe_id_ = ComplicationConnector::GetInst().SubscribeSignal(
                     ComplicationConnector::Editable,
-                    ComplicationConnector::GetInst().GetAppId(), 0, this);
+                    ComplicationConnector::GetInst().GetAppId(), -1, this);
   LOGI("subscribe signal %d", subscribe_id_);
 }
 
@@ -66,13 +66,21 @@ void EditablesContainer::Impl::OnSignal(const std::string& sender_name,
           ComplicationConnector::EditableEditPreview)) == 0) {
     int editable_id;
     int selected_idx;
-    g_variant_get(parameters, "(ii)", &selected_idx, &editable_id);
+    char *context = NULL;
+    std::string ctx_str;
+
+    g_variant_get(parameters, "(iis)", &selected_idx, &editable_id, &context);
     LOGI("preview selected_idx, editable_id, state: %d, %d", selected_idx,
         editable_id);
+
+    if (context != NULL)
+      ctx_str = std::string(context);
     for (auto& i : ed_list_) {
       if (i.get()->GetId() == editable_id) {
         i.get()->SetState(IEditable::OnGoing);
         i.get()->SetCurDataIdx(selected_idx);
+        if (!ctx_str.empty())
+          i.get()->SetContext(std::unique_ptr<Bundle>(new Bundle(ctx_str)));
         i.get()->OnEditableUpdated(i.get()->GetCurDataIdx(), IEditable::OnGoing);
         parent_->OnUpdate(*i.get(), i.get()->GetCurDataIdx(), IEditable::OnGoing);
       }
@@ -84,32 +92,37 @@ void EditablesContainer::Impl::OnSignal(const std::string& sender_name,
       i.get()->SetState(IEditable::Complete);
       i.get()->SetCurDataIdx(i.get()->GetCurDataIdx());
       i.get()->UpdateLastDataIdx();
+      i.get()->UpdateLastContext();
       i.get()->OnEditableUpdated(i.get()->GetCurDataIdx(), IEditable::Complete);
       parent_->OnUpdate(*i.get(), i.get()->GetCurDataIdx(), IEditable::Complete);
     }
-  } else if (signal_name.compare(
-      ComplicationConnector::GetInst().GetCmdStr(
+  } else if (signal_name.compare(ComplicationConnector::GetInst().GetCmdStr(
           ComplicationConnector::EditableEditCancel)) == 0) {
-    for (auto& i : ed_list_) {
-      i.get()->SetState(IEditable::Cancel);
-      i.get()->SetCurDataIdx(i.get()->GetLastDataIdx());
-      i.get()->OnEditableUpdated(i.get()->GetCurDataIdx(), IEditable::Cancel);
-      parent_->OnUpdate(*i.get(), i.get()->GetCurDataIdx(), IEditable::Cancel);
-    }
+    CancelEditing();
   }
 }
 
-void EditablesContainer::Impl::OnVanish(const std::string& name) {
+void EditablesContainer::Impl::CancelEditing() {
   for (auto& i : ed_list_) {
     if (i.get()->GetState() != IEditable::Complete) {
       i.get()->SetState(IEditable::Cancel);
       i.get()->SetCurDataIdx(i.get()->GetLastDataIdx());
+      if (i.get()->GetLastContext().get() != NULL) {
+        i.get()->SetContext(std::unique_ptr<Bundle>(
+            new Bundle(i.get()->GetLastContext().get()->GetRaw())));
+      } else {
+        i.get()->SetContext(std::unique_ptr<Bundle>{});
+      }
       i.get()->OnEditableUpdated(i.get()->GetCurDataIdx(), IEditable::Cancel);
       parent_->OnUpdate(*i.get(), i.get()->GetCurDataIdx(), IEditable::Cancel);
     }
   }
 }
 
+void EditablesContainer::Impl::OnVanish(const std::string& name) {
+  CancelEditing();
+}
+
 void EditablesContainer::Impl::OnAppear(const std::string& name,
     const std::string& name_owner) {
 }
@@ -174,7 +187,7 @@ int EditablesContainer::RequestEdit(const std::string& editor_id) {
     ComplicationConnector::Editable,
     editor_id,
     editor_id,
-    0,
+    -1,
     ComplicationConnector::GetInst().GetCmdStr(
         ComplicationConnector::EditableEditRequest),
     g_variant_new("(ss)",
index 9c9960e..475bb78 100644 (file)
@@ -37,6 +37,7 @@ class EXPORT_API EditablesContainer : IEditablesEditorEvent {
   virtual void OnUpdate(const IEditable& ed, int selected_idx,
       IEditable::EditableState state);
   void OnEditReady(const std::string& editor_id) override;
+
  private:
   class Impl;
   std::unique_ptr<Impl> impl_;
index 292918e..5ca772c 100644 (file)
@@ -34,17 +34,19 @@ class EditablesManager::Impl {
   virtual ~Impl() {
     if (setting_db_ != NULL)
       sqlite3_close(setting_db_);
+    if (context_db_ != NULL)
+      sqlite3_close(context_db_);
   };
 
  private:
   friend class EditablesManager;
   Impl();
-  static std::string GetSettingDataPath() {
+  static std::string GetEditablesDataPath() {
     char* app_data_path = app_get_data_path();
     char setting_data_path[PATH_MAX] = {0, };
 
     if (app_data_path != NULL) {
-      snprintf(setting_data_path, PATH_MAX, "%s.watchface_editables_setting.db",
+      snprintf(setting_data_path, PATH_MAX, "%s.watchface_editables.db",
           app_data_path);
       LOGI("get setting data path %s", setting_data_path);
       free(app_data_path);
@@ -55,6 +57,7 @@ class EditablesManager::Impl {
 
  private:
   sqlite3* setting_db_ = NULL;
+  sqlite3* context_db_ = NULL;
 };
 
 }  // namespace watchface_complication
index bdd0dcd..1227071 100644 (file)
@@ -56,12 +56,17 @@ void EditablesManager::Init() {
     LOGI("setting db already exist");
     return;
   }
-  std::string table_command =
+  std::string context_table_command =
+    "CREATE TABLE IF NOT EXISTS editable_context" \
+    "(editable_id INTEGER NOT NULL, provider_id TEXT NOT NULL, "\
+    "context_data TEXT NULL, "\
+    "PRIMARY KEY(editable_id, provider_id))";
+
+  std::string setting_table_command =
     "CREATE TABLE IF NOT EXISTS editable_setting" \
     "(editable_id INTEGER NOT NULL, setting_data TEXT NOT NULL, "\
-    "context_data TEXT NULL, "\
     "PRIMARY KEY(editable_id))";
-  std::string db_path = impl_->GetSettingDataPath();
+  std::string db_path = impl_->GetEditablesDataPath();
   if (db_path.empty()) {
     LOGE("GetSettingDataPath failed");
     return;
@@ -73,9 +78,20 @@ void EditablesManager::Init() {
     LOGE("database creation failed with error: %d", ret);
     return;
   }
-  ret = sqlite3_exec(impl_->setting_db_, table_command.c_str(), NULL, NULL, NULL);
+  ret = sqlite3_exec(impl_->setting_db_, setting_table_command.c_str(),
+      NULL, NULL, NULL);
+  if (ret != SQLITE_OK)
+    LOGE("database setting table creation failed: %d", ret);
+
+  ret = sqlite3_open_v2(db_path.c_str(), &impl_->context_db_, open_flags, NULL);
+  if (ret != SQLITE_OK) {
+    LOGE("database creation failed with error: %d", ret);
+    return;
+  }
+  ret = sqlite3_exec(impl_->context_db_, context_table_command.c_str(),
+      NULL, NULL, NULL);
   if (ret != SQLITE_OK)
-    LOGE("database table creation failed: %d", ret);
+    LOGE("database context table creation failed: %d", ret);
 }
 
 int EditablesManager::StoreSetting(int editable_id, bundle_raw* raw_data) {
@@ -136,4 +152,65 @@ std::unique_ptr<Bundle> EditablesManager::LoadSetting(int editable_id) {
   return std::move(setting_data);
 }
 
+int EditablesManager::StoreContext(int editable_id, const char* provider_id,
+    Bundle& context) {
+  int r;
+  char* error = NULL;
+  char query[QUERY_MAXLEN] = {0, };
+
+  if (impl_->setting_db_ == NULL) {
+    LOGE("DB is not initialized.");
+    return COMPLICATION_ERROR_IO_ERROR;
+  }
+
+  sqlite3_snprintf(QUERY_MAXLEN, query,
+      "INSERT OR REPLACE INTO editable_context(editable_id, provider_id, " \
+      "context_data) " \
+      "VALUES (%d, %Q, %Q)",
+      editable_id, provider_id, context.ToString());
+  LOGI("editables context insert sql : %s", query);
+  r = sqlite3_exec(impl_->context_db_, query, NULL, NULL, &error);
+  if (r != SQLITE_OK) {
+    LOGE("sqlite3_exec error(query = %s, error = %s)", query, error);
+    sqlite3_free(error);
+    return COMPLICATION_ERROR_IO_ERROR;
+  }
+  return COMPLICATION_ERROR_NONE;
+}
+
+std::unique_ptr<Bundle> EditablesManager::LoadContext(int editable_id,
+    const char* provider_id) {
+  char query[QUERY_MAXLEN];
+  std::unique_ptr<Bundle> context_data = nullptr;
+  const char* raw_data;
+  sqlite3_stmt* stmt;
+  int ret;
+
+  if (impl_->context_db_ == NULL) {
+    return nullptr;
+  }
+
+  sqlite3_snprintf(QUERY_MAXLEN, query,
+      "SELECT context_data FROM editable_context WHERE " \
+      "editable_id = %d AND provider_id = %Q ", editable_id, provider_id);
+  LOGI("editable context select sql : %s", query);
+  ret = sqlite3_prepare_v2(impl_->context_db_,
+      query, strlen(query), &stmt, NULL);
+  if (ret != SQLITE_OK) {
+    LOGE("execute query = %s fail %s\n",
+        query, sqlite3_errmsg(impl_->context_db_));
+    sqlite3_close_v2(impl_->context_db_);
+    return nullptr;
+  }
+
+  if (sqlite3_step(stmt) == SQLITE_ROW) {
+    raw_data = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
+    context_data = std::unique_ptr<Bundle>(new Bundle(std::string(raw_data)));
+  }
+  sqlite3_finalize(stmt);
+
+  return std::move(context_data);
+}
+
+
 }  // namespace watchface_complication
index 1441e90..f53904f 100644 (file)
@@ -31,6 +31,8 @@ class EXPORT_API EditablesManager {
   static EditablesManager& GetInst();
   int StoreSetting(int editable_id, bundle_raw* raw_data);
   std::unique_ptr<Bundle> LoadSetting(int editable_id);
+  int StoreContext(int editable_id, const char* provider_id, Bundle& context);
+  std::unique_ptr<Bundle> LoadContext(int editable_id, const char* provider_id);
 
  private:
   EditablesManager();
index f8625e6..e99d48d 100644 (file)
 
 #include "watchface-complication/include/watchface-common.h"
 
+#define SETUP_EDITOR_APPID_KEY "__SETUP_EDITOR_APPID_KEY__"
+#define SETUP_EDITABLE_ID_KEY "__SETUP_EDITABLE_ID_KEY__"
+#define SETUP_CONTEXT_DATA_KEY "__SETUP_CONTEXT_DATA_KEY__"
+
 namespace watchface_complication {
 
 typedef enum {
index 30e24b8..e5fe964 100644 (file)
@@ -50,6 +50,8 @@ class ReceivedEditable::Impl {
   int cur_data_idx_;
   int last_data_idx_;
   IEditable::EditableState ed_state_;
+  std::unique_ptr<Bundle> context_data_;
+  std::unique_ptr<Bundle> last_context_data_ = nullptr;
 };
 
 }  // namespace watchface_complication
index 240b389..0ffeeb3 100644 (file)
@@ -154,4 +154,32 @@ IEditable::EditableState ReceivedEditable::GetState() {
   return impl_->ed_state_;
 }
 
+const std::string ReceivedEditable::GetSetupAppId() {
+  // TODO(?): from db
+  return "org.tizen.comp_setting";
+}
+
+int ReceivedEditable::SetContext(std::unique_ptr<Bundle> context) {
+  impl_->context_data_.reset();
+  impl_->context_data_ = std::move(context);
+  return COMPLICATION_ERROR_NONE;
+}
+
+std::unique_ptr<Bundle>& ReceivedEditable::GetContext() const {
+  return impl_->context_data_;
+}
+
+int ReceivedEditable::UpdateLastContext() {
+  if (impl_->context_data_.get() == NULL) {
+    LOGI("Empty context");
+    return COMPLICATION_ERROR_NONE;
+  }
+  impl_->last_context_data_.reset(new Bundle((impl_->context_data_.get())->GetRaw()));
+  return COMPLICATION_ERROR_NONE;
+}
+
+std::unique_ptr<Bundle>& ReceivedEditable::GetLastContext() const {
+  return impl_->last_context_data_;
+}
+
 }  // namespace watchface_complication
index 8d5efeb..78a3b71 100644 (file)
@@ -53,6 +53,11 @@ class EXPORT_API ReceivedEditable : public IEditable {
   void SetName(const std::string& name) override;
   void SetState(IEditable::EditableState state) override;
   IEditable::EditableState GetState() override;
+  int SetContext(std::unique_ptr<Bundle> context) override;
+  std::unique_ptr<Bundle>& GetContext() const override;
+  int UpdateLastContext() override;
+  std::unique_ptr<Bundle>& GetLastContext() const override;
+  const std::string GetSetupAppId() override;
 
  private:
   class Impl;
index 2c7510d..e16a2a1 100755 (executable)
@@ -100,7 +100,7 @@ extern "C" EXPORT_API int complication_update_cb_add(complication_h handle,
   auto ptr = SharedHandle<WatchComplicationStub>::Share(sh);
   ptr.get()->AddCallbackInfo(new CallbackInfo(cb, user_data));
 
-  return 0;
+  return COMPLICATION_ERROR_NONE;
 }
 
 extern "C" EXPORT_API int complication_update_cb_del(complication_h handle,
@@ -108,7 +108,7 @@ extern "C" EXPORT_API int complication_update_cb_del(complication_h handle,
   if (handle == NULL || cb == NULL)
     return COMPLICATION_ERROR_INVALID_PARAMETER;
 
-  return 0;
+  return COMPLICATION_ERROR_NONE;
 }
 
 extern "C" EXPORT_API int complication_send_update_request(
@@ -141,19 +141,23 @@ extern "C" EXPORT_API int complication_create(int complication_id,
       support_types > COMPLICATION_TYPE_MAX)
     return COMPLICATION_ERROR_INVALID_PARAMETER;
 
-  // TODO(?) check default value and type is valid
-  auto ws = new WatchComplicationStub(
+  try {
+    auto ws = new WatchComplicationStub(
               complication_id,
               support_types,
               default_provider_id,
               static_cast<ComplicationType>(default_type),
               std::shared_ptr<IEditable::Geometry>(
                 new IEditable::Geometry(0, 0, 100, 100)));
-  LOGI("comp created");
-  auto sh = SharedHandle<WatchComplicationStub>::Make(ws);
-  *created_handle = static_cast<void*>(sh);
+    LOGI("comp created");
+    auto sh = SharedHandle<WatchComplicationStub>::Make(ws);
+    *created_handle = static_cast<void*>(sh);
+  } catch(...) {
+    LOGE("Create complication fail");
+    return COMPLICATION_ERROR_IO_ERROR;
+  }
 
-  return 0;
+  return COMPLICATION_ERROR_NONE;
 }
 
 extern "C" EXPORT_API int complication_destroy(complication_h handle) {
@@ -175,7 +179,7 @@ extern "C" EXPORT_API int complication_get_cur_provider_id(complication_h handle
   auto ptr = SharedHandle<WatchComplicationStub>::Share(sh);
   *cur_provider_id = ptr.get()->GetCurProviderId();
 
-  return 0;
+  return COMPLICATION_ERROR_NONE;
 }
 
 extern "C" EXPORT_API int complication_get_cur_type(complication_h handle,
@@ -189,7 +193,7 @@ extern "C" EXPORT_API int complication_get_cur_type(complication_h handle,
   if (ret != -1)
     *cur_type = static_cast<complication_type>(ret);
 
-  return 0;
+  return COMPLICATION_ERROR_NONE;
 }
 
 extern "C" EXPORT_API int complication_get_provider_id(const bundle* candidate,
@@ -204,9 +208,9 @@ extern "C" EXPORT_API int complication_get_provider_id(const bundle* candidate,
   if (val != NULL)
     *provider_id = val;
   else
-    return -1;
+    return COMPLICATION_ERROR_INVALID_PARAMETER;
 
-  return 0;
+  return COMPLICATION_ERROR_NONE;
 }
 
 extern "C" EXPORT_API int complication_get_type(const bundle* candidate,
@@ -221,7 +225,7 @@ extern "C" EXPORT_API int complication_get_type(const bundle* candidate,
   if (val != NULL)
     *cur_type = static_cast<complication_type>(atoi(val));
   else
-    return -1;
+    return COMPLICATION_ERROR_INVALID_PARAMETER;
 
-  return 0;
+  return COMPLICATION_ERROR_NONE;
 }
index bbc02a1..b4d365f 100755 (executable)
@@ -13,6 +13,7 @@ pkg_check_modules(watchface-editor REQUIRED
        glib-2.0
        bundle
        dlog
+       capi-appfw-app-control
 )
 
 FOREACH(flag ${watchface-editor_CFLAGS})
index f4fd1c5..26156c8 100644 (file)
@@ -40,7 +40,7 @@ EditablesEditor::Impl::Impl(EditablesEditor* parent)
   : parent_(parent) {
   subscribe_id_ = ComplicationConnector::GetInst().SubscribeSignal(
                     ComplicationConnector::Editable,
-                    ComplicationConnector::GetInst().GetAppId(), 0, this);
+                    ComplicationConnector::GetInst().GetAppId(), -1, this);
   LOGI("subscribe signal %d", subscribe_id_);
 }
 
@@ -83,9 +83,20 @@ void EditablesEditor::Impl::OnSignal(const std::string& sender_name,
                   new ReceivedEditable(std::string(str_arr[i]))));
     }
     parent_->OnRequestEdit(std::string(appid), std::move(e_list));
+  } else if (signal_name.compare(
+      ComplicationConnector::GetInst().GetCmdStr(
+          ComplicationConnector::SetupReply)) == 0) {
+    int edit_id;
+    char* raw_str;
+    g_variant_get(parameters, "(i&s)", &edit_id, &raw_str);
+    parent_->OnSetupReply(edit_id, std::unique_ptr<Bundle>(new Bundle(std::string(raw_str))));
   }
 }
 
+void EditablesEditor::OnSetupReply(int editable_id, std::unique_ptr<Bundle> context) {
+
+}
+
 void EditablesEditor::OnRequestEdit(const std::string& appid,
                                     std::list<std::unique_ptr<IEditable>> e_list) {
 }
@@ -99,14 +110,16 @@ int EditablesEditor::EditPreview(IEditable& ed, int cur_data_idx) {
   ReceivedEditable& re = static_cast<ReceivedEditable&>(ed);
   re.SetCurDataIdx(cur_data_idx);
 
+  Bundle *context = re.GetContext().get();
   ComplicationConnector::GetInst().EmitSignal(
     ComplicationConnector::Editable,
     impl_->edit_appid_.c_str(),
     impl_->edit_appid_.c_str(),
-    0,
+    -1,
     ComplicationConnector::GetInst().GetCmdStr(
         ComplicationConnector::EditableEditPreview),
-    g_variant_new("(ii)", cur_data_idx, ed.GetId()));
+    g_variant_new("(iis)", cur_data_idx, ed.GetId(),
+        (context == nullptr) ? "" : context->ToString()));
 
   return 0;
 }
@@ -121,7 +134,7 @@ int EditablesEditor::EditComplete() {
     ComplicationConnector::Editable,
     impl_->edit_appid_.c_str(),
     impl_->edit_appid_.c_str(),
-    0,
+    -1,
     ComplicationConnector::GetInst().GetCmdStr(
         ComplicationConnector::EditableEditComplete), NULL);
 
@@ -138,7 +151,7 @@ int EditablesEditor::EditCancel() {
     ComplicationConnector::Editable,
     impl_->edit_appid_.c_str(),
     impl_->edit_appid_.c_str(),
-    0,
+    -1,
     ComplicationConnector::GetInst().GetCmdStr(
         ComplicationConnector::EditableEditCancel), NULL);
 
@@ -153,7 +166,7 @@ int EditablesEditor::NotifyEditReady(std::string appid) {
     ComplicationConnector::Editable,
     appid,
     appid,
-    0,
+    -1,
     ComplicationConnector::GetInst().GetCmdStr(
         ComplicationConnector::EditableEditReady),
     g_variant_new("(s)", ComplicationConnector::GetInst().GetAppId().c_str()));
index 524afcf..98e1288 100644 (file)
@@ -33,6 +33,7 @@ class EXPORT_API EditablesEditor : IEditablesContainerEvent {
   virtual ~EditablesEditor();
   void OnRequestEdit(const std::string& appid,
                      std::list<std::unique_ptr<IEditable>> e_list) override;
+  void OnSetupReply(int editable_id, std::unique_ptr<Bundle> context) override;
   int EditPreview(IEditable& ed, int cur_data_idx);
   int EditComplete();
   int EditCancel();
index 4c7eb1a..0982936 100755 (executable)
@@ -27,8 +27,9 @@
 extern "C" {
 #endif
 
-
 typedef GList *editable_list_h;
+typedef void (*on_setup_result)(editable_h ed, bundle *new_context,
+        void *user_data);
 typedef int (*on_request_edit)(const char *appid, editable_list_h list_h,
                                void *user_data);
 typedef int (*editable_list_foreach_cb)(const editable_h handle,
@@ -52,6 +53,84 @@ int editor_editable_candidate_list_get_size(const editable_h handle);
 const bundle* editor_editable_candidate_list_get_nth(const editable_h handle,
                                                      int nth);
 
+/**
+ * @brief Set editable's contest
+ * @since_tizen 5.0
+ * @param[in] handle The editable handle
+ * @param[in] context The new context data
+ * @see #editor_launch_setup_app
+ * @return #COMPLICATION_ERROR_NONE on success,
+ *         otherwise an error code (see COMPLICATION_ERROR_XXX) on failure
+ * @retval #COMPLICATION_ERROR_NONE Successful
+ * @retval #COMPLICATION_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #COMPLICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par Sample code:
+ * @code
+#include <watchface-editor.h>
+void on_setup_result(editable_h ed, bundle *new_context,
+        void *user_data)
+{
+        editor_set_context(ed, new_context);
+        // send update info to the watchface
+        editor_edit_preview(ed, __candidate_selected);
+}
+ * @endcode
+ */
+int editor_set_context(const editable_h handle, bundle *context);
+
+/**
+ * @brief Launch editable's setup app
+ * @since_tizen 5.0
+ * @param[in] handle The editable handle
+ * @param[in] cb The setup result callback
+ * @param[in] user_data The setup result callback's user data
+ * @see #editor_is_setup_app_exist
+ * @return #COMPLICATION_ERROR_NONE on success,
+ *         otherwise an error code (see COMPLICATION_ERROR_XXX) on failure
+ * @retval #COMPLICATION_ERROR_NONE Successful
+ * @retval #COMPLICATION_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #COMPLICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par Sample code:
+ * @code
+#include <watchface-editor.h>
+
+{
+        bool exist;
+        editor_is_setup_app_exist(handle, &exist);
+        if (exist) {
+                editor_launch_setup_app(handle, on_setup_result, NULL);
+        }
+}
+ * @endcode
+ */
+int editor_launch_setup_app(const editable_h handle, on_setup_result cb, void *user_data);
+
+/**
+ * @brief Check setup app is exist
+ * @since_tizen 5.0
+ * @param[in] handle The editable handle
+ * @param[out] exist The flag whether setup app is exist or not
+ * @see #editor_launch_setup_app
+ * @return #COMPLICATION_ERROR_NONE on success,
+ *         otherwise an error code (see COMPLICATION_ERROR_XXX) on failure
+ * @retval #COMPLICATION_ERROR_NONE Successful
+ * @retval #COMPLICATION_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #COMPLICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @par Sample code:
+ * @code
+#include <watchface-editor.h>
+
+{
+        bool exist;
+        editor_is_setup_app_exist(handle, &exist);
+        if (exist) {
+                editor_launch_setup_app(handle, on_setup_result, NULL);
+        }
+}
+ * @endcode
+ */
+int editor_is_setup_app_exist(const editable_h handle, bool *exist);
+
 #ifdef __cplusplus
 }
 #endif
index 1d81c42..c5eb1c5 100644 (file)
 #include <stdio.h>
 #include <errno.h>
 #include <glib.h>
-#include <dlog.h>
-
 #include <string>
 
+#include <dlog.h>
+#include <app_control.h>
+
 #include "watchface-editor/include/watchface-editor.h"
 #include "watchface-complication/complication.h"
 #include "watchface-editor/editables-editor.h"
 
 #define LOG_TAG "WATCHFACE_COMPLICATION"
 
-using watchface_complication::EditablesEditor;
-using watchface_complication::Complication;
-using watchface_complication::Bundle;
-using watchface_complication::IEditable;
+using namespace watchface_complication;
 
 class CallbackInfo {
  public:
@@ -51,6 +49,21 @@ class CallbackInfo {
   void* user_data_;
 };
 
+class SetupCallbackInfo {
+ public:
+  SetupCallbackInfo(on_setup_result cb, void* user_data)
+    : cb_(cb), user_data_(user_data) {
+  }
+
+  void Invoke(void* handle, bundle* new_context) {
+    cb_(handle, new_context, user_data_);
+  }
+
+ private:
+  on_setup_result cb_;
+  void* user_data_;
+};
+
 class EditablesEditorStub : public EditablesEditor {
  public:
   EditablesEditorStub()
@@ -74,6 +87,31 @@ class EditablesEditorStub : public EditablesEditor {
     LOGI("request edit!! %s", appid.c_str());
   }
 
+  void OnSetupReply(int editable_id, std::unique_ptr<Bundle> context) override {
+
+    for (auto& i : e_list_) {
+      LOGI("Setup reply!! %d, %d", i.get()->GetId(), editable_id);
+      if (i.get()->GetId() == editable_id) {
+        for (auto& j : setup_cb_list_) {
+          j->Invoke(i.get(), context.get()->GetRaw());
+        }
+      }
+    }
+  }
+
+  void AddSetupCallbackInfo(SetupCallbackInfo* ci) {
+    setup_cb_list_.emplace_back(ci);
+  }
+
+  void RemoveCallbackInfo(SetupCallbackInfo* ci) {
+    for (auto& i : setup_cb_list_) {
+      if (i.get() == ci) {
+        setup_cb_list_.remove(i);
+        break;
+      }
+    }
+  }
+
   void AddCallbackInfo(CallbackInfo* ci) {
     cb_list_.emplace_back(ci);
   }
@@ -94,6 +132,7 @@ class EditablesEditorStub : public EditablesEditor {
  private:
   std::list<std::unique_ptr<IEditable>> e_list_;
   std::list<std::unique_ptr<CallbackInfo>> cb_list_;
+  std::list<std::unique_ptr<SetupCallbackInfo>> setup_cb_list_;
 };
 
 static std::unique_ptr<EditablesEditorStub> __stub = nullptr;
@@ -120,7 +159,7 @@ extern "C" EXPORT_API int editor_on_request_edit_cb_del(on_request_edit cb) {
 
 extern "C" EXPORT_API int editor_edit_preview(const editable_h handle,
     int cur_data_idx) {
- if (handle == NULL)
 if (handle == NULL)
     return COMPLICATION_ERROR_INVALID_PARAMETER;
 
   IEditable* ed = static_cast<IEditable*>(handle);
@@ -149,7 +188,6 @@ extern "C" EXPORT_API int editor_notify_edit_ready(const char *appid) {
   return 0;
 }
 
-
 extern "C" EXPORT_API int editor_foreach_editable_list(editable_list_h list_h,
     editable_list_foreach_cb cb, void *user_data) {
   if (list_h == NULL || cb == NULL)
@@ -234,3 +272,123 @@ extern "C" EXPORT_API const bundle* editor_editable_candidate_list_get_nth(
   auto nx = std::next(it, nth);
   return ((*nx).get())->GetRaw();
 }
+
+extern "C" EXPORT_API int editor_get_setup_appid(const editable_h handle,
+    char **setup_appid) {
+  if (handle == NULL || setup_appid == NULL)
+    return COMPLICATION_ERROR_INVALID_PARAMETER;
+
+  IEditable* ed = static_cast<IEditable*>(handle);
+  std::string appid = ed->GetSetupAppId();
+  if (appid.empty())
+    return COMPLICATION_ERROR_NO_DATA;
+  *setup_appid = strdup(appid.c_str());
+
+  return COMPLICATION_ERROR_NONE;
+}
+
+extern "C" EXPORT_API int editor_set_context(const editable_h handle,
+    bundle *new_context) {
+  if (handle == NULL) {
+    LOGE("Invalid parameter");
+    return COMPLICATION_ERROR_INVALID_PARAMETER;
+  }
+
+  int re = COMPLICATION_ERROR_NONE;
+  IEditable* ed = static_cast<IEditable*>(handle);
+  if (new_context) {
+    std::unique_ptr<Bundle> b(new Bundle(new_context));
+    if (b.get() == nullptr)
+      return COMPLICATION_ERROR_OUT_OF_MEMORY;
+    re = ed->SetContext(std::move(b));
+  } else {
+    re = ed->SetContext(std::unique_ptr<Bundle>{});
+  }
+  return re;
+}
+
+extern "C" EXPORT_API int editor_is_setup_app_exist(const editable_h handle,
+    bool *exist) {
+  if (handle == NULL) {
+    LOGE("Invalid parameter");
+    return COMPLICATION_ERROR_INVALID_PARAMETER;
+  }
+  IEditable* ed = static_cast<IEditable*>(handle);
+  std::string appid = ed->GetSetupAppId();
+  if (appid.empty())
+    *exist = false;
+  *exist = true;
+  return COMPLICATION_ERROR_NONE;
+}
+
+static int _add_extra_data(app_control_h* service, const char* key, const char* value) {
+  int ret = app_control_add_extra_data(*service, key, value);
+  if (ret != APP_CONTROL_ERROR_NONE) {
+    if (ret == APP_CONTROL_ERROR_OUT_OF_MEMORY) {
+      LOGE("Fail to get context data");
+      return COMPLICATION_ERROR_OUT_OF_MEMORY;
+    }
+    LOGE("Fail to get context data");
+    return COMPLICATION_ERROR_INVALID_PARAMETER;
+  }
+  return COMPLICATION_ERROR_NONE;
+}
+
+extern "C" EXPORT_API int editor_launch_setup_app(const editable_h handle,
+    on_setup_result cb, void* user_data) {
+
+  if (handle == NULL || cb == NULL) {
+    LOGE("Invalid parameter");
+    return COMPLICATION_ERROR_INVALID_PARAMETER;
+  }
+
+  IEditable* ed = static_cast<IEditable*>(handle);
+  std::string appid = ed->GetSetupAppId();
+  app_control_h service = NULL;
+  Bundle* context_data;
+  char ed_id[256] = {0,};
+  if(APP_CONTROL_ERROR_NONE != app_control_create(&service)) {
+    LOGE("Fail to create app control");
+    return COMPLICATION_ERROR_IO_ERROR;
+  }
+
+  LOGI("LAUNCH !!! %s", appid.c_str());
+  context_data = (ed->GetContext()).get();
+  app_control_set_app_id(service, appid.c_str());
+
+  int ret = _add_extra_data(&service, SETUP_EDITOR_APPID_KEY,
+      ComplicationConnector::GetInst().GetAppId().c_str());
+  if (ret != COMPLICATION_ERROR_NONE) {
+    LOGE("Fail to add appid ");
+    app_control_destroy(service);
+    return ret;
+  }
+
+  snprintf(ed_id, sizeof(ed_id), "%d", ed->GetId());
+  LOGI("add ed_id %s", ed_id);
+  ret = _add_extra_data(&service, SETUP_EDITABLE_ID_KEY, ed_id);
+  if (ret != COMPLICATION_ERROR_NONE) {
+    LOGE("Fail to add ed_id %s", ed_id);
+    app_control_destroy(service);
+    return ret;
+  }
+
+  ret = _add_extra_data(&service, SETUP_CONTEXT_DATA_KEY,
+      context_data == nullptr ? "" : context_data->ToString());
+
+  ret = app_control_send_launch_request(service, NULL, NULL);
+  if (ret != APP_CONTROL_ERROR_NONE) {
+    LOGE("Failed to launch:%d", ret);
+    app_control_destroy(service);
+    return COMPLICATION_ERROR_IO_ERROR;
+  }
+  app_control_destroy(service);
+
+  if (__stub == nullptr)
+    __stub = std::unique_ptr<EditablesEditorStub>(new EditablesEditorStub());
+
+  auto ci = new SetupCallbackInfo(cb, user_data);
+  __stub->AddSetupCallbackInfo(ci);
+
+  return COMPLICATION_ERROR_NONE;
+}
\ No newline at end of file