Add APIs for allow list feature 24/175224/24
authorhyunho <hhstark.kang@samsung.com>
Mon, 9 Apr 2018 09:58:42 +0000 (18:58 +0900)
committerhyunho <hhstark.kang@samsung.com>
Mon, 16 Apr 2018 07:45:37 +0000 (16:45 +0900)
Some complications want to display sepecific provider & types on editor application

Change-Id: Ic563b531a4b2753a6bbff51cb55464b8f6bd1ac2
Signed-off-by: hyunho <hhstark.kang@samsung.com>
19 files changed:
unittest/src/test_complication.cc
unittest/src/test_design_element.cc
unittest/src/test_editables_container.cc
unittest/src/test_received_editable.cc
watchface-complication-provider/complication-provider-event-interface.h
watchface-complication/complication-implementation.h
watchface-complication/complication.cc
watchface-complication/complication.h
watchface-complication/db-manager.cc
watchface-complication/db-manager.h
watchface-complication/design-element.cc
watchface-complication/design-element.h
watchface-complication/editable-interface.h
watchface-complication/include/watchface-complication.h
watchface-complication/include/watchface-editable.h
watchface-complication/received-editable.cc
watchface-complication/received-editable.h
watchface-complication/watchface-complication.cc
watchface-complication/watchface-editable.cc

index 8c98bff..ffc1268 100644 (file)
@@ -91,19 +91,17 @@ TEST_F(WC, GetCandidates)
 
 TEST_F(WC, GetData)
 {
-  Bundle& curData = WC::complication->GetCurData();
-  Bundle& nthData = WC::complication->GetNthData(1);
+  const Bundle* curData = WC::complication->GetCurData();
+  const Bundle* nthData = WC::complication->GetNthData(1);
 
-  EXPECT_NE(curData.GetRaw(), nullptr);
-  EXPECT_NE(nthData.GetRaw(), nullptr);
-
-  EXPECT_EQ(WC::complication->GetType(curData), ShortText);
+  EXPECT_NE(curData->GetConstRaw(), nullptr);
+  EXPECT_NE(nthData->GetConstRaw(), nullptr);
 }
 
 TEST_F(WC, DataIdx)
 {
-  EXPECT_EQ(WC::complication->GetCurDataIdx(),0);
-  EXPECT_EQ(WC::complication->GetLastDataIdx(), 0);
+  EXPECT_EQ(WC::complication->GetCurDataIdx(), 0);
+  EXPECT_EQ(WC::complication->GetLastDataIdx(), -1);
   EXPECT_EQ(WC::complication->UpdateLastDataIdx(), -1);
 }
 
@@ -156,7 +154,7 @@ TEST_F(WFC, Create)
 TEST_F(WFC, Callback)
 {
   EXPECT_EQ(watchface_complication_update_cb_add(WFC::complication, _on_complication_update_cb, NULL), 0);
-  EXPECT_EQ(watchface_complication_send_update_request(WFC::complication), 0);
+  EXPECT_EQ(watchface_complication_send_update_request(WFC::complication), COMPLICATION_ERROR_IO_ERROR);
   EXPECT_EQ(watchface_complication_update_cb_del(WFC::complication, _on_complication_update_cb), 0);
 }
 
@@ -170,5 +168,5 @@ TEST_F(WFC, GetData)
 
 TEST_F(WFC, UpdateRequest)
 {
-  EXPECT_EQ(watchface_complication_send_update_request(WFC::complication), 0);
+  EXPECT_EQ(watchface_complication_send_update_request(WFC::complication), COMPLICATION_ERROR_IO_ERROR);
 }
index 48ee379..306c50f 100644 (file)
@@ -84,11 +84,11 @@ TEST_F(DE, GetCandidates)
 
 TEST_F(DE, GetData)
 {
-  Bundle& curData = DE::element->GetCurData();
-  Bundle& nthData = DE::element->GetNthData(0);
+  const Bundle* curData = DE::element->GetCurData();
+  const Bundle* nthData = DE::element->GetNthData(0);
 
-  EXPECT_NE(curData.GetRaw(), nullptr);
-  EXPECT_NE(nthData.GetRaw(), nullptr);
+  EXPECT_NE(curData->GetConstRaw(), nullptr);
+  EXPECT_NE(nthData->GetConstRaw(), nullptr);
 }
 
 TEST_F(DE, DataIdx)
