2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "app-core-cpp/app_core_base.hh"
20 #include <aul_app_lifecycle.h>
21 #include <aul_watchdog.h>
22 #include <bundle_internal.h>
27 #include <glib-unix.h>
30 #include <linux/limits.h>
33 #include <sensor_internal.h>
38 #include <sys/types.h>
39 #include <system_info.h>
54 #include "app-core-cpp/app_core_plugin_private.hh"
55 #include "app-core-cpp/sigterm_handler_private.hh"
56 #include "common/glib_private.hh"
57 #include "common/log_private.hh"
59 #define SIGRTANR (SIGRTMIN + 3)
61 #define _ERR(fmt, ...) fprintf(stderr, fmt "\n", ##__VA_ARGS__)
63 extern "C" void aul_finalize();
66 AppCoreBase* AppCoreBase::context_ = nullptr;
70 constexpr const int BACKTRACE_BUFFER_SIZE = 128;
72 void PrintBacktrace() {
73 char* buffer[BACKTRACE_BUFFER_SIZE];
74 int nptrs = backtrace(reinterpret_cast<void**>(buffer),
75 BACKTRACE_BUFFER_SIZE);
76 _ERR("backtrace() returned %d addresses", nptrs);
78 backtrace_symbols_fd(reinterpret_cast<void**>(buffer), nptrs, STDERR_FILENO);
84 on_exit(OnExit, this);
88 static void OnExit(int status, void *user_data) {
94 _ERR("%s(%d) abort()", __FUNCTION__, __LINE__);
99 ExitHandler exit_handler;
104 struct sigaction action;
105 memset(&action, '\0', sizeof(action));
106 sigemptyset(&action.sa_mask);
107 action.sa_flags = SA_RESTART;
108 action.sa_handler = SignalHandler;
110 if (sigaction(SIGRTANR, &action, &old_action_) != 0)
111 _E("sigaction() is failed. errno(%d)", errno);
115 if (sigaction(SIGRTANR, &old_action_, nullptr) != 0)
116 _W("sigaction() is failed. errno(%d)", errno);
120 static void SignalHandler(int signo) {
121 static unsigned int count;
122 _ERR("===================================================================");
123 _ERR("=================== Application Not Responding ====================");
125 _ERR("============== Application did not respond %d times ===============",
127 _ERR("===================================================================");
131 struct sigaction old_action_;
134 AnrMonitor anr_monitor;
135 internal::SigtermHandler sigterm_handler;
146 TizenProfile TizenProfileGet() {
147 static TizenProfile profile = TizenProfile::Unknown;
148 if (__builtin_expect(profile != TizenProfile::Unknown, 1))
151 char* profile_name = nullptr;
152 system_info_get_platform_string("http://tizen.org/feature/profile",
154 if (profile_name == nullptr)
157 switch (*profile_name) {
160 profile = TizenProfile::Mobile;
164 profile = TizenProfile::Wearable;
168 profile = TizenProfile::Tv;
172 profile = TizenProfile::Ivi;
175 profile = TizenProfile::Common;
183 constexpr const char PATH_LOCALE[] = "locale";
184 constexpr int SQLITE_FLUSH_MAX = 1024 * 1024;
185 constexpr const char RESOURCED_FREEZER_PATH[] =
186 "/Org/Tizen/ResourceD/Freezer";
187 constexpr const char RESOURCED_FREEZER_INTERFACE[] =
188 "org.tizen.resourced.freezer";
189 constexpr const char RESOURCED_FREEZER_SIGNAL[] =
196 tizen_cpp::AppCoreBase::RotationState rm;
202 GDBusConnection* __bus;
203 guint __suspend_dbus_handler_initialized;
204 AppCoreBase::DisplayState __display_state = AppCoreBase::DISPLAY_STATE_UNKNOWN;
208 class AppCoreBase::EventBase::Impl {
210 friend class AppCoreBase;
211 Type type_ = IEvent::Type::START;
212 std::string str_val_;
216 class AppCoreBase::Impl {
218 explicit Impl(AppCoreBase* parent) : parent_(parent) {
219 if (TizenProfileGet() & TizenProfile::Wearable)
220 feature_ |= FEATURE_CHARGER_STATUS;
221 if (!(TizenProfileGet() & TizenProfile::Tv))
222 feature_ |= FEATURE_BACKGROUND_MANAGEMENT;
226 void UnregisterRotationChangedEvent();
227 void RegisterRotationChangedEvent();
228 std::string GetAppName(const char* appid);
229 std::string GetLocaleResourceDir();
232 std::list<std::string> SplitLanguage(const std::string& lang);
233 std::string GetLanguage(std::string lang);
234 void AppendDefaultLangs(std::vector<std::string>& lang_set);
235 std::string GetStringBefore(const char* str, const char* delim);
236 std::map<std::string, std::set<std::string>> GetLangTable();
237 void AppendLangs(const std::string& lang, std::vector<std::string>& lang_set,
238 std::map<std::string, std::set<std::string>>& table);
240 void OnFreezerSignal();
243 void InvokeCallback(T event, IEvent::Type type) {
244 for (auto& i : events_) {
245 if (i->GetType() != type)
248 if (i->GetVal(event) != event ||
249 type == IEvent::Type::START ||
250 type == IEvent::Type::UPDATE_REQUESTED) {
257 static void InitSuspendDbusHandler(gpointer data);
258 static gboolean InitSuspendCb(gpointer data);
259 static gboolean InvokeLangChangeCb(gpointer data);
260 static void ReceiveSuspendSignalCb(GDBusConnection*, const gchar*,
261 const gchar*, const gchar*, const gchar*, GVariant*, gpointer);
262 static void OnLowBatteryCb(keynode_t* key, void* data);
263 static void LockCb(keynode_t* node, void* user_data);
264 static void AutoRotationChangedCb(sensor_t sensor, unsigned int event_type,
265 sensor_data_t* data, void* user_data);
266 static void ChargerStatusChangedCb(keynode_t* keynode, void* user_data);
267 static void LanguageChangeCb(keynode_t* key, void* data);
268 static void RegionChangeCb(keynode_t* key, void* data);
269 static void LowMemoryCb(keynode_t* key, void* data);
272 RotationState GetRm(sensor_data_t data);
273 void VerifyLanguage();
274 void SetDefaultEvents();
275 void UnsetDefaultEvents();
276 void PluginInit(int argc, char** argv);
280 friend class AppCoreBase;
281 AppCoreBase* parent_ = nullptr;
284 char** argv_ = nullptr;
285 bool suspended_state_ = false;
286 bool allowed_bg_ = false;
288 unsigned int tid_ = 0;
289 std::list<std::shared_ptr<EventBase>> events_;
290 std::string locale_dir_;
293 IAppCore* core_delegator_ = nullptr;
294 IMainLoop* loop_delegator_ = nullptr;
295 guint signal_handler_source_ = 0;
296 std::unique_ptr<AppCorePlugin> plugin_;
299 AppCoreBase::EventBase::EventBase(Type type)
300 : impl_(std::make_unique<EventBase::Impl>()) {
304 AppCoreBase::EventBase::~EventBase() = default;
306 IAppCore::IEvent::Type AppCoreBase::EventBase::GetType() const {
310 std::string AppCoreBase::EventBase::GetVal(std::string cur) const {
311 return impl_->str_val_;
314 int AppCoreBase::EventBase::GetVal(int cur) const {
318 void AppCoreBase::EventBase::SetVal(std::string val) {
319 impl_->str_val_ = std::move(val);
322 void AppCoreBase::EventBase::SetVal(int val) {
323 impl_->val_ = std::move(val);
326 AppCoreBase::AppCoreBase()
327 : impl_(std::make_unique<AppCoreBase::Impl>(this)) {
328 if (context_ != nullptr) {
329 _E("Context is already initialized");
335 AppCoreBase::~AppCoreBase() {
340 AppCoreBase* AppCoreBase::GetContext() {
341 if (context_ == nullptr) {
342 _E("Context is not initialized.");
349 void AppCoreBase::Impl::ChangeLang() {
350 const char* lang = getenv("LANG");
354 InvokeCallback(lang, IEvent::Type::LANG_CHANGE);
357 void AppCoreBase::RaiseEvent(int event, IEvent::Type type) {
358 impl_->InvokeCallback(event, type);
361 void AppCoreBase::RaiseEvent(const std::string& event, IEvent::Type type) {
362 impl_->InvokeCallback(event, type);
365 void AppCoreBase::Impl::OnFreezerSignal() {
366 if (!allowed_bg_ && suspended_state_) {
367 parent_->RemoveSuspendTimer();
368 InvokeCallback(SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND,
369 IEvent::Type::SUSPENDED_STATE_CHANGE);
370 suspended_state_ = false;
371 parent_->AddSuspendTimer();
375 AppCoreBase::RotationState AppCoreBase::Impl::GetRm(sensor_data_t data) {
376 if (data.value_count <= 0) {
377 _E("Failed to get sensor data");
378 return ROTATION_UNKNOWN;
381 int event = data.values[0];
383 case AUTO_ROTATION_DEGREE_0:
384 return ROTATION_PORTRAIT_NORMAL;
385 case AUTO_ROTATION_DEGREE_90:
386 return ROTATION_LANDSCAPE_NORMAL;
387 case AUTO_ROTATION_DEGREE_180:
388 return ROTATION_PORTRAIT_REVERSE;
389 case AUTO_ROTATION_DEGREE_270:
390 return ROTATION_LANDSCAPE_REVERSE;
392 return ROTATION_UNKNOWN;
396 void AppCoreBase::Impl::InitSuspendDbusHandler(gpointer data) {
397 if (__suspend_dbus_handler_initialized)
400 if (__bus == nullptr) {
401 GError* err = nullptr;
402 __bus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &err);
403 if (__bus == nullptr) {
404 _E("Failed to connect to the D-BUS daemon: %s", err ? err->message : "");
412 __suspend_dbus_handler_initialized = g_dbus_connection_signal_subscribe(
413 __bus, nullptr, RESOURCED_FREEZER_INTERFACE, RESOURCED_FREEZER_SIGNAL,
414 RESOURCED_FREEZER_PATH, nullptr, G_DBUS_SIGNAL_FLAGS_NONE,
415 ReceiveSuspendSignalCb, data, nullptr);
417 if (__suspend_dbus_handler_initialized == 0) {
418 _E("g_dbus_connection_signal_subscribe() is failed.");
422 _D("[__SUSPEND__] suspend signal initialized");
425 gboolean AppCoreBase::Impl::InitSuspendCb(gpointer data) {
426 InitSuspendDbusHandler(data);
427 return G_SOURCE_REMOVE;
430 gboolean AppCoreBase::Impl::InvokeLangChangeCb(gpointer data) {
431 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(data);
432 base->impl_->sid_ = 0;
433 base->impl_->ChangeLang();
434 return G_SOURCE_REMOVE;
437 void AppCoreBase::Impl::ReceiveSuspendSignalCb(GDBusConnection*, const gchar*,
438 const gchar*, const gchar*, const gchar* signal_name, GVariant* parameters,
439 gpointer user_data) {
440 if (g_strcmp0(signal_name, RESOURCED_FREEZER_SIGNAL) == 0) {
443 g_variant_get(parameters, "(ii)", &status, &pid);
444 if (pid == getpid() && status == 0) {
445 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
446 base->impl_->OnFreezerSignal();
451 void AppCoreBase::Impl::LanguageChangeCb(keynode_t* key, void* user_data) {
452 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
453 if (base->impl_->sid_) {
454 GLib::SourceRemove(base->impl_->sid_);
455 base->impl_->sid_ = 0;
458 char* val = vconf_keynode_get_str(key);
462 base->impl_->UpdateLang();
463 base->impl_->InvokeCallback(val, IEvent::Type::LANG_CHANGE);
466 void AppCoreBase::Impl::RegionChangeCb(keynode_t* key, void* user_data) {
467 const char* name = vconf_keynode_get_name(key);
471 if (strcmp(name, VCONFKEY_REGIONFORMAT) &&
472 strcmp(name, VCONFKEY_REGIONFORMAT_TIME1224))
475 char* val = vconf_get_str(VCONFKEY_REGIONFORMAT);
478 std::unique_ptr<char, decltype(std::free)*> region_auto(val, std::free);
480 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
481 base->impl_->UpdateRegion();
482 base->impl_->InvokeCallback(val, IEvent::Type::REGION_CHANGE);
485 void AppCoreBase::Impl::LowMemoryCb(keynode_t* key, void* user_data) {
486 int val = vconf_keynode_get_int(key);
487 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
488 base->impl_->InvokeCallback(val, IEvent::Type::LOW_MEMORY);
489 if (val >= VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING)
493 void AppCoreBase::Impl::ChargerStatusChangedCb(keynode_t* keynode,
495 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
496 if (base->impl_->feature_ & FEATURE_CHARGER_STATUS) {
497 __rotation.charger_status = vconf_keynode_get_int(keynode);
498 if (__rotation.ref) {
499 if (__rotation.charger_status) {
500 base->impl_->InitRotation();
502 base->impl_->FiniRotation();
506 _D("charger status(%d)", __rotation.charger_status);
510 void AppCoreBase::Impl::LockCb(keynode_t* node, void* user_data) {
511 AppCoreBase::RotationState rm;
512 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
514 __rotation.lock = !vconf_keynode_get_bool(node);
515 if (__rotation.lock) {
516 _D("Rotation locked");
517 rm = ROTATION_PORTRAIT_NORMAL;
519 _D("Rotation unlocked");
521 bool r = sensord_get_data(__rotation.conn, AUTO_ROTATION_SENSOR, &data);
523 _E("Failed to get sensor data");
527 rm = base->impl_->GetRm(data);
528 if (rm == ROTATION_UNKNOWN) {
534 if (__rotation.rm == rm)
537 _D("Rotation: %d -> %d", __rotation.rm, rm);
539 base->impl_->InvokeCallback(__rotation.rm,
540 IEvent::Type::DEVICE_ORIENTATION_CHANGED);
543 void AppCoreBase::Impl::AutoRotationChangedCb(sensor_t sensor,
544 unsigned int event_type, sensor_data_t* data, void* user_data) {
551 if (event_type != AUTO_ROTATION_CHANGE_STATE_EVENT)
554 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
555 AppCoreBase::RotationState rm = base->impl_->GetRm(*data);
556 if (rm == ROTATION_UNKNOWN) {
561 _D("Rotation: %d -> %d", __rotation.rm, rm);
563 base->impl_->InvokeCallback(__rotation.rm,
564 IEvent::Type::DEVICE_ORIENTATION_CHANGED);
567 void AppCoreBase::Impl::InitRotation() {
568 if (__rotation.initialized)
571 sensor_t sensor = sensord_get_sensor(AUTO_ROTATION_SENSOR);
572 __rotation.conn = sensord_connect(sensor);
573 if (__rotation.conn < 0) {
574 _E("Failed to connect sensord");
578 bool r = sensord_register_event(__rotation.conn,
579 AUTO_ROTATION_CHANGE_STATE_EVENT, SENSOR_INTERVAL_NORMAL, 0,
580 AutoRotationChangedCb, parent_);
582 _E("Failed to register auto rotation change event");
583 sensord_disconnect(__rotation.conn);
587 r = sensord_start(__rotation.conn, 0);
589 _E("Failed to start sensord");
590 sensord_unregister_event(__rotation.conn, AUTO_ROTATION_CHANGE_STATE_EVENT);
591 sensord_disconnect(__rotation.conn);
596 vconf_get_bool(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, &lock);
597 vconf_notify_key_changed(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, LockCb,
600 __rotation.lock = !lock;
601 __rotation.initialized = true;
604 void AppCoreBase::Impl::FiniRotation() {
605 if (!__rotation.initialized)
608 vconf_ignore_key_changed(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, LockCb);
609 sensord_unregister_event(__rotation.conn, AUTO_ROTATION_CHANGE_STATE_EVENT);
610 sensord_stop(__rotation.conn);
611 sensord_disconnect(__rotation.conn);
614 __rotation.initialized = false;
617 void AppCoreBase::Impl::VerifyLanguage() {
618 const char* env_lang = getenv("LANG");
619 if (env_lang == nullptr)
622 char* lang = vconf_get_str(VCONFKEY_LANGSET);
626 std::unique_ptr<char, decltype(std::free)*> lang_auto(lang, std::free);
628 if (strcmp(env_lang, lang) != 0) {
629 _I("LANG(%s), LANGSET(%s)", env_lang, lang);
630 sid_ = GLib::IdleAdd(InvokeLangChangeCb, parent_);
634 void AppCoreBase::Impl::SetDefaultEvents() {
635 vconf_notify_key_changed(VCONFKEY_LANGSET, LanguageChangeCb, parent_);
636 int r = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT, RegionChangeCb,
639 vconf_notify_key_changed(VCONFKEY_REGIONFORMAT_TIME1224, RegionChangeCb,
643 vconf_notify_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY, LowMemoryCb, parent_);
646 void AppCoreBase::Impl::UnsetDefaultEvents() {
647 vconf_ignore_key_changed(VCONFKEY_LANGSET, LanguageChangeCb);
648 int r = vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT, RegionChangeCb);
650 vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT_TIME1224, RegionChangeCb);
652 vconf_ignore_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY, LowMemoryCb);
655 int AppCoreBase::OnReceive(aul_type type, tizen_base::Bundle b) {
658 _D("[APP %d] AUL event: AUL_START", getpid());
659 if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT) {
660 std::string bg = b.GetString(AUL_K_ALLOWED_BG);
661 if (bg == "ALLOWED_BG") {
662 _D("[__SUSPEND__] allowed background");
663 impl_->allowed_bg_ = true;
664 RemoveSuspendTimer();
668 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:RESET");
669 if (impl_->core_delegator_)
670 impl_->core_delegator_->OnControl(std::move(b));
672 OnControl(std::move(b));
673 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
676 _D("[APP %d] AUL event: AUL_RESUME", getpid());
677 if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT) {
678 std::string bg = b.GetString(AUL_K_ALLOWED_BG);
679 if (bg == "ALLOWED_BG") {
680 _D("[__SUSPEND__] allowed background");
681 impl_->allowed_bg_ = true;
682 RemoveSuspendTimer();
687 _D("[APP %d] AUL event: AUL_TERMINATE", getpid());
688 aul_status_update(STATUS_DYING);
689 if (!impl_->allowed_bg_)
690 RemoveSuspendTimer();
694 case AUL_TERMINATE_INST:
695 case AUL_TERMINATE_BG_INST:
696 case AUL_TERMINATE_BGAPP:
697 _D("[APP %d] AUL event: %d", getpid(), type);
698 if (!impl_->allowed_bg_)
699 RemoveSuspendTimer();
702 _D("[APP %d] AUL event: AUL_WAKE", getpid());
703 if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT) {
704 if (!impl_->allowed_bg_ && impl_->suspended_state_) {
705 RemoveSuspendTimer();
706 int suspend = SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND;
707 impl_->InvokeCallback(suspend, IEvent::Type::SUSPENDED_STATE_CHANGE);
708 impl_->suspended_state_ = false;
713 _D("[APP %d] AUL event: AUL_SUSPEND", getpid());
714 if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT) {
715 if (!impl_->allowed_bg_ && !impl_->suspended_state_) {
716 RemoveSuspendTimer();
721 case AUL_UPDATE_REQUESTED:
722 _D("[APP %d] AUL event: AUL_UPDATE_REQUESTED", getpid());
723 impl_->InvokeCallback(0, IEvent::Type::UPDATE_REQUESTED);
726 _D("[APP %d] AUL event: %d", getpid(), type);
734 int AppCoreBase::OnCreate() {
735 int ret = aul_launch_init([](aul_type type, bundle* b, void* data) -> int {
736 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(data);
737 if (base->impl_->core_delegator_) {
738 return base->impl_->core_delegator_->OnReceive(type,
739 b ? tizen_base::Bundle(b, false, false) : tizen_base::Bundle());
741 return base->OnReceive(type,
742 b ? tizen_base::Bundle(b, false, false) : tizen_base::Bundle());
744 if (ret < 0 && ret != AUL_R_ECANCELED) {
745 _E("aul_launch_init() is failed. error(%d)", ret);
749 ret = aul_launch_argv_handler(impl_->argc_, impl_->argv_);
751 _E("aul_launch_argv_handler() is failed. error(%d)", ret);
758 int AppCoreBase::OnControl(tizen_base::Bundle b) {
762 int AppCoreBase::OnTerminate() {
767 void AppCoreBase::SetCoreDelegator(IAppCore* delegator) {
768 impl_->core_delegator_ = delegator;
771 void AppCoreBase::SetLoopDelegator(IMainLoop* delegator) {
772 impl_->loop_delegator_ = delegator;
775 std::string AppCoreBase::Impl::GetAppName(const char* appid) {
776 if (appid == nullptr)
779 /* com.vendor.name -> name */
780 const char* name_token = strrchr(appid, '.');
781 if (name_token == nullptr)
788 std::string AppCoreBase::Impl::GetLocaleResourceDir() {
789 const char* res_path = aul_get_app_resource_path();
790 if (res_path == nullptr) {
791 _E("Failed to get resource path");
795 return std::string(res_path) + PATH_LOCALE;
798 int AppCoreBase::OnSetI18n() {
799 char appid[PATH_MAX];
800 int ret = aul_app_get_appid_bypid(getpid(), appid, PATH_MAX);
802 _E("aul_app_get_appid_bypid() is failed. error(%d)", ret);
806 std::string name = impl_->GetAppName(appid);
810 std::string locale_dir = impl_->GetLocaleResourceDir();
811 if (locale_dir.empty())
814 return SetI18n(move(name), move(locale_dir));
817 void AppCoreBase::Impl::OnLowBatteryCb(keynode_t* key, void* data) {
818 int val = vconf_keynode_get_int(key);
819 if (val <= VCONFKEY_SYSMAN_BAT_CRITICAL_LOW) {
820 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(data);
821 base->impl_->InvokeCallback(val, IEvent::Type::LOW_BATTERY);
825 void AppCoreBase::Impl::UnregisterRotationChangedEvent() {
830 if (__rotation.ref == 0) {
832 if (feature_ & FEATURE_CHARGER_STATUS) {
833 vconf_ignore_key_changed(VCONFKEY_SYSMAN_CHARGER_STATUS,
834 ChargerStatusChangedCb);
839 void AppCoreBase::Impl::RegisterRotationChangedEvent() {
840 if (__rotation.ref == 0) {
841 if (feature_ & FEATURE_CHARGER_STATUS) {
842 vconf_get_int(VCONFKEY_SYSMAN_CHARGER_STATUS, &__rotation.charger_status);
843 vconf_notify_key_changed(VCONFKEY_SYSMAN_CHARGER_STATUS,
844 ChargerStatusChangedCb, parent_);
845 if (__rotation.charger_status)
855 int AppCoreBase::OnSetEvent(IEvent::Type event) {
857 case IEvent::Type::LOW_BATTERY:
858 vconf_notify_key_changed(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW,
859 impl_->OnLowBatteryCb, this);
861 case IEvent::Type::DEVICE_ORIENTATION_CHANGED:
862 impl_->RegisterRotationChangedEvent();
864 case IEvent::Type::SUSPENDED_STATE_CHANGE:
873 int AppCoreBase::OnUnsetEvent(IEvent::Type event) {
875 case IEvent::Type::LOW_BATTERY:
876 vconf_ignore_key_changed(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW,
877 impl_->OnLowBatteryCb);
879 case IEvent::Type::DEVICE_ORIENTATION_CHANGED:
880 impl_->UnregisterRotationChangedEvent();
882 case IEvent::Type::SUSPENDED_STATE_CHANGE:
891 int AppCoreBase::OnTrimMemory() {
892 int (*sqlite3_free_heap_memory)(int);
894 sqlite3_free_heap_memory = reinterpret_cast<
895 decltype(sqlite3_free_heap_memory)>(
896 dlsym(RTLD_DEFAULT, "sqlite3_release_memory"));
897 if (sqlite3_free_heap_memory)
898 sqlite3_free_heap_memory(SQLITE_FLUSH_MAX);
904 void AppCoreBase::AddEvent(std::shared_ptr<EventBase> event) {
906 for (auto& ev : impl_->events_) {
907 if (ev->GetType() == event->GetType()) {
914 if (impl_->core_delegator_)
915 impl_->core_delegator_->OnSetEvent(event->GetType());
917 OnSetEvent(event->GetType());
920 impl_->events_.push_back(move(event));
923 bool AppCoreBase::RemoveEvent(std::shared_ptr<EventBase> event) {
925 impl_->events_.remove_if([&](const std::shared_ptr<EventBase>& ptr)->bool {
926 if (event.get() == ptr.get()) {
936 void AppCoreBase::FlushMemory() {
937 if (impl_->core_delegator_)
938 impl_->core_delegator_->OnTrimMemory();
943 if (!impl_->allowed_bg_ && !impl_->suspended_state_) {
944 _D("[__SUSPEND__] flush case");
945 int suspend = SUSPENDED_STATE_WILL_ENTER_SUSPEND;
946 impl_->InvokeCallback(suspend, IEvent::Type::SUSPENDED_STATE_CHANGE);
947 impl_->suspended_state_ = true;
951 AppCoreBase::RotationState AppCoreBase::GetRotationState() {
953 throw std::runtime_error("invalid rotation state");
955 return __rotation.rm;
958 bool AppCoreBase::IsBgAllowed() {
959 return impl_->allowed_bg_;
962 bool AppCoreBase::IsSuspended() {
963 return impl_->suspended_state_;
966 void AppCoreBase::ToggleSuspendedState() {
967 impl_->suspended_state_ = !impl_->suspended_state_;
970 std::list<std::string> AppCoreBase::Impl::SplitLanguage(
971 const std::string& lang) {
972 std::istringstream ss(lang);
973 std::list<std::string> li;
976 while (std::getline(ss, token, ':'))
982 void AppCoreBase::Impl::AppendDefaultLangs(std::vector<std::string>& langs) {
983 langs.push_back("en_US");
984 langs.push_back("en_GB");
985 langs.push_back("en");
988 std::string AppCoreBase::Impl::GetStringBefore(const char* cstr,
990 if (cstr == nullptr || delim == nullptr)
993 auto str = std::string(cstr);
994 auto idx = str.find(delim);
995 return str.substr(0, idx);
998 std::map<std::string, std::set<std::string>> AppCoreBase::Impl::GetLangTable() {
999 if (locale_dir_.empty())
1002 DIR* dp = opendir(locale_dir_.c_str());
1006 std::map<std::string, std::set<std::string>> table;
1007 struct dirent *dentry;
1008 while ((dentry = readdir(dp)) != nullptr) {
1009 if (!strcmp(dentry->d_name, ".") ||
1010 !strcmp(dentry->d_name, ".."))
1013 std::string buf = locale_dir_ + "/" + dentry->d_name;
1014 struct stat stat_buf;
1015 int ret = stat(buf.c_str(), &stat_buf);
1016 if (ret != 0 || !S_ISDIR(stat_buf.st_mode))
1019 std::string parent_lang = GetStringBefore(dentry->d_name, "_");
1020 if (parent_lang.empty()) {
1021 _E("Out of memory");
1025 table[parent_lang].insert(dentry->d_name);
1032 void AppCoreBase::Impl::AppendLangs(const std::string& lang,
1033 std::vector<std::string>& langs,
1034 std::map<std::string, std::set<std::string>>& table) {
1038 langs.push_back(lang);
1039 std::string extract_lang = GetStringBefore(lang.c_str(), ".");
1040 if (extract_lang.empty())
1043 if (std::find(langs.begin(), langs.end(), extract_lang) != langs.end())
1046 std::string parent_lang = GetStringBefore(extract_lang.c_str(), "_");
1047 if (parent_lang.empty())
1050 if (table.find(parent_lang) == table.end())
1053 auto it = table[parent_lang].find(extract_lang);
1054 if (it != table[parent_lang].end()) {
1055 std::string value = *it;
1056 if (std::find(langs.begin(), langs.end(), value) == langs.end())
1057 langs.push_back(std::move(value));
1059 table[parent_lang].erase(it);
1063 it = table[parent_lang].find(parent_lang);
1064 if (it != table[parent_lang].end()) {
1065 std::string value = *it;
1066 if (std::find(langs.begin(), langs.end(), value) == langs.end())
1067 langs.push_back(std::move(value));
1069 table[parent_lang].erase(parent_lang);
1073 if (!table[parent_lang].empty()) {
1074 auto i = table[parent_lang].begin();
1075 std::string value = *i;
1076 if (std::find(langs.begin(), langs.end(), value) == langs.end())
1077 langs.push_back(std::move(value));
1079 table[parent_lang].erase(i);
1083 std::string AppCoreBase::Impl::GetLanguage(std::string lang) {
1084 std::list<std::string> l = SplitLanguage(lang);
1088 auto table = GetLangTable();
1092 std::vector<std::string> langs;
1094 AppendLangs(i, langs, table);
1096 AppendDefaultLangs(langs);
1098 for (auto& i : langs) {
1108 void AppCoreBase::Impl::UpdateLang() {
1109 char* lang = vconf_get_str(VCONFKEY_LANGSET);
1110 if (lang == nullptr)
1113 std::unique_ptr<char, decltype(std::free)*> lang_auto(lang, std::free);
1114 std::string language = GetLanguage(lang);
1115 if (!language.empty()) {
1116 _D("*****language(%s)", language.c_str());
1117 setenv("LANGUAGE", language.c_str(), 1);
1119 setenv("LANGUAGE", lang, 1);
1121 setenv("LANG", lang, 1);
1122 setenv("LC_MESSAGES", lang, 1);
1123 setenv("LC_ALL", lang, 1);
1124 char* r = setlocale(LC_ALL, "");
1126 r = setlocale(LC_ALL, "en_US.UTF-8");
1128 _D("*****appcore setlocale=%s\n", r);
1130 _D("*****appcore setlocale=\"C\"");
1131 setenv("LC_ALL", "C", 1);
1132 r = setlocale(LC_ALL, "");
1134 _E("failed to setlocale");
1139 void AppCoreBase::Impl::UpdateRegion() {
1140 char* region = vconf_get_str(VCONFKEY_REGIONFORMAT);
1141 if (region == nullptr)
1144 std::unique_ptr<char, decltype(std::free)*> region_auto(region, std::free);
1145 setenv("LC_CTYPE", region, 1);
1146 setenv("LC_NUMERIC", region, 1);
1147 setenv("LC_TIME", region, 1);
1148 setenv("LC_COLLATE", region, 1);
1149 setenv("LC_MONETARY", region, 1);
1150 setenv("LC_PAPER", region, 1);
1151 setenv("LC_NAME", region, 1);
1152 setenv("LC_ADDRESS", region, 1);
1153 setenv("LC_TELEPHONE", region, 1);
1154 setenv("LC_MEASUREMENT", region, 1);
1155 setenv("LC_IDENTIFICATION", region, 1);
1156 char* r = setlocale(LC_ALL, "");
1158 _D("*****appcore setlocale=%s\n", r);
1160 _D("*****appcore setlocale=\"C\"");
1161 setenv("LC_ALL", "C", 1);
1162 r = setlocale(LC_ALL, "");
1164 _E("failed to setlocale");
1168 int AppCoreBase::SetI18n(std::string domain_name, std::string dir_name) {
1169 if (domain_name.empty()) {
1174 if (!dir_name.empty())
1175 impl_->locale_dir_ = dir_name;
1177 impl_->UpdateLang();
1178 impl_->UpdateRegion();
1180 char* r = setlocale(LC_ALL, "");
1181 /* if locale is not set properly, try to set "en_US" again */
1183 r = setlocale(LC_ALL, "en_US.UTF-8");
1185 _E("appcore: setlocale() error");
1186 _D("*****appcore setlocale=\"C\"");
1187 setenv("LC_ALL", "C", 1);
1188 r = setlocale(LC_ALL, "");
1190 _E("failed to setlocale");
1195 _D("*****appcore setlocale=%s\n", r);
1197 r = bindtextdomain(domain_name.c_str(), dir_name.c_str());
1199 _E("appcore: bindtextdomain() error");
1201 r = textdomain(domain_name.c_str());
1203 _E("appcore: textdomain() error");
1208 void AppCoreBase::Exit() {
1209 aul_status_update(STATUS_DYING);
1210 if (impl_->loop_delegator_)
1211 impl_->loop_delegator_->OnLoopExit();
1216 void AppCoreBase::AddSuspendTimer() {
1217 impl_->tid_ = GLib::TimeoutAdd(5000, [](gpointer data) -> gboolean {
1218 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(data);
1219 base->FlushMemory();
1224 void AppCoreBase::RemoveSuspendTimer() {
1225 if (impl_->tid_ > 0) {
1226 GLib::SourceRemove(impl_->tid_);
1231 void AppCoreBase::SetDisplayState(DisplayState state) {
1232 __display_state = state;
1235 AppCoreBase::DisplayState AppCoreBase::GetDisplayState() {
1236 return __display_state;
1239 int AppCoreBase::EnableWatchdog() {
1240 _I("[__APPCORE_WATCHDOG__] enable");
1241 return aul_watchdog_enable();
1244 int AppCoreBase::DisableWatchdog() {
1245 _I("[__APPCORE_WATCHDOG__] disable");
1246 return aul_watchdog_disable();
1249 int AppCoreBase::KickWatchdog() {
1250 _I("[__APPCORE_WATCHDOG__] kick");
1251 return aul_watchdog_kick();
1254 void AppCoreBase::Run(int argc, char** argv) {
1259 void AppCoreBase::Init(int argc, char** argv) {
1261 impl_->suspended_state_ = false;
1262 impl_->allowed_bg_ = false;
1263 impl_->argc_ = argc;
1264 impl_->argv_ = argv;
1265 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:OPS_INIT");
1266 sigterm_handler.Restore();
1267 if (impl_->loop_delegator_)
1268 impl_->loop_delegator_->OnLoopInit(argc, argv);
1270 OnLoopInit(argc, argv);
1272 impl_->signal_handler_source_ = g_unix_signal_add(SIGTERM,
1273 [](gpointer data) -> gboolean {
1274 _W("sigterm handler");
1275 if (context_ != nullptr) {
1277 context_->impl_->signal_handler_source_ = 0;
1280 return G_SOURCE_REMOVE;
1283 if (impl_->signal_handler_source_ == 0)
1284 _E("Failed to add sigterm handler.");
1286 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1288 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:PLUGIN_INIT");
1289 impl_->PluginInit(argc, argv);
1290 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1292 if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT)
1293 GLib::IdleAdd(Impl::InitSuspendCb, this);
1295 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:SET_SYSTEM_EVENT");
1296 if (!impl_->dirty_) {
1297 impl_->dirty_ = true;
1299 for (auto& e : impl_->events_) {
1300 if (impl_->core_delegator_)
1301 impl_->core_delegator_->OnSetEvent(e->GetType());
1303 OnSetEvent(e->GetType());
1306 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1308 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:VERIFY_LANG");
1309 impl_->VerifyLanguage();
1310 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1312 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:SET_DEFAULT_EVENTS");
1313 impl_->SetDefaultEvents();
1314 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1316 if (impl_->core_delegator_)
1317 impl_->core_delegator_->OnSetI18n();
1321 aul_app_lifecycle_update_state(AUL_APP_LIFECYCLE_STATE_INITIALIZED);
1323 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:CREATE");
1325 if (impl_->core_delegator_)
1326 create = impl_->core_delegator_->OnCreate();
1328 create = OnCreate();
1329 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1331 aul_app_lifecycle_update_state(AUL_APP_LIFECYCLE_STATE_CREATED);
1335 if (impl_->loop_delegator_)
1336 impl_->loop_delegator_->OnLoopRun();
1341 void AppCoreBase::Fini() {
1342 if (impl_->signal_handler_source_) {
1343 g_source_remove(impl_->signal_handler_source_);
1344 impl_->signal_handler_source_ = 0;
1350 void AppCoreBase::Dispose() {
1351 aul_status_update(STATUS_DYING);
1353 aul_app_lifecycle_update_state(AUL_APP_LIFECYCLE_STATE_DESTROYED);
1355 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:TERMINATE");
1356 if (impl_->core_delegator_)
1357 impl_->core_delegator_->OnTerminate();
1360 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1362 for (auto& e : impl_->events_) {
1363 if (impl_->core_delegator_)
1364 impl_->core_delegator_->OnUnsetEvent(e->GetType());
1366 OnUnsetEvent(e->GetType());
1369 impl_->UnsetDefaultEvents();
1371 GLib::SourceRemove(impl_->sid_);
1375 RemoveSuspendTimer();
1376 impl_->PluginFini();
1377 impl_->dirty_ = false;
1378 if (impl_->loop_delegator_)
1379 impl_->loop_delegator_->OnLoopFinish();
1384 void AppCoreBase::SetFeature(int feature) {
1385 impl_->feature_ = feature;
1388 int AppCoreBase::GetFeature() const {
1389 return impl_->feature_;
1392 void AppCoreBase::Impl::PluginInit(int argc, char** argv) {
1393 plugin_.reset(AppCorePlugin::Load());
1397 plugin_->Init(argc, argv);
1400 void AppCoreBase::Impl::PluginFini() {
1407 } // namespace tizen_cpp