Add log prints for debugging
[platform/core/appfw/app-core.git] / tizen-cpp / app-core-cpp / app_core_base.cc
index 5bceb80..aa55b1d 100644 (file)
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include "app-core-cpp/app_core_base.hh"
+
 #include <aul.h>
 #include <aul_app_lifecycle.h>
 #include <aul_watchdog.h>
 #include <dlfcn.h>
 #include <errno.h>
 #include <gio/gio.h>
+#include <glib-unix.h>
 #include <glib.h>
 #include <libintl.h>
 #include <linux/limits.h>
 #include <locale.h>
 #include <malloc.h>
 #include <sensor_internal.h>
+#include <signal.h>
 #include <stdbool.h>
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <unistd.h>
 #include <vconf.h>
 
+#include <algorithm>
 #include <cstring>
 #include <list>
 #include <map>
+#include <memory>
 #include <set>
 #include <sstream>
+#include <utility>
+#include <vector>
 
-#include "app-core-cpp/app_core_base.hh"
+#include "app-core-cpp/app_core_plugin_private.hh"
+#include "app-core-cpp/exit_handler_private.hh"
+#include "app-core-cpp/sigterm_handler_private.hh"
 #include "common/glib_private.hh"
 #include "common/log_private.hh"
+#include "common/log_tracer.hh"
 
 extern "C" void aul_finalize();
