BuildRequires: pkgconfig(capi-appfw-app-common)
BuildRequires: pkgconfig(libtzplatform-config)
BuildRequires: pkgconfig(pkgmgr-info)
+BuildRequires: pkgconfig(pkgmgr)
BuildRequires: pkgconfig(pkgmgr-installer)
BuildRequires: pkgconfig(capi-appfw-app-control)
BuildRequires: pkgconfig(cynara-client)
EXPECT_EQ(WC::complication->GetEditableId(), 1);
}
-TEST_F(WC, GetCandidates)
-{
- WC::complication->UpdateCandidatesInfo();
- std::list<std::unique_ptr<Bundle>> const& list = WC::complication->GetCandidates();
- EXPECT_NE(list.empty(), true);
-}
-
-TEST_F(WC, GetData)
-{
- WC::complication->UpdateCandidatesInfo();
- const Bundle* curData = WC::complication->GetCurData();
- const Bundle* nthData = WC::complication->GetNthData(0);
-
- EXPECT_NE(curData->GetConstRaw(), nullptr);
- EXPECT_NE(nthData->GetConstRaw(), nullptr);
-}
-
TEST_F(WC, DataIdx)
{
EXPECT_EQ(WC::complication->GetCurDataIdx(), 0);
void* user_data) {
}
+void _on_complication_error_cb(int complication_id, const char* provider_id,
+ watchface_complication_type_e type,
+ watchface_complication_error_e error,
+ void* user_data) {
+}
+
TEST_F(WFC, Create)
{
EXPECT_NE(WFC::complication, nullptr);
TEST_F(WFC, Callback)
{
- EXPECT_EQ(watchface_complication_add_updated_cb(WFC::complication, _on_complication_update_cb, NULL), 0);
+ EXPECT_EQ(watchface_complication_add_updated_cb(WFC::complication, _on_complication_update_cb, _on_complication_error_cb, NULL), 0);
EXPECT_EQ(watchface_complication_send_update_request(WFC::complication), WATCHFACE_COMPLICATION_ERROR_IO_ERROR);
EXPECT_EQ(watchface_complication_remove_updated_cb(WFC::complication, _on_complication_update_cb), 0);
}
WATCHFACE_COMPLICATION_ERROR_EDIT_NOT_READY = TIZEN_ERROR_COMPLICATION | 0x3, /**< Edit not ready */
WATCHFACE_COMPLICATION_ERROR_EXIST_ID = TIZEN_ERROR_COMPLICATION | 0x4, /**< ID already exist */
WATCHFACE_COMPLICATION_ERROR_NOT_EXIST = TIZEN_ERROR_COMPLICATION | 0x5, /**< Not exist */
+ WATCHFACE_COMPLICATION_ERROR_PROVIDER_NOT_AVAILABLE = TIZEN_ERROR_COMPLICATION | 0x6, /**< Provider is not available, it could be uninstalled or disabled */
} watchface_complication_error_e;
/**
public:
virtual void OnDataUpdated(const std::string& provider_id,
ComplicationType type, const std::unique_ptr<Bundle>& data) = 0;
+ virtual void OnProviderError(const std::string& provider_id,
+ ComplicationType type, int error) = 0;
virtual void OnNotifyDataUpdate() = 0;
};
pkgmgr-installer
cynara-client
cynara-creds-gdbus
+ pkgmgr
+ pkgmgr-info
)
FOREACH(flag ${watchface-complication_CFLAGS})
#define WATCHFACE_COMPLICATION_COMPLICATION_CONNECTOR_IMPLEMENTATION_H_
#include <gio/gio.h>
+#include <dlog.h>
#include <memory>
#include <string>
#include "watchface-complication/complication.h"
#include "watchface-complication/complication-connector.h"
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "WATCHFACE_COMPLICATION"
+#define LOG_TAG "WATCHFACE_COMPLICATION"
+
namespace watchface_complication {
class ComplicationConnector::Impl {
rs->OnAppear(name, name_owner);
}
+ static int PackageAppinfoCallback(const pkgmgrinfo_appinfo_h handle,
+ void* user_data) {
+ char* appid = NULL;
+ int ret = pkgmgrinfo_appinfo_get_appid(handle, &appid);
+ if (ret < 0) {
+ LOGE("Failed to get appid");
+ return 0;
+ }
+ LOGI("add (%s) for delete/disable list", appid);
+ package_app_list_.push_back(appid);
+ return 0;
+ }
+
+ static int HandlingPackageCb(const char* pkgname, const char* val) {
+ pkgmgrinfo_appinfo_filter_h handle;
+ int ret = pkgmgrinfo_appinfo_filter_create(&handle);
+ if (ret != PMINFO_R_OK) {
+ LOGE("filter create failed [%d]", ret);
+ return WATCHFACE_COMPLICATION_ERROR_IO_ERROR;
+ }
+
+ ret = pkgmgrinfo_appinfo_filter_add_string(handle,
+ PMINFO_APPINFO_PROP_APP_PACKAGE, pkgname);
+ if (ret != PMINFO_R_OK) {
+ LOGE("filter add pkgname failed [%d]", ret);
+ return WATCHFACE_COMPLICATION_ERROR_IO_ERROR;
+ }
+
+ ret = pkgmgrinfo_appinfo_filter_foreach_appinfo(handle,
+ PackageAppinfoCallback, NULL);
+ if (ret != PMINFO_R_OK) {
+ LOGE("foreach failed [%d]", ret);
+ return WATCHFACE_COMPLICATION_ERROR_IO_ERROR;
+ }
+
+ return 0;
+ }
+
+ static int PkgmgrPackageStatusCb(uid_t target_uid, int req_id,
+ const char* pkg_type, const char* pkgid, const char* key,
+ const char* val, const void* pmsg, void* data) {
+ LOGI("%s, (%s : %s)", pkgid, key, val);
+ if (strcmp(key, "start") == 0) {
+ if (strcmp(val, "disable_app") == 0 || strcmp(val, "uninstall") == 0) {
+ current_pkg_event_ = std::string(val);
+ HandlingPackageCb(pkgid, current_pkg_event_.c_str());
+ } else {
+ current_pkg_event_ = "";
+ }
+ } else if (strcmp(key, "end") == 0) {
+ if (strcmp(val, "ok") == 0 &&
+ (strcmp(current_pkg_event_.c_str(), "disable_app") == 0 ||
+ strcmp(current_pkg_event_.c_str(), "uninstall") == 0)) {
+ LOGW("handling package event (%s)", current_pkg_event_.c_str());
+ for (std::string& appid : package_app_list_) {
+ for (IPackageEventListener* pe : package_listener_list_) {
+ if (strcmp(current_pkg_event_.c_str(), "disable_app") == 0) {
+ LOGI("disabled cb (%s)", appid.c_str());
+ pe->OnAppDisabled(appid);
+ } else if (strcmp(current_pkg_event_.c_str(), "uninstall") == 0) {
+ LOGI("uninstalled cb (%s)", appid.c_str());
+ pe->OnAppUninstalled(appid);
+ }
+ }
+ }
+ }
+ package_app_list_.clear();
+ }
+
+ return 0;
+ }
+
private:
+ pkgmgr_client* pkgmgr_client_ = NULL;
GDBusConnection* conn_ = nullptr;
IEventListener* listener_ = nullptr;
std::string appid_;
+ static std::list<IPackageEventListener*> package_listener_list_;
+ static std::list<std::string> package_app_list_;
+ static std::string current_pkg_event_;
};
} // namespace watchface_complication
#include <glib.h>
#include <unistd.h>
#include <aul.h>
+#include <package-manager.h>
+#include <pkgmgr-info.h>
#include "watchface-complication/complication-connector.h"
#include "watchface-complication/complication-connector-implementation.h"
#define MAX_PACKAGE_STR_SIZE 512
namespace watchface_complication {
+std::list<ComplicationConnector::IPackageEventListener*> ComplicationConnector::Impl::package_listener_list_;
+std::list<std::string> ComplicationConnector::Impl::package_app_list_;
+std::string ComplicationConnector::Impl::current_pkg_event_;
ComplicationConnector& ComplicationConnector::GetInst() {
static ComplicationConnector w_inst;
ComplicationConnector::~ComplicationConnector() = default;
ComplicationConnector::Impl::Impl() = default;
+void ComplicationConnector::AddPackageEventListener(IPackageEventListener* pe) {
+ if (impl_->pkgmgr_client_ == NULL) {
+ impl_->pkgmgr_client_ = pkgmgr_client_new(PC_LISTENING);
+
+ if (impl_->pkgmgr_client_ == NULL) {
+ LOGE("fail to create pkgmgr client");
+ return;
+ }
+
+ if (pkgmgr_client_listen_status(impl_->pkgmgr_client_ ,
+ impl_->PkgmgrPackageStatusCb, NULL) <= 0) {
+ LOGE("fail to listen pkg status");
+ pkgmgr_client_free(impl_->pkgmgr_client_);
+ return;
+ }
+ LOGI("listen pkg status");
+ }
+
+ impl_->package_listener_list_.push_back(pe);
+}
+
+void ComplicationConnector::RemovePackageEventListener(IPackageEventListener* pe) {
+ impl_->package_listener_list_.remove(pe);
+ if (impl_->package_listener_list_.size() == 0) {
+ pkgmgr_client_free(impl_->pkgmgr_client_);
+ impl_->pkgmgr_client_ = NULL;
+ }
+}
+
std::string ComplicationConnector::GetAppId() {
return impl_->appid_;
}
LOGE("Out of memory");
return WATCHFACE_COMPLICATION_ERROR_OUT_OF_MEMORY;
}
+
tmp_impl->conn_ = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
if (tmp_impl->conn_ == NULL) {
if (error != NULL) {
const std::string& name_owner) = 0;
};
+ class IPackageEventListener {
+ public:
+ virtual void OnAppDisabled(const std::string& appid) = 0;
+ virtual void OnAppUninstalled(const std::string& appid) = 0;
+ };
+
static ComplicationConnector& GetInst();
int Watch(std::string id, IEventListener* listener);
void UnWatch(int watcher_id);
void UnSubscribeSignal(int subscribe_id);
std::string GetAppId();
std::string GetCmdStr(CmdType type);
+ void AddPackageEventListener(IPackageEventListener* pe);
+ void RemovePackageEventListener(IPackageEventListener* pe);
private:
ComplicationConnector();
};
std::string EncodeStr(EncodeType type, std::string appid);
std::string EncodeStr(EncodeType type, std::string appid, int compid);
+
class Impl;
std::unique_ptr<Impl> impl_;
};
namespace watchface_complication {
-class Complication::Impl : ComplicationConnector::IEventListener {
+class Complication::Impl : ComplicationConnector::IEventListener,
+ ComplicationConnector::IPackageEventListener {
public:
void OnSignal(GDBusConnection* connection,
const std::string& sender_name,
GVariant* parameters) override;
void OnVanish(const std::string& name) override;
void OnAppear(const std::string& name, const std::string& name_owner) override;
+ void OnAppDisabled(const std::string& appid) override;
+ void OnAppUninstalled(const std::string& appid) override;
virtual ~Impl();
private:
int MakeCandidatesList();
int LoadPeriod();
int LoadLabel();
+ int LoadContext();
+ int LoadCurProviderAppid();
+ int LoadCurDataIdx();
+ int LoadPrevProviderInfo();
+ int LoadDefaultProviderInfo();
int UpdateLastDataFields();
+ int UpdateProviderInfo();
+ int DeleteAppContext(const char* appid);
+ int ReplaceUnavailableProvider(const char* deleted_appid);
private:
Complication* parent_;
int complication_id_ = -1;
int editable_id_ = -1;
int support_types_ = -1;
+ std::string default_provider_appid_;
std::string default_provider_id_;
ComplicationType default_type_;
std::unique_ptr<IEditable::Highlight> highlight_;
+ std::string cur_provider_appid_;
std::string cur_provider_id_;
ComplicationType cur_type_;
std::string last_provider_id_;
#include <aul.h>
#include <aul_complication.h>
#include <appsvc.h>
+#include <pkgmgr-info.h>
#include <stdexcept>
-#include "watchface-common/watchface-util.h"
#include "watchface-complication/complication.h"
#include "watchface-complication/complication-implementation.h"
+#include "watchface-common/watchface-util.h"
#include "watchface-complication/include/watchface-complication-internal.h"
#ifdef LOG_TAG
const std::string& default_provider_id,
ComplicationType default_type)
: impl_(new Impl(this, id, support_types, default_provider_id, default_type)) {
+ ComplicationConnector::GetInst().AddPackageEventListener(impl_.get());
}
Complication::~Complication() {
+ ComplicationConnector::GetInst().RemovePackageEventListener(impl_.get());
}
Complication::Impl::Impl(Complication* parent, int id,
ComplicationType default_type)
: parent_(parent), complication_id_(id), support_types_(support_types),
default_provider_id_(default_provider_id), default_type_(default_type) {
- RestoreStateOrSetDefault();
- LoadPeriod();
- LoadLabel();
- if (cur_type_ != NoData) {
- try {
- subscribe_id_ = ComplicationConnector::GetInst().SubscribeSignal(
- ComplicationConnector::Complication, cur_provider_id_,
- -1, this);
- } catch (...) {
- throw;
- }
+ int ret;
+ ret = LoadPrevProviderInfo();
+ if (ret == WATCHFACE_COMPLICATION_ERROR_PROVIDER_NOT_AVAILABLE) {
+ ret = LoadDefaultProviderInfo();
+ if (ret != WATCHFACE_COMPLICATION_ERROR_NONE)
+ THROW(ret);
+ }
+
+ UpdateCandidatesInfo();
+ ret = UpdateProviderInfo();
+ if (ret != WATCHFACE_COMPLICATION_ERROR_NONE)
+ THROW(ret);
+
+ default_provider_appid_ =
+ DBManager::GetProviderAppId(cur_provider_id_.c_str());
+ if (default_provider_appid_.empty()) {
+ LOGE("fail to get default provider info");
+ THROW(WATCHFACE_COMPLICATION_ERROR_PROVIDER_NOT_AVAILABLE);
}
- LOGI("subscribe signal %d %d ", subscribe_id_, cur_type_);
}
Complication::Impl::~Impl() {
return;
}
std::string provider_appid =
- DBManager::GetProviderAppId(cur_provider_id_.c_str());
+ DBManager::GetProviderAppId(cur_provider_id_.c_str());
if (provider_appid.empty()) {
LOGI("invalid provider_appid");
return;
return ret;
}
-void Complication::Impl::RestoreStateOrSetDefault() {
+int Complication::Impl::LoadContext() {
+ context_data_ = EditablesManager::GetInst().LoadContext(complication_id_,
+ cur_provider_id_.c_str());
+ try {
+ if (context_data_ != nullptr)
+ last_context_data_.reset(new Bundle(context_data_.get()->GetRaw()));
+ } catch (...) {
+ LOGE("Out of memory");
+ return WATCHFACE_COMPLICATION_ERROR_OUT_OF_MEMORY;
+ }
+ return WATCHFACE_COMPLICATION_ERROR_NONE;
+}
+
+int Complication::Impl::LoadCurProviderAppid() {
+ std::string appid = DBManager::GetProviderAppId(cur_provider_id_.c_str());
+ if (appid.empty()) {
+ LOGE("Fail to get provider appid");
+ return WATCHFACE_COMPLICATION_ERROR_PROVIDER_NOT_AVAILABLE;
+ }
+ cur_provider_appid_ = appid;
+ LOGI("cur provider appid (%s)", cur_provider_appid_.c_str());
+ return WATCHFACE_COMPLICATION_ERROR_NONE;
+}
+
+int Complication::Impl::LoadCurDataIdx() {
+ int ret = FindCandidateDataIdx(cur_provider_id_, cur_type_);
+ if (ret == -1) {
+ LOGE("Fail to find data index (%s)(%d)", cur_provider_id_.c_str(), cur_type_);
+ return WATCHFACE_COMPLICATION_ERROR_NO_DATA;
+ }
+
+ cur_data_idx_ = ret;
+ return WATCHFACE_COMPLICATION_ERROR_NONE;
+}
+
+int Complication::Impl::LoadPrevProviderInfo() {
char* prev_provider_id = NULL;
char* prev_provider_type = NULL;
+ std::string prev_provider_id_str;
std::unique_ptr<Bundle> setting_data;
try {
setting_data = EditablesManager::GetInst().LoadSetting(complication_id_);
- } catch (...) {
- throw;
+ } catch (watchface_complication::Exception &ex) {
+ LOGE("%s %d", ex.what(), ex.GetErrorCode());
+ return ex.GetErrorCode();
}
- if (setting_data == nullptr) {
- cur_provider_id_ = default_provider_id_;
- cur_type_ = default_type_;
- } else {
+ if (setting_data != nullptr) {
bundle_get_str(setting_data.get()->GetRaw(), provider_id_key_.c_str(),
&prev_provider_id);
- if (prev_provider_id != NULL)
- cur_provider_id_ = std::string(prev_provider_id);
- else
- cur_provider_id_ = default_provider_id_;
-
bundle_get_str(setting_data.get()->GetRaw(), provider_type_key_.c_str(),
&prev_provider_type);
- if (prev_provider_type != NULL)
- cur_type_ = static_cast<ComplicationType>(atoi(prev_provider_type));
- else
- cur_type_ = default_type_;
+ if (prev_provider_id)
+ prev_provider_id_str = std::string(prev_provider_id);
- LOGI("prev provider info %s, %s", prev_provider_id, prev_provider_type);
+ LOGI("get setting from bundle %s, %s", prev_provider_id, prev_provider_type);
}
- cur_data_idx_ = FindCandidateDataIdx(cur_provider_id_, cur_type_);
- context_data_ = EditablesManager::GetInst().LoadContext(complication_id_,
- cur_provider_id_.c_str());
- try {
- if (context_data_ != nullptr)
- last_context_data_.reset(new Bundle(context_data_.get()->GetRaw()));
- } catch (...) {
- throw;
+ if (prev_provider_id &&
+ DBManager::IsProviderExist(prev_provider_id_str,
+ atoi((const char*)prev_provider_type))) {
+ cur_provider_id_ = std::string(prev_provider_id);
+ cur_type_ = static_cast<ComplicationType>(atoi((const char*)prev_provider_type));
+ LOGI("Successfully get previous provider info");
+ return WATCHFACE_COMPLICATION_ERROR_NONE;
}
+
+ return WATCHFACE_COMPLICATION_ERROR_PROVIDER_NOT_AVAILABLE;
+}
+
+int Complication::Impl::LoadDefaultProviderInfo() {
+ if (!DBManager::IsProviderExist(default_provider_id_,
+ static_cast<int>(default_type_))) {
+ LOGE("Default provider do not exist (%s)(%d)",
+ default_provider_id_.c_str(), default_type_);
+ return WATCHFACE_COMPLICATION_ERROR_PROVIDER_NOT_AVAILABLE;
+ }
+
+ cur_type_ = default_type_;
+ cur_provider_id_ = default_provider_id_;
+
+ LOGI("Successfully get default provider info");
+ return WATCHFACE_COMPLICATION_ERROR_NONE;
}
int Complication::Impl::StoreSetting(int comp_id, std::string& provider_id,
int Complication::SetCandidates(
std::list<std::unique_ptr<Bundle>> candidates_list) {
- return UpdateCandidatesInfo();
+ return impl_->UpdateCandidatesInfo();
}
std::list<std::unique_ptr<Bundle>> const& Complication::GetCandidates() const {
return impl_->last_data_idx_;
}
+int Complication::Impl::DeleteAppContext(const char* appid) {
+ int ret = WATCHFACE_COMPLICATION_ERROR_NONE;
+ std::list<std::string> list = DBManager::GetProviderListWithAppId(appid);
+ for (std::string& info : list) {
+ ret = EditablesManager::GetInst().DeleteContext(editable_id_, info.c_str());
+ if (ret != WATCHFACE_COMPLICATION_ERROR_NONE) {
+ LOGE("delete editable context fail %d", ret);
+ return ret;
+ } else {
+ LOGI("delete context for (%d)(%s) done", editable_id_, info.c_str());
+ }
+ }
+ return ret;
+}
+
+int Complication::Impl::ReplaceUnavailableProvider(const char* deleted_appid) {
+ int ret = WATCHFACE_COMPLICATION_ERROR_NONE;
+
+ if (strcmp(deleted_appid, cur_provider_appid_.c_str()) != 0) {
+ LOGI("it is not current provider skip replace process (%s)(%s)",
+ deleted_appid, cur_provider_appid_.c_str());
+ return ret;
+ }
+
+ LOGI("current provider is uninstalled try to replace it with default");
+ if (strcmp(deleted_appid, default_provider_appid_.c_str()) == 0) {
+ LOGE("deleted provider is default provider (%s)",
+ default_provider_appid_.c_str());
+ ret = WATCHFACE_COMPLICATION_ERROR_PROVIDER_NOT_AVAILABLE;
+ } else {
+ ret = LoadDefaultProviderInfo();
+ }
+
+ if (ret == WATCHFACE_COMPLICATION_ERROR_PROVIDER_NOT_AVAILABLE) {
+ parent_->OnProviderError(default_provider_id_, default_type_,
+ WATCHFACE_COMPLICATION_ERROR_PROVIDER_NOT_AVAILABLE);
+ } else {
+ ret = UpdateProviderInfo();
+ }
+
+ return ret;
+}
+
+void Complication::Impl::OnAppDisabled(const std::string& appid) {
+ ReplaceUnavailableProvider(appid.c_str());
+}
+
+void Complication::Impl::OnAppUninstalled(const std::string& appid) {
+ pkgmgrinfo_appinfo_h app_handle;
+
+ int ret = pkgmgrinfo_appinfo_get_disabled_appinfo(appid.c_str(), &app_handle);
+ if (ret != PMINFO_R_OK)
+ DeleteAppContext(appid.c_str());
+
+ ReplaceUnavailableProvider(appid.c_str());
+}
+
int Complication::Impl::UpdateLastDataFields() {
int ret;
if (ret != WATCHFACE_COMPLICATION_ERROR_NONE)
return ret;
ret = LoadLabel();
- return ret;;
+ return ret;
+}
+
+/*
+* update provider relate information according to
+* cur_provider_id_, cur_provider_type_
+*/
+int Complication::Impl::UpdateProviderInfo() {
+ int ret = LoadCurDataIdx();
+ if (ret != WATCHFACE_COMPLICATION_ERROR_NONE)
+ return ret;
+
+ ret = LoadCurProviderAppid();
+ if (ret != WATCHFACE_COMPLICATION_ERROR_NONE)
+ return ret;
+
+ ret = LoadContext();
+ if (ret != WATCHFACE_COMPLICATION_ERROR_NONE)
+ return ret;
+
+ ret = LoadPeriod();
+ if (ret != WATCHFACE_COMPLICATION_ERROR_NONE)
+ return ret;
+
+ ret = LoadLabel();
+ if (ret != WATCHFACE_COMPLICATION_ERROR_NONE)
+ return ret;
+
+ if (cur_type_ != NoData) {
+ try {
+ subscribe_id_ = ComplicationConnector::GetInst().SubscribeSignal(
+ ComplicationConnector::Complication, cur_provider_id_,
+ -1, this);
+ } catch (Exception &ex) {
+ LOGE("%s %d", ex.what(), ex.GetErrorCode());
+ return ex.GetErrorCode();
+ }
+ LOGI("subscribe signal %d %d ", subscribe_id_, cur_type_);
+ }
+
+ return ret;
}
int Complication::Impl::LoadLabel() {
int Complication::SetCurDataIdx(int cur_data_idx) {
char* provider_id = NULL;
char* type = NULL;
+ int ret = WATCHFACE_COMPLICATION_ERROR_NONE;
if (impl_->cur_data_idx_ == cur_data_idx) {
LOGI("Same with cur data idx skip setting process %d, %d",
if (impl_->cur_type_ == NoData) {
impl_->subscribe_id_ = -1;
} else {
- impl_->subscribe_id_ = ComplicationConnector::GetInst().SubscribeSignal(
- ComplicationConnector::Complication,
- impl_->cur_provider_id_, -1, impl_.get());
+ ret = impl_->UpdateProviderInfo();
LOGI("subscribe signal %d", impl_->subscribe_id_);
}
- return WATCHFACE_COMPLICATION_ERROR_NONE;
+ return ret;
}
const char* Complication::GetCurProviderId() {
}
}
+void Complication::OnProviderError(const std::string& provider_id,
+ ComplicationType type, int error) {
+}
+
void Complication::OnDataUpdated(const std::string& provider_id,
ComplicationType type,
const std::unique_ptr<Bundle>& data) {
}
try {
- impl_->last_context_data_.reset(
- new Bundle((impl_->context_data_.get())->GetRaw()));
+ impl_->last_context_data_.reset(new Bundle((impl_->context_data_.get())->GetRaw()));
} catch (const std::bad_alloc &ba) {
LOGE("Bundle::Exception bad_alloc");
return WATCHFACE_COMPLICATION_ERROR_OUT_OF_MEMORY;
return WATCHFACE_COMPLICATION_ERROR_NONE;
}
-int Complication::UpdateCandidatesInfo() {
- int ret = impl_->MakeCandidatesList();
+int Complication::Impl::UpdateCandidatesInfo() {
+ int ret = MakeCandidatesList();
if (ret != WATCHFACE_COMPLICATION_ERROR_NONE)
return ret;
- int idx = impl_->FindCandidateDataIdx(
- impl_->cur_provider_id_, impl_->cur_type_);
+ int idx = FindCandidateDataIdx(cur_provider_id_, cur_type_);
if (idx != -1) {
- impl_->cur_data_idx_ = idx;
- ret = impl_->UpdateLastDataFields();
+ cur_data_idx_ = idx;
+ ret = UpdateLastDataFields();
}
return ret;
std::list<std::unique_ptr<ProviderInfo>> allowed_list) {
impl_->allowed_list_ = std::move(allowed_list);
impl_->candidates_list_.clear();
- return UpdateCandidatesInfo();
+ return impl_->UpdateCandidatesInfo();
}
int Complication::ClearAllowedList() {
void OnDataUpdated(const std::string& provider_id,
ComplicationType type,
const std::unique_ptr<Bundle>& data) override;
+ void OnProviderError(const std::string& provider_id, ComplicationType type,
+ int error) override;
void OnNotifyDataUpdate() override;
int GetComplicationId();
int GetEditableId() override;
int UpdateLastContext() override;
std::unique_ptr<Bundle>& GetLastContext() const override;
const std::string GetSetupAppId() override;
+
int SendDataUpdateRequest();
const char* GetCurProviderId();
const char* GetProviderId(const Bundle* data);
return WATCHFACE_COMPLICATION_ERROR_NONE;
}
+bool DBManager::IsProviderExist(std::string& provider_id,
+ int support_type) {
+ int ret;
+ std::string appid;
+ sqlite3_stmt* stmt = NULL;
+ sqlite3* db;
+ bool is_exist = false;
+
+ static const char query[] =
+ "SELECT DISTINCT appid FROM complication_provider "
+ "WHERE provider_id=? AND support_type=?";
+
+ db = OpenDB();
+ if (db == NULL) {
+ LOGE("parser db not exist");
+ return false;
+ }
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query),
+ &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ LOGE("prepare error: %s", sqlite3_errmsg(db));
+ CloseDB(db);
+ return false;
+ }
+
+ sqlite3_bind_text(stmt, 1, provider_id.c_str(), -1, SQLITE_TRANSIENT);
+ sqlite3_bind_int(stmt, 2, support_type);
+
+ if (sqlite3_step(stmt) == SQLITE_ROW)
+ is_exist = true;
+
+ sqlite3_finalize(stmt);
+ CloseDB(db);
+
+ return is_exist;
+}
+
std::string DBManager::GetProviderAppId(const char* provider_id) {
int ret;
std::string appid;
return provider_list;
}
+std::list<std::string> DBManager::GetProviderListWithAppId(
+ const char* provider_id) {
+ int ret;
+ char* provider = NULL;
+ sqlite3_stmt* stmt;
+ sqlite3* db;
+ std::list<std::string> provider_list;
+
+ static const char query[] =
+ "SELECT DISTINCT provider_id FROM complication_provider "
+ "WHERE appid=?";
+
+ 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_text(stmt, 1, provider_id, -1, SQLITE_TRANSIENT);
+
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
+ provider = (char*)sqlite3_column_text(stmt, 0);
+ provider_list.push_back(std::string(provider));
+ }
+
+ sqlite3_finalize(stmt);
+ CloseDB(db);
+
+ return provider_list;
+}
+
int DBManager::GetSupportTypes(std::string& provider_id, int* types) {
int ret;
int support_types = 0;
static int GetProviderPeriod(std::string& provider_id, int* period);
static std::string GetLabel(const char* provider_id);
static std::string GetSetupAppId(const char* provider_id);
+ static bool IsProviderExist(std::string& provider_id, int support_type);
+ static std::list<std::string> GetProviderListWithAppId(const char* provider_id);
private:
DBManager();
return std::move(context_data);
}
+int EditablesManager::DeleteContext(int editable_id,
+ const char* provider_id) {
+ char query[QUERY_MAXLEN];
+ std::unique_ptr<Bundle> context_data = nullptr;
+ sqlite3_stmt* stmt;
+ int ret;
+
+ if (impl_->context_db_ == NULL)
+ return WATCHFACE_COMPLICATION_ERROR_DB;
+
+ sqlite3_snprintf(QUERY_MAXLEN, query,
+ "DELETE FROM editable_context WHERE " \
+ "editable_id = %d AND provider_id = %Q ", editable_id, provider_id);
+ LOGI("editable context delete : (%d)(%s)", editable_id, provider_id);
+ ret = sqlite3_prepare_v2(impl_->context_db_,
+ query, strlen(query), &stmt, NULL);
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE) {
+ LOGE("execute fail %s", sqlite3_errmsg(impl_->context_db_));
+ sqlite3_close_v2(impl_->context_db_);
+ sqlite3_finalize(stmt);
+ return WATCHFACE_COMPLICATION_ERROR_DB;
+ }
+ sqlite3_finalize(stmt);
+
+ return WATCHFACE_COMPLICATION_ERROR_NONE;
+}
+
} // namespace watchface_complication
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);
+ int DeleteContext(int editable_id, const char* provider_id);
private:
EditablesManager();
void *user_data);
/**
+ * @brief Called when the complication provider error is occured.
+ * @since_tizen 5.0
+ * @param[in] complication_id A number that identifies the complication
+ * @param[in] provider_id The name of the provider.
+ * The @a provider_id can be used only in the callback. To use outside, make a copy.
+ * @param[in] type The type shown in the complication
+ * @param[in] error The error related with complication provider \n
+ * #WATCHFACE_COMPLICATION_ERROR_PROVIDER_NOT_AVAILABLE : Provider aplication is not available now for some reason. (eg. uninstall, disable) \n
+ * #WATCHFACE_COMPLICATION_ERROR_IO_ERROR : Provider aplication is not responding for update request. \n
+ * #WATCHFACE_COMPLICATION_ERROR_OUT_OF_MEMORY : Out of memory \n
+ * @param[in] user_data The user data passed from the callback function
+ */
+typedef void (*watchface_complication_error_cb)(
+ int complication_id,
+ const char *provider_id,
+ watchface_complication_type_e type,
+ watchface_complication_error_e error,
+ void *user_data);
+
+/**
* @brief Gets the id of provider in the complication.
* @since_tizen 5.0
* @remarks The @a cur_provider should be released using free().
* @since_tizen 5.0
* @param[in] handle Complication handle
* @param[in] cb The callback function
+ * @param[in] error_cb The error callback function
* @param[in] user_data The user data to pass to the callback function
* @return #WATCHFACE_COMPLICATION_ERROR_NONE if success, other value if failure
* @retval #WATCHFACE_COMPLICATION_ERROR_NONE Success
*/
int watchface_complication_add_updated_cb(complication_h handle,
watchface_complication_updated_cb cb,
+ watchface_complication_error_cb error_cb,
void *user_data);
/**
* If user selects the other provider and type, they are no longer used.
* You can specify support_types by combining the types you want to show in the complication.
* @since_tizen 5.0
+ * @privilege http://tizen.org/privilege/packagemanager.info
* @remarks The @a created_handle should be released using watchface_complication_destroy().
+ * Package manager privliege is needed to lookup provider application.
* @param[in] complication_id A number that identifies the complication
* @param[in] default_provider_id The default provider id
* @param[in] default_type The default type to display
* @retval #WATCHFACE_COMPLICATION_ERROR_NOT_EXIST Provider does not exist
* @retval #WATCHFACE_COMPLICATION_ERROR_OUT_OF_MEMORY Out of memory
* @retval #WATCHFACE_COMPLICATION_ERROR_DB Database error
+ * @retval #WATCHFACE_COMPLICATION_ERROR_PERMISSION_DENIED Permission denied
* @retval #WATCHFACE_COMPLICATION_ERROR_NOT_SUPPORTED Not supported
+ * @retval #WATCHFACE_COMPLICATION_ERROR_PROVIDER_NOT_AVAILABLE Provider aplication is not available now for some reason. (eg. uninstall, disable)
* @see watchface_complication_type_e
* @par Sample code:
* @code
using namespace watchface_complication;
class CallbackInfo {
public:
- CallbackInfo(watchface_complication_updated_cb cb, void* user_data)
- : cb_(cb), user_data_(user_data) {
+ CallbackInfo(watchface_complication_updated_cb cb,
+ watchface_complication_error_cb error_cb, void* user_data)
+ : cb_(cb), error_cb_(error_cb), user_data_(user_data) {
}
void Invoke(int complication_id,
data.get() == NULL ? NULL : data.get()->GetConstRaw(), user_data_);
}
+ void InvokeErrorCallback(int complication_id,
+ const std::string& provider_id,
+ ComplicationType type, int error) {
+ error_cb_(complication_id,
+ provider_id.c_str(), static_cast<watchface_complication_type_e>(type),
+ static_cast<watchface_complication_error_e>(error), user_data_);
+ }
+
watchface_complication_updated_cb GetCallback() {
return cb_;
}
+ watchface_complication_error_cb GetErrorCallback() {
+ return error_cb_;
+ }
+
private:
watchface_complication_updated_cb cb_;
+ watchface_complication_error_cb error_cb_;
+ void* user_data_;
+};
+
+class ErrorCallbackInfo {
+ public:
+ ErrorCallbackInfo(watchface_complication_error_cb cb, void* user_data)
+ : cb_(cb), user_data_(user_data) {
+ }
+
+ void Invoke(int complication_id,
+ const std::string& provider_id,
+ ComplicationType type, int error) {
+ cb_(complication_id,
+ provider_id.c_str(), static_cast<watchface_complication_type_e>(type),
+ static_cast<watchface_complication_error_e>(error), user_data_);
+ }
+
+ watchface_complication_error_cb GetCallback() {
+ return cb_;
+ }
+
+ private:
+ watchface_complication_error_cb cb_;
void* user_data_;
};
virtual ~WatchComplicationStub() = default;
+ void OnProviderError(const std::string& provider_id, ComplicationType type,
+ int error) override {
+ for (auto& i : cb_list_) {
+ i->InvokeErrorCallback(GetComplicationId(), provider_id, type, error);
+ }
+ LOGI("update call!! done");
+ }
+
void OnDataUpdated(const std::string& provider_id, ComplicationType type,
const std::unique_ptr<Bundle>& data) override {
for (auto& i : cb_list_) {
extern "C" EXPORT_API int watchface_complication_add_updated_cb(
complication_h handle, watchface_complication_updated_cb cb,
- void* user_data) {
- if (handle == NULL || cb == NULL)
+ watchface_complication_error_cb error_cb, void* user_data) {
+ if (handle == NULL || cb == NULL || error_cb == NULL)
return WATCHFACE_COMPLICATION_ERROR_INVALID_PARAMETER;
int ret;
auto sh = static_cast<SharedHandle<WatchComplicationStub>*>(handle);
auto ptr = SharedHandle<WatchComplicationStub>::Share(sh);
try {
- ret = ptr.get()->AddCallbackInfo(new CallbackInfo(cb, user_data));
+ ret = ptr.get()->AddCallbackInfo(new CallbackInfo(cb, error_cb, user_data));
+ if (ret != WATCHFACE_COMPLICATION_ERROR_NONE)
+ return ret;
} catch (const std::bad_alloc &ba) {
LOGE("WatchComplicationProviderStub::Exception bad_alloc");
return WATCHFACE_COMPLICATION_ERROR_OUT_OF_MEMORY;
setting_data = EditablesManager::GetInst().LoadSetting(editable_id);
} catch (watchface_complication::Exception &ex) {
LOGE("%s %d", ex.what(), ex.GetErrorCode());
- return ex.GetErrorCode();;
+ return ex.GetErrorCode();
}
if (setting_data != nullptr) {
*selected_data = bundle_dup(setting_data.get()->GetRaw());
*highlight = hi;
return WATCHFACE_COMPLICATION_ERROR_NONE;
-}
\ No newline at end of file
+}