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>
54 #include "app-core-cpp/app_core_plugin_private.hh"
55 #include "app-core-cpp/exit_handler_private.hh"
56 #include "app-core-cpp/sigterm_handler_private.hh"
57 #include "common/glib_private.hh"
58 #include "common/log_private.hh"
59 #include "common/log_tracer.hh"
61 extern "C" void aul_finalize();
64 AppCoreBase* AppCoreBase::context_ = nullptr;
68 internal::ExitHandler exit_handler;
69 internal::SigtermHandler sigterm_handler;
80 TizenProfile TizenProfileGet() {
81 static TizenProfile profile = TizenProfile::Unknown;
82 if (__builtin_expect(profile != TizenProfile::Unknown, 1))
85 char* profile_name = nullptr;
86 system_info_get_platform_string("http://tizen.org/feature/profile",
88 if (profile_name == nullptr)
91 switch (*profile_name) {
94 profile = TizenProfile::Mobile;
98 profile = TizenProfile::Wearable;
102 profile = TizenProfile::Tv;
106 profile = TizenProfile::Ivi;
109 profile = TizenProfile::Common;
117 constexpr const char PATH_LOCALE[] = "locale";
118 constexpr int SQLITE_FLUSH_MAX = 1024 * 1024;
119 constexpr const char RESOURCED_FREEZER_PATH[] =
120 "/Org/Tizen/ResourceD/Freezer";
121 constexpr const char RESOURCED_FREEZER_INTERFACE[] =
122 "org.tizen.resourced.freezer";
123 constexpr const char RESOURCED_FREEZER_SIGNAL[] =
130 tizen_cpp::AppCoreBase::RotationState rm;
136 GDBusConnection* __bus;
137 guint __suspend_dbus_handler_initialized;
138 AppCoreBase::DisplayState __display_state = AppCoreBase::DISPLAY_STATE_UNKNOWN;
142 class AppCoreBase::EventBase::Impl {
144 friend class AppCoreBase;
145 Type type_ = IEvent::Type::START;
146 std::string str_val_;
150 class AppCoreBase::Impl {
152 explicit Impl(AppCoreBase* parent) : parent_(parent) {
153 if (TizenProfileGet() & TizenProfile::Wearable)
154 feature_ |= FEATURE_CHARGER_STATUS;
155 if (!(TizenProfileGet() & TizenProfile::Tv))
156 feature_ |= FEATURE_BACKGROUND_MANAGEMENT;
160 void UnregisterRotationChangedEvent();
161 void RegisterRotationChangedEvent();
162 std::string GetAppName(const char* appid);
163 std::string GetLocaleResourceDir();
166 std::list<std::string> SplitLanguage(const std::string& lang);
167 std::string GetLanguage(std::string lang);
168 void AppendDefaultLangs(std::vector<std::string>& lang_set);
169 std::string GetStringBefore(const char* str, const char* delim);
170 std::map<std::string, std::set<std::string>> GetLangTable();
171 void AppendLangs(const std::string& lang, std::vector<std::string>& lang_set,
172 std::map<std::string, std::set<std::string>>& table);
174 void OnFreezerSignal();
177 void InvokeCallback(T event, IEvent::Type type) {
178 for (auto& i : events_) {
179 if (i->GetType() != type)
182 if (i->GetVal(event) != event ||
183 type == IEvent::Type::START ||
184 type == IEvent::Type::UPDATE_REQUESTED) {
191 static void InitSuspendDbusHandler(gpointer data);
192 static gboolean InitSuspendCb(gpointer data);
193 static gboolean InvokeLangChangeCb(gpointer data);
194 static void ReceiveSuspendSignalCb(GDBusConnection*, const gchar*,
195 const gchar*, const gchar*, const gchar*, GVariant*, gpointer);
196 static void OnLowBatteryCb(keynode_t* key, void* data);
197 static void OnTimeZoneChangedCb(keynode_t* key, void* data);
198 static void LockCb(keynode_t* node, void* user_data);
199 static void AutoRotationChangedCb(sensor_t sensor, unsigned int event_type,
200 sensor_data_t* data, void* user_data);
201 static void ChargerStatusChangedCb(keynode_t* keynode, void* user_data);
202 static void LanguageChangeCb(keynode_t* key, void* data);
203 static void RegionChangeCb(keynode_t* key, void* data);
204 static void LowMemoryCb(keynode_t* key, void* data);
207 RotationState GetRm(sensor_data_t data);
208 void VerifyLanguage();
209 void SetDefaultEvents();
210 void UnsetDefaultEvents();
211 void PluginInit(int argc, char** argv);
215 friend class AppCoreBase;
216 AppCoreBase* parent_ = nullptr;
219 char** argv_ = nullptr;
220 bool suspended_state_ = false;
221 bool allowed_bg_ = false;
223 unsigned int tid_ = 0;
224 std::list<std::shared_ptr<EventBase>> events_;
225 std::string locale_dir_;
228 IAppCore* core_delegator_ = nullptr;
229 IMainLoop* loop_delegator_ = nullptr;
230 guint signal_handler_source_ = 0;
231 std::unique_ptr<AppCorePlugin> plugin_;
234 AppCoreBase::EventBase::EventBase(Type type)
235 : impl_(std::make_unique<EventBase::Impl>()) {
239 AppCoreBase::EventBase::~EventBase() = default;
241 IAppCore::IEvent::Type AppCoreBase::EventBase::GetType() const {
245 std::string AppCoreBase::EventBase::GetVal(std::string cur) const {
246 return impl_->str_val_;
249 int AppCoreBase::EventBase::GetVal(int cur) const {
253 void AppCoreBase::EventBase::SetVal(std::string val) {
254 impl_->str_val_ = std::move(val);
257 void AppCoreBase::EventBase::SetVal(int val) {
258 impl_->val_ = std::move(val);
261 AppCoreBase::AppCoreBase()
262 : impl_(std::make_unique<AppCoreBase::Impl>(this)) {
263 if (context_ != nullptr) {
264 _E("Context is already initialized");
270 AppCoreBase::~AppCoreBase() {
275 AppCoreBase* AppCoreBase::GetContext() {
276 if (context_ == nullptr) {
277 _E("Context is not initialized.");
284 void AppCoreBase::Impl::ChangeLang() {
285 const char* lang = getenv("LANG");
289 InvokeCallback(lang, IEvent::Type::LANG_CHANGE);
292 void AppCoreBase::RaiseEvent(int event, IEvent::Type type) {
293 impl_->InvokeCallback(event, type);
296 void AppCoreBase::RaiseEvent(const std::string& event, IEvent::Type type) {
297 impl_->InvokeCallback(event, type);
300 void AppCoreBase::Impl::OnFreezerSignal() {
301 if (!allowed_bg_ && suspended_state_) {
302 parent_->RemoveSuspendTimer();
303 InvokeCallback(SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND,
304 IEvent::Type::SUSPENDED_STATE_CHANGE);
305 suspended_state_ = false;
306 parent_->AddSuspendTimer();
310 AppCoreBase::RotationState AppCoreBase::Impl::GetRm(sensor_data_t data) {
311 if (data.value_count <= 0) {
312 _E("Failed to get sensor data");
313 return ROTATION_UNKNOWN;
316 int event = data.values[0];
318 case AUTO_ROTATION_DEGREE_0:
319 return ROTATION_PORTRAIT_NORMAL;
320 case AUTO_ROTATION_DEGREE_90:
321 return ROTATION_LANDSCAPE_NORMAL;
322 case AUTO_ROTATION_DEGREE_180:
323 return ROTATION_PORTRAIT_REVERSE;
324 case AUTO_ROTATION_DEGREE_270:
325 return ROTATION_LANDSCAPE_REVERSE;
327 return ROTATION_UNKNOWN;
331 void AppCoreBase::Impl::InitSuspendDbusHandler(gpointer data) {
332 if (__suspend_dbus_handler_initialized)
335 if (__bus == nullptr) {
336 GError* err = nullptr;
337 __bus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &err);
338 if (__bus == nullptr) {
339 _E("Failed to connect to the D-BUS daemon: %s", err ? err->message : "");
347 __suspend_dbus_handler_initialized = g_dbus_connection_signal_subscribe(
348 __bus, nullptr, RESOURCED_FREEZER_INTERFACE, RESOURCED_FREEZER_SIGNAL,
349 RESOURCED_FREEZER_PATH, nullptr, G_DBUS_SIGNAL_FLAGS_NONE,
350 ReceiveSuspendSignalCb, data, nullptr);
352 if (__suspend_dbus_handler_initialized == 0) {
353 _E("g_dbus_connection_signal_subscribe() is failed.");
357 _D("[__SUSPEND__] suspend signal initialized");
360 gboolean AppCoreBase::Impl::InitSuspendCb(gpointer data) {
361 InitSuspendDbusHandler(data);
362 return G_SOURCE_REMOVE;
365 gboolean AppCoreBase::Impl::InvokeLangChangeCb(gpointer data) {
366 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(data);
367 base->impl_->sid_ = 0;
368 base->impl_->ChangeLang();
369 return G_SOURCE_REMOVE;
372 void AppCoreBase::Impl::ReceiveSuspendSignalCb(GDBusConnection*, const gchar*,
373 const gchar*, const gchar*, const gchar* signal_name, GVariant* parameters,
374 gpointer user_data) {
375 if (g_strcmp0(signal_name, RESOURCED_FREEZER_SIGNAL) == 0) {
378 g_variant_get(parameters, "(ii)", &status, &pid);
379 if (pid == getpid() && status == 0) {
380 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
381 base->impl_->OnFreezerSignal();
386 void AppCoreBase::Impl::LanguageChangeCb(keynode_t* key, void* user_data) {
387 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
388 if (base->impl_->sid_) {
389 GLib::SourceRemove(base->impl_->sid_);
390 base->impl_->sid_ = 0;
393 char* val = vconf_keynode_get_str(key);
397 base->impl_->UpdateLang();
398 base->impl_->InvokeCallback(val, IEvent::Type::LANG_CHANGE);
401 void AppCoreBase::Impl::RegionChangeCb(keynode_t* key, void* user_data) {
402 const char* name = vconf_keynode_get_name(key);
406 if (strcmp(name, VCONFKEY_REGIONFORMAT) &&
407 strcmp(name, VCONFKEY_REGIONFORMAT_TIME1224))
410 char* val = vconf_get_str(VCONFKEY_REGIONFORMAT);
413 std::unique_ptr<char, decltype(std::free)*> region_auto(val, std::free);
415 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
416 base->impl_->UpdateRegion();
417 base->impl_->InvokeCallback(val, IEvent::Type::REGION_CHANGE);
420 void AppCoreBase::Impl::LowMemoryCb(keynode_t* key, void* user_data) {
421 int val = vconf_keynode_get_int(key);
422 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
423 base->impl_->InvokeCallback(val, IEvent::Type::LOW_MEMORY);
424 if (val >= VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING)
428 void AppCoreBase::Impl::ChargerStatusChangedCb(keynode_t* keynode,
430 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
431 if (base->impl_->feature_ & FEATURE_CHARGER_STATUS) {
432 __rotation.charger_status = vconf_keynode_get_int(keynode);
433 if (__rotation.ref) {
434 if (__rotation.charger_status) {
435 base->impl_->InitRotation();
437 base->impl_->FiniRotation();
441 _D("charger status(%d)", __rotation.charger_status);
445 void AppCoreBase::Impl::LockCb(keynode_t* node, void* user_data) {
446 AppCoreBase::RotationState rm;
447 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
449 __rotation.lock = !vconf_keynode_get_bool(node);
450 if (__rotation.lock) {
451 _D("Rotation locked");
452 rm = ROTATION_PORTRAIT_NORMAL;
454 _D("Rotation unlocked");
456 bool r = sensord_get_data(__rotation.conn, AUTO_ROTATION_SENSOR, &data);
458 _E("Failed to get sensor data");
462 rm = base->impl_->GetRm(data);
463 if (rm == ROTATION_UNKNOWN) {
469 if (__rotation.rm == rm)
472 _D("Rotation: %d -> %d", __rotation.rm, rm);
474 base->impl_->InvokeCallback(__rotation.rm,
475 IEvent::Type::DEVICE_ORIENTATION_CHANGED);
478 void AppCoreBase::Impl::AutoRotationChangedCb(sensor_t sensor,
479 unsigned int event_type, sensor_data_t* data, void* user_data) {
486 if (event_type != AUTO_ROTATION_CHANGE_STATE_EVENT)
489 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
490 AppCoreBase::RotationState rm = base->impl_->GetRm(*data);
491 if (rm == ROTATION_UNKNOWN) {
496 _D("Rotation: %d -> %d", __rotation.rm, rm);
498 base->impl_->InvokeCallback(__rotation.rm,
499 IEvent::Type::DEVICE_ORIENTATION_CHANGED);
502 void AppCoreBase::Impl::InitRotation() {
503 if (__rotation.initialized)
506 sensor_t sensor = sensord_get_sensor(AUTO_ROTATION_SENSOR);
507 __rotation.conn = sensord_connect(sensor);
508 if (__rotation.conn < 0) {
509 _E("Failed to connect sensord");
513 bool r = sensord_register_event(__rotation.conn,
514 AUTO_ROTATION_CHANGE_STATE_EVENT, SENSOR_INTERVAL_NORMAL, 0,
515 AutoRotationChangedCb, parent_);
517 _E("Failed to register auto rotation change event");
518 sensord_disconnect(__rotation.conn);
522 r = sensord_start(__rotation.conn, 0);
524 _E("Failed to start sensord");
525 sensord_unregister_event(__rotation.conn, AUTO_ROTATION_CHANGE_STATE_EVENT);
526 sensord_disconnect(__rotation.conn);
531 vconf_get_bool(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, &lock);
532 vconf_notify_key_changed(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, LockCb,
535 __rotation.lock = !lock;
536 __rotation.initialized = true;
539 void AppCoreBase::Impl::FiniRotation() {
540 if (!__rotation.initialized)
543 vconf_ignore_key_changed(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, LockCb);
544 sensord_unregister_event(__rotation.conn, AUTO_ROTATION_CHANGE_STATE_EVENT);
545 sensord_stop(__rotation.conn);
546 sensord_disconnect(__rotation.conn);
549 __rotation.initialized = false;
552 void AppCoreBase::Impl::VerifyLanguage() {
553 const char* env_lang = getenv("LANG");
554 if (env_lang == nullptr)
557 char* lang = vconf_get_str(VCONFKEY_LANGSET);
561 std::unique_ptr<char, decltype(std::free)*> lang_auto(lang, std::free);
563 if (strcmp(env_lang, lang) != 0) {
564 _I("LANG(%s), LANGSET(%s)", env_lang, lang);
565 sid_ = GLib::IdleAdd(InvokeLangChangeCb, parent_);
569 void AppCoreBase::Impl::SetDefaultEvents() {
570 vconf_notify_key_changed(VCONFKEY_LANGSET, LanguageChangeCb, parent_);
571 int r = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT, RegionChangeCb,
574 vconf_notify_key_changed(VCONFKEY_REGIONFORMAT_TIME1224, RegionChangeCb,
578 vconf_notify_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY, LowMemoryCb, parent_);
579 vconf_notify_key_changed(VCONFKEY_SETAPPL_TIMEZONE_ID, OnTimeZoneChangedCb,
583 void AppCoreBase::Impl::UnsetDefaultEvents() {
584 vconf_ignore_key_changed(VCONFKEY_LANGSET, LanguageChangeCb);
585 int r = vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT, RegionChangeCb);
587 vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT_TIME1224, RegionChangeCb);
589 vconf_ignore_key_changed(VCONFKEY_SYSMAN_LOW_MEMORY, LowMemoryCb);
590 vconf_ignore_key_changed(VCONFKEY_SETAPPL_TIMEZONE_ID, OnTimeZoneChangedCb);
593 int AppCoreBase::OnReceive(aul_type type, tizen_base::Bundle b) {
596 _D("[APP %d] AUL event: AUL_START", getpid());
597 if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT) {
598 std::string bg = b.GetString(AUL_K_ALLOWED_BG);
599 if (bg == "ALLOWED_BG") {
600 _D("[__SUSPEND__] allowed background");
601 impl_->allowed_bg_ = true;
602 RemoveSuspendTimer();
606 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:RESET");
607 if (impl_->core_delegator_)
608 impl_->core_delegator_->OnControl(std::move(b));
610 OnControl(std::move(b));
611 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
614 _D("[APP %d] AUL event: AUL_RESUME", getpid());
615 if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT) {
616 std::string bg = b.GetString(AUL_K_ALLOWED_BG);
617 if (bg == "ALLOWED_BG") {
618 _D("[__SUSPEND__] allowed background");
619 impl_->allowed_bg_ = true;
620 RemoveSuspendTimer();
625 _D("[APP %d] AUL event: AUL_TERMINATE", getpid());
626 aul_status_update(STATUS_DYING);
627 if (!impl_->allowed_bg_)
628 RemoveSuspendTimer();
632 case AUL_TERMINATE_INST:
633 case AUL_TERMINATE_BG_INST:
634 case AUL_TERMINATE_BGAPP:
635 _D("[APP %d] AUL event: %d", getpid(), type);
636 if (!impl_->allowed_bg_)
637 RemoveSuspendTimer();
640 _D("[APP %d] AUL event: AUL_WAKE", getpid());
641 if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT) {
642 if (!impl_->allowed_bg_ && impl_->suspended_state_) {
643 RemoveSuspendTimer();
644 int suspend = SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND;
645 impl_->InvokeCallback(suspend, IEvent::Type::SUSPENDED_STATE_CHANGE);
646 impl_->suspended_state_ = false;
651 _D("[APP %d] AUL event: AUL_SUSPEND", getpid());
652 if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT) {
653 if (!impl_->allowed_bg_ && !impl_->suspended_state_) {
654 RemoveSuspendTimer();
659 case AUL_UPDATE_REQUESTED:
660 _D("[APP %d] AUL event: AUL_UPDATE_REQUESTED", getpid());
661 impl_->InvokeCallback(0, IEvent::Type::UPDATE_REQUESTED);
664 _D("[APP %d] AUL event: %d", getpid(), type);
672 int AppCoreBase::OnCreate() {
673 int ret = aul_launch_init([](aul_type type, bundle* b, void* data) -> int {
674 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(data);
675 if (base->impl_->core_delegator_) {
676 return base->impl_->core_delegator_->OnReceive(type,
677 b ? tizen_base::Bundle(b, false, false) : tizen_base::Bundle());
679 return base->OnReceive(type,
680 b ? tizen_base::Bundle(b, false, false) : tizen_base::Bundle());
682 if (ret < 0 && ret != AUL_R_ECANCELED) {
683 _E("aul_launch_init() is failed. error(%d)", ret);
687 ret = aul_launch_argv_handler(impl_->argc_, impl_->argv_);
689 _E("aul_launch_argv_handler() is failed. error(%d)", ret);
696 int AppCoreBase::OnControl(tizen_base::Bundle b) {
700 int AppCoreBase::OnTerminate() {
705 void AppCoreBase::SetCoreDelegator(IAppCore* delegator) {
706 impl_->core_delegator_ = delegator;
709 void AppCoreBase::SetLoopDelegator(IMainLoop* delegator) {
710 impl_->loop_delegator_ = delegator;
713 std::string AppCoreBase::Impl::GetAppName(const char* appid) {
714 if (appid == nullptr)
717 /* com.vendor.name -> name */
718 const char* name_token = strrchr(appid, '.');
719 if (name_token == nullptr)
726 std::string AppCoreBase::Impl::GetLocaleResourceDir() {
727 const char* res_path = aul_get_app_resource_path();
728 if (res_path == nullptr) {
729 _E("Failed to get resource path");
733 return std::string(res_path) + PATH_LOCALE;
736 int AppCoreBase::OnSetI18n() {
737 char appid[PATH_MAX];
738 int ret = aul_app_get_appid_bypid(getpid(), appid, PATH_MAX);
740 _E("aul_app_get_appid_bypid() is failed. error(%d)", ret);
744 std::string name = impl_->GetAppName(appid);
748 std::string locale_dir = impl_->GetLocaleResourceDir();
749 if (locale_dir.empty())
752 return SetI18n(move(name), move(locale_dir));
755 void AppCoreBase::Impl::OnLowBatteryCb(keynode_t* key, void* data) {
756 int val = vconf_keynode_get_int(key);
757 if (val <= VCONFKEY_SYSMAN_BAT_CRITICAL_LOW) {
758 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(data);
759 base->impl_->InvokeCallback(val, IEvent::Type::LOW_BATTERY);
763 void AppCoreBase::Impl::OnTimeZoneChangedCb(keynode_t* key, void* data) {
765 char* time_zone_id = vconf_keynode_get_str(key);
766 if (time_zone_id == nullptr) {
770 char* time_zone = vconf_get_str(VCONFKEY_SETAPPL_TIMEZONE_INT);
771 if (time_zone != nullptr) {
772 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(data);
773 base->impl_->InvokeCallback(std::string(time_zone) + "|" + time_zone_id,
774 IEvent::Type::TIME_ZONE_CHANGED);
779 void AppCoreBase::Impl::UnregisterRotationChangedEvent() {
784 if (__rotation.ref == 0) {
786 if (feature_ & FEATURE_CHARGER_STATUS) {
787 vconf_ignore_key_changed(VCONFKEY_SYSMAN_CHARGER_STATUS,
788 ChargerStatusChangedCb);
793 void AppCoreBase::Impl::RegisterRotationChangedEvent() {
794 if (__rotation.ref == 0) {
795 if (feature_ & FEATURE_CHARGER_STATUS) {
796 vconf_get_int(VCONFKEY_SYSMAN_CHARGER_STATUS, &__rotation.charger_status);
797 vconf_notify_key_changed(VCONFKEY_SYSMAN_CHARGER_STATUS,
798 ChargerStatusChangedCb, parent_);
799 if (__rotation.charger_status)
809 int AppCoreBase::OnSetEvent(IEvent::Type event) {
811 case IEvent::Type::LOW_BATTERY:
812 vconf_notify_key_changed(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW,
813 impl_->OnLowBatteryCb, this);
815 case IEvent::Type::DEVICE_ORIENTATION_CHANGED:
816 impl_->RegisterRotationChangedEvent();
818 case IEvent::Type::SUSPENDED_STATE_CHANGE:
827 int AppCoreBase::OnUnsetEvent(IEvent::Type event) {
829 case IEvent::Type::LOW_BATTERY:
830 vconf_ignore_key_changed(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW,
831 impl_->OnLowBatteryCb);
833 case IEvent::Type::DEVICE_ORIENTATION_CHANGED:
834 impl_->UnregisterRotationChangedEvent();
836 case IEvent::Type::SUSPENDED_STATE_CHANGE:
845 int AppCoreBase::OnTrimMemory() {
846 int (*sqlite3_free_heap_memory)(int);
848 sqlite3_free_heap_memory = reinterpret_cast<
849 decltype(sqlite3_free_heap_memory)>(
850 dlsym(RTLD_DEFAULT, "sqlite3_release_memory"));
851 if (sqlite3_free_heap_memory)
852 sqlite3_free_heap_memory(SQLITE_FLUSH_MAX);
858 void AppCoreBase::AddEvent(std::shared_ptr<EventBase> event) {
860 for (auto& ev : impl_->events_) {
861 if (ev->GetType() == event->GetType()) {
868 if (impl_->core_delegator_)
869 impl_->core_delegator_->OnSetEvent(event->GetType());
871 OnSetEvent(event->GetType());
874 impl_->events_.push_back(move(event));
877 bool AppCoreBase::RemoveEvent(std::shared_ptr<EventBase> event) {
879 impl_->events_.remove_if([&](const std::shared_ptr<EventBase>& ptr)->bool {
880 if (event.get() == ptr.get()) {
890 void AppCoreBase::FlushMemory() {
891 if (impl_->core_delegator_)
892 impl_->core_delegator_->OnTrimMemory();
897 if (!impl_->allowed_bg_ && !impl_->suspended_state_) {
898 _D("[__SUSPEND__] flush case");
899 int suspend = SUSPENDED_STATE_WILL_ENTER_SUSPEND;
900 impl_->InvokeCallback(suspend, IEvent::Type::SUSPENDED_STATE_CHANGE);
901 impl_->suspended_state_ = true;
905 AppCoreBase::RotationState AppCoreBase::GetRotationState() {
907 throw std::runtime_error("invalid rotation state");
909 return __rotation.rm;
912 bool AppCoreBase::IsBgAllowed() {
913 return impl_->allowed_bg_;
916 bool AppCoreBase::IsSuspended() {
917 return impl_->suspended_state_;
920 void AppCoreBase::ToggleSuspendedState() {
921 impl_->suspended_state_ = !impl_->suspended_state_;
924 std::list<std::string> AppCoreBase::Impl::SplitLanguage(
925 const std::string& lang) {
926 std::istringstream ss(lang);
927 std::list<std::string> li;
930 while (std::getline(ss, token, ':'))
936 void AppCoreBase::Impl::AppendDefaultLangs(std::vector<std::string>& langs) {
937 langs.push_back("en_US");
938 langs.push_back("en_GB");
939 langs.push_back("en");
942 std::string AppCoreBase::Impl::GetStringBefore(const char* cstr,
944 if (cstr == nullptr || delim == nullptr)
947 auto str = std::string(cstr);
948 auto idx = str.find(delim);
949 return str.substr(0, idx);
952 std::map<std::string, std::set<std::string>> AppCoreBase::Impl::GetLangTable() {
953 if (locale_dir_.empty())
956 DIR* dp = opendir(locale_dir_.c_str());
960 std::map<std::string, std::set<std::string>> table;
961 struct dirent *dentry;
962 while ((dentry = readdir(dp)) != nullptr) {
963 if (!strcmp(dentry->d_name, ".") ||
964 !strcmp(dentry->d_name, ".."))
967 std::string buf = locale_dir_ + "/" + dentry->d_name;
968 struct stat stat_buf;
969 int ret = stat(buf.c_str(), &stat_buf);
970 if (ret != 0 || !S_ISDIR(stat_buf.st_mode))
973 std::string parent_lang = GetStringBefore(dentry->d_name, "_");
974 if (parent_lang.empty()) {
979 table[parent_lang].insert(dentry->d_name);
986 void AppCoreBase::Impl::AppendLangs(const std::string& lang,
987 std::vector<std::string>& langs,
988 std::map<std::string, std::set<std::string>>& table) {
992 langs.push_back(lang);
993 std::string extract_lang = GetStringBefore(lang.c_str(), ".");
994 if (extract_lang.empty())
997 if (std::find(langs.begin(), langs.end(), extract_lang) != langs.end())
1000 std::string parent_lang = GetStringBefore(extract_lang.c_str(), "_");
1001 if (parent_lang.empty())
1004 if (table.find(parent_lang) == table.end())
1007 auto it = table[parent_lang].find(extract_lang);
1008 if (it != table[parent_lang].end()) {
1009 std::string value = *it;
1010 if (std::find(langs.begin(), langs.end(), value) == langs.end())
1011 langs.push_back(std::move(value));
1013 table[parent_lang].erase(it);
1017 it = table[parent_lang].find(parent_lang);
1018 if (it != table[parent_lang].end()) {
1019 std::string value = *it;
1020 if (std::find(langs.begin(), langs.end(), value) == langs.end())
1021 langs.push_back(std::move(value));
1023 table[parent_lang].erase(parent_lang);
1027 if (!table[parent_lang].empty()) {
1028 auto i = table[parent_lang].begin();
1029 std::string value = *i;
1030 if (std::find(langs.begin(), langs.end(), value) == langs.end())
1031 langs.push_back(std::move(value));
1033 table[parent_lang].erase(i);
1037 std::string AppCoreBase::Impl::GetLanguage(std::string lang) {
1038 std::list<std::string> l = SplitLanguage(lang);
1042 auto table = GetLangTable();
1046 std::vector<std::string> langs;
1048 AppendLangs(i, langs, table);
1050 AppendDefaultLangs(langs);
1052 for (auto& i : langs) {
1062 void AppCoreBase::Impl::UpdateLang() {
1063 char* lang = vconf_get_str(VCONFKEY_LANGSET);
1064 if (lang == nullptr)
1067 std::unique_ptr<char, decltype(std::free)*> lang_auto(lang, std::free);
1068 std::string language = GetLanguage(lang);
1069 if (!language.empty()) {
1070 _D("*****language(%s)", language.c_str());
1071 setenv("LANGUAGE", language.c_str(), 1);
1073 setenv("LANGUAGE", lang, 1);
1075 setenv("LANG", lang, 1);
1076 setenv("LC_MESSAGES", lang, 1);
1077 setenv("LC_ALL", lang, 1);
1078 char* r = setlocale(LC_ALL, "");
1080 r = setlocale(LC_ALL, "en_US.UTF-8");
1082 _D("*****appcore setlocale=%s\n", r);
1084 _D("*****appcore setlocale=\"C\"");
1085 setenv("LC_ALL", "C", 1);
1086 r = setlocale(LC_ALL, "");
1088 _E("failed to setlocale");
1093 void AppCoreBase::Impl::UpdateRegion() {
1094 char* region = vconf_get_str(VCONFKEY_REGIONFORMAT);
1095 if (region == nullptr)
1098 std::unique_ptr<char, decltype(std::free)*> region_auto(region, std::free);
1099 setenv("LC_CTYPE", region, 1);
1100 setenv("LC_NUMERIC", region, 1);
1101 setenv("LC_TIME", region, 1);
1102 setenv("LC_COLLATE", region, 1);
1103 setenv("LC_MONETARY", region, 1);
1104 setenv("LC_PAPER", region, 1);
1105 setenv("LC_NAME", region, 1);
1106 setenv("LC_ADDRESS", region, 1);
1107 setenv("LC_TELEPHONE", region, 1);
1108 setenv("LC_MEASUREMENT", region, 1);
1109 setenv("LC_IDENTIFICATION", region, 1);
1110 char* r = setlocale(LC_ALL, "");
1112 _D("*****appcore setlocale=%s\n", r);
1114 _D("*****appcore setlocale=\"C\"");
1115 setenv("LC_ALL", "C", 1);
1116 r = setlocale(LC_ALL, "");
1118 _E("failed to setlocale");
1122 int AppCoreBase::SetI18n(std::string domain_name, std::string dir_name) {
1123 if (domain_name.empty()) {
1128 if (!dir_name.empty())
1129 impl_->locale_dir_ = dir_name;
1131 impl_->UpdateLang();
1132 impl_->UpdateRegion();
1134 char* r = setlocale(LC_ALL, "");
1135 /* if locale is not set properly, try to set "en_US" again */
1137 r = setlocale(LC_ALL, "en_US.UTF-8");
1139 _E("appcore: setlocale() error");
1140 _D("*****appcore setlocale=\"C\"");
1141 setenv("LC_ALL", "C", 1);
1142 r = setlocale(LC_ALL, "");
1144 _E("failed to setlocale");
1149 _D("*****appcore setlocale=%s\n", r);
1151 r = bindtextdomain(domain_name.c_str(), dir_name.c_str());
1153 _E("appcore: bindtextdomain() error");
1155 r = textdomain(domain_name.c_str());
1157 _E("appcore: textdomain() error");
1162 void AppCoreBase::Exit() {
1163 aul_status_update(STATUS_DYING);
1164 if (impl_->loop_delegator_)
1165 impl_->loop_delegator_->OnLoopExit();
1170 void AppCoreBase::AddSuspendTimer() {
1171 impl_->tid_ = GLib::TimeoutAdd(5000, [](gpointer data) -> gboolean {
1172 AppCoreBase* base = reinterpret_cast<AppCoreBase*>(data);
1173 base->FlushMemory();
1178 void AppCoreBase::RemoveSuspendTimer() {
1179 if (impl_->tid_ > 0) {
1180 GLib::SourceRemove(impl_->tid_);
1185 void AppCoreBase::SetDisplayState(DisplayState state) {
1186 __display_state = state;
1189 AppCoreBase::DisplayState AppCoreBase::GetDisplayState() {
1190 return __display_state;
1193 int AppCoreBase::EnableWatchdog() {
1194 _I("[__APPCORE_WATCHDOG__] enable");
1195 return aul_watchdog_enable();
1198 int AppCoreBase::DisableWatchdog() {
1199 _I("[__APPCORE_WATCHDOG__] disable");
1200 return aul_watchdog_disable();
1203 int AppCoreBase::KickWatchdog() {
1204 _I("[__APPCORE_WATCHDOG__] kick");
1205 return aul_watchdog_kick();
1208 void AppCoreBase::Run(int argc, char** argv) {
1213 void AppCoreBase::Init(int argc, char** argv) {
1214 LogTracer tracer("AppCoreBase::Init()");
1216 impl_->suspended_state_ = false;
1217 impl_->allowed_bg_ = false;
1218 impl_->argc_ = argc;
1219 impl_->argv_ = argv;
1220 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:OPS_INIT");
1221 sigterm_handler.Restore();
1222 if (impl_->loop_delegator_)
1223 impl_->loop_delegator_->OnLoopInit(argc, argv);
1225 OnLoopInit(argc, argv);
1227 impl_->signal_handler_source_ = g_unix_signal_add(SIGTERM,
1228 [](gpointer data) -> gboolean {
1229 _W("sigterm handler");
1230 if (context_ != nullptr) {
1232 context_->impl_->signal_handler_source_ = 0;
1235 return G_SOURCE_REMOVE;
1238 if (impl_->signal_handler_source_ == 0)
1239 _E("Failed to add sigterm handler.");
1241 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1243 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:PLUGIN_INIT");
1244 impl_->PluginInit(argc, argv);
1245 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1247 if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT)
1248 GLib::IdleAdd(Impl::InitSuspendCb, this);
1250 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:SET_SYSTEM_EVENT");
1251 if (!impl_->dirty_) {
1252 impl_->dirty_ = true;
1254 for (auto& e : impl_->events_) {
1255 if (impl_->core_delegator_)
1256 impl_->core_delegator_->OnSetEvent(e->GetType());
1258 OnSetEvent(e->GetType());
1261 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1263 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:VERIFY_LANG");
1264 impl_->VerifyLanguage();
1265 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1267 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:SET_DEFAULT_EVENTS");
1268 impl_->SetDefaultEvents();
1269 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1271 if (impl_->core_delegator_)
1272 impl_->core_delegator_->OnSetI18n();
1276 aul_app_lifecycle_update_state(AUL_APP_LIFECYCLE_STATE_INITIALIZED);
1278 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:CREATE");
1280 if (impl_->core_delegator_)
1281 create = impl_->core_delegator_->OnCreate();
1283 create = OnCreate();
1284 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1286 aul_app_lifecycle_update_state(AUL_APP_LIFECYCLE_STATE_CREATED);
1290 if (impl_->loop_delegator_)
1291 impl_->loop_delegator_->OnLoopRun();
1296 void AppCoreBase::Fini() {
1297 LogTracer tracer("AppCoreBase::Fini()");
1298 if (impl_->signal_handler_source_) {
1299 g_source_remove(impl_->signal_handler_source_);
1300 impl_->signal_handler_source_ = 0;
1306 void AppCoreBase::Dispose() {
1307 aul_status_update(STATUS_DYING);
1309 aul_app_lifecycle_update_state(AUL_APP_LIFECYCLE_STATE_DESTROYED);
1311 traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:TERMINATE");
1312 if (impl_->core_delegator_)
1313 impl_->core_delegator_->OnTerminate();
1316 traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
1318 for (auto& e : impl_->events_) {
1319 if (impl_->core_delegator_)
1320 impl_->core_delegator_->OnUnsetEvent(e->GetType());
1322 OnUnsetEvent(e->GetType());
1325 impl_->UnsetDefaultEvents();
1327 GLib::SourceRemove(impl_->sid_);
1331 RemoveSuspendTimer();
1332 impl_->PluginFini();
1333 impl_->dirty_ = false;
1334 if (impl_->loop_delegator_)
1335 impl_->loop_delegator_->OnLoopFinish();
1340 void AppCoreBase::SetFeature(int feature) {
1341 impl_->feature_ = feature;
1344 int AppCoreBase::GetFeature() const {
1345 return impl_->feature_;
1348 void AppCoreBase::Impl::PluginInit(int argc, char** argv) {
1349 plugin_.reset(AppCorePlugin::Load());
1353 plugin_->Init(argc, argv);
1356 void AppCoreBase::Impl::PluginFini() {
1363 } // namespace tizen_cpp