Add consumer monitoring feature 13/222813/3
authorJusung Son <jusung07.son@samsung.com>
Mon, 20 Jan 2020 08:27:11 +0000 (17:27 +0900)
committerjusung son <jusung07.son@samsung.com>
Wed, 5 Feb 2020 04:47:49 +0000 (04:47 +0000)
Change-Id: I937e3684260a96285d5ac97c26a5f0455a644e0d
Signed-off-by: Jusung Son <jusung07.son@samsung.com>
13 files changed:
watchface-common/watchface-util.cc
watchface-common/watchface-util.h
watchface-complication-provider/CMakeLists.txt
watchface-complication-provider/complication-provider-implementation.h
watchface-complication-provider/complication-provider.cc
watchface-complication-provider/complication-provider.h
watchface-complication-provider/include/watchface-complication-provider-internal.h
watchface-complication-provider/watchface-complication-provider.cc
watchface-complication/complication-event-interface.h
watchface-complication/complication-implementation.h
watchface-complication/complication.cc
watchface-complication/complication.h
watchface-complication/watchface-complication.cc

index 183cb42..ba2ea79 100644 (file)
@@ -351,6 +351,9 @@ out:
     case CompNotifyDataUpdate :
       ret = "__COMP_NOTIFY_DATA_UPDATE__";
       break;
+    case CompNotifyListeningStatus :
+      ret = "__COMP_NOTIFY_LISTENING_STATUS__";
+      break;
     case EditableEditRequest :
       ret = "__EDITABLE_EDIT_REQUEST__";
       break;
index b26b714..7a65414 100644 (file)
@@ -41,6 +41,7 @@ namespace util {
     CompUpdateRequest,
     CompUpdated,
     CompNotifyDataUpdate,
+    CompNotifyListeningStatus,
     EditableEditRequest,
     EditableEditComplete,
     EditableEditPreview,
index 6abb8ff..8112ba4 100644 (file)
@@ -49,4 +49,5 @@ INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR})
 INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
 
 INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/watchface-complication-provider.h DESTINATION include/${PROJECT_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/watchface-complication-provider-internal.h DESTINATION include/${PROJECT_NAME})
 
