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>
26 #include <glib-unix.h>
29 #include <linux/limits.h>
32 #include <sensor_internal.h>
37 #include <sys/types.h>
38 #include <system_info.h>
53 #include "app-core-cpp/app_core_plugin_private.hh"
54 #include "app-core-cpp/exit_handler_private.hh"
55 #include "app-core-cpp/sigterm_handler_private.hh"
56 #include "common/glib_private.hh"
57 #include "common/log_private.hh"
59 extern "C" void aul_finalize();
62 AppCoreBase* AppCoreBase::context_ = nullptr;
66 internal::ExitHandler exit_handler;
67 internal::SigtermHandler sigterm_handler;
78 TizenProfile TizenProfileGet() {
79 static TizenProfile profile = TizenProfile::Unknown;
80 if (__builtin_expect(profile != TizenProfile::Unknown, 1))
83 char* profile_name = nullptr;
84 system_info_get_platform_string("http://tizen.org/feature/profile",
86 if (profile_name == nullptr)
89 switch (*profile_name) {
92 profile = TizenProfile::Mobile;
96 profile = TizenProfile::Wearable;
100 profile = TizenProfile::Tv;
104 profile = TizenProfile::Ivi;
107 profile = TizenProfile::Common;
115 constexpr const char PATH_LOCALE[] = "locale";
116 constexpr int SQLITE_FLUSH_MAX = 1024 * 1024;
117 constexpr const char RESOURCED_FREEZER_PATH[] =
118 "/Org/Tizen/ResourceD/Freezer";
119 constexpr const char RESOURCED_FREEZER_INTERFACE[] =
120 "org.tizen.resourced.freezer";
121 constexpr const char RESOURCED_FREEZER_SIGNAL[] =
128 tizen_cpp::AppCoreBase::RotationState rm;
134 GDBusConnection* __bus;
135 guint __suspend_dbus_handler_initialized;
136 AppCoreBase::DisplayState __display_state = AppCoreBase::DISPLAY_STATE_UNKNOWN;
140 class AppCoreBase::EventBase::Impl {
142 friend class AppCoreBase;
143 Type type_ = IEvent::Type::START;
144 std::string str_val_;
148 class AppCoreBase::Impl {
150 explicit Impl(AppCoreBase* parent) : parent_(parent) {
151 if (TizenProfileGet() & TizenProfile::Wearable)
152 feature_ |= FEATURE_CHARGER_STATUS;
153 if (!(TizenProfileGet() & TizenProfile::Tv))
154 feature_ |= FEATURE_BACKGROUND_MANAGEMENT;
158 void UnregisterRotationChangedEvent();
159 void RegisterRotationChangedEvent();
160 std::string GetAppName(const char* appid);
161 std::string GetLocaleResourceDir();
164 std::list<std::string> SplitLanguage(const std::string& lang);
165 std::string GetLanguage(std::string lang);
166 void AppendDefaultLangs(std::vector<std::string>& lang_set);
167 std::string GetStringBefore(const char* str, const char* delim);
168 std::map<std::string, std::set<std::string>> GetLangTable();
169 void AppendLangs(const std::string& lang, std::vector<std::string>& lang_set,
170 std::map<std::string, std::set<std::string>>& table);
172 void OnFreezerSignal();
175 void InvokeCallback(T event, IEvent::Type type) {
176 for (auto& i : events_) {
177 if (i->GetType() != type)
180 if (i->GetVal(event) != event ||
181 type == IEvent::Type::START ||
182 type == IEvent::Type::UPDATE_REQUESTED) {
189 static void InitSuspendDbusHandler(gpointer data);
190 static gboolean InitSuspendCb(gpointer data);
191 static gboolean InvokeLangChangeCb(gpointer data);
192 static void ReceiveSuspendSignalCb(GDBusConnection*, const gchar*,
193 const gchar*, const gchar*, const gchar*, GVariant*, gpointer);
194 static void OnLowBatteryCb(keynode_t* key, void* data);
195 static void OnTimeZoneChangedCb(keynode_t* key, void* data);
196 static void LockCb(keynode_t* node, void* user_data);
197 static void AutoRotationChangedCb(sensor_t sensor, unsigned int event_type,
198 sensor_data_t* data, void* user_data);
199 static void ChargerStatusChangedCb(keynode_t* keynode, void* user_data);
200 static void LanguageChangeCb(keynode_t* key, void* data);
201 static void RegionChangeCb(keynode_t* key, void* data);
202 static void LowMemoryCb(keynode_t* key, void* data);
205 RotationState GetRm(sensor_data_t data);
206 void VerifyLanguage();
207 void SetDefaultEvents();
208 void UnsetDefaultEvents();
209 void PluginInit(int argc, char** argv);
213 friend class AppCoreBase;
214 AppCoreBase* parent_ = nullptr;
217 char** argv_ = nullptr;
218 bool suspended_state_ = false;
219 bool allowed_bg_ = false;
221 unsigned int tid_ = 0;
222 std::list<std::shared_ptr<EventBase>> events_;
223 std::string locale_dir_;
226 IAppCore* core_delegator_ = nullptr;
227 IMainLoop* loop_delegator_ = nullptr;
228 guint signal_handler_source_ = 0;
229 std::unique_ptr<AppCorePlugin> plugin_;
232 AppCoreBase::EventBase::EventBase(Type type)
233 : impl_(std::make_unique<EventBase::Impl>()) {
237 AppCoreBase::EventBase::~EventBase() = default;
239 IAppCore::IEvent::Type AppCoreBase::EventBase::GetType() const {
243 std::string AppCoreBase::EventBase::GetVal(std::string cur) const {
244 return impl_->str_val_;
247 int AppCoreBase::EventBase::GetVal(int cur) const {
251 void AppCoreBase::EventBase::SetVal(std::string val) {
252 impl_->str_val_ = std::move(val);
255 void AppCoreBase::EventBase::SetVal(int val) {
256 impl_->val_ = std::move(val);
259 AppCoreBase::AppCoreBase()
260 : impl_(std::make_unique<AppCoreBase::Impl>(this)) {
261 if (context_ != nullptr) {
262 _E("Context is already initialized");
268 AppCoreBase::~AppCoreBase() {
273 AppCoreBase* AppCoreBase::GetContext() {
274 if (context_ == nullptr) {
275 _E("Context is not initialized.");
282 void AppCoreBase::Impl::ChangeLang() {
283 const char* lang = getenv("LANG");
287 InvokeCallback(lang, IEvent::Type::LANG_CHANGE);
290 void AppCoreBase::RaiseEvent(int event, IEvent::Type type) {
291 impl_->InvokeCallback(event, type);
294 void AppCoreBase::RaiseEvent(const std::string& event, IEvent::Type type) {
295 impl_->InvokeCallback(event, type);
298 void AppCoreBase::Impl::OnFreezerSignal() {
299 if (!allowed_bg_ && suspended_state_) {
300 parent_->RemoveSuspendTimer();
301 InvokeCallback(SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND,
302 IEvent::Type::SUSPENDED_STATE_CHANGE);
303 suspended_state_ = false;
304 parent_->AddSuspendTimer();
308 AppCoreBase::RotationState AppCoreBase::Impl::GetRm(sensor_data_t data) {
309 if (data.value_count <= 0) {
310 _E("Failed to get sensor data");
311 return ROTATION_UNKNOWN;
314 int event = data.values[0];
316 case AUTO_ROTATION_DEGREE_0:
317 return ROTATION_PORTRAIT_NORMAL;
318 case AUTO_ROTATION_DEGREE_90:
319 return ROTATION_LANDSCAPE_NORMAL;
320 case AUTO_ROTATION_DEGREE_180:
321 return ROTATION_PORTRAIT_REVERSE;
322 case AUTO_ROTATION_DEGREE_270:
323 return ROTATION_LANDSCAPE_REVERSE;
325 return ROTATION_UNKNOWN;
329 void AppCoreBase::Impl::InitSuspendDbusHandler(gpointer data) {
330 if (__suspend_dbus_handler_initialized)
333 if (__bus == nullptr) {
334 GError* err = nullptr;
335 __bus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &err);
336 if (__bus == nullptr) {
337 _E("Failed to connect to the D-BUS daemon: %s", err ? err->message : "");
345 __suspend_dbus_handler_initialized = g_dbus_connection_signal_subscribe(
346 __bus, nullptr, RESOURCED_FREEZER_INTERFACE, RESOURCED_FREEZER_SIGNAL,
347 RESOURCED_FREEZER_PATH, nullptr, G_DBUS_SIGNAL_FLAGS_NONE,
348 ReceiveSuspendSignalCb, data, nullptr);
350 if (__suspend_dbus_handler_initialized == 0) {
351 _E("g_dbus_connection_signal_subscribe() is failed.");
355 _D("[__SUSPEND__] suspend signal initialized");
358 gboolean AppCoreBase::Impl::InitSuspendCb(gpointer data) {
359 InitSuspendDbusHandler(data);
360 return G_SOURCE_REMOVE;
363 gboolean AppCoreBase::Impl::InvokeLangChangeCb(gpointer data) {
364 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(data);
365 base->impl_->sid_ = 0;
366 base->impl_->ChangeLang();
367 return G_SOURCE_REMOVE;
370 void AppCoreBase::Impl::ReceiveSuspendSignalCb(GDBusConnection*, const gchar*,
371 const gchar*, const gchar*, const gchar* signal_name, GVariant* parameters,
372 gpointer user_data) {
373 if (g_strcmp0(signal_name, RESOURCED_FREEZER_SIGNAL) == 0) {
376 g_variant_get(parameters, "(ii)", &status, &pid);
377 if (pid == getpid() && status == 0) {
378 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
379 base->impl_->OnFreezerSignal();
384 void AppCoreBase::Impl::LanguageChangeCb(keynode_t* key, void* user_data) {
385 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
386 if (base->impl_->sid_) {
387 GLib::SourceRemove(base->impl_->sid_);
388 base->impl_->sid_ = 0;
391 char* val = vconf_keynode_get_str(key);
395 base->impl_->UpdateLang();
396 base->impl_->InvokeCallback(val, IEvent::Type::LANG_CHANGE);
399 void AppCoreBase::Impl::RegionChangeCb(keynode_t* key, void* user_data) {
400 const char* name = vconf_keynode_get_name(key);
404 if (strcmp(name, VCONFKEY_REGIONFORMAT) &&
405 strcmp(name, VCONFKEY_REGIONFORMAT_TIME1224))
408 char* val = vconf_get_str(VCONFKEY_REGIONFORMAT);
411 std::unique_ptr<char, decltype(std::free)*> region_auto(val, std::free);
413 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
414 base->impl_->UpdateRegion();
415 base->impl_->InvokeCallback(val, IEvent::Type::REGION_CHANGE);
418 void AppCoreBase::Impl::LowMemoryCb(keynode_t* key, void* user_data) {
419 int val = vconf_keynode_get_int(key);
420 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
421 base->impl_->InvokeCallback(val, IEvent::Type::LOW_MEMORY);
422 if (val >= VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING)
426 void AppCoreBase::Impl::ChargerStatusChangedCb(keynode_t* keynode,
428 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
429 if (base->impl_->feature_ & FEATURE_CHARGER_STATUS) {
430 __rotation.charger_status = vconf_keynode_get_int(keynode);
431 if (__rotation.ref) {
432 if (__rotation.charger_status) {
433 base->impl_->InitRotation();
435 base->impl_->FiniRotation();
439 _D("charger status(%d)", __rotation.charger_status);
443 void AppCoreBase::Impl::LockCb(keynode_t* node, void* user_data) {
444 AppCoreBase::RotationState rm;
445 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
447 __rotation.lock = !vconf_keynode_get_bool(node);
448 if (__rotation.lock) {
449 _D("Rotation locked");
450 rm = ROTATION_PORTRAIT_NORMAL;
452 _D("Rotation unlocked");
454 bool r = sensord_get_data(__rotation.conn, AUTO_ROTATION_SENSOR, &data);
456 _E("Failed to get sensor data");
460 rm = base->impl_->GetRm(data);
461 if (rm == ROTATION_UNKNOWN) {
467 if (__rotation.rm == rm)
470 _D("Rotation: %d -> %d", __rotation.rm, rm);
472 base->impl_->InvokeCallback(__rotation.rm,
473 IEvent::Type::DEVICE_ORIENTATION_CHANGED);
476 void AppCoreBase::Impl::AutoRotationChangedCb(sensor_t sensor,
477 unsigned int event_type, sensor_data_t* data, void* user_data) {
484 if (event_type != AUTO_ROTATION_CHANGE_STATE_EVENT)
487 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
488 AppCoreBase::RotationState rm = base->impl_->GetRm(*data);
489 if (rm == ROTATION_UNKNOWN) {
494 _D("Rotation: %d -> %d", __rotation.rm, rm);
496 base->impl_->InvokeCallback(__rotation.rm,
497 IEvent::Type::DEVICE_ORIENTATION_CHANGED);
500 void AppCoreBase::Impl::InitRotation() {
501 if (__rotation.initialized)
504 sensor_t sensor = sensord_get_sensor(AUTO_ROTATION_SENSOR);
505 __rotation.conn = sensord_connect(sensor);
506 if (__rotation.conn < 0) {
507 _E("Failed to connect sensord");
511 bool r = sensord_register_event(__rotation.conn,
512 AUTO_ROTATION_CHANGE_STATE_EVENT, SENSOR_INTERVAL_NORMAL, 0,
513 AutoRotationChangedCb, parent_);
515 _E("Failed to register auto rotation change event");
516 sensord_disconnect(__rotation.conn);
520 r = sensord_start(__rotation.conn, 0);
522 _E("Failed to start sensord");
523 sensord_unregister_event(__rotation.conn, AUTO_ROTATION_CHANGE_STATE_EVENT);
524 sensord_disconnect(__rotation.conn);
529 vconf_get_bool(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, &lock);
530 vconf_notify_key_changed(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, LockCb,
533 __rotation.lock = !lock;
534 __rotation.initialized = true;
537 void AppCoreBase::Impl::FiniRotation() {
538 if (!__rotation.initialized)
541 vconf_ignore_key_changed(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, LockCb);
542 sensord_unregister_event(__rotation.conn, AUTO_ROTATION_CHANGE_STATE_EVENT);
543 sensord_stop(__rotation.conn);
544 sensord_disconnect(__rotation.conn);
547 __rotation.initialized = false;
550 void AppCoreBase::Impl::VerifyLanguage() {
551 const char* env_lang = getenv("LANG");
552 if (env_lang == nullptr)
555 char* lang = vconf_get_str(VCONFKEY_LANGSET);
559 std::unique_ptr<char, decltype(std::free)*> lang_auto(lang, std::free);
561 if (strcmp(env_lang, lang) != 0) {
562 _I("LANG(%s), LANGSET(%s)", env_lang, lang);
563 sid_ = GLib::IdleAdd(InvokeLangChangeCb, parent_);
567 void AppCoreBase::Impl::SetDefaultEvents() {
568 vconf_notify_key_changed(VCONFKEY_LANGSET, LanguageChangeCb, parent_);
569 int r = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT, RegionChangeCb,
572 vconf_notify_key_changed(VCONFKEY_REGIONFORMAT_TIME1224, RegionChangeCb,
576 vconf_notify_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY, LowMemoryCb, parent_);
579 void AppCoreBase::Impl::UnsetDefaultEvents() {
580 vconf_ignore_key_changed(VCONFKEY_LANGSET, LanguageChangeCb);
581 int r = vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT, RegionChangeCb);
583 vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT_TIME1224, RegionChangeCb);
585 vconf_ignore_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY, LowMemoryCb);
588 int AppCoreBase::OnReceive(aul_type type, tizen_base::Bundle b) {
591 _D("[APP %d] AUL event: AUL_START", getpid());
592 if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT) {
593 std::string bg = b.GetString(AUL_K_ALLOWED_BG);
594 if (bg == "ALLOWED_BG") {
595 _D("[__SUSPEND__] allowed background");
596 impl_->allowed_bg_ = true;
597 RemoveSuspendTimer();
601 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:RESET");
602 if (impl_->core_delegator_)
603 impl_->core_delegator_->OnControl(std::move(b));
605 OnControl(std::move(b));
606 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
609 _D("[APP %d] AUL event: AUL_RESUME", getpid());
610 if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT) {
611 std::string bg = b.GetString(AUL_K_ALLOWED_BG);
612 if (bg == "ALLOWED_BG") {
613 _D("[__SUSPEND__] allowed background");
614 impl_->allowed_bg_ = true;
615 RemoveSuspendTimer();
620 _D("[APP %d] AUL event: AUL_TERMINATE", getpid());
621 aul_status_update(STATUS_DYING);
622 if (!impl_->allowed_bg_)
623 RemoveSuspendTimer();
627 case AUL_TERMINATE_INST:
628 case AUL_TERMINATE_BG_INST:
629 case AUL_TERMINATE_BGAPP:
630 _D("[APP %d] AUL event: %d", getpid(), type);
631 if (!impl_->allowed_bg_)
632 RemoveSuspendTimer();
635 _D("[APP %d] AUL event: AUL_WAKE", getpid());
636 if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT) {
637 if (!impl_->allowed_bg_ && impl_->suspended_state_) {
638 RemoveSuspendTimer();
639 int suspend = SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND;
640 impl_->InvokeCallback(suspend, IEvent::Type::SUSPENDED_STATE_CHANGE);
641 impl_->suspended_state_ = false;
646 _D("[APP %d] AUL event: AUL_SUSPEND", getpid());
647 if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT) {
648 if (!impl_->allowed_bg_ && !impl_->suspended_state_) {
649 RemoveSuspendTimer();
654 case AUL_UPDATE_REQUESTED:
655 _D("[APP %d] AUL event: AUL_UPDATE_REQUESTED", getpid());
656 impl_->InvokeCallback(0, IEvent::Type::UPDATE_REQUESTED);
659 _D("[APP %d] AUL event: %d", getpid(), type);
667 int AppCoreBase::OnCreate() {
668 int ret = aul_launch_init([](aul_type type, bundle* b, void* data) -> int {
669 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(data);
670 if (base->impl_->core_delegator_) {
671 return base->impl_->core_delegator_->OnReceive(type,
672 b ? tizen_base::Bundle(b, false, false) : tizen_base::Bundle());
674 return base->OnReceive(type,
675 b ? tizen_base::Bundle(b, false, false) : tizen_base::Bundle());
677 if (ret < 0 && ret != AUL_R_ECANCELED) {
678 _E("aul_launch_init() is failed. error(%d)", ret);
682 ret = aul_launch_argv_handler(impl_->argc_, impl_->argv_);
684 _E("aul_launch_argv_handler() is failed. error(%d)", ret);
691 int AppCoreBase::OnControl(tizen_base::Bundle b) {
695 int AppCoreBase::OnTerminate() {
700 void AppCoreBase::SetCoreDelegator(IAppCore* delegator) {
701 impl_->core_delegator_ = delegator;
704 void AppCoreBase::SetLoopDelegator(IMainLoop* delegator) {
705 impl_->loop_delegator_ = delegator;
708 std::string AppCoreBase::Impl::GetAppName(const char* appid) {
709 if (appid == nullptr)
712 /* com.vendor.name -> name */
713 const char* name_token = strrchr(appid, '.');
714 if (name_token == nullptr)
721 std::string AppCoreBase::Impl::GetLocaleResourceDir() {
722 const char* res_path = aul_get_app_resource_path();
723 if (res_path == nullptr) {
724 _E("Failed to get resource path");
728 return std::string(res_path) + PATH_LOCALE;
731 int AppCoreBase::OnSetI18n() {
732 char appid[PATH_MAX];
733 int ret = aul_app_get_appid_bypid(getpid(), appid, PATH_MAX);
735 _E("aul_app_get_appid_bypid() is failed. error(%d)", ret);
739 std::string name = impl_->GetAppName(appid);
743 std::string locale_dir = impl_->GetLocaleResourceDir();
744 if (locale_dir.empty())
747 return SetI18n(move(name), move(locale_dir));
750 void AppCoreBase::Impl::OnLowBatteryCb(keynode_t* key, void* data) {
751 int val = vconf_keynode_get_int(key);
752 if (val <= VCONFKEY_SYSMAN_BAT_CRITICAL_LOW) {
753 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(data);
754 base->impl_->InvokeCallback(val, IEvent::Type::LOW_BATTERY);
758 void AppCoreBase::Impl::OnTimeZoneChangedCb(keynode_t* key, void* data) {
759 char* time_zone_id = vconf_keynode_get_str(key);
760 if (time_zone_id == nullptr) {
764 char* time_zone = vconf_get_str(VCONFKEY_SETAPPL_TIMEZONE_INT);
765 if (time_zone != nullptr) {
766 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(data);
767 base->impl_->InvokeCallback(std::string(time_zone) + "|" + time_zone_id,
768 IEvent::Type::TIME_ZONE_CHANGED);
773 void AppCoreBase::Impl::UnregisterRotationChangedEvent() {
778 if (__rotation.ref == 0) {
780 if (feature_ & FEATURE_CHARGER_STATUS) {
781 vconf_ignore_key_changed(VCONFKEY_SYSMAN_CHARGER_STATUS,
782 ChargerStatusChangedCb);
787 void AppCoreBase::Impl::RegisterRotationChangedEvent() {
788 if (__rotation.ref == 0) {
789 if (feature_ & FEATURE_CHARGER_STATUS) {
790 vconf_get_int(VCONFKEY_SYSMAN_CHARGER_STATUS, &__rotation.charger_status);
791 vconf_notify_key_changed(VCONFKEY_SYSMAN_CHARGER_STATUS,
792 ChargerStatusChangedCb, parent_);
793 if (__rotation.charger_status)
803 int AppCoreBase::OnSetEvent(IEvent::Type event) {
805 case IEvent::Type::LOW_BATTERY:
806 vconf_notify_key_changed(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW,
807 impl_->OnLowBatteryCb, this);
809 case IEvent::Type::DEVICE_ORIENTATION_CHANGED:
810 impl_->RegisterRotationChangedEvent();
812 case IEvent::Type::SUSPENDED_STATE_CHANGE:
814 case IEvent::Type::TIME_ZONE_CHANGED:
815 vconf_notify_key_changed(VCONFKEY_SETAPPL_TIMEZONE_ID,
816 impl_->OnTimeZoneChangedCb, this);
825 int AppCoreBase::OnUnsetEvent(IEvent::Type event) {
827 case IEvent::Type::LOW_BATTERY:
828 vconf_ignore_key_changed(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW,
829 impl_->OnLowBatteryCb);
831 case IEvent::Type::DEVICE_ORIENTATION_CHANGED:
832 impl_->UnregisterRotationChangedEvent();
834 case IEvent::Type::SUSPENDED_STATE_CHANGE:
843 int AppCoreBase::OnTrimMemory() {
844 int (*sqlite3_free_heap_memory)(int);
846 sqlite3_free_heap_memory = reinterpret_cast<
847 decltype(sqlite3_free_heap_memory)>(
848 dlsym(RTLD_DEFAULT, "sqlite3_release_memory"));
849 if (sqlite3_free_heap_memory)
850 sqlite3_free_heap_memory(SQLITE_FLUSH_MAX);
856 void AppCoreBase::AddEvent(std::shared_ptr<EventBase> event) {
858 for (auto& ev : impl_->events_) {
859 if (ev->GetType() == event->GetType()) {
866 if (impl_->core_delegator_)
867 impl_->core_delegator_->OnSetEvent(event->GetType());
869 OnSetEvent(event->GetType());
872 impl_->events_.push_back(move(event));
875 bool AppCoreBase::RemoveEvent(std::shared_ptr<EventBase> event) {
877 impl_->events_.remove_if([&](const std::shared_ptr<EventBase>& ptr)->bool {
878 if (event.get() == ptr.get()) {
888 void AppCoreBase::FlushMemory() {
889 if (impl_->core_delegator_)
890 impl_->core_delegator_->OnTrimMemory();
895 if (!impl_->allowed_bg_ && !impl_->suspended_state_) {
896 _D("[__SUSPEND__] flush case");
897 int suspend = SUSPENDED_STATE_WILL_ENTER_SUSPEND;
898 impl_->InvokeCallback(suspend, IEvent::Type::SUSPENDED_STATE_CHANGE);
899 impl_->suspended_state_ = true;
903 AppCoreBase::RotationState AppCoreBase::GetRotationState() {
905 throw std::runtime_error("invalid rotation state");
907 return __rotation.rm;
910 bool AppCoreBase::IsBgAllowed() {
911 return impl_->allowed_bg_;
914 bool AppCoreBase::IsSuspended() {
915 return impl_->suspended_state_;
918 void AppCoreBase::ToggleSuspendedState() {
919 impl_->suspended_state_ = !impl_->suspended_state_;
922 std::list<std::string> AppCoreBase::Impl::SplitLanguage(
923 const std::string& lang) {
924 std::istringstream ss(lang);
925 std::list<std::string> li;
928 while (std::getline(ss, token, ':'))
934 void AppCoreBase::Impl::AppendDefaultLangs(std::vector<std::string>& langs) {
935 langs.push_back("en_US");
936 langs.push_back("en_GB");
937 langs.push_back("en");
940 std::string AppCoreBase::Impl::GetStringBefore(const char* cstr,
942 if (cstr == nullptr || delim == nullptr)
945 auto str = std::string(cstr);
946 auto idx = str.find(delim);
947 return str.substr(0, idx);
950 std::map<std::string, std::set<std::string>> AppCoreBase::Impl::GetLangTable() {
951 if (locale_dir_.empty())
954 DIR* dp = opendir(locale_dir_.c_str());
958 std::map<std::string, std::set<std::string>> table;
959 struct dirent *dentry;
960 while ((dentry = readdir(dp)) != nullptr) {
961 if (!strcmp(dentry->d_name, ".") ||
962 !strcmp(dentry->d_name, ".."))
965 std::string buf = locale_dir_ + "/" + dentry->d_name;
966 struct stat stat_buf;
967 int ret = stat(buf.c_str(), &stat_buf);
968 if (ret != 0 || !S_ISDIR(stat_buf.st_mode))
971 std::string parent_lang = GetStringBefore(dentry->d_name, "_");
972 if (parent_lang.empty()) {
977 table[parent_lang].insert(dentry->d_name);
984 void AppCoreBase::Impl::AppendLangs(const std::string& lang,
985 std::vector<std::string>& langs,
986 std::map<std::string, std::set<std::string>>& table) {
990 langs.push_back(lang);
991 std::string extract_lang = GetStringBefore(lang.c_str(), ".");
992 if (extract_lang.empty())
995 if (std::find(langs.begin(), langs.end(), extract_lang) != langs.end())
998 std::string parent_lang = GetStringBefore(extract_lang.c_str(), "_");
999 if (parent_lang.empty())
1002 if (table.find(parent_lang) == table.end())
1005 auto it = table[parent_lang].find(extract_lang);
1006 if (it != table[parent_lang].end()) {
1007 std::string value = *it;
1008 if (std::find(langs.begin(), langs.end(), value) == langs.end())
1009 langs.push_back(std::move(value));
1011 table[parent_lang].erase(it);
1015 it = table[parent_lang].find(parent_lang);
1016 if (it != table[parent_lang].end()) {
1017 std::string value = *it;
1018 if (std::find(langs.begin(), langs.end(), value) == langs.end())
1019 langs.push_back(std::move(value));
1021 table[parent_lang].erase(parent_lang);
1025 if (!table[parent_lang].empty()) {
1026 auto i = table[parent_lang].begin();
1027 std::string value = *i;
1028 if (std::find(langs.begin(), langs.end(), value) == langs.end())
1029 langs.push_back(std::move(value));
1031 table[parent_lang].erase(i);
1035 std::string AppCoreBase::Impl::GetLanguage(std::string lang) {
1036 std::list<std::string> l = SplitLanguage(lang);
1040 auto table = GetLangTable();
1044 std::vector<std::string> langs;
1046 AppendLangs(i, langs, table);
1048 AppendDefaultLangs(langs);
1050 for (auto& i : langs) {
1060 void AppCoreBase::Impl::UpdateLang() {
1061 char* lang = vconf_get_str(VCONFKEY_LANGSET);
1062 if (lang == nullptr)
1065 std::unique_ptr<char, decltype(std::free)*> lang_auto(lang, std::free);
1066 std::string language = GetLanguage(lang);
1067 if (!language.empty()) {
1068 _D("*****language(%s)", language.c_str());
1069 setenv("LANGUAGE", language.c_str(), 1);
1071 setenv("LANGUAGE", lang, 1);
1073 setenv("LANG", lang, 1);
1074 setenv("LC_MESSAGES", lang, 1);
1075 setenv("LC_ALL", lang, 1);
1076 char* r = setlocale(LC_ALL, "");
1078 r = setlocale(LC_ALL, "en_US.UTF-8");
1080 _D("*****appcore setlocale=%s\n", r);
1082 _D("*****appcore setlocale=\"C\"");
1083 setenv("LC_ALL", "C", 1);
1084 r = setlocale(LC_ALL, "");
1086 _E("failed to setlocale");
1091 void AppCoreBase::Impl::UpdateRegion() {
1092 char* region = vconf_get_str(VCONFKEY_REGIONFORMAT);
1093 if (region == nullptr)
1096 std::unique_ptr<char, decltype(std::free)*> region_auto(region, std::free);
1097 setenv("LC_CTYPE", region, 1);
1098 setenv("LC_NUMERIC", region, 1);
1099 setenv("LC_TIME", region, 1);
1100 setenv("LC_COLLATE", region, 1);
1101 setenv("LC_MONETARY", region, 1);
1102 setenv("LC_PAPER", region, 1);
1103 setenv("LC_NAME", region, 1);
1104 setenv("LC_ADDRESS", region, 1);
1105 setenv("LC_TELEPHONE", region, 1);
1106 setenv("LC_MEASUREMENT", region, 1);
1107 setenv("LC_IDENTIFICATION", region, 1);
1108 char* r = setlocale(LC_ALL, "");
1110 _D("*****appcore setlocale=%s\n", r);
1112 _D("*****appcore setlocale=\"C\"");
1113 setenv("LC_ALL", "C", 1);
1114 r = setlocale(LC_ALL, "");
1116 _E("failed to setlocale");
1120 int AppCoreBase::SetI18n(std::string domain_name, std::string dir_name) {
1121 if (domain_name.empty()) {
1126 if (!dir_name.empty())
1127 impl_->locale_dir_ = dir_name;
1129 impl_->UpdateLang();
1130 impl_->UpdateRegion();
1132 char* r = setlocale(LC_ALL, "");
1133 /* if locale is not set properly, try to set "en_US" again */
1135 r = setlocale(LC_ALL, "en_US.UTF-8");
1137 _E("appcore: setlocale() error");
1138 _D("*****appcore setlocale=\"C\"");
1139 setenv("LC_ALL", "C", 1);
1140 r = setlocale(LC_ALL, "");
1142 _E("failed to setlocale");
1147 _D("*****appcore setlocale=%s\n", r);
1149 r = bindtextdomain(domain_name.c_str(), dir_name.c_str());
1151 _E("appcore: bindtextdomain() error");
1153 r = textdomain(domain_name.c_str());
1155 _E("appcore: textdomain() error");
1160 void AppCoreBase::Exit() {
1161 aul_status_update(STATUS_DYING);
1162 if (impl_->loop_delegator_)
1163 impl_->loop_delegator_->OnLoopExit();
1168 void AppCoreBase::AddSuspendTimer() {
1169 impl_->tid_ = GLib::TimeoutAdd(5000, [](gpointer data) -> gboolean {
1170 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(data);
1171 base->FlushMemory();
1176 void AppCoreBase::RemoveSuspendTimer() {
1177 if (impl_->tid_ > 0) {
1178 GLib::SourceRemove(impl_->tid_);
1183 void AppCoreBase::SetDisplayState(DisplayState state) {
1184 __display_state = state;
1187 AppCoreBase::DisplayState AppCoreBase::GetDisplayState() {
1188 return __display_state;
1191 int AppCoreBase::EnableWatchdog() {
1192 _I("[__APPCORE_WATCHDOG__] enable");
1193 return aul_watchdog_enable();
1196 int AppCoreBase::DisableWatchdog() {
1197 _I("[__APPCORE_WATCHDOG__] disable");
1198 return aul_watchdog_disable();
1201 int AppCoreBase::KickWatchdog() {
1202 _I("[__APPCORE_WATCHDOG__] kick");
1203 return aul_watchdog_kick();
1206 void AppCoreBase::Run(int argc, char** argv) {
1211 void AppCoreBase::Init(int argc, char** argv) {
1213 impl_->suspended_state_ = false;
1214 impl_->allowed_bg_ = false;
1215 impl_->argc_ = argc;
1216 impl_->argv_ = argv;
1217 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:OPS_INIT");
1218 sigterm_handler.Restore();
1219 if (impl_->loop_delegator_)
1220 impl_->loop_delegator_->OnLoopInit(argc, argv);
1222 OnLoopInit(argc, argv);
1224 impl_->signal_handler_source_ = g_unix_signal_add(SIGTERM,
1225 [](gpointer data) -> gboolean {
1226 _W("sigterm handler");
1227 if (context_ != nullptr) {
1229 context_->impl_->signal_handler_source_ = 0;
1232 return G_SOURCE_REMOVE;
1235 if (impl_->signal_handler_source_ == 0)
1236 _E("Failed to add sigterm handler.");
1238 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1240 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:PLUGIN_INIT");
1241 impl_->PluginInit(argc, argv);
1242 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1244 if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT)
1245 GLib::IdleAdd(Impl::InitSuspendCb, this);
1247 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:SET_SYSTEM_EVENT");
1248 if (!impl_->dirty_) {
1249 impl_->dirty_ = true;
1251 for (auto& e : impl_->events_) {
1252 if (impl_->core_delegator_)
1253 impl_->core_delegator_->OnSetEvent(e->GetType());
1255 OnSetEvent(e->GetType());
1258 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1260 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:VERIFY_LANG");
1261 impl_->VerifyLanguage();
1262 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1264 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:SET_DEFAULT_EVENTS");
1265 impl_->SetDefaultEvents();
1266 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1268 if (impl_->core_delegator_)
1269 impl_->core_delegator_->OnSetI18n();
1273 aul_app_lifecycle_update_state(AUL_APP_LIFECYCLE_STATE_INITIALIZED);
1275 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:CREATE");
1277 if (impl_->core_delegator_)
1278 create = impl_->core_delegator_->OnCreate();
1280 create = OnCreate();
1281 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1283 aul_app_lifecycle_update_state(AUL_APP_LIFECYCLE_STATE_CREATED);
1287 if (impl_->loop_delegator_)
1288 impl_->loop_delegator_->OnLoopRun();
1293 void AppCoreBase::Fini() {
1294 if (impl_->signal_handler_source_) {
1295 g_source_remove(impl_->signal_handler_source_);
1296 impl_->signal_handler_source_ = 0;
1302 void AppCoreBase::Dispose() {
1303 aul_status_update(STATUS_DYING);
1305 aul_app_lifecycle_update_state(AUL_APP_LIFECYCLE_STATE_DESTROYED);
1307 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:TERMINATE");
1308 if (impl_->core_delegator_)
1309 impl_->core_delegator_->OnTerminate();
1312 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1314 for (auto& e : impl_->events_) {
1315 if (impl_->core_delegator_)
1316 impl_->core_delegator_->OnUnsetEvent(e->GetType());
1318 OnUnsetEvent(e->GetType());
1321 impl_->UnsetDefaultEvents();
1323 GLib::SourceRemove(impl_->sid_);
1327 RemoveSuspendTimer();
1328 impl_->PluginFini();
1329 impl_->dirty_ = false;
1330 if (impl_->loop_delegator_)
1331 impl_->loop_delegator_->OnLoopFinish();
1336 void AppCoreBase::SetFeature(int feature) {
1337 impl_->feature_ = feature;
1340 int AppCoreBase::GetFeature() const {
1341 return impl_->feature_;
1344 void AppCoreBase::Impl::PluginInit(int argc, char** argv) {
1345 plugin_.reset(AppCorePlugin::Load());
1349 plugin_->Init(argc, argv);
1352 void AppCoreBase::Impl::PluginFini() {
1359 } // namespace tizen_cpp