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.
18 #include <aul_app_lifecycle.h>
19 #include <aul_watchdog.h>
20 #include <bundle_internal.h>
26 #include <linux/limits.h>
29 #include <sensor_internal.h>
34 #include <sys/types.h>
35 #include <system_info.h>
50 #include "app-core-cpp/app_core_base.hh"
51 #include "common/glib_private.hh"
52 #include "common/log_private.hh"
54 extern "C" void aul_finalize();
57 AppCoreBase* AppCoreBase::context_ = nullptr;
70 TizenProfile TizenProfileGet() {
71 static TizenProfile profile = TizenProfile::Unknown;
72 if (__builtin_expect(profile != TizenProfile::Unknown, 1))
75 char* profile_name = nullptr;
76 system_info_get_platform_string("http://tizen.org/feature/profile",
78 if (profile_name == nullptr)
81 switch (*profile_name) {
84 profile = TizenProfile::Mobile;
88 profile = TizenProfile::Wearable;
92 profile = TizenProfile::Tv;
96 profile = TizenProfile::Ivi;
99 profile = TizenProfile::Common;
107 constexpr const char PATH_LOCALE[] = "locale";
108 constexpr int SQLITE_FLUSH_MAX = 1024 * 1024;
109 constexpr const char RESOURCED_FREEZER_PATH[] =
110 "/Org/Tizen/ResourceD/Freezer";
111 constexpr const char RESOURCED_FREEZER_INTERFACE[] =
112 "org.tizen.resourced.freezer";
113 constexpr const char RESOURCED_FREEZER_SIGNAL[] =
120 tizen_cpp::AppCoreBase::RotationState rm;
126 GDBusConnection* __bus;
127 guint __suspend_dbus_handler_initialized;
128 AppCoreBase::DisplayState __display_state = AppCoreBase::DISPLAY_STATE_UNKNOWN;
132 class AppCoreBase::EventBase::Impl {
134 friend class AppCoreBase;
135 Type type_ = IEvent::Type::START;
136 std::string str_val_;
140 class AppCoreBase::Impl {
142 explicit Impl(AppCoreBase* parent) : parent_(parent) {
143 if (TizenProfileGet() & TizenProfile::Wearable)
144 feature_ |= FEATURE_CHARGER_STATUS;
145 if (!(TizenProfileGet() & TizenProfile::Tv))
146 feature_ |= FEATURE_BACKGROUND_MANAGEMENT;
150 void UnregisterRotationChangedEvent();
151 void RegisterRotationChangedEvent();
152 std::string GetAppName(const char* appid);
153 std::string GetLocaleResourceDir();
156 std::list<std::string> SplitLanguage(const std::string& lang);
157 std::string GetLanguage(std::string lang);
158 void AppendDefaultLangs(std::vector<std::string>& lang_set);
159 std::string GetStringBefore(const char* str, const char* delim);
160 std::map<std::string, std::set<std::string>> GetLangTable();
161 void AppendLangs(const std::string& lang, std::vector<std::string>& lang_set,
162 std::map<std::string, std::set<std::string>>& table);
164 void OnFreezerSignal();
167 void InvokeCallback(T event, IEvent::Type type) {
168 for (auto& i : events_) {
169 if (i->GetType() != type)
172 if (i->GetVal(event) != event ||
173 type == IEvent::Type::START ||
174 type == IEvent::Type::UPDATE_REQUESTED) {
181 static void InitSuspendDbusHandler(gpointer data);
182 static gboolean InitSuspendCb(gpointer data);
183 static gboolean InvokeLangChangeCb(gpointer data);
184 static void ReceiveSuspendSignalCb(GDBusConnection*, const gchar*,
185 const gchar*, const gchar*, const gchar*, GVariant*, gpointer);
186 static void OnLowBatteryCb(keynode_t* key, void* data);
187 static void LockCb(keynode_t* node, void* user_data);
188 static void AutoRotationChangedCb(sensor_t sensor, unsigned int event_type,
189 sensor_data_t* data, void* user_data);
190 static void ChargerStatusChangedCb(keynode_t* keynode, void* user_data);
191 static void LanguageChangeCb(keynode_t* key, void* data);
192 static void RegionChangeCb(keynode_t* key, void* data);
193 static void LowMemoryCb(keynode_t* key, void* data);
196 RotationState GetRm(sensor_data_t data);
197 void VerifyLanguage();
198 void SetDefaultEvents();
199 void UnsetDefaultEvents();
202 friend class AppCoreBase;
203 AppCoreBase* parent_ = nullptr;
206 char** argv_ = nullptr;
207 bool suspended_state_ = false;
208 bool allowed_bg_ = false;
210 unsigned int tid_ = 0;
211 std::list<std::shared_ptr<EventBase>> events_;
212 std::string locale_dir_;
215 IAppCore* core_delegator_ = nullptr;
216 IMainLoop* loop_delegator_ = nullptr;
219 AppCoreBase::EventBase::EventBase(Type type)
220 : impl_(std::make_unique<EventBase::Impl>()) {
224 AppCoreBase::EventBase::~EventBase() = default;
226 IAppCore::IEvent::Type AppCoreBase::EventBase::GetType() const {
230 std::string AppCoreBase::EventBase::GetVal(std::string cur) const {
231 return impl_->str_val_;
234 int AppCoreBase::EventBase::GetVal(int cur) const {
238 void AppCoreBase::EventBase::SetVal(std::string val) {
239 impl_->str_val_ = std::move(val);
242 void AppCoreBase::EventBase::SetVal(int val) {
243 impl_->val_ = std::move(val);
246 AppCoreBase::AppCoreBase()
247 : impl_(std::make_unique<AppCoreBase::Impl>(this)) {
248 if (context_ != nullptr) {
249 _E("Context is already initialized");
255 AppCoreBase::~AppCoreBase() {
260 AppCoreBase* AppCoreBase::GetContext() {
261 if (context_ == nullptr) {
262 _E("Context is not initialized.");
269 void AppCoreBase::Impl::ChangeLang() {
270 const char* lang = getenv("LANG");
274 InvokeCallback(lang, IEvent::Type::LANG_CHANGE);
277 void AppCoreBase::RaiseEvent(int event, IEvent::Type type) {
278 impl_->InvokeCallback(event, type);
281 void AppCoreBase::RaiseEvent(const std::string& event, IEvent::Type type) {
282 impl_->InvokeCallback(event, type);
285 void AppCoreBase::Impl::OnFreezerSignal() {
286 if (!allowed_bg_ && suspended_state_) {
287 parent_->RemoveSuspendTimer();
288 InvokeCallback(SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND,
289 IEvent::Type::SUSPENDED_STATE_CHANGE);
290 suspended_state_ = false;
291 parent_->AddSuspendTimer();
295 AppCoreBase::RotationState AppCoreBase::Impl::GetRm(sensor_data_t data) {
296 if (data.value_count <= 0) {
297 _E("Failed to get sensor data");
298 return ROTATION_UNKNOWN;
301 int event = data.values[0];
303 case AUTO_ROTATION_DEGREE_0:
304 return ROTATION_PORTRAIT_NORMAL;
305 case AUTO_ROTATION_DEGREE_90:
306 return ROTATION_LANDSCAPE_NORMAL;
307 case AUTO_ROTATION_DEGREE_180:
308 return ROTATION_PORTRAIT_REVERSE;
309 case AUTO_ROTATION_DEGREE_270:
310 return ROTATION_LANDSCAPE_REVERSE;
312 return ROTATION_UNKNOWN;
316 void AppCoreBase::Impl::InitSuspendDbusHandler(gpointer data) {
317 if (__suspend_dbus_handler_initialized)
320 if (__bus == nullptr) {
321 GError* err = nullptr;
322 __bus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &err);
323 if (__bus == nullptr) {
324 _E("Failed to connect to the D-BUS daemon: %s", err->message);
330 __suspend_dbus_handler_initialized = g_dbus_connection_signal_subscribe(
331 __bus, nullptr, RESOURCED_FREEZER_INTERFACE, RESOURCED_FREEZER_SIGNAL,
332 RESOURCED_FREEZER_PATH, nullptr, G_DBUS_SIGNAL_FLAGS_NONE,
333 ReceiveSuspendSignalCb, data, nullptr);
335 if (__suspend_dbus_handler_initialized == 0) {
336 _E("g_dbus_connection_signal_subscribe() is failed.");
340 _D("[__SUSPEND__] suspend signal initialized");
343 gboolean AppCoreBase::Impl::InitSuspendCb(gpointer data) {
344 InitSuspendDbusHandler(data);
345 return G_SOURCE_REMOVE;
348 gboolean AppCoreBase::Impl::InvokeLangChangeCb(gpointer data) {
349 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(data);
350 base->impl_->sid_ = 0;
351 base->impl_->ChangeLang();
352 return G_SOURCE_REMOVE;
355 void AppCoreBase::Impl::ReceiveSuspendSignalCb(GDBusConnection*, const gchar*,
356 const gchar*, const gchar*, const gchar* signal_name, GVariant* parameters,
357 gpointer user_data) {
358 if (g_strcmp0(signal_name, RESOURCED_FREEZER_SIGNAL) == 0) {
361 g_variant_get(parameters, "(ii)", &status, &pid);
362 if (pid == getpid() && status == 0) {
363 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
364 base->impl_->OnFreezerSignal();
369 void AppCoreBase::Impl::LanguageChangeCb(keynode_t* key, void* user_data) {
370 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
371 if (base->impl_->sid_) {
372 GLib::SourceRemove(base->impl_->sid_);
373 base->impl_->sid_ = 0;
376 char* val = vconf_keynode_get_str(key);
380 base->impl_->UpdateLang();
381 base->impl_->InvokeCallback(val, IEvent::Type::LANG_CHANGE);
384 void AppCoreBase::Impl::RegionChangeCb(keynode_t* key, void* user_data) {
385 const char* name = vconf_keynode_get_name(key);
389 if (strcmp(name, VCONFKEY_REGIONFORMAT) &&
390 strcmp(name, VCONFKEY_REGIONFORMAT_TIME1224))
393 char* val = vconf_get_str(VCONFKEY_REGIONFORMAT);
396 std::unique_ptr<char, decltype(std::free)*> region_auto(val, std::free);
398 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
399 base->impl_->UpdateRegion();
400 base->impl_->InvokeCallback(val, IEvent::Type::REGION_CHANGE);
403 void AppCoreBase::Impl::LowMemoryCb(keynode_t* key, void* user_data) {
404 int val = vconf_keynode_get_int(key);
405 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
406 base->impl_->InvokeCallback(val, IEvent::Type::LOW_MEMORY);
407 if (val >= VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING)
411 void AppCoreBase::Impl::ChargerStatusChangedCb(keynode_t* keynode,
413 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
414 if (base->impl_->feature_ & FEATURE_CHARGER_STATUS) {
415 __rotation.charger_status = vconf_keynode_get_int(keynode);
416 if (__rotation.ref) {
417 if (__rotation.charger_status) {
418 base->impl_->InitRotation();
420 base->impl_->FiniRotation();
424 _D("charger status(%d)", __rotation.charger_status);
428 void AppCoreBase::Impl::LockCb(keynode_t* node, void* user_data) {
429 AppCoreBase::RotationState rm;
430 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
432 __rotation.lock = !vconf_keynode_get_bool(node);
433 if (__rotation.lock) {
434 _D("Rotation locked");
435 rm = ROTATION_PORTRAIT_NORMAL;
437 _D("Rotation unlocked");
439 bool r = sensord_get_data(__rotation.conn, AUTO_ROTATION_SENSOR, &data);
441 _E("Failed to get sensor data");
445 rm = base->impl_->GetRm(data);
446 if (rm == ROTATION_UNKNOWN) {
452 if (__rotation.rm == rm)
455 _D("Rotation: %d -> %d", __rotation.rm, rm);
457 base->impl_->InvokeCallback(__rotation.rm,
458 IEvent::Type::DEVICE_ORIENTATION_CHANGED);
461 void AppCoreBase::Impl::AutoRotationChangedCb(sensor_t sensor,
462 unsigned int event_type, sensor_data_t* data, void* user_data) {
469 if (event_type != AUTO_ROTATION_CHANGE_STATE_EVENT)
472 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
473 AppCoreBase::RotationState rm = base->impl_->GetRm(*data);
474 if (rm == ROTATION_UNKNOWN) {
479 _D("Rotation: %d -> %d", __rotation.rm, rm);
481 base->impl_->InvokeCallback(__rotation.rm,
482 IEvent::Type::DEVICE_ORIENTATION_CHANGED);
485 void AppCoreBase::Impl::InitRotation() {
486 if (__rotation.initialized)
489 sensor_t sensor = sensord_get_sensor(AUTO_ROTATION_SENSOR);
490 __rotation.conn = sensord_connect(sensor);
491 if (__rotation.conn < 0) {
492 _E("Failed to connect sensord");
496 bool r = sensord_register_event(__rotation.conn,
497 AUTO_ROTATION_CHANGE_STATE_EVENT, SENSOR_INTERVAL_NORMAL, 0,
498 AutoRotationChangedCb, parent_);
500 _E("Failed to register auto rotation change event");
501 sensord_disconnect(__rotation.conn);
505 r = sensord_start(__rotation.conn, 0);
507 _E("Failed to start sensord");
508 sensord_unregister_event(__rotation.conn, AUTO_ROTATION_CHANGE_STATE_EVENT);
509 sensord_disconnect(__rotation.conn);
514 vconf_get_bool(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, &lock);
515 vconf_notify_key_changed(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, LockCb,
518 __rotation.lock = !lock;
519 __rotation.initialized = true;
522 void AppCoreBase::Impl::FiniRotation() {
523 if (!__rotation.initialized)
526 vconf_ignore_key_changed(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, LockCb);
527 sensord_unregister_event(__rotation.conn, AUTO_ROTATION_CHANGE_STATE_EVENT);
528 sensord_stop(__rotation.conn);
529 sensord_disconnect(__rotation.conn);
532 __rotation.initialized = false;
535 void AppCoreBase::Impl::VerifyLanguage() {
536 const char* env_lang = getenv("LANG");
537 if (env_lang == nullptr)
540 char* lang = vconf_get_str(VCONFKEY_LANGSET);
544 std::unique_ptr<char, decltype(std::free)*> lang_auto(lang, std::free);
546 if (strcmp(env_lang, lang) != 0) {
547 _I("LANG(%s), LANGSET(%s)", env_lang, lang);
548 sid_ = GLib::IdleAdd(InvokeLangChangeCb, parent_);
552 void AppCoreBase::Impl::SetDefaultEvents() {
553 vconf_notify_key_changed(VCONFKEY_LANGSET, LanguageChangeCb, parent_);
554 int r = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT, RegionChangeCb,
557 vconf_notify_key_changed(VCONFKEY_REGIONFORMAT_TIME1224, RegionChangeCb,
561 vconf_notify_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY, LowMemoryCb, parent_);
564 void AppCoreBase::Impl::UnsetDefaultEvents() {
565 vconf_ignore_key_changed(VCONFKEY_LANGSET, LanguageChangeCb);
566 int r = vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT, RegionChangeCb);
568 vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT_TIME1224, RegionChangeCb);
570 vconf_ignore_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY, LowMemoryCb);
573 int AppCoreBase::OnReceive(aul_type type, tizen_base::Bundle b) {
576 _D("[APP %d] AUL event: AUL_START", getpid());
577 if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT) {
578 std::string bg = b.GetString(AUL_K_ALLOWED_BG);
579 if (bg == "ALLOWED_BG") {
580 _D("[__SUSPEND__] allowed background");
581 impl_->allowed_bg_ = true;
582 RemoveSuspendTimer();
586 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:RESET");
587 if (impl_->core_delegator_)
588 impl_->core_delegator_->OnControl(std::move(b));
590 OnControl(std::move(b));
591 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
594 _D("[APP %d] AUL event: AUL_RESUME", getpid());
595 if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT) {
596 std::string bg = b.GetString(AUL_K_ALLOWED_BG);
597 if (bg == "ALLOWED_BG") {
598 _D("[__SUSPEND__] allowed background");
599 impl_->allowed_bg_ = true;
600 RemoveSuspendTimer();
605 _D("[APP %d] AUL event: AUL_TERMINATE", getpid());
606 aul_status_update(STATUS_DYING);
607 if (!impl_->allowed_bg_)
608 RemoveSuspendTimer();
612 case AUL_TERMINATE_INST:
613 case AUL_TERMINATE_BG_INST:
614 case AUL_TERMINATE_BGAPP:
615 _D("[APP %d] AUL event: %d", getpid(), type);
616 if (!impl_->allowed_bg_)
617 RemoveSuspendTimer();
620 _D("[APP %d] AUL event: AUL_WAKE", getpid());
621 if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT) {
622 if (!impl_->allowed_bg_ && impl_->suspended_state_) {
623 RemoveSuspendTimer();
624 int suspend = SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND;
625 impl_->InvokeCallback(suspend, IEvent::Type::SUSPENDED_STATE_CHANGE);
626 impl_->suspended_state_ = false;
631 _D("[APP %d] AUL event: AUL_SUSPEND", getpid());
632 if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT) {
633 if (!impl_->allowed_bg_ && !impl_->suspended_state_) {
634 RemoveSuspendTimer();
639 case AUL_UPDATE_REQUESTED:
640 _D("[APP %d] AUL event: AUL_UPDATE_REQUESTED", getpid());
641 impl_->InvokeCallback(0, IEvent::Type::UPDATE_REQUESTED);
644 _D("[APP %d] AUL event: %d", getpid(), type);
652 int AppCoreBase::OnCreate() {
653 int ret = aul_launch_init([](aul_type type, bundle* b, void* data) -> int {
654 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(data);
655 if (base->impl_->core_delegator_) {
656 return base->impl_->core_delegator_->OnReceive(type,
657 b ? tizen_base::Bundle(b, false, false) : tizen_base::Bundle());
659 return base->OnReceive(type,
660 b ? tizen_base::Bundle(b, false, false) : tizen_base::Bundle());
662 if (ret < 0 && ret != AUL_R_ECANCELED) {
663 _E("aul_launch_init() is failed. error(%d)", ret);
667 ret = aul_launch_argv_handler(impl_->argc_, impl_->argv_);
669 _E("aul_launch_argv_handler() is failed. error(%d)", ret);
676 int AppCoreBase::OnControl(tizen_base::Bundle b) {
680 int AppCoreBase::OnTerminate() {
685 void AppCoreBase::SetCoreDelegator(IAppCore* delegator) {
686 impl_->core_delegator_ = delegator;
689 void AppCoreBase::SetLoopDelegator(IMainLoop* delegator) {
690 impl_->loop_delegator_ = delegator;
693 std::string AppCoreBase::Impl::GetAppName(const char* appid) {
694 if (appid == nullptr)
697 /* com.vendor.name -> name */
698 const char* name_token = strrchr(appid, '.');
699 if (name_token == nullptr)
706 std::string AppCoreBase::Impl::GetLocaleResourceDir() {
707 const char* res_path = aul_get_app_resource_path();
708 if (res_path == nullptr) {
709 _E("Failed to get resource path");
713 return std::string(res_path) + PATH_LOCALE;
716 int AppCoreBase::OnSetI18n() {
717 char appid[PATH_MAX];
718 int ret = aul_app_get_appid_bypid(getpid(), appid, PATH_MAX);
720 _E("aul_app_get_appid_bypid() is failed. error(%d)", ret);
724 std::string name = impl_->GetAppName(appid);
728 std::string locale_dir = impl_->GetLocaleResourceDir();
729 if (locale_dir.empty())
732 return SetI18n(move(name), move(locale_dir));
735 void AppCoreBase::Impl::OnLowBatteryCb(keynode_t* key, void* data) {
736 int val = vconf_keynode_get_int(key);
737 if (val <= VCONFKEY_SYSMAN_BAT_CRITICAL_LOW) {
738 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(data);
739 base->impl_->InvokeCallback(val, IEvent::Type::LOW_BATTERY);
743 void AppCoreBase::Impl::UnregisterRotationChangedEvent() {
748 if (__rotation.ref == 0) {
750 if (feature_ & FEATURE_CHARGER_STATUS) {
751 vconf_ignore_key_changed(VCONFKEY_SYSMAN_CHARGER_STATUS,
752 ChargerStatusChangedCb);
757 void AppCoreBase::Impl::RegisterRotationChangedEvent() {
758 if (__rotation.ref == 0) {
759 if (feature_ & FEATURE_CHARGER_STATUS) {
760 vconf_get_int(VCONFKEY_SYSMAN_CHARGER_STATUS, &__rotation.charger_status);
761 vconf_notify_key_changed(VCONFKEY_SYSMAN_CHARGER_STATUS,
762 ChargerStatusChangedCb, parent_);
763 if (__rotation.charger_status)
773 int AppCoreBase::OnSetEvent(IEvent::Type event) {
775 case IEvent::Type::LOW_BATTERY:
776 vconf_notify_key_changed(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW,
777 impl_->OnLowBatteryCb, this);
779 case IEvent::Type::DEVICE_ORIENTATION_CHANGED:
780 impl_->RegisterRotationChangedEvent();
782 case IEvent::Type::SUSPENDED_STATE_CHANGE:
791 int AppCoreBase::OnUnsetEvent(IEvent::Type event) {
793 case IEvent::Type::LOW_BATTERY:
794 vconf_ignore_key_changed(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW,
795 impl_->OnLowBatteryCb);
797 case IEvent::Type::DEVICE_ORIENTATION_CHANGED:
798 impl_->UnregisterRotationChangedEvent();
800 case IEvent::Type::SUSPENDED_STATE_CHANGE:
809 int AppCoreBase::OnTrimMemory() {
810 int (*sqlite3_free_heap_memory)(int);
812 sqlite3_free_heap_memory = reinterpret_cast<
813 decltype(sqlite3_free_heap_memory)>(
814 dlsym(RTLD_DEFAULT, "sqlite3_release_memory"));
815 if (sqlite3_free_heap_memory)
816 sqlite3_free_heap_memory(SQLITE_FLUSH_MAX);
822 void AppCoreBase::AddEvent(std::shared_ptr<EventBase> event) {
824 for (auto& ev : impl_->events_) {
825 if (ev->GetType() == event->GetType()) {
832 if (impl_->core_delegator_)
833 impl_->core_delegator_->OnSetEvent(event->GetType());
835 OnSetEvent(event->GetType());
838 impl_->events_.push_back(move(event));
841 bool AppCoreBase::RemoveEvent(std::shared_ptr<EventBase> event) {
843 impl_->events_.remove_if([&](const std::shared_ptr<EventBase>& ptr)->bool {
844 if (event.get() == ptr.get()) {
854 void AppCoreBase::FlushMemory() {
855 if (impl_->core_delegator_)
856 impl_->core_delegator_->OnTrimMemory();
861 if (!impl_->allowed_bg_ && !impl_->suspended_state_) {
862 _D("[__SUSPEND__] flush case");
863 int suspend = SUSPENDED_STATE_WILL_ENTER_SUSPEND;
864 impl_->InvokeCallback(suspend, IEvent::Type::SUSPENDED_STATE_CHANGE);
865 impl_->suspended_state_ = true;
869 AppCoreBase::RotationState AppCoreBase::GetRotationState() {
871 throw std::runtime_error("invalid rotation state");
873 return __rotation.rm;
876 bool AppCoreBase::IsBgAllowed() {
877 return impl_->allowed_bg_;
880 bool AppCoreBase::IsSuspended() {
881 return impl_->suspended_state_;
884 void AppCoreBase::ToggleSuspendedState() {
885 impl_->suspended_state_ = !impl_->suspended_state_;
888 std::list<std::string> AppCoreBase::Impl::SplitLanguage(
889 const std::string& lang) {
890 std::istringstream ss(lang);
891 std::list<std::string> li;
894 while (std::getline(ss, token, ':'))
900 void AppCoreBase::Impl::AppendDefaultLangs(std::vector<std::string>& langs) {
901 langs.push_back("en_US");
902 langs.push_back("en_GB");
903 langs.push_back("en");
906 std::string AppCoreBase::Impl::GetStringBefore(const char* cstr,
908 if (cstr == nullptr || delim == nullptr)
911 auto str = std::string(cstr);
912 auto idx = str.find(delim);
913 return str.substr(0, idx);
916 std::map<std::string, std::set<std::string>> AppCoreBase::Impl::GetLangTable() {
917 if (locale_dir_.empty())
920 DIR* dp = opendir(locale_dir_.c_str());
924 std::map<std::string, std::set<std::string>> table;
925 struct dirent *dentry;
926 while ((dentry = readdir(dp)) != nullptr) {
927 if (!strcmp(dentry->d_name, ".") ||
928 !strcmp(dentry->d_name, ".."))
931 std::string buf = locale_dir_ + "/" + dentry->d_name;
932 struct stat stat_buf;
933 int ret = stat(buf.c_str(), &stat_buf);
934 if (ret != 0 || !S_ISDIR(stat_buf.st_mode))
937 std::string parent_lang = GetStringBefore(dentry->d_name, "_");
938 if (parent_lang.empty()) {
943 table[parent_lang].insert(dentry->d_name);
950 void AppCoreBase::Impl::AppendLangs(const std::string& lang,
951 std::vector<std::string>& langs,
952 std::map<std::string, std::set<std::string>>& table) {
956 langs.push_back(lang);
957 std::string extract_lang = GetStringBefore(lang.c_str(), ".");
958 if (extract_lang.empty())
961 if (std::find(langs.begin(), langs.end(), extract_lang) != langs.end())
964 std::string parent_lang = GetStringBefore(extract_lang.c_str(), "_");
965 if (parent_lang.empty())
968 if (table.find(parent_lang) == table.end())
971 auto it = table[parent_lang].find(extract_lang);
972 if (it != table[parent_lang].end()) {
973 std::string value = *it;
974 if (std::find(langs.begin(), langs.end(), value) == langs.end())
975 langs.push_back(std::move(value));
977 table[parent_lang].erase(it);
981 it = table[parent_lang].find(parent_lang);
982 if (it != table[parent_lang].end()) {
983 std::string value = *it;
984 if (std::find(langs.begin(), langs.end(), value) == langs.end())
985 langs.push_back(std::move(value));
987 table[parent_lang].erase(parent_lang);
991 if (!table[parent_lang].empty()) {
992 auto i = table[parent_lang].begin();
993 std::string value = *i;
994 if (std::find(langs.begin(), langs.end(), value) == langs.end())
995 langs.push_back(std::move(value));
997 table[parent_lang].erase(i);
1001 std::string AppCoreBase::Impl::GetLanguage(std::string lang) {
1002 std::list<std::string> l = SplitLanguage(lang);
1006 auto table = GetLangTable();
1010 std::vector<std::string> langs;
1012 AppendLangs(i, langs, table);
1014 AppendDefaultLangs(langs);
1016 for (auto& i : langs) {
1026 void AppCoreBase::Impl::UpdateLang() {
1027 char* lang = vconf_get_str(VCONFKEY_LANGSET);
1028 if (lang == nullptr)
1031 std::unique_ptr<char, decltype(std::free)*> lang_auto(lang, std::free);
1032 std::string language = GetLanguage(lang);
1033 if (!language.empty()) {
1034 _D("*****language(%s)", language.c_str());
1035 setenv("LANGUAGE", language.c_str(), 1);
1037 setenv("LANGUAGE", lang, 1);
1039 setenv("LANG", lang, 1);
1040 setenv("LC_MESSAGES", lang, 1);
1041 setenv("LC_ALL", lang, 1);
1042 char* r = setlocale(LC_ALL, "");
1044 r = setlocale(LC_ALL, "en_US.UTF-8");
1046 _D("*****appcore setlocale=%s\n", r);
1048 _D("*****appcore setlocale=\"C\"");
1049 setenv("LC_ALL", "C", 1);
1050 r = setlocale(LC_ALL, "");
1052 _E("failed to setlocale");
1057 void AppCoreBase::Impl::UpdateRegion() {
1058 char* region = vconf_get_str(VCONFKEY_REGIONFORMAT);
1059 if (region == nullptr)
1062 std::unique_ptr<char, decltype(std::free)*> region_auto(region, std::free);
1063 setenv("LC_CTYPE", region, 1);
1064 setenv("LC_NUMERIC", region, 1);
1065 setenv("LC_TIME", region, 1);
1066 setenv("LC_COLLATE", region, 1);
1067 setenv("LC_MONETARY", region, 1);
1068 setenv("LC_PAPER", region, 1);
1069 setenv("LC_NAME", region, 1);
1070 setenv("LC_ADDRESS", region, 1);
1071 setenv("LC_TELEPHONE", region, 1);
1072 setenv("LC_MEASUREMENT", region, 1);
1073 setenv("LC_IDENTIFICATION", region, 1);
1074 char* r = setlocale(LC_ALL, "");
1076 _D("*****appcore setlocale=%s\n", r);
1078 _D("*****appcore setlocale=\"C\"");
1079 setenv("LC_ALL", "C", 1);
1080 r = setlocale(LC_ALL, "");
1082 _E("failed to setlocale");
1086 int AppCoreBase::SetI18n(std::string domain_name, std::string dir_name) {
1087 if (domain_name.empty()) {
1092 if (!dir_name.empty())
1093 impl_->locale_dir_ = dir_name;
1095 impl_->UpdateLang();
1096 impl_->UpdateRegion();
1098 char* r = setlocale(LC_ALL, "");
1099 /* if locale is not set properly, try to set "en_US" again */
1101 r = setlocale(LC_ALL, "en_US.UTF-8");
1103 _E("appcore: setlocale() error");
1104 _D("*****appcore setlocale=\"C\"");
1105 setenv("LC_ALL", "C", 1);
1106 r = setlocale(LC_ALL, "");
1108 _E("failed to setlocale");
1113 _D("*****appcore setlocale=%s\n", r);
1115 r = bindtextdomain(domain_name.c_str(), dir_name.c_str());
1117 _E("appcore: bindtextdomain() error");
1119 r = textdomain(domain_name.c_str());
1121 _E("appcore: textdomain() error");
1126 void AppCoreBase::Exit() {
1127 aul_status_update(STATUS_DYING);
1128 if (impl_->loop_delegator_)
1129 impl_->loop_delegator_->OnLoopExit();
1134 void AppCoreBase::AddSuspendTimer() {
1135 impl_->tid_ = GLib::TimeoutAdd(5000, [](gpointer data) -> gboolean {
1136 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(data);
1137 base->FlushMemory();
1142 void AppCoreBase::RemoveSuspendTimer() {
1143 if (impl_->tid_ > 0) {
1144 GLib::SourceRemove(impl_->tid_);
1149 void AppCoreBase::SetDisplayState(DisplayState state) {
1150 __display_state = state;
1153 AppCoreBase::DisplayState AppCoreBase::GetDisplayState() {
1154 return __display_state;
1157 int AppCoreBase::EnableWatchdog() {
1158 _I("[__APPCORE_WATCHDOG__] enable");
1159 return aul_watchdog_enable();
1162 int AppCoreBase::DisableWatchdog() {
1163 _I("[__APPCORE_WATCHDOG__] disable");
1164 return aul_watchdog_disable();
1167 int AppCoreBase::KickWatchdog() {
1168 _I("[__APPCORE_WATCHDOG__] kick");
1169 return aul_watchdog_kick();
1172 void AppCoreBase::Run(int argc, char** argv) {
1177 void AppCoreBase::Init(int argc, char** argv) {
1179 impl_->suspended_state_ = false;
1180 impl_->allowed_bg_ = false;
1181 impl_->argc_ = argc;
1182 impl_->argv_ = argv;
1183 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:OPS_INIT");
1184 if (impl_->loop_delegator_)
1185 impl_->loop_delegator_->OnLoopInit(argc, argv);
1187 OnLoopInit(argc, argv);
1189 signal(SIGTERM, [](int n) {
1190 _W("sigterm handler");
1191 if (context_ != nullptr)
1195 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1197 if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT)
1198 GLib::IdleAdd(Impl::InitSuspendCb, this);
1200 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:SET_SYSTEM_EVENT");
1201 if (!impl_->dirty_) {
1202 impl_->dirty_ = true;
1204 for (auto& e : impl_->events_) {
1205 if (impl_->core_delegator_)
1206 impl_->core_delegator_->OnSetEvent(e->GetType());
1208 OnSetEvent(e->GetType());
1211 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1213 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:VERIFY_LANG");
1214 impl_->VerifyLanguage();
1215 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1217 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:SET_DEFAULT_EVENTS");
1218 impl_->SetDefaultEvents();
1219 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1221 if (impl_->core_delegator_)
1222 impl_->core_delegator_->OnSetI18n();
1226 aul_app_lifecycle_update_state(AUL_APP_LIFECYCLE_STATE_INITIALIZED);
1228 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:CREATE");
1230 if (impl_->core_delegator_)
1231 create = impl_->core_delegator_->OnCreate();
1233 create = OnCreate();
1234 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1236 aul_app_lifecycle_update_state(AUL_APP_LIFECYCLE_STATE_CREATED);
1240 if (impl_->loop_delegator_)
1241 impl_->loop_delegator_->OnLoopRun();
1246 void AppCoreBase::Fini() {
1250 void AppCoreBase::Dispose() {
1251 aul_status_update(STATUS_DYING);
1253 aul_app_lifecycle_update_state(AUL_APP_LIFECYCLE_STATE_DESTROYED);
1255 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:TERMINATE");
1256 if (impl_->core_delegator_)
1257 impl_->core_delegator_->OnTerminate();
1260 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1262 for (auto& e : impl_->events_) {
1263 if (impl_->core_delegator_)
1264 impl_->core_delegator_->OnUnsetEvent(e->GetType());
1266 OnUnsetEvent(e->GetType());
1269 impl_->UnsetDefaultEvents();
1271 GLib::SourceRemove(impl_->sid_);
1275 RemoveSuspendTimer();
1276 impl_->dirty_ = false;
1277 if (impl_->loop_delegator_)
1278 impl_->loop_delegator_->OnLoopFinish();
1283 void AppCoreBase::SetFeature(int feature) {
1284 impl_->feature_ = feature;
1287 int AppCoreBase::GetFeature() const {
1288 return impl_->feature_;
1291 } // namespace tizen_cpp