index 281264c..86c6137 100644 (file)
@@ -56,10 +56,13 @@ class ComplicationProvider::Impl : IGDBus::IGDBusEvent {
     int CheckPrivilege(std::list<std::string>& required_privileges,
                         GDBusConnection* connection);
     bool CheckAppid(const std::string& Appid);
+    const std::string& GetAppid() const;
     int GetWatcherID();
     std::string& GetWatchName();
     cynara_result GetPrivilegeResult();
     void SetPrivilegeResult(cynara_result result);
+    int GetListeningCount() const;
+    void SetListeningCount(int count);
 
    private:
     std::string sender_name_;
@@ -68,6 +71,7 @@ class ComplicationProvider::Impl : IGDBus::IGDBusEvent {
     std::string watch_name_;
     std::list<std::string> sender_privileges_;
     cynara_result privilege_result_;
+    int listening_count_ = 0;
   };
   SenderInfo* GetSenderInfo(std::string sender_name,
       GDBusConnection* connection, GVariant* parameters);
index 888c1f6..e177185 100644 (file)
@@ -124,10 +124,22 @@ bool ComplicationProvider::Impl::SenderInfo::CheckAppid(
   return false;
 }
 
+const std::string& ComplicationProvider::Impl::SenderInfo::GetAppid() const {
+  return sender_app_id_;
+}
+
 int ComplicationProvider::Impl::SenderInfo::GetWatcherID() {
   return watcher_id_;
 }
 
+int ComplicationProvider::Impl::SenderInfo::GetListeningCount() const {
+  return listening_count_;
+}
+
+void ComplicationProvider::Impl::SenderInfo::SetListeningCount(int count) {
+  listening_count_ = count;
+}
+
 std::string& ComplicationProvider::Impl::SenderInfo::GetWatchName() {
   return watch_name_;
 }
@@ -151,6 +163,10 @@ void ComplicationProvider::Impl::OnVanish(const std::string& watch_name) {
   for (; iter != sender_info_.end(); iter++) {
     SenderInfo* si = iter->second;
     if (watch_name.compare(si->GetWatchName()) == 0) {
+      if (si->GetListeningCount() > 0)
+        parent_->OnConsumerStatusChange(si->GetAppid(),
+            WATCHFACE_COMPLICATION_CONSUMER_LISTENING_STOP);
+
       gdbus_.get()->UnWatch(si->GetWatcherID());
       sender_info_.erase(iter);
       delete si;
@@ -314,6 +330,41 @@ void ComplicationProvider::Impl::OnSignal(GDBusConnection* connection,
       LOGE("Exception bad_alloc");
       return;
     }
+  } else if(signal_name.compare(util::GetCmdStr(
+                 util::CmdType::CompNotifyListeningStatus)) == 0) {
+    watchface_complication_consumer_status_e state;
+    int type;
+    char* sender_app_id = nullptr;
+    g_variant_get(parameters, "(&sii)", &sender_app_id, &type, &state);
+
+    if (si->CheckAppid(sender_app_id) == false) {
+      LOGE("invaild app id [%s]", sender_app_id);
+      return;
+    }
+
+    if (!util::CheckComplicationType(static_cast<int>(type))) {
+      LOGE("invaild type [%d]", type);
+      return;
+    }
+
+    if ((supported_types_ & type) == 0) {
+      LOGE("Not supported type [%d][%d]", supported_types_, type);
+      return;
+    }
+
+    int listening_count = si->GetListeningCount();
+
+    if (state == WATCHFACE_COMPLICATION_CONSUMER_LISTENING_START)
+      listening_count++;
+    else
+      listening_count--;
+
+    si->SetListeningCount(listening_count);
+
+    if ((state == WATCHFACE_COMPLICATION_CONSUMER_LISTENING_START && listening_count == 1)
+         || (state == WATCHFACE_COMPLICATION_CONSUMER_LISTENING_STOP && listening_count == 0))
+      parent_->OnConsumerStatusChange(sender_app_id, state);
+
   }
 }
 
@@ -321,6 +372,11 @@ void ComplicationProvider::Impl::OnSignal(GDBusConnection* connection,
 void ComplicationProvider::OnDataUpdateRequest(const std::string& sender_appid,
     ComplicationType type, const Bundle& context, Bundle* shared_data) {
 }
+
+void ComplicationProvider::OnConsumerStatusChange(const std::string& sender_appid,
+    watchface_complication_consumer_status_e status) {
+}
+
 /* LCOV_EXCL_STOP */
 
 const std::string& ComplicationProvider::GetProviderId() const {
index a8a6b11..24f67d0 100644 (file)
@@ -36,6 +36,8 @@ class EXPORT_API ComplicationProvider : public IComplicationEvent {
                            ComplicationType type,
                            const tizen_base::Bundle& context,
                            tizen_base::Bundle* shared_data) override;
+  void OnConsumerStatusChange(const std::string& sender_appid,
+       watchface_complication_consumer_status_e status) override;
 
   int NotifyDataUpdate();
   const std::string& GetProviderId() const;
index f8babf1..8f66aa2 100644 (file)
@@ -19,7 +19,7 @@
 
 #include <tizen.h>
 #include <bundle.h>
-#include <watchface-complication-provider.h>
+#include <watchface-common.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -54,6 +54,18 @@ int watchface_complication_provider_data_set_icon_path_with_aod(
 int watchface_complication_provider_data_set_image_path_with_aod(
        bundle *shared_data, const char *image_path, const char *aod_image_path);
 
+
+typedef enum _watchface_complication_consumer_status {
+       WATCHFACE_COMPLICATION_CONSUMER_LISTENING_START = 0x1,
+       WATCHFACE_COMPLICATION_CONSUMER_LISTENING_STOP = 0x2
+} watchface_complication_consumer_status_e;
+
+typedef void (*watchface_complication_consumer_status_cb)(const char *provider_id,
+       const char *request_appid, watchface_complication_consumer_status_e status, void *user_data);
+
+void watchface_complication_provider_set_consumer_status_cb(
+       watchface_complication_consumer_status_cb callback, void *user_data);
+
 #ifdef __cplusplus
 }
 #endif
index 12e8b1d..636c4f4 100644 (file)
@@ -33,6 +33,7 @@
 #include "watchface-common/watchface-common-internal.h"
 #include "watchface-complication-provider/complication-provider.h"
 #include "watchface-complication-provider/include/watchface-complication-provider.h"
+#include "watchface-complication-provider/include/watchface-complication-provider-internal.h"
 #include "watchface-complication/db-manager.h"
 #include "watchface-complication/complication-internal.h"
 
@@ -105,6 +106,17 @@ class WatchComplicationProviderStub : public ComplicationProvider {
         GetProviderId().c_str(), sender_appid.c_str());
   }
 
+  void OnConsumerStatusChange(const std::string& sender_appid,
+        watchface_complication_consumer_status_e status) override {
+    if (status_cb_ == nullptr)
+      return;
+
+    LOGI("ConsumerStatusChange call done provider(%s) sender(%s) %d ",
+        GetProviderId().c_str(), sender_appid.c_str(), status);
+
+    status_cb_(GetProviderId().c_str(), sender_appid.c_str(), status, user_data_);
+  }
+
   int AddCallbackInfo(unique_ptr<CallbackInfo> ci) {
     for (auto& i : cb_list_) {
       if (i.get()->GetCallback() == ci->GetCallback()) {
@@ -127,11 +139,21 @@ class WatchComplicationProviderStub : public ComplicationProvider {
     return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
   }
 
+  void SetStatusCallback(watchface_complication_consumer_status_cb cb, void* user_data) {
+    status_cb_ = cb;
+    user_data_ = user_data;
+  }
+
  private:
   std::list<std::unique_ptr<CallbackInfo>> cb_list_;
+  watchface_complication_consumer_status_cb status_cb_ = nullptr;
+  void* user_data_ = nullptr;
 };
 
 static std::map<std::string, WatchComplicationProviderStub*> __providers;
+static watchface_complication_consumer_status_cb __status_cb;
+static void* __user_data;
+
 extern "C" EXPORT_API int watchface_complication_provider_add_update_requested_cb(
     const char* provider_id,
     watchface_complication_provider_update_requested_cb cb,
@@ -172,6 +194,9 @@ extern "C" EXPORT_API int watchface_complication_provider_add_update_requested_c
     return WATCHFACE_COMPLICATION_ERROR_OUT_OF_MEMORY;
   }
 
+  if (__status_cb != nullptr)
+    ws->SetStatusCallback(__status_cb, __user_data);
+
   return ws->AddCallbackInfo(move(ci));
 }
 
@@ -195,6 +220,15 @@ extern "C" EXPORT_API int watchface_complication_provider_remove_update_requeste
   return ws->RemoveCallbackInfo(cb);
 }
 
+extern "C" EXPORT_API void watchface_complication_provider_set_consumer_status_cb(
+      watchface_complication_consumer_status_cb callback, void *user_data) {
+  __status_cb = callback;
+  __user_data = user_data;
+
+  for (auto& i : __providers)
+    i.second->SetStatusCallback(callback, user_data);
+}
+
 extern "C" EXPORT_API int watchface_complication_provider_notify_update(
     const char* updated_provider_id) {
   if (!watchface_complication::util::CheckWatchFeatureEnabled())
index 68b0549..6ce27b3 100644 (file)
@@ -22,6 +22,7 @@
 #include <string>
 
 #include "watchface-complication/complication-internal.h"
+#include "watchface-complication-provider/include/watchface-complication-provider-internal.h"
 
 namespace watchface_complication {
 
@@ -31,6 +32,8 @@ class EXPORT_API IComplicationEvent {
                                    ComplicationType type,
                                    const tizen_base::Bundle& context,
                                    tizen_base::Bundle* shared_data) = 0;
+ virtual void OnConsumerStatusChange(const std::string& sender_appid,
+                                   watchface_complication_consumer_status_e status) = 0;
 };
 
 }  // namespace watchface_complication
index f04b5c8..cf1ca59 100644 (file)
@@ -124,6 +124,8 @@ class Complication::Impl : IGDBus::IGDBusEvent, IPackageManager::IPackageEvent {
   std::unique_ptr<IPackageManager> package_;
   EditablesManager& editables_manager_;
   bool mock_ = false;
+  bool is_provider_ready_ = false;
+  int listening_status_ = 0;
 };
 
 }  // namespace watchface_complication
index 6a4835b..bd70ee5 100644 (file)
@@ -27,6 +27,7 @@
 #include "watchface-common/watchface-util.h"
 #include "watchface-common/watchface-common-internal.h"
 #include "watchface-complication/complication-internal.h"
+#include "watchface-complication/include/watchface-complication-internal.h"
 
 #include <iostream>
 
@@ -236,7 +237,13 @@ void Complication::Impl::ProviderReadyProcess(GVariant* parameters) {
     LOGI("It's not mine %s", provider_id);
     return;
   }
-  parent_->SendDataUpdateRequest(false);
+
+  is_provider_ready_ = true;
+
+  if (listening_status_ == WATCHFACE_COMPLICATION_CONSUMER_LISTENING_START)
+    parent_->NotifyListeningStatus(WATCHFACE_COMPLICATION_CONSUMER_LISTENING_START);
+  else
+    LOGI("Not exist registered callback %s", provider_id);
 }
 
 void Complication::Impl::OnSignal(GDBusConnection* connection,
@@ -449,6 +456,8 @@ int Complication::Impl::UpdateProviderInfo() {
     LOGI("subscribe signal %d %d ", subscribe_id_, cur_type_);
   }
 
+  is_provider_ready_ = false;
+
   return ret;
 }
 