-
 namespace tizen_cpp {
+
+AppCoreBase* AppCoreBase::context_ = nullptr;
+
 namespace {
 
+internal::ExitHandler exit_handler;
+internal::SigtermHandler sigterm_handler;
+
 enum TizenProfile {
   Unknown = 0x00,
   Mobile = 0x01,
@@ -148,10 +164,10 @@ class AppCoreBase::Impl {
   void UpdateRegion();
   std::list<std::string> SplitLanguage(const std::string& lang);
   std::string GetLanguage(std::string lang);
-  void AppendDefaultLangs(std::set<std::string>& lang_set);
+  void AppendDefaultLangs(std::vector<std::string>& lang_set);
   std::string GetStringBefore(const char* str, const char* delim);
   std::map<std::string, std::set<std::string>> GetLangTable();
-  void AppendLangs(const std::string& lang, std::set<std::string>& lang_set,
+  void AppendLangs(const std::string& lang, std::vector<std::string>& lang_set,
       std::map<std::string, std::set<std::string>>& table);
   void ChangeLang();
   void OnFreezerSignal();
@@ -177,6 +193,7 @@ class AppCoreBase::Impl {
   static void ReceiveSuspendSignalCb(GDBusConnection*, const gchar*,
       const gchar*, const gchar*, const gchar*, GVariant*, gpointer);
   static void OnLowBatteryCb(keynode_t* key, void* data);
+  static void OnTimeZoneChangedCb(keynode_t* key, void* data);
   static void LockCb(keynode_t* node, void* user_data);
   static void AutoRotationChangedCb(sensor_t sensor, unsigned int event_type,
       sensor_data_t* data, void* user_data);
@@ -190,6 +207,8 @@ class AppCoreBase::Impl {
   void VerifyLanguage();
   void SetDefaultEvents();
   void UnsetDefaultEvents();
+  void PluginInit(int argc, char** argv);
+  void PluginFini();
 
  private:
   friend class AppCoreBase;
@@ -207,6 +226,8 @@ class AppCoreBase::Impl {
   int feature_ = 0;
   IAppCore* core_delegator_ = nullptr;
   IMainLoop* loop_delegator_ = nullptr;
+  guint signal_handler_source_ = 0;
+  std::unique_ptr<AppCorePlugin> plugin_;
 };
 
 AppCoreBase::EventBase::EventBase(Type type)
@@ -236,8 +257,28 @@ void AppCoreBase::EventBase::SetVal(int val) {
   impl_->val_ = std::move(val);
 }
 
-AppCoreBase::AppCoreBase() : impl_(std::make_unique<AppCoreBase::Impl>(this)) {}
-AppCoreBase::~AppCoreBase() = default;
+AppCoreBase::AppCoreBase()
+    : impl_(std::make_unique<AppCoreBase::Impl>(this)) {
+  if (context_ != nullptr) {
+    _E("Context is already initialized");
+  }
+
+  context_ = this;
+}
+
+AppCoreBase::~AppCoreBase() {
+  _I("");
+  context_ = nullptr;
+}
+
+AppCoreBase* AppCoreBase::GetContext() {
+  if (context_ == nullptr) {
+    _E("Context is not initialized.");
+    return nullptr;
+  }
+
+  return context_;
+}
 
 void AppCoreBase::Impl::ChangeLang() {
   const char* lang = getenv("LANG");
@@ -294,8 +335,10 @@ void AppCoreBase::Impl::InitSuspendDbusHandler(gpointer data) {
     GError* err = nullptr;
     __bus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &err);
     if (__bus == nullptr) {
-      _E("Failed to connect to the D-BUS daemon: %s", err->message);
-      g_error_free(err);
+      _E("Failed to connect to the D-BUS daemon: %s", err ? err->message : "");
+      if (err)
+        g_error_free(err);
+
       return;
     }
   }
@@ -375,11 +418,10 @@ void AppCoreBase::Impl::RegionChangeCb(keynode_t* key, void* user_data) {
 
 void AppCoreBase::Impl::LowMemoryCb(keynode_t* key, void* user_data) {
   int val = vconf_keynode_get_int(key);
-  if (val >= VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING) {
-    AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
-    base->impl_->InvokeCallback(val, IEvent::Type::LOW_MEMORY);
+  AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
+  base->impl_->InvokeCallback(val, IEvent::Type::LOW_MEMORY);
+  if (val >= VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING)
     malloc_trim(0);
-  }
 }
 
 void AppCoreBase::Impl::ChargerStatusChangedCb(keynode_t* keynode,
@@ -714,6 +756,21 @@ void AppCoreBase::Impl::OnLowBatteryCb(keynode_t* key, void* data) {
   }
 }
 
+void AppCoreBase::Impl::OnTimeZoneChangedCb(keynode_t* key, void* data) {
+  char* time_zone_id = vconf_keynode_get_str(key);
+  if (time_zone_id == nullptr) {
+    return;
+  }
+
+  char* time_zone = vconf_get_str(VCONFKEY_SETAPPL_TIMEZONE_INT);
+  if (time_zone != nullptr) {
+    AppCoreBase* base = reinterpret_cast<AppCoreBase*>(data);
+    base->impl_->InvokeCallback(std::string(time_zone) + "|" + time_zone_id,
+        IEvent::Type::TIME_ZONE_CHANGED);
+    free(time_zone);
+  }
+}
+
 void AppCoreBase::Impl::UnregisterRotationChangedEvent() {
   if (!__rotation.ref)
     return;
@@ -755,6 +812,10 @@ int AppCoreBase::OnSetEvent(IEvent::Type event) {
     break;
   case IEvent::Type::SUSPENDED_STATE_CHANGE:
     break;
+  case IEvent::Type::TIME_ZONE_CHANGED:
+    vconf_notify_key_changed(VCONFKEY_SETAPPL_TIMEZONE_ID,
+        impl_->OnTimeZoneChangedCb, this);
+    break;
   default:
     break;
   }
@@ -871,8 +932,10 @@ std::list<std::string> AppCoreBase::Impl::SplitLanguage(
   return li;
 }
 
-void AppCoreBase::Impl::AppendDefaultLangs(std::set<std::string>& lang_set) {
-  lang_set.insert({"en_US", "en_GB", "en"});
+void AppCoreBase::Impl::AppendDefaultLangs(std::vector<std::string>& langs) {
+  langs.push_back("en_US");
+  langs.push_back("en_GB");
+  langs.push_back("en");
 }
 
 std::string AppCoreBase::Impl::GetStringBefore(const char* cstr,
@@ -920,17 +983,17 @@ std::map<std::string, std::set<std::string>> AppCoreBase::Impl::GetLangTable() {
 }
 
 void AppCoreBase::Impl::AppendLangs(const std::string& lang,
-    std::set<std::string>& lang_set,
+    std::vector<std::string>& langs,
     std::map<std::string, std::set<std::string>>& table) {
   if (lang.empty())
     return;
 
-  lang_set.insert(lang);
+  langs.push_back(lang);
   std::string extract_lang = GetStringBefore(lang.c_str(), ".");
   if (extract_lang.empty())
     return;
 
-  if (lang_set.find(extract_lang) != lang_set.end())
+  if (std::find(langs.begin(), langs.end(), extract_lang) != langs.end())
     return;
 
   std::string parent_lang = GetStringBefore(extract_lang.c_str(), "_");
@@ -942,21 +1005,30 @@ void AppCoreBase::Impl::AppendLangs(const std::string& lang,
 
   auto it = table[parent_lang].find(extract_lang);
   if (it != table[parent_lang].end()) {
-    lang_set.insert(move(*it));
+    std::string value = *it;
+    if (std::find(langs.begin(), langs.end(), value) == langs.end())
+      langs.push_back(std::move(value));
+
     table[parent_lang].erase(it);
     return;
   }
 
   it = table[parent_lang].find(parent_lang);
   if (it != table[parent_lang].end()) {
-    lang_set.insert(move(*it));
+    std::string value = *it;
+    if (std::find(langs.begin(), langs.end(), value) == langs.end())
+      langs.push_back(std::move(value));
+
     table[parent_lang].erase(parent_lang);
     return;
   }
 
   if (!table[parent_lang].empty()) {
     auto i = table[parent_lang].begin();
-    lang_set.insert(move(*i));
+    std::string value = *i;
+    if (std::find(langs.begin(), langs.end(), value) == langs.end())
+      langs.push_back(std::move(value));
+
     table[parent_lang].erase(i);
   }
 }
@@ -970,17 +1042,17 @@ std::string AppCoreBase::Impl::GetLanguage(std::string lang) {
   if (table.empty())
     return "";
 
-  std::set<std::string> lang_set {};
+  std::vector<std::string> langs;
   for (auto& i : l)
-    AppendLangs(i, lang_set, table);
+    AppendLangs(i, langs, table);
 
-  AppendDefaultLangs(lang_set);
+  AppendDefaultLangs(langs);
   std::string ret;
-  for (auto& i : lang_set) {
+  for (auto& i : langs) {
     if (ret.empty())
       ret = i;
     else
-      ret = i + ":" + ret;
+      ret += ":" + i;
   }
 
   return ret;
@@ -1138,16 +1210,37 @@ void AppCoreBase::Run(int argc, char** argv) {
 }
 
 void AppCoreBase::Init(int argc, char** argv) {
+  LogTracer tracer("AppCoreBase::Init()");
   impl_->tid_ = 0;
   impl_->suspended_state_ = false;
   impl_->allowed_bg_ = false;
   impl_->argc_ = argc;
   impl_->argv_ = argv;
   traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:OPS_INIT");
+  sigterm_handler.Restore();
   if (impl_->loop_delegator_)
     impl_->loop_delegator_->OnLoopInit(argc, argv);
   else
     OnLoopInit(argc, argv);
+
+  impl_->signal_handler_source_ = g_unix_signal_add(SIGTERM,
+      [](gpointer data) -> gboolean {
+        _W("sigterm handler");
+        if (context_ != nullptr) {
+          context_->Exit();
+          context_->impl_->signal_handler_source_ = 0;
+        }
+
+        return G_SOURCE_REMOVE;
+      }, nullptr);
+
+  if (impl_->signal_handler_source_ == 0)
+    _E("Failed to add sigterm handler.");
+
+  traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
+
+  traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:PLUGIN_INIT");
+  impl_->PluginInit(argc, argv);
   traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
 
   if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT)
@@ -1200,6 +1293,12 @@ void AppCoreBase::Init(int argc, char** argv) {
 }
 
 void AppCoreBase::Fini() {
+  LogTracer tracer("AppCoreBase::Fini()");
+  if (impl_->signal_handler_source_) {
+    g_source_remove(impl_->signal_handler_source_);
+    impl_->signal_handler_source_ = 0;
+  }
+
   Dispose();
 }
 
@@ -1229,6 +1328,7 @@ void AppCoreBase::Dispose() {
   }
 
   RemoveSuspendTimer();
+  impl_->PluginFini();
   impl_->dirty_ = false;
   if (impl_->loop_delegator_)
     impl_->loop_delegator_->OnLoopFinish();
@@ -1244,4 +1344,19 @@ int AppCoreBase::GetFeature() const {
   return impl_->feature_;
 }
 
+void AppCoreBase::Impl::PluginInit(int argc, char** argv) {
+  plugin_.reset(AppCorePlugin::Load());
+  if (!plugin_)
+    return;
+
+  plugin_->Init(argc, argv);
+}
+
+void AppCoreBase::Impl::PluginFini() {
+  if (!plugin_)
+    return;
+
+  plugin_->Fini();
+}
+
 }  // namespace tizen_cpp