index 1125e44..0e330ac 100644 (file)
@@ -134,7 +134,7 @@ TEST_F(EC, EditReadyCb)
 
 TEST_F(EC, GetData)
 {
-  int idx = 1;
+  int idx = 0;
   int idx_check;
   int id;
   bundle* data = nullptr;
@@ -145,9 +145,9 @@ TEST_F(EC, GetData)
   EXPECT_EQ(watchface_editable_get_cur_data_idx(EC::received, &idx_check), 0);
   EXPECT_EQ(idx, idx_check);
 
-  EXPECT_EQ(watchface_editable_get_cur_data(EC::received, &data), 0);
-  EXPECT_EQ(watchface_editable_get_nth_data(EC::received, 1, &nthdata), 0);
-  EXPECT_EQ(watchface_editable_get_editable_id(EC::received, &id), 0);
+  EXPECT_EQ(watchface_editable_get_cur_data(EC::received, &data), COMPLICATION_ERROR_NONE);
+  EXPECT_EQ(watchface_editable_get_nth_data(EC::received, 1, &nthdata), COMPLICATION_ERROR_NONE);
+  EXPECT_EQ(watchface_editable_get_editable_id(EC::received, &id), COMPLICATION_ERROR_NONE);
   EXPECT_EQ(id, 0);
 
   EXPECT_EQ(watchface_editable_get_geometry(EC::received, &geo), 0);
index d94565a..b4a3a4e 100644 (file)
@@ -91,11 +91,11 @@ TEST_F(RE, GetCandidates)
 
 TEST_F(RE, GetData)
 {
-  Bundle& curData = RE::received->GetCurData();
-  Bundle& nthData = RE::received->GetNthData(1);
+  const Bundle* curData = RE::received->GetCurData();
+  const Bundle* nthData = RE::received->GetNthData(1);
 
-  EXPECT_NE(curData.GetRaw(), nullptr);
-  EXPECT_NE(nthData.GetRaw(), nullptr);
+  EXPECT_NE(curData->GetConstRaw(), nullptr);
+  EXPECT_NE(nthData->GetConstRaw(), nullptr);
 }
 
 TEST_F(RE, DataIdx)
index 01c5b9d..ef0e9cf 100644 (file)
@@ -28,7 +28,7 @@ namespace watchface_complication {
 class EXPORT_API IComplicationProviderEvent {
  public:
   virtual void OnDataUpdated(const std::string& provider_id,
-                             ComplicationType type, const Bundle& data) = 0;
+                ComplicationType type, const std::unique_ptr<Bundle>& data) = 0;
   virtual void OnNotifyDataUpdate() = 0;
 };
 
index 742ce0d..fb81b9d 100644 (file)
@@ -58,7 +58,10 @@ class Complication::Impl : ComplicationConnector::IEventListener {
   void RestoreStateOrSetDefault();
   int StoreSetting(int comp_id, std::string& provider_id, ComplicationType type);
   std::unique_ptr<Bundle> LoadSetting();
-  std::string GetProviderAppId();
+  int AddCandidate(std::string provider_id, int type);
+  int AddCandidateList(std::string provider_id, int types);
+  int AddCandidateList(int types);
+  int MakeCandidatesList();
 
  private:
   Complication* parent_;
@@ -70,7 +73,10 @@ class Complication::Impl : ComplicationConnector::IEventListener {
   std::shared_ptr<IEditable::Geometry> geo_;
   std::string cur_provider_id_;
   ComplicationType cur_type_;
+  std::string last_provider_id_;
+  ComplicationType last_type_;
   std::list<std::unique_ptr<Bundle>> candidates_list_;
+  std::list<std::unique_ptr<ProviderInfo>> allowed_list_;
   int cur_data_idx_;
   std::unique_ptr<Bundle> context_data_ = nullptr;
   std::unique_ptr<Bundle> last_context_data_ = nullptr;
index d5cce6c..d674fff 100644 (file)
@@ -57,23 +57,7 @@ Complication::Impl::Impl(Complication* parent, int id,
   : parent_(parent), complication_id_(id), support_types_(support_types),
     default_provider_id_(default_provider_id), default_type_(default_type),
     geo_(geo) {
-  // TODO(?): Make candidates using DB (support_types)
-  for (int type = ShortText; type <= Image; type *= 2) {
-    if ((type & support_types_) == 0)
-      continue;
-    std::list<std::string> provider_list =
-        parent_->Complication::GetProviderList(static_cast<ComplicationType>(type));
-    for (auto& provider_id : provider_list) {
-      bundle* data = bundle_create();
-      if (data == NULL)
-        std::runtime_error("bundle create failed");
-
-      bundle_add_str(data, provider_id_key_.c_str(), provider_id.c_str());
-      bundle_add_str(data, provider_type_key_.c_str(), std::to_string(type).c_str());
-      candidates_list_.emplace_back(new Bundle(data));
-      bundle_free(data);
-    }
-  }
+  MakeCandidatesList();
   RestoreStateOrSetDefault();
   subscribe_id_ = ComplicationConnector::GetInst().SubscribeSignal(
                     ComplicationConnector::Complication, cur_provider_id_,
@@ -116,7 +100,7 @@ void Complication::Impl::OnSignal(GDBusConnection* connection,
     LOGI("data: %s, %d, cur_type :%d", provider_id, complication_id, cur_type_);
     if (last_data_ != nullptr) {
       parent_->OnDataUpdated(
-          std::string(provider_id), cur_type_, *last_data_.get());
+          std::string(provider_id), cur_type_, last_data_);
     }
   } else if (signal_name.compare(ComplicationConnector::GetInst().GetCmdStr(
           ComplicationConnector::CompNotifyDataUpdate)) == 0) {
@@ -151,7 +135,6 @@ void Complication::Impl::RestoreStateOrSetDefault() {
   char* prev_provider_type = NULL;
   std::unique_ptr<Bundle> setting_data =
       EditablesManager::GetInst().LoadSetting(complication_id_);
-  int ret;
 
   if (setting_data == nullptr) {
     cur_provider_id_ = default_provider_id_;
@@ -174,19 +157,11 @@ void Complication::Impl::RestoreStateOrSetDefault() {
     LOGI("get setting from bundle %s, %s", prev_provider_id, prev_provider_type);
   }
 
-  cur_data_idx_ = 0;
-  ret = FindCandidateDataIdx(cur_provider_id_, cur_type_);
-  if (ret != -1)
-    cur_data_idx_ = ret;
+  last_provider_id_ = cur_provider_id_;
+  last_type_ = cur_type_;
 
   /* 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());
@@ -202,7 +177,7 @@ int Complication::Impl::StoreSetting(int comp_id, std::string& provider_id,
   int ret;
   char buf[32];
 
-  if (provider_id.empty() || type < 0)
+  if (provider_id.empty() && type != NoData)
     return COMPLICATION_ERROR_INVALID_PARAMETER;
 
   setting_data = bundle_create();
@@ -227,10 +202,6 @@ int Complication::Impl::StoreSetting(int comp_id, std::string& provider_id,
   return COMPLICATION_ERROR_NONE;
 }
 
-std::string Complication::Impl::GetProviderAppId() {
-  return DBManager::GetProviderAppId(cur_provider_id_.c_str());
-}
-
 int Complication::GetComplicationId() {
   return impl_->complication_id_;
 }
@@ -248,30 +219,32 @@ const IEditable::Geometry* Complication::GetGeo() {
   return impl_->geo_.get();
 }
 
-std::list<std::string> Complication::GetProviderList(ComplicationType type) {
-  return DBManager::GetProviderList(static_cast<int>(type));
-}
-
 std::list<std::unique_ptr<Bundle>> const& Complication::GetCandidates() const {
   return impl_->candidates_list_;
 }
 
-Bundle& Complication::GetCurData() {
+const Bundle* Complication::GetCurData() {
+
+  if (impl_->candidates_list_.size() == 0)
+    return NULL;
   std::list<std::unique_ptr<Bundle>>::iterator it
                                   = impl_->candidates_list_.begin();
 
   LOGI("get cur data %d", impl_->cur_data_idx_);
   auto nx = std::next(it, impl_->cur_data_idx_);
-  return *(*nx).get();
+  return nx->get();
 }
 
-Bundle& Complication::GetNthData(int nth) {
+const Bundle* Complication::GetNthData(int nth) {
+  if ((int)impl_->candidates_list_.size() <= nth)
+    return NULL;
+
   std::list<std::unique_ptr<Bundle>>::iterator it
                                   = impl_->candidates_list_.begin();
 
   LOGI("get cur data %d", impl_->cur_data_idx_);
   auto nx = std::next(it, nth);
-  return *(*nx).get();
+  return nx->get();
 }
 
 int Complication::GetCurDataIdx() {
@@ -290,6 +263,8 @@ int Complication::UpdateLastDataIdx() {
   if (ret != COMPLICATION_ERROR_NONE)
     return ret;
 
+  impl_->last_provider_id_ = impl_->cur_provider_id_;
+  impl_->last_type_ = impl_->cur_type_;
   impl_->last_data_idx_ = impl_->cur_data_idx_;
   LOGI("update last data idx : %d", impl_->last_data_idx_);
   return COMPLICATION_ERROR_NONE;
@@ -299,31 +274,33 @@ int Complication::SetCurDataIdx(int cur_data_idx) {
   char* provider_id = NULL;
   char* type = NULL;
 
-  if (cur_data_idx < 0 || cur_data_idx >= (int)impl_->candidates_list_.size()) {
-    LOGE("Invalid index");
-    return COMPLICATION_ERROR_INVALID_PARAMETER;
-  }
-
   if (impl_->cur_data_idx_ == cur_data_idx) {
     LOGI("Same with cur data idx skip setting process");
     return COMPLICATION_ERROR_NONE;
   }
 
-
-  impl_->cur_data_idx_ = cur_data_idx;
-  Bundle& data = GetCurData();
-  if (data.GetRaw() == NULL) {
-    LOGI("GetCurData failed");
-    return COMPLICATION_ERROR_NO_DATA;
+  if (cur_data_idx < 0 || cur_data_idx >= (int)impl_->candidates_list_.size()) {
+    LOGE("Invalid index");
+    impl_->cur_data_idx_ = -1;
+    impl_->cur_provider_id_ = impl_->last_provider_id_;
+    impl_->cur_type_ = impl_->last_type_;
+  } else {
+    const Bundle* data = GetNthData(cur_data_idx);
+    if (data == NULL) {
+      LOGI("GetCurData failed");
+      return COMPLICATION_ERROR_NO_DATA;
+    }
+    bundle_get_str(const_cast<Bundle*>(data)->GetRaw(),
+        impl_->provider_id_key_.c_str(), &provider_id);
+    bundle_get_str(const_cast<Bundle*>(data)->GetRaw(),
+        impl_->provider_type_key_.c_str(), &type);
+    if (provider_id != NULL)
+      impl_->cur_provider_id_ = std::string(provider_id);
+    if (type != NULL)
+      impl_->cur_type_ = static_cast<ComplicationType>(atoi(type));
   }
 
-  bundle_get_str(data.GetRaw(), impl_->provider_id_key_.c_str(), &provider_id);
-  bundle_get_str(data.GetRaw(), impl_->provider_type_key_.c_str(), &type);
-  if (provider_id != NULL)
-    impl_->cur_provider_id_ = std::string(provider_id);
-  if (type != NULL)
-    impl_->cur_type_ = static_cast<ComplicationType>(atoi(type));
-
+  impl_->cur_data_idx_ = cur_data_idx;
   LOGI("cur idx %d, cur provider %s, cur type %d", impl_->cur_data_idx_,
     impl_->cur_provider_id_.c_str(), impl_->cur_type_);
 
@@ -337,49 +314,26 @@ int Complication::SetCurDataIdx(int cur_data_idx) {
 }
 
 const char* Complication::GetCurProviderId() {
-  char* provider_id = NULL;
-  Bundle& data = GetCurData();
-  bundle_get_str(data.GetRaw(), impl_->provider_id_key_.c_str(), &provider_id);
+  if (!impl_->cur_provider_id_.empty())
+    return impl_->cur_provider_id_.c_str();
 
-  return provider_id;
+  return NULL;
 }
 
-const char* Complication::GetProviderId(Bundle& data) {
+const char* Complication::GetProviderId(const Bundle* data) {
   char* provider_id = NULL;
 
-  if (data.GetRaw() == nullptr)
+  if (data == NULL)
     return NULL;
 
-  bundle_get_str(data.GetRaw(), impl_->provider_id_key_.c_str(), &provider_id);
+  bundle_get_str(const_cast<Bundle*>(data)->GetRaw(),
+      impl_->provider_id_key_.c_str(), &provider_id);
 
   return provider_id;
 }
 
 int Complication::GetCurType() {
-  char* type;
-  int ret = -1;
-  Bundle& data = GetCurData();
-  bundle_get_str(data.GetRaw(), impl_->provider_type_key_.c_str(), &type);
-
-  if (type)
-    ret = atoi(type);
-
-  return ret;
-}
-
-int Complication::GetType(Bundle& data) {
-  char* type;
-  int ret = -1;
-
-  if (data.GetRaw() == nullptr)
-    return ret;
-
-  bundle_get_str(data.GetRaw(), impl_->provider_type_key_.c_str(), &type);
-
-  if (type)
-    ret = atoi(type);
-
-  return ret;
+  return static_cast<int>(impl_->cur_type_);
 }
 
 const std::string& Complication::GetName() {
@@ -408,9 +362,11 @@ void Complication::OnEditableUpdated(int selected_idx,
     LOGI("ongoing editing : %d", impl_->complication_id_);
     std::unique_ptr<Bundle> ptr = nullptr;
     const char* provider_id = GetCurProviderId();
+    std::string provider_id_str =
+        provider_id == NULL ? "" : std::string(provider_id);
     int type = GetCurType();
-    ptr = GetDefault(provider_id, type);
-    OnDataUpdated(provider_id, static_cast<ComplicationType>(type), *ptr.get());
+    ptr = DBManager::GetDefaultData(provider_id, type);
+    OnDataUpdated(provider_id_str, static_cast<ComplicationType>(type), ptr);
   } else if (state == Complete) {
     LOGI("complete editing : %d", impl_->complication_id_);
     SendDataUpdateRequest();
@@ -419,28 +375,29 @@ void Complication::OnEditableUpdated(int selected_idx,
         impl_->cur_type_);
     OnDataUpdated(impl_->cur_provider_id_,
         static_cast<ComplicationType>(impl_->cur_type_),
-        *impl_->last_data_.get());
+        impl_->last_data_);
   }
 }
 
 void Complication::OnDataUpdated(const std::string& provider_id,
                                  ComplicationType type,
-                                 const Bundle& data) {
+                                 const std::unique_ptr<Bundle>& data) {
 }
 
 void Complication::OnNotifyDataUpdate() {
   SendDataUpdateRequest();
 }
 
-std::unique_ptr<Bundle> Complication::GetDefault(const char* provider_id,
-                                                       int support_type) {
-  return DBManager::GetDefaultData(provider_id, support_type);
-}
-
 int Complication::SendDataUpdateRequest() {
   LOGI("emit signal comp_id %d, type %d",
       impl_->complication_id_, impl_->cur_type_);
-  std::string provider_appid = impl_->GetProviderAppId();
+  std::string provider_appid = DBManager::GetProviderAppId(
+      impl_->cur_provider_id_.c_str());
+  if (provider_appid.empty()) {
+    LOGE("Can not find provider info from DB");
+    return COMPLICATION_ERROR_IO_ERROR;
+  }
+
   const char* context_data_raw = "";
   int ret;
 
@@ -528,7 +485,13 @@ std::unique_ptr<Bundle>& Complication::GetLastContext() const {
 
 int Complication::TouchLaunch() {
   const char* context_data_raw = NULL;
-  std::string provider_appid = impl_->GetProviderAppId();
+  std::string provider_appid = DBManager::GetProviderAppId(
+      impl_->cur_provider_id_.c_str());
+  if (provider_appid.empty()) {
+    LOGE("Can not find provider info from DB");
+    return COMPLICATION_ERROR_IO_ERROR;
+  }
+
   if (impl_->context_data_ != nullptr)
     context_data_raw = impl_->context_data_->ToString();
 
@@ -574,4 +537,103 @@ int Complication::TouchLaunch() {
   return COMPLICATION_ERROR_NONE;
 }
 
+int Complication::Impl::AddCandidate(std::string provider_id, int type) {
+  bundle* data = bundle_create();
+  if (data == NULL)
+    return COMPLICATION_ERROR_OUT_OF_MEMORY;
+  bundle_add_str(data, provider_id_key_.c_str(), provider_id.c_str());
+  bundle_add_str(data, provider_type_key_.c_str(),
+      std::to_string(type).c_str());
+  candidates_list_.emplace_back(new Bundle(data));
+
+  return COMPLICATION_ERROR_NONE;
+}
+
+int Complication::Impl::AddCandidateList(std::string provider_id, int types) {
+  for (int type = ShortText; type <= Image; type *= 2) {
+    if ((type & types) == 0)
+      continue;
+    int ret = AddCandidate(provider_id, type);
+    if (ret != COMPLICATION_ERROR_NONE) {
+      candidates_list_.clear();
+      return ret;
+    }
+  }
+
+  return COMPLICATION_ERROR_NONE;
+}
+
+int Complication::Impl::AddCandidateList(int types) {
+  std::list<std::unique_ptr<DBManager::ProviderInfo>> provider_list
+      = DBManager::GetProviderListWithTypes(types);
+
+  for (auto& info : provider_list) {
+    std::string provider_id = info.get()->GetProviderId();
+    int provider_types = info.get()->GetTypes();
+    for (int type = ShortText; type <= Image; type *= 2) {
+      if ((type & types & provider_types) == 0)
+        continue;
+      int ret = AddCandidate(provider_id, type);
+      if (ret != COMPLICATION_ERROR_NONE) {
+        candidates_list_.clear();
+        return ret;
+      }
+    }
+  }
+
+  return COMPLICATION_ERROR_NONE;
+}
+
+int Complication::Impl::MakeCandidatesList() {
+
+  if ((support_types_ & NoData) == 1) {
+    int ret = AddCandidate("", (int)NoData);
+    if (ret != COMPLICATION_ERROR_NONE)
+          return ret;
+  }
+
+  if (allowed_list_.size() != 0) {
+    for(auto& i : allowed_list_) {
+      std::string provider_id = i.get()->GetProviderId();
+      int available_types;
+      int ret = DBManager::GetSupportTypes(provider_id, &available_types);
+      if (ret != COMPLICATION_ERROR_NONE)
+        continue;
+      available_types &= i.get()->GetTypes();
+      if (available_types != 0) {
+        int ret = AddCandidateList(provider_id, available_types);
+        if (ret != COMPLICATION_ERROR_NONE)
+          return ret;
+      }
+    }
+  } else {
+    int ret = AddCandidateList(support_types_);
+    if (ret != COMPLICATION_ERROR_NONE)
+      return ret;
+  }
+
+  return COMPLICATION_ERROR_NONE;
+}
+
+int Complication::ApplyAllowedList(
+      std::list<std::unique_ptr<ProviderInfo>> allowed_list) {
+  impl_->allowed_list_ = std::move(allowed_list);
+  impl_->candidates_list_.clear();
+  int ret = impl_->MakeCandidatesList();
+  if (ret != COMPLICATION_ERROR_NONE)
+      return ret;
+
+  int idx = impl_->FindCandidateDataIdx(
+      impl_->cur_provider_id_, impl_->cur_type_);
+  impl_->cur_data_idx_ = idx;
+  impl_->last_data_idx_ = impl_->cur_data_idx_;
+
+  return COMPLICATION_ERROR_NONE;
+}
+
+int Complication::ClearAllowedList() {
+  impl_->allowed_list_.clear();
+  return COMPLICATION_ERROR_NONE;
+}
+
 }  // namespace watchface_complication
index ab186eb..6dcfbf6 100644 (file)
@@ -41,10 +41,24 @@ class EXPORT_API Complication : public IEditable
   virtual ~Complication();
 
  public:
+  class ProviderInfo {
+    std::string provider_id_;
+    int types_;
+   public:
+    ProviderInfo(std::string provider_id, int types)
+      : provider_id_(provider_id), types_(types) {
+    }
+    std::string& GetProviderId() {
+      return provider_id_;
+    }
+    int GetTypes() {
+      return types_;
+    }
+  };
   const IEditable::Geometry* GetGeo() override;
   std::list<std::unique_ptr<Bundle>> const& GetCandidates() const override;
-  Bundle& GetCurData() override;
-  Bundle& GetNthData(int nth) override;
+  const Bundle* GetCurData() override;
+  const Bundle* GetNthData(int nth) override;
   int GetCurDataIdx() override;
   int SetCurDataIdx(int cur_data_idx) override;
   int GetLastDataIdx() override;
@@ -55,7 +69,7 @@ class EXPORT_API Complication : public IEditable
                     IEditable::EditableState state) override;
   void OnDataUpdated(const std::string& provider_id,
                     ComplicationType type,
-                    const Bundle& data) override;
+                    const std::unique_ptr<Bundle>& data) override;
   void OnNotifyDataUpdate() override;
   int GetComplicationId();
   int GetEditableId() override;
@@ -72,19 +86,16 @@ class EXPORT_API Complication : public IEditable
   void SetShapeType(IEditable::EditableShapeType shape_type);
 
   const char* GetCurProviderId();
-  const char* GetProviderId(Bundle& data);
+  const char* GetProviderId(const Bundle* data);
   int GetCurType();
-  int GetType(Bundle& data);
   int TouchLaunch();
+  int ApplyAllowedList(
+      std::list<std::unique_ptr<ProviderInfo>> allowed_list);
+  int ClearAllowedList();
 
  public:
   static const char* GetProviderIdKey();
   static const char* GetProviderTypeKey();
-  static std::list<std::string> GetProviderList(
-                                         ComplicationType type);
-  static std::unique_ptr<Bundle> GetDefault(
-                                            const char* provider_id,
-                                            int type);
 
  private:
   class Impl;
index 75410fb..088a48b 100644 (file)
@@ -140,6 +140,50 @@ std::string DBManager::GetProviderAppId(const char* provider_id) {
   return appid;
 }
 
+std::list<std::unique_ptr<DBManager::ProviderInfo>>
+DBManager::GetProviderListWithTypes(int support_types) {
+  int ret;
+  char *provider_id = NULL;
+  int types = 0;
+  sqlite3_stmt* stmt;
+  sqlite3* db = NULL;
+  std::list<std::unique_ptr<DBManager::ProviderInfo>> provider_list;
+
+  static const char query[] =
+    "SELECT provider_id, SUM(support_type) FROM complication_provider "
+    "WHERE (support_type & ?) > 0 GROUP BY provider_id";
+
+  db = OpenDB();
+  if (db == NULL) {
+    LOGE("parser db not exist");
+    return provider_list;
+  }
+
+  ret = sqlite3_prepare_v2(db, query, strlen(query),
+                        &stmt, NULL);
+  if (ret != SQLITE_OK) {
+    LOGE("prepare error: %s", sqlite3_errmsg(db));
+    CloseDB(db);
+    return provider_list;
+  }
+
+  sqlite3_bind_int(stmt, 1, support_types);
+  while (sqlite3_step(stmt) == SQLITE_ROW) {
+    provider_id = (char *)sqlite3_column_text(stmt, 0);
+    types = sqlite3_column_int(stmt, 1);
+    provider_list.emplace_back(
+        std::unique_ptr<ProviderInfo>(new ProviderInfo(provider_id, types)));
+  }
+
+  if (stmt)
+    sqlite3_finalize(stmt);
+
+  CloseDB(db);
+
+  return std::move(provider_list);
+
+}
+
 std::list<std::string> DBManager::GetProviderList(int support_type) {
   int ret;
   char *provider_id = NULL;
index e636a92..9a86ead 100644 (file)
@@ -30,11 +30,27 @@ namespace watchface_complication {
 
 class EXPORT_API DBManager {
  public:
+  class ProviderInfo {
+    std::string provider_id_;
+    int types_;
+   public:
+    ProviderInfo(std::string provider_id, int types)
+      : provider_id_(provider_id), types_(types) {
+    }
+    std::string& GetProviderId() {
+      return provider_id_;
+    }
+    int GetTypes() {
+      return types_;
+    }
+  };
   static std::unique_ptr<Bundle> GetDefaultData(const char* provider_id,
                                         int support_type);
   static std::string GetProviderAppId(const char* provider_id);
   static std::list<std::string> GetProviderList(int support_type);
   static std::list<std::string> GetRequiredPrivlegeList(std::string& provider_id);
+  static std::list<std::unique_ptr<ProviderInfo>> GetProviderListWithTypes(
+    int support_types);
   static int GetSupportTypes(std::string& provider_id, int* types);
 
  private:
index 565c62d..2cf6c5d 100644 (file)
@@ -67,22 +67,28 @@ std::list<std::unique_ptr<Bundle>> const& DesignElement::GetCandidates() const {
   return impl_->candidates_list_;
 }
 
-Bundle& DesignElement::GetCurData() {
+const Bundle* DesignElement::GetCurData() {
+
+  if (impl_->candidates_list_.size() == 0)
+    return NULL;
   std::list<std::unique_ptr<Bundle>>::iterator it
                                   = impl_->candidates_list_.begin();
 
-  LOGI("cur data idx %d", impl_->cur_data_idx_);
+  LOGI("get cur data %d", impl_->cur_data_idx_);
   auto nx = std::next(it, impl_->cur_data_idx_);
-  return *(*nx).get();
+  return nx->get();
 }
 
-Bundle& DesignElement::GetNthData(int nth) {
+const Bundle* DesignElement::GetNthData(int nth) {
+  if ((int)impl_->candidates_list_.size() <= nth)
+    return NULL;
+
   std::list<std::unique_ptr<Bundle>>::iterator it
                                   = impl_->candidates_list_.begin();
 
-  LOGI("cur data idx %d", impl_->cur_data_idx_);
+  LOGI("get cur data %d", impl_->cur_data_idx_);
   auto nx = std::next(it, nth);
-  return *(*nx).get();
+  return nx->get();
 }
 
 int DesignElement::GetCurDataIdx() {
@@ -95,10 +101,13 @@ int DesignElement::GetLastDataIdx() {
 }
 
 int DesignElement::UpdateLastDataIdx() {
-  Bundle& cur_data = GetCurData();
+  const Bundle* cur_data = GetCurData();
+  if (cur_data == NULL)
+    return COMPLICATION_ERROR_NO_DATA;
+
   bundle_raw* raw_data = NULL;
   int raw_len;
-  bundle_encode(cur_data.GetRaw(), &raw_data, &raw_len);
+  bundle_encode(const_cast<Bundle*>(cur_data)->GetRaw(), &raw_data, &raw_len);
   int ret = EditablesManager::GetInst().StoreSetting(impl_->id_, raw_data);
   free(raw_data);
 
index 117adac..dfdfa88 100644 (file)
@@ -41,8 +41,8 @@ class EXPORT_API DesignElement : public IEditable {
  public:
   const IEditable::Geometry* GetGeo() override;
   std::list<std::unique_ptr<Bundle>> const& GetCandidates() const override;
-  Bundle& GetCurData() override;
-  Bundle& GetNthData(int nth) override;
+  const Bundle* GetCurData() override;
+  const Bundle* GetNthData(int nth) override;
   int GetCurDataIdx() override;
   int SetCurDataIdx(int cur_data_idx) override;
   int GetLastDataIdx() override;
index 85f9d4e..a526709 100644 (file)
@@ -69,8 +69,8 @@ class IEditable {
   virtual int SetEditableId(int id) = 0;
   virtual const IEditable::Geometry* GetGeo() = 0;
   virtual std::list<std::unique_ptr<Bundle>> const& GetCandidates() const = 0;
-  virtual Bundle& GetCurData() = 0;
-  virtual Bundle& GetNthData(int nth) = 0;
+  virtual const Bundle* GetCurData() = 0;
+  virtual const Bundle* GetNthData(int nth) = 0;
   virtual int GetCurDataIdx() = 0;
   virtual int SetCurDataIdx(int cur_data_idx) = 0;
   virtual int GetLastDataIdx() = 0;
index b71f544..3499407 100644 (file)
@@ -54,7 +54,7 @@ typedef void (*on_complication_update_cb)(int complication_id,
                                       void *user_data);
 
 int watchface_complication_get_cur_provider_id(complication_h handle,
-    const char **cur_provider);
+    char **cur_provider);
 int watchface_complication_get_cur_type(complication_h handle,
     complication_type *cur_type);
 int watchface_complication_get_support_types(complication_h handle, int *support_types);
@@ -382,6 +382,254 @@ void _on_complication_clicked(complication_h handle)
  */
 int watchface_complication_touch_launch(complication_h handle);
 
+typedef struct complication_allowed_list_ *complication_allowed_list_h;
+/**
+ * @brief Creates allowed list.
+ * @details The allowed list created by this API is provider list which
+ *          will be shown on the editor app's candidate provider list.
+ * @since_tizen 5.0
+ * @remarks Created allowed list should be applied with
+ *          watchface_complication_allowed_list_apply() API
+ * @remarks Created allowed list should be destroyed after applied
+ * @param[in] handle The complication allowed list handle
+ * @return #COMPLICATION_ERROR_NONE on success,
+ *         otherwise an error code (see COMPLICATION_ERROR_XXX) on failure
+ * @retval #COMPLICATION_ERROR_NONE Successful
+ * @retval #COMPLICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #COMPLICATION_ERROR_OUT_OF_MEMORY Out of memory
+ * @see watchface_complication_allowed_list_destroy()
+ * @see watchface_complication_allowed_list_add()
+ * @see watchface_complication_allowed_list_del()
+ * @see watchface_complication_allowed_list_get_nth()
+ * @see watchface_complication_allowed_list_apply()
+ * @see watchface_complication_allowed_list_clear()
+ * @par Sample code:
+ * @code
+#include <watchface-complication.h>
+
+{
+  complication_allowed_list_h handle;
+  int ret = watchface_complication_allowed_list_create(&handle);
+}
+ * @endcode
+ */
+int watchface_complication_allowed_list_create(
+               complication_allowed_list_h *handle);
+
+/**
+ * @brief Destroys allowed list.
+ * @since_tizen 5.0
+ * @param[in] handle The complication allowed list handle
+ * @return #COMPLICATION_ERROR_NONE on success,
+ *         otherwise an error code (see COMPLICATION_ERROR_XXX) on failure
+ * @retval #COMPLICATION_ERROR_NONE Successful
+ * @retval #COMPLICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #COMPLICATION_ERROR_OUT_OF_MEMORY Out of memory
+ * @see watchface_complication_allowed_list_create()
+ * @see watchface_complication_allowed_list_add()
+ * @see watchface_complication_allowed_list_del()
+ * @see watchface_complication_allowed_list_get_nth()
+ * @see watchface_complication_allowed_list_apply()
+ * @see watchface_complication_allowed_list_clear()
+ * @par Sample code:
+ * @code
+#include <watchface-complication.h>
+
+{
+  complication_allowed_list_h handle;
+  int ret = watchface_complication_allowed_list_create(&handle);
+  ret = watchface_complication_allowed_list_destroy(handle);
+}
+ * @endcode
+ */
+int watchface_complication_allowed_list_destroy(
+               complication_allowed_list_h handle);
+
+/**
+ * @brief Adds provider info to the allowed list.
+ * @details Using this API the complication can add provider id and types
+ *          which will be shown on the editor app's candidate provider list.
+ * @since_tizen 5.0
+ * @param[in] handle The complication allowed list handle
+ * @param[in] provider_id The complication provider id
+ * @param[in] types The complication types
+ * @return #COMPLICATION_ERROR_NONE on success,
+ *         otherwise an error code (see COMPLICATION_ERROR_XXX) on failure
+ * @retval #COMPLICATION_ERROR_NONE Successful
+ * @retval #COMPLICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #COMPLICATION_ERROR_OUT_OF_MEMORY Out of memory
+ * @retval #COMPLICATION_ERROR_EXIST_ID The provider id is already exists in allowed list
+ * @see watchface_complication_allowed_list_create()
+ * @see watchface_complication_allowed_list_destroy()
+ * @see watchface_complication_allowed_list_del()
+ * @see watchface_complication_allowed_list_get_nth()
+ * @see watchface_complication_allowed_list_apply()
+ * @see watchface_complication_allowed_list_clear()
+ * @par Sample code:
+ * @code
+#include <watchface-complication.h>
+
+{
+  complication_allowed_list_h handle;
+  int ret = watchface_complication_allowed_list_create(&handle);
+  if (ret == COMPLICATION_ERROR_NONE)
+      ret = watchface_complication_allowed_list_add(handle, provider_id, types);
+}
+ * @endcode
+ */
+int watchface_complication_allowed_list_add(complication_allowed_list_h handle,
+               const char *provider_id, int types);
+
+/**
+ * @brief Deletes provider info from the allowed list.
+ * @since_tizen 5.0
+ * @param[in] handle The complication allowed list handle
+ * @param[in] provider_id The complication provider id
+ * @return #COMPLICATION_ERROR_NONE on success,
+ *         otherwise an error code (see COMPLICATION_ERROR_XXX) on failure
+ * @retval #COMPLICATION_ERROR_NONE Successful
+ * @retval #COMPLICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #COMPLICATION_ERROR_NO_DATA No data
+ * @see watchface_complication_allowed_list_create()
+ * @see watchface_complication_allowed_list_destroy()
+ * @see watchface_complication_allowed_list_add()
+ * @see watchface_complication_allowed_list_get_nth()
+ * @see watchface_complication_allowed_list_apply()
+ * @see watchface_complication_allowed_list_clear()
+ * @par Sample code:
+ * @code
+#include <watchface-complication.h>
+
+{
+  complication_allowed_list_h handle;
+  int ret = watchface_complication_allowed_list_create(&handle);
+  if (ret == COMPLICATION_ERROR_NONE) {
+      ret = watchface_complication_allowed_list_add(handle, provider_id, types);
+      if (ret == COMPLICATION_ERROR_EXIST_ID) {
+        watchface_complication_allowed_list_del(handle, provider_id);
+        watchface_complication_allowed_list_add(handle, provider_id, types);
+      }
+  }
+}
+ * @endcode
+ */
+int watchface_complication_allowed_list_del(complication_allowed_list_h handle,
+               const char *provider_id);
+
+/**
+ * @brief Gets nth item of the allowed list.
+ * @since_tizen 5.0
+ * @param[in] handle The complication allowed list handle
+ * @param[out] provider_id The complication provider id
+ * @param[out] types The complication types
+ * @return #COMPLICATION_ERROR_NONE on success,
+ *         otherwise an error code (see COMPLICATION_ERROR_XXX) on failure
+ * @retval #COMPLICATION_ERROR_NONE Successful
+ * @retval #COMPLICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #COMPLICATION_ERROR_IO_ERROR IO Error
+ * @retval #COMPLICATION_ERROR_OUT_OF_MEMORY Out of memory
+ * @see watchface_complication_allowed_list_create()
+ * @see watchface_complication_allowed_list_destroy()
+ * @see watchface_complication_allowed_list_add()
+ * @see watchface_complication_allowed_list_del()
+ * @see watchface_complication_allowed_list_apply()
+ * @see watchface_complication_allowed_list_clear()
+ * @par Sample code:
+ * @code
+#include <watchface-complication.h>
+
+{
+  complication_allowed_list_h handle;
+  int ret = watchface_complication_allowed_list_create(&handle);
+  if (ret == COMPLICATION_ERROR_NONE) {
+      ret = watchface_complication_allowed_list_add(handle, provider_id, types);
+      if (ret == COMPLICATION_ERROR_EXIST_ID) {
+        watchface_complication_allowed_list_del(handle, provider_id);
+        watchface_complication_allowed_list_add(handle, provider_id, types);
+      }
+      watchface_complication_allowed_list_get_nth(handle, 0, &n_provider_id, &n_types);
+  }
+}
+ * @endcode
+ */
+int watchface_complication_allowed_list_get_nth(
+               complication_allowed_list_h handle, int index,
+               char **provider_id, int *types);
+
+/**
+ * @brief Applys allowed list.
+ * @since_tizen 5.0
+ * @param[in] handle The complication allowed list handle
+ * @param[in] list_handle The allowed list handle
+ * @return #COMPLICATION_ERROR_NONE on success,
+ *         otherwise an error code (see COMPLICATION_ERROR_XXX) on failure
+ * @retval #COMPLICATION_ERROR_NONE Successful
+ * @retval #COMPLICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #COMPLICATION_ERROR_OUT_OF_MEMORY Out of memory
+ * @see watchface_complication_allowed_list_create()
+ * @see watchface_complication_allowed_list_destroy()
+ * @see watchface_complication_allowed_list_add()
+ * @see watchface_complication_allowed_list_del()
+ * @see watchface_complication_allowed_list_get_nth()
+ * @see watchface_complication_allowed_list_clear()
+ * @par Sample code:
+ * @code
+#include <watchface-complication.h>
+
+{
+  complication_allowed_list_h handle;
+  int ret = watchface_complication_allowed_list_create(&handle);
+  if (ret == COMPLICATION_ERROR_NONE) {
+      ret = watchface_complication_allowed_list_add(handle, provider_id, types);
+      if (ret == COMPLICATION_ERROR_EXIST_ID) {
+        watchface_complication_allowed_list_del(handle, provider_id);
+        watchface_complication_allowed_list_add(handle, provider_id, types);
+      }
+      watchface_complication_allowed_list_get_nth(handle, 0, &n_provider_id, &n_types);
+      watchface_complication_allowed_list_apply(handle, list_handle);
+  }
+}
+ * @endcode
+ */
+int watchface_complication_allowed_list_apply(complication_h handle,
+               complication_allowed_list_h list_handle);
+
+/**
+ * @brief Removes applied allowed list.
+ * @since_tizen 5.0
+ * @param[in] handle The complication allowed list handle
+ * @return #COMPLICATION_ERROR_NONE on success,
+ *         otherwise an error code (see COMPLICATION_ERROR_XXX) on failure
+ * @retval #COMPLICATION_ERROR_NONE Successful
+ * @retval #COMPLICATION_ERROR_INVALID_PARAMETER Invalid parameter
+ * @see watchface_complication_allowed_list_create()
+ * @see watchface_complication_allowed_list_destroy()
+ * @see watchface_complication_allowed_list_add()
+ * @see watchface_complication_allowed_list_del()
+ * @see watchface_complication_allowed_list_get_nth()
+ * @see watchface_complication_allowed_list_apply()
+ * @par Sample code:
+ * @code
+#include <watchface-complication.h>
+
+{
+  complication_allowed_list_h handle;
+  int ret = watchface_complication_allowed_list_create(&handle);
+  if (ret == COMPLICATION_ERROR_NONE) {
+      ret = watchface_complication_allowed_list_add(handle, provider_id, types);
+      if (ret == COMPLICATION_ERROR_EXIST_ID) {
+        watchface_complication_allowed_list_del(handle, provider_id);
+        watchface_complication_allowed_list_add(handle, provider_id, types);
+      }
+      watchface_complication_allowed_list_get_nth(handle, 0, &n_provider_id, &n_types);
+      watchface_complication_allowed_list_apply(handle, list_handle);
+      watchface_complication_allowed_list_clear(handle);
+  }
+}
+ * @endcode
+ */
+int watchface_complication_allowed_list_clear(complication_h handle);
+
 /**
  * @}
  */
index 8d0c816..178bc81 100644 (file)
@@ -67,8 +67,9 @@ int watchface_editable_get_editable_name(const editable_h handle,
 int watchface_editable_set_editable_name(const editable_h handle,
     const char *editable_name);
 int watchface_editable_get_nth_data(const editable_h handle, int nth,
+    bundle **nth_data);
+int watchface_editable_get_cur_data(const editable_h handle,
     bundle **cur_data);
-int watchface_editable_get_cur_data(const editable_h handle, bundle **cur_data);
 int watchface_editable_get_cur_data_idx(const editable_h handle, int *idx);
 int watchface_editable_set_cur_data_idx(const editable_h handle, int idx);
 int watchface_editable_get_editable_id(const editable_h handle,
index 59ea6c2..53e7b89 100644 (file)
@@ -108,18 +108,27 @@ int ReceivedEditable::UpdateLastDataIdx() {
   return COMPLICATION_ERROR_NONE;
 }
 
-Bundle& ReceivedEditable::GetCurData() {
+const Bundle* ReceivedEditable::GetCurData() {
+  if (impl_->candidates_list_.size() == 0)
+    return NULL;
   std::list<std::unique_ptr<Bundle>>::iterator it
                                   = impl_->candidates_list_.begin();
+
+  LOGI("get cur data %d", impl_->cur_data_idx_);
   auto nx = std::next(it, impl_->cur_data_idx_);
-  return *(*nx).get();
+  return nx->get();
 }
 
-Bundle& ReceivedEditable::GetNthData(int nth) {
+const Bundle* ReceivedEditable::GetNthData(int nth) {
+  if ((int)impl_->candidates_list_.size() <= nth)
+    return NULL;
+
   std::list<std::unique_ptr<Bundle>>::iterator it
                                   = impl_->candidates_list_.begin();
+
+  LOGI("get cur data %d", impl_->cur_data_idx_);
   auto nx = std::next(it, nth);
-  return *(*nx).get();
+  return nx->get();
 }
 
 int ReceivedEditable::SetCurDataIdx(int cur_data_idx) {
index e1d4105..b0c3b9a 100644 (file)
@@ -39,8 +39,8 @@ class EXPORT_API ReceivedEditable : public IEditable {
  public:
   const IEditable::Geometry* GetGeo() override;
   std::list<std::unique_ptr<Bundle>> const& GetCandidates() const override;
-  Bundle& GetCurData() override;
-  Bundle& GetNthData(int nth) override;
+  const Bundle* GetCurData() override;
+  const Bundle* GetNthData(int nth) override;
   int GetCurDataIdx() override;
   int SetCurDataIdx(int cur_data_idx) override;
   int GetLastDataIdx() override;
index fa78cd8..1099609 100644 (file)
 
 #define LOG_TAG "WATCHFACE_COMPLICATION"
 
+struct complication_allowed_list_ {
+  GList* allowed_list;
+};
+
 using namespace watchface_complication;
 class CallbackInfo {
  public:
@@ -44,10 +48,10 @@ class CallbackInfo {
 
   void Invoke(int complication_id,
               const std::string& provider_id,
-              ComplicationType type, const Bundle& data) {
+              ComplicationType type, const std::unique_ptr<Bundle>& data) {
     cb_(complication_id,
         provider_id.c_str(), static_cast<complication_type>(type),
-        data.GetConstRaw(), user_data_);
+        data.get() == NULL ? NULL : data.get()->GetConstRaw(), user_data_);
   }
 
  private:
@@ -66,8 +70,8 @@ class WatchComplicationStub : public Complication {
 
   virtual ~WatchComplicationStub() = default;
 
-  void OnDataUpdated(const std::string& provider_id,
-                     ComplicationType type, const Bundle& data) override {
+  void OnDataUpdated(const std::string& provider_id, ComplicationType type,
+      const std::unique_ptr<Bundle>& data) override {
     for (auto& i : cb_list_) {
       i->Invoke(GetComplicationId(), provider_id, type, data);
     }
@@ -167,13 +171,17 @@ extern "C" EXPORT_API int watchface_complication_destroy(complication_h handle)
 }
 
 extern "C" EXPORT_API int watchface_complication_get_cur_provider_id(
-    complication_h handle, const char** cur_provider_id) {
+    complication_h handle, char** cur_provider_id) {
   if (handle == NULL || cur_provider_id == NULL)
     return COMPLICATION_ERROR_INVALID_PARAMETER;
 
   auto sh = static_cast<SharedHandle<WatchComplicationStub>*>(handle);
   auto ptr = SharedHandle<WatchComplicationStub>::Share(sh);
-  *cur_provider_id = ptr.get()->GetCurProviderId();
+  if (ptr.get()->GetCurProviderId() == NULL)
+    return COMPLICATION_ERROR_NO_DATA;
+
+  LOGI("provider id : %s", ptr.get()->GetCurProviderId());
+  *cur_provider_id = strdup(ptr.get()->GetCurProviderId());
 
   return COMPLICATION_ERROR_NONE;
 }
@@ -423,3 +431,190 @@ extern "C" EXPORT_API int watchface_complication_touch_launch(
   auto ptr = SharedHandle<WatchComplicationStub>::Share(sh);
   return ptr.get()->TouchLaunch();
 }
+
+typedef struct provider_info_ {
+  char* provider_id;
+  int types;
+} provider_info;
+
+
+static void __free_provider_info(gpointer data)
+{
+  provider_info* info = (provider_info*)data;
+  if (info->provider_id)
+    free(info->provider_id);
+  free(info);
+}
+
+extern "C" EXPORT_API int watchface_complication_allowed_list_create(
+    complication_allowed_list_h* handle) {
+  complication_allowed_list_h h = NULL;
+
+  if (handle == NULL) {
+    LOGE("Invalid param");
+    return COMPLICATION_ERROR_INVALID_PARAMETER;
+  }
+
+  h = (complication_allowed_list_h)calloc(1,
+      sizeof(struct complication_allowed_list_));
+
+  if (h == NULL) {
+    LOGE("Out of memory");
+    return COMPLICATION_ERROR_OUT_OF_MEMORY;
+  }
+
+  *handle = h;
+
+  return COMPLICATION_ERROR_NONE;
+}
+
+extern "C" EXPORT_API int watchface_complication_allowed_list_destroy(
+    complication_allowed_list_h handle) {
+
+  if (handle == NULL) {
+    LOGE("Invalid param");
+    return COMPLICATION_ERROR_INVALID_PARAMETER;
+  }
+
+  if (handle->allowed_list)
+    g_list_free_full(handle->allowed_list, __free_provider_info);
+  free(handle);
+
+  return COMPLICATION_ERROR_NONE;
+}
+
+static gint __provider_info_cmp(gconstpointer a, gconstpointer b) {
+  provider_info* data = (provider_info*)a;
+  const char* provider_id = (const char*)b;
+  if (data == NULL || data->provider_id == NULL)
+    return -1;
+  return strcmp(data->provider_id, provider_id);
+}
+
+extern "C" EXPORT_API int watchface_complication_allowed_list_add(
+    complication_allowed_list_h handle, const char *provider_id, int types) {
+
+  if (handle == NULL || provider_id == NULL) {
+    LOGE("Invalid param");
+    return COMPLICATION_ERROR_INVALID_PARAMETER;
+  }
+
+  GList* find = g_list_find_custom(handle->allowed_list, provider_id,
+      __provider_info_cmp);
+  if (find) {
+    LOGE("Provider id (%s) already exist", provider_id);
+    return COMPLICATION_ERROR_EXIST_ID;
+  }
+
+  provider_info* info = (provider_info*)calloc(1, sizeof(provider_info));
+  if (info == NULL) {
+    LOGE("Out of memory");
+    return COMPLICATION_ERROR_OUT_OF_MEMORY;
+  }
+  info->provider_id = strdup(provider_id);
+  if (info->provider_id == NULL) {
+    LOGE("Out of memory");
+    free(info);
+    return COMPLICATION_ERROR_OUT_OF_MEMORY;
+  }
+  info->types = types;
+  handle->allowed_list = g_list_append(handle->allowed_list, info);
+
+  return COMPLICATION_ERROR_NONE;
+}
+
+extern "C" EXPORT_API int watchface_complication_allowed_list_del(
+    complication_allowed_list_h handle, const char *provider_id) {
+
+  if (handle == NULL || provider_id == NULL || handle->allowed_list) {
+    LOGE("Invalid param");
+    return COMPLICATION_ERROR_INVALID_PARAMETER;
+  }
+
+  GList* find = g_list_find_custom(handle->allowed_list,
+      provider_id, __provider_info_cmp);
+  if (!find) {
+    LOGE("Provider id (%s) already exist", provider_id);
+    return COMPLICATION_ERROR_NO_DATA;
+  }
+
+  provider_info* data = (provider_info*)find->data;
+  handle->allowed_list = g_list_remove(handle->allowed_list, find->data);
+  __free_provider_info(data);
+
+  return COMPLICATION_ERROR_NONE;
+}
+
+extern "C" EXPORT_API int watchface_complication_allowed_list_get_nth(
+    complication_allowed_list_h handle, int index, char **provider_id,
+    int *types) {
+
+  if (handle == NULL || provider_id == NULL || types == NULL ||
+      handle->allowed_list == NULL ||
+      index >= (int)g_list_length(handle->allowed_list) || index < 0) {
+    LOGE("Invalid param");
+    return COMPLICATION_ERROR_INVALID_PARAMETER;
+  }
+  provider_info* info =
+      (provider_info*)g_list_nth_data(handle->allowed_list, index);
+  if (info == NULL || info->provider_id == NULL) {
+    LOGE("fail to get provider id");
+    return COMPLICATION_ERROR_IO_ERROR;
+  }
+  char* id = strdup(info->provider_id);
+  if (id == NULL) {
+    LOGE("Out of memory");
+    return COMPLICATION_ERROR_OUT_OF_MEMORY;
+  }
+  *provider_id = id;
+  *types = info->types;
+
+  return COMPLICATION_ERROR_NONE;
+}
+
+extern "C" EXPORT_API int watchface_complication_allowed_list_apply(
+    complication_h handle, complication_allowed_list_h list_handle) {
+
+  if (handle == NULL || list_handle == NULL || list_handle->allowed_list == NULL
+      || g_list_length(list_handle->allowed_list) == 0) {
+    LOGE("Invalid param");
+    return COMPLICATION_ERROR_INVALID_PARAMETER;
+  }
+
+  auto sh = static_cast<SharedHandle<WatchComplicationStub>*>(handle);
+  auto ptr = SharedHandle<WatchComplicationStub>::Share(sh);
+  std::list<std::unique_ptr<Complication::ProviderInfo>> allowed_list;
+
+  for (unsigned int i = 0; i < g_list_length(list_handle->allowed_list); i++) {
+    provider_info* info =
+        (provider_info*)g_list_nth_data(list_handle->allowed_list, i);
+    if (info == NULL || info->provider_id == NULL)
+      continue;
+    allowed_list.emplace_back(std::unique_ptr<Complication::ProviderInfo>(
+      new Complication::ProviderInfo(
+        std::string(info->provider_id), info->types))
+    );
+  }
+
+  int ret = ptr.get()->ApplyAllowedList(std::move(allowed_list));
+  if (ret != COMPLICATION_ERROR_NONE)
+    return ret;
+
+  return COMPLICATION_ERROR_NONE;
+}
+
+extern "C" EXPORT_API int watchface_complication_allowed_list_clear(
+    complication_h handle) {
+
+  if (handle == NULL) {
+    LOGE("Invalid param");
+    return COMPLICATION_ERROR_INVALID_PARAMETER;
+  }
+  auto sh = static_cast<SharedHandle<WatchComplicationStub>*>(handle);
+  auto ptr = SharedHandle<WatchComplicationStub>::Share(sh);
+  int ret = ptr.get()->ClearAllowedList();
+  if (ret != COMPLICATION_ERROR_NONE)
+    return ret;
+
+  return COMPLICATION_ERROR_NONE;
+}
\ No newline at end of file
index 55a1c87..0a2da6a 100644 (file)
@@ -245,24 +245,40 @@ extern "C" EXPORT_API int watchface_editable_set_cur_data_idx(
 }
 
 extern "C" EXPORT_API int watchface_editable_get_cur_data(
-    const editable_h handle, bundle **cur_data) {
+    const editable_h handle, bundle** cur_data) {
   if (handle == NULL || cur_data == NULL)
     return COMPLICATION_ERROR_INVALID_PARAMETER;
 
   IEditable* ie = static_cast<IEditable*>(handle);
-  Bundle& data = ie->GetCurData();
-  *cur_data = data.GetRaw();
+  const Bundle* data = ie->GetCurData();
+  if (data == NULL)
+    return COMPLICATION_ERROR_NO_DATA;
+  if (data->GetConstRaw() != NULL) {
+    *cur_data = bundle_dup(const_cast<bundle*>(data->GetConstRaw()));
+    if (*cur_data == NULL)
+      return COMPLICATION_ERROR_OUT_OF_MEMORY;
+  } else {
+    return COMPLICATION_ERROR_NO_DATA;
+  }
   return COMPLICATION_ERROR_NONE;
 }
 
 extern "C" EXPORT_API int watchface_editable_get_nth_data(
-    const editable_h handle, int nth, bundle **cur_data) {
-  if (handle == NULL || cur_data == NULL)
+    const editable_h handle, int nth, bundle** nth_data) {
+  if (handle == NULL || nth_data == NULL)
     return COMPLICATION_ERROR_INVALID_PARAMETER;
 
   IEditable* ie = static_cast<IEditable*>(handle);
-  Bundle& data = ie->GetNthData(nth);
-  *cur_data = data.GetRaw();
+  const Bundle* data = ie->GetNthData(nth);
+  if (data == NULL)
+    return COMPLICATION_ERROR_NO_DATA;
+  if (data->GetConstRaw() != NULL) {
+    *nth_data = bundle_dup(const_cast<bundle*>(data->GetConstRaw()));
+    if (*nth_data == NULL)
+      return COMPLICATION_ERROR_OUT_OF_MEMORY;
+  } else {
+    return COMPLICATION_ERROR_NO_DATA;
+  }
   return COMPLICATION_ERROR_NONE;
 }