@@ -507,6 +516,11 @@ int Complication::Impl::UpdateCurProvider(std::string new_provider_id,
   if (ret != WATCHFACE_COMPLICATION_ERROR_NONE)
     return ret;
 
+  if (!cur_provider_id_.empty()) {
+    parent_->NotifyListeningStatus(WATCHFACE_COMPLICATION_CONSUMER_LISTENING_STOP);
+    is_provider_ready_ = false;
+ }
+
   cur_type_ = type;
   cur_provider_id_ = new_provider_id;
   cur_provider_appid_ = appid;
@@ -531,6 +545,49 @@ int Complication::UpdateLastData() {
   return WATCHFACE_COMPLICATION_ERROR_NONE;
 }
 
+void Complication::SetListeningStatus(
+    watchface_complication_consumer_status_e state) {
+  impl_->listening_status_ = state;
+  NotifyListeningStatus(state);
+}
+
+void Complication::NotifyListeningStatus(
+    watchface_complication_consumer_status_e state) {
+  if (impl_->is_provider_ready_ == false)
+    return;
+
+  LOGI("emit signal comp_id %d, type %d %d",
+       impl_->complication_id_,  impl_->cur_type_, state);
+
+  std::string provider_appid = DBManager::GetProviderAppId(
+      impl_->cur_provider_id_.c_str());
+
+  if (provider_appid.empty()) {
+    LOGE("Can not find provider info from DB : provider_id(%s)",
+          impl_->cur_provider_id_.c_str());
+    return;
+  }
+
+  int emit_ret = impl_->gdbus_.get()->EmitSignal(
+      IGDBus::SigType::Complication,
+      provider_appid,
+      impl_->cur_provider_id_,
+      -1,
+      util::GetCmdStr(util::CompNotifyListeningStatus),
+      g_variant_new("(sii)",
+                    util::GetAppId().c_str(),
+                    impl_->cur_type_,
+                    state));
+  if (!emit_ret)
+      LOGE("EmitSignal failed %s: %d",
+         impl_->cur_provider_id_.c_str(), state);
+
+  if (state == WATCHFACE_COMPLICATION_CONSUMER_LISTENING_START)
+    SendDataUpdateRequest(false);
+
+  LOGI("emit signal done");
+}
+
 int Complication::SetCurDataIdx(int cur_data_idx) {
   int ret = WATCHFACE_COMPLICATION_ERROR_NONE;
   if (impl_->cur_data_idx_ == cur_data_idx) {
index d3e7337..acfbc64 100644 (file)
@@ -31,6 +31,7 @@
 #include "watchface-complication/editables-manager.h"
 #include "watchface-complication/db-manager.h"
 #include "watchface-common/watchface-exception.h"
+#include "watchface-complication-provider/include/watchface-complication-provider-internal.h"
 
 namespace watchface_complication {
 
@@ -103,6 +104,8 @@ class EXPORT_API Complication : public IEditable
       std::list<std::unique_ptr<ProviderInfo>> allowed_list);
   int ClearAllowedList();
   int Init();
+  void SetListeningStatus(watchface_complication_consumer_status_e state);
+  void NotifyListeningStatus(watchface_complication_consumer_status_e state);
 
  public:
   static const char* GetProviderIdKey();
index 60a0157..e0bf784 100644 (file)
@@ -161,6 +161,9 @@ class WatchComplicationStub : public Complication {
       }
     }
     cb_list_.emplace_back(move(ci));
+    if (cb_list_.size() == 1)
+      SetListeningStatus(WATCHFACE_COMPLICATION_CONSUMER_LISTENING_START);
+
     return WATCHFACE_COMPLICATION_ERROR_NONE;
   }
 
@@ -168,6 +171,10 @@ class WatchComplicationStub : public Complication {
     for (auto& i : cb_list_) {
       if (i.get()->GetCallback() == cb) {
         cb_list_.remove(i);
+
+        if (cb_list_.size() == 0)
+          SetListeningStatus(WATCHFACE_COMPLICATION_CONSUMER_LISTENING_STOP);
+
         return WATCHFACE_COMPLICATION_ERROR_NONE;
       }
     }