PKG_CHECK_MODULES(AUL_DEPS REQUIRED aul)
PKG_CHECK_MODULES(BUNDLE_DEPS REQUIRED bundle)
-PKG_CHECK_MODULES(CAPI_SYSTEM_INFO_DEPS REQUIRED capi-system-info)
PKG_CHECK_MODULES(DLOG_DEPS REQUIRED dlog)
PKG_CHECK_MODULES(ECORE_DEPS REQUIRED ecore)
PKG_CHECK_MODULES(ECORE_WL2_DEPS REQUIRED ecore-wl2)
appcore_base_control.h)
INCLUDE(FindPkgConfig)
-SET(APPCORE_PKG_CHECK_MODULES "gio-2.0 vconf sensor aul dlog capi-system-info ttrace pkgmgr-info")
+SET(APPCORE_PKG_CHECK_MODULES "gio-2.0 vconf sensor aul dlog ttrace pkgmgr-info")
pkg_check_modules(pkg_common REQUIRED ${APPCORE_PKG_CHECK_MODULES})
#include <dlfcn.h>
#include <vconf.h>
#include <bundle_internal.h>
-#include <system_info.h>
#include <gio/gio.h>
#include "appcore-internal.h"
BuildRequires: cmake
BuildRequires: pkgconfig(aul)
BuildRequires: pkgconfig(bundle)
-BuildRequires: pkgconfig(capi-system-info)
BuildRequires: pkgconfig(dlog)
BuildRequires: pkgconfig(ecore)
BuildRequires: pkgconfig(ecore-wl2)
APPLY_PKG_CONFIG(${TARGET_APP_CORE_CPP} PUBLIC
AUL_DEPS
BUNDLE_DEPS
- CAPI_SYSTEM_INFO_DEPS
DLOG_DEPS
GIO_2_DEPS
SENSOR_DEPS
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
-#include <system_info.h>
#include <time.h>
#include <ttrace.h>
#include <unistd.h>
#include "app-core-cpp/app_core_plugin_private.hh"
#include "app-core-cpp/exit_handler_private.hh"
#include "app-core-cpp/sigterm_handler_private.hh"
+#include "app-core-cpp/suspend_event_private.hh"
#include "common/glib_private.hh"
#include "common/log_private.hh"
#include "common/log_tracer.hh"
internal::ExitHandler exit_handler;
internal::SigtermHandler sigterm_handler;
-enum TizenProfile {
- Unknown = 0x00,
- Mobile = 0x01,
- Wearable = 0x02,
- Tv = 0x04,
- Ivi = 0x08,
- Common = 0x10,
-};
-
-TizenProfile TizenProfileGet() {
- static TizenProfile profile = TizenProfile::Unknown;
- if (__builtin_expect(profile != TizenProfile::Unknown, 1))
- return profile;
-
- char* profile_name = nullptr;
- system_info_get_platform_string("http://tizen.org/feature/profile",
- &profile_name);
- if (profile_name == nullptr)
- return profile;
-
- switch (*profile_name) {
- case 'm':
- case 'M':
- profile = TizenProfile::Mobile;
- break;
- case 'w':
- case 'W':
- profile = TizenProfile::Wearable;
- break;
- case 't':
- case 'T':
- profile = TizenProfile::Tv;
- break;
- case 'i':
- case 'I':
- profile = TizenProfile::Ivi;
- break;
- default:
- profile = TizenProfile::Common;
- break;
- }
- free(profile_name);
-
- return profile;
-}
-
constexpr const char PATH_LOCALE[] = "locale";
constexpr int SQLITE_FLUSH_MAX = 1024 * 1024;
-constexpr const char RESOURCED_FREEZER_PATH[] =
- "/Org/Tizen/ResourceD/Freezer";
-constexpr const char RESOURCED_FREEZER_INTERFACE[] =
- "org.tizen.resourced.freezer";
-constexpr const char RESOURCED_FREEZER_SIGNAL[] =
- "FreezerState";
struct Rotation {
int conn;
};
Rotation __rotation;
-GDBusConnection* __bus;
-guint __suspend_dbus_handler_initialized;
AppCoreBase::DisplayState __display_state = AppCoreBase::DISPLAY_STATE_UNKNOWN;
} // namespace
int val_ = -1;
};
-class AppCoreBase::Impl {
+class AppCoreBase::Impl : public SuspendEvent::IEventListener {
public:
- explicit Impl(AppCoreBase* parent) : parent_(parent) {
- if (TizenProfileGet() & TizenProfile::Wearable)
- feature_ |= FEATURE_CHARGER_STATUS;
- if (!(TizenProfileGet() & TizenProfile::Tv))
- feature_ |= FEATURE_BACKGROUND_MANAGEMENT;
- }
+ explicit Impl(AppCoreBase* parent) : parent_(parent) {}
private:
void UnregisterRotationChangedEvent();
}
}
- static void InitSuspendDbusHandler(gpointer data);
- static gboolean InitSuspendCb(gpointer data);
+ void InitSuspend();
+ void OnSuspend(pid_t pid, int status) override;
static gboolean InvokeLangChangeCb(gpointer data);
- static void ReceiveSuspendSignalCb(GDBusConnection*, const gchar*,
- const gchar*, const gchar*, const gchar*, GVariant*, gpointer);
static void OnLowBatteryCb(keynode_t* key, void* data);
static void OnTimeZoneChangedCb(keynode_t* key, void* data);
static void LockCb(keynode_t* node, void* user_data);
static void AutoRotationChangedCb(sensor_t sensor, unsigned int event_type,
sensor_data_t* data, void* user_data);
- static void ChargerStatusChangedCb(keynode_t* keynode, void* user_data);
static void LanguageChangeCb(keynode_t* key, void* data);
static void RegionChangeCb(keynode_t* key, void* data);
static void LowMemoryCb(keynode_t* key, void* data);
IMainLoop* loop_delegator_ = nullptr;
guint signal_handler_source_ = 0;
std::unique_ptr<AppCorePlugin> plugin_;
+ std::unique_ptr<SuspendEvent> suspend_event_;
};
AppCoreBase::EventBase::EventBase(Type type)
}
}
-void AppCoreBase::Impl::InitSuspendDbusHandler(gpointer data) {
- if (__suspend_dbus_handler_initialized)
- return;
-
- if (__bus == nullptr) {
- GError* err = nullptr;
- __bus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &err);
- if (__bus == nullptr) {
- _E("Failed to connect to the D-BUS daemon: %s", err ? err->message : "");
- if (err)
- g_error_free(err);
-
- return;
- }
- }
-
- __suspend_dbus_handler_initialized = g_dbus_connection_signal_subscribe(
- __bus, nullptr, RESOURCED_FREEZER_INTERFACE, RESOURCED_FREEZER_SIGNAL,
- RESOURCED_FREEZER_PATH, nullptr, G_DBUS_SIGNAL_FLAGS_NONE,
- ReceiveSuspendSignalCb, data, nullptr);
-
- if (__suspend_dbus_handler_initialized == 0) {
- _E("g_dbus_connection_signal_subscribe() is failed.");
- return;
- }
-
- _D("[__SUSPEND__] suspend signal initialized");
-}
-
-gboolean AppCoreBase::Impl::InitSuspendCb(gpointer data) {
- InitSuspendDbusHandler(data);
- return G_SOURCE_REMOVE;
+void AppCoreBase::Impl::InitSuspend() {
+ suspend_event_.reset(new SuspendEvent(this));
}
gboolean AppCoreBase::Impl::InvokeLangChangeCb(gpointer data) {
return G_SOURCE_REMOVE;
}
-void AppCoreBase::Impl::ReceiveSuspendSignalCb(GDBusConnection*, const gchar*,
- const gchar*, const gchar*, const gchar* signal_name, GVariant* parameters,
- gpointer user_data) {
- if (g_strcmp0(signal_name, RESOURCED_FREEZER_SIGNAL) == 0) {
- gint pid = -1;
- gint status = 0;
- g_variant_get(parameters, "(ii)", &status, &pid);
- if (pid == getpid() && status == 0) {
- AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
- base->impl_->OnFreezerSignal();
- }
- }
+void AppCoreBase::Impl::OnSuspend(pid_t pid, int status) {
+ if (pid == getpid() && status == 0) OnFreezerSignal();
}
void AppCoreBase::Impl::LanguageChangeCb(keynode_t* key, void* user_data) {
malloc_trim(0);
}
-void AppCoreBase::Impl::ChargerStatusChangedCb(keynode_t* keynode,
- void* user_data) {
- AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
- if (base->impl_->feature_ & FEATURE_CHARGER_STATUS) {
- __rotation.charger_status = vconf_keynode_get_int(keynode);
- if (__rotation.ref) {
- if (__rotation.charger_status) {
- base->impl_->InitRotation();
- } else {
- base->impl_->FiniRotation();
- }
- }
-
- _D("charger status(%d)", __rotation.charger_status);
- }
-}
-
void AppCoreBase::Impl::LockCb(keynode_t* node, void* user_data) {
AppCoreBase::RotationState rm;
AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
switch (type) {
case AUL_START:
_D("[APP %d] AUL event: AUL_START", getpid());
- if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT) {
- std::string bg = b.GetString(AUL_K_ALLOWED_BG);
- if (bg == "ALLOWED_BG") {
- _D("[__SUSPEND__] allowed background");
- impl_->allowed_bg_ = true;
- RemoveSuspendTimer();
- }
+ if (b.GetString(AUL_K_ALLOWED_BG) == "ALLOWED_BG") {
+ _D("[__SUSPEND__] allowed background");
+ impl_->allowed_bg_ = true;
+ RemoveSuspendTimer();
}
traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:RESET");
break;
case AUL_RESUME:
_D("[APP %d] AUL event: AUL_RESUME", getpid());
- if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT) {
- std::string bg = b.GetString(AUL_K_ALLOWED_BG);
- if (bg == "ALLOWED_BG") {
- _D("[__SUSPEND__] allowed background");
- impl_->allowed_bg_ = true;
- RemoveSuspendTimer();
- }
+ if (b.GetString(AUL_K_ALLOWED_BG) == "ALLOWED_BG") {
+ _D("[__SUSPEND__] allowed background");
+ impl_->allowed_bg_ = true;
+ RemoveSuspendTimer();
}
break;
case AUL_TERMINATE:
break;
case AUL_WAKE:
_D("[APP %d] AUL event: AUL_WAKE", getpid());
- if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT) {
- if (!impl_->allowed_bg_ && impl_->suspended_state_) {
- RemoveSuspendTimer();
- int suspend = SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND;
- impl_->InvokeCallback(suspend, IEvent::Type::SUSPENDED_STATE_CHANGE);
- impl_->suspended_state_ = false;
- }
+ if (!impl_->allowed_bg_ && impl_->suspended_state_) {
+ RemoveSuspendTimer();
+ int suspend = SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND;
+ impl_->InvokeCallback(suspend, IEvent::Type::SUSPENDED_STATE_CHANGE);
+ impl_->suspended_state_ = false;
}
break;
case AUL_SUSPEND:
_D("[APP %d] AUL event: AUL_SUSPEND", getpid());
- if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT) {
- if (!impl_->allowed_bg_ && !impl_->suspended_state_) {
- RemoveSuspendTimer();
- FlushMemory();
- }
+ if (!impl_->allowed_bg_ && !impl_->suspended_state_) {
+ RemoveSuspendTimer();
+ FlushMemory();
}
break;
case AUL_UPDATE_REQUESTED:
return;
__rotation.ref--;
- if (__rotation.ref == 0) {
- FiniRotation();
- if (feature_ & FEATURE_CHARGER_STATUS) {
- vconf_ignore_key_changed(VCONFKEY_SYSMAN_CHARGER_STATUS,
- ChargerStatusChangedCb);
- }
- }
+ if (__rotation.ref == 0) FiniRotation();
}
void AppCoreBase::Impl::RegisterRotationChangedEvent() {
- if (__rotation.ref == 0) {
- if (feature_ & FEATURE_CHARGER_STATUS) {
- vconf_get_int(VCONFKEY_SYSMAN_CHARGER_STATUS, &__rotation.charger_status);
- vconf_notify_key_changed(VCONFKEY_SYSMAN_CHARGER_STATUS,
- ChargerStatusChangedCb, parent_);
- if (__rotation.charger_status)
- InitRotation();
- } else {
- InitRotation();
- }
- }
+ if (__rotation.ref == 0) InitRotation();
__rotation.ref++;
}
impl_->PluginInit(argc, argv);
traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
- if (impl_->feature_ & FEATURE_BACKGROUND_MANAGEMENT)
- GLib::IdleAdd(Impl::InitSuspendCb, this);
+ GLib::IdleAdd(
+ [](gpointer data) -> gboolean {
+ AppCoreBase* base = reinterpret_cast<AppCoreBase*>(data);
+ base->impl_->InitSuspend();
+ return G_SOURCE_REMOVE;
+ },
+ this);
traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:SET_SYSTEM_EVENT");
if (!impl_->dirty_) {
--- /dev/null
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "app-core-cpp/suspend_event_private.hh"
+
+#include "common/log_private.hh"
+
+namespace {
+
+constexpr const char RESOURCED_FREEZER_PATH[] =
+ "/Org/Tizen/ResourceD/Freezer";
+constexpr const char RESOURCED_FREEZER_INTERFACE[] =
+ "org.tizen.resourced.freezer";
+constexpr const char RESOURCED_FREEZER_SIGNAL[] =
+ "FreezerState";
+
+} // namespace
+
+namespace tizen_cpp {
+
+SuspendEvent::SuspendEvent(IEventListener* listener) : listener_(listener) {
+ cancellable_ = g_cancellable_new();
+ if (cancellable_ == nullptr) {
+ _E("g_cancellable_new() is failed");
+ return;
+ }
+
+ g_bus_get(G_BUS_TYPE_SYSTEM, cancellable_, GAsyncReadyCb, this);
+}
+
+SuspendEvent::~SuspendEvent() {
+ if (source_ != 0)
+ g_dbus_connection_signal_unsubscribe(conn_, source_);
+
+ if (conn_ != nullptr)
+ g_object_unref(conn_);
+
+ if (cancellable_ != nullptr) {
+ g_cancellable_cancel(cancellable_);
+ g_object_unref(cancellable_);
+ }
+}
+
+void SuspendEvent::GAsyncReadyCb(GObject* source_object, GAsyncResult* res,
+ gpointer user_data) {
+ auto* event = static_cast<SuspendEvent*>(user_data);
+ g_object_unref(event->cancellable_);
+ event->cancellable_ = nullptr;
+
+ GError* error = nullptr;
+ event->conn_ = g_bus_get_finish(res, &error);
+ if (event->conn_ == nullptr) {
+ _E("g_bus_get_finish() is failed. error(%s)", error ? error->message : "");
+ g_clear_error(&error);
+ return;
+ }
+
+ event->source_ = g_dbus_connection_signal_subscribe(
+ event->conn_, nullptr, RESOURCED_FREEZER_INTERFACE,
+ RESOURCED_FREEZER_SIGNAL, RESOURCED_FREEZER_PATH, nullptr,
+ G_DBUS_SIGNAL_FLAGS_NONE, GDBusSignalCb, user_data, nullptr);
+ if (event->source_ == 0) {
+ _E("g_dbus_connection_signal_subscribe() is failed");
+ return;
+ }
+
+ _D("Suspend signal subscribed");
+}
+
+void SuspendEvent::GDBusSignalCb(GDBusConnection* conn,
+ const gchar* sender_name,
+ const gchar* object_path,
+ const gchar* interface_name,
+ const gchar* signal_name, GVariant* parameters,
+ gpointer user_data) {
+ if (g_strcmp0(signal_name, RESOURCED_FREEZER_SIGNAL) != 0)
+ return;
+
+ gint pid = -1;
+ gint status = 0;
+ g_variant_get(parameters, "(ii)", &status, &pid);
+ auto* event = static_cast<SuspendEvent*>(user_data);
+ event->listener_->OnSuspend(pid, status);
+}
+
+} // namespace tizen_cpp
--- /dev/null
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TIZEN_CPP_APP_CORE_CPP_SUSPEND_EVENT_PRIVATE_HH_
+#define TIZEN_CPP_APP_CORE_CPP_SUSPEND_EVENT_PRIVATE_HH_
+
+#include <gio/gio.h>
+#include <glib.h>
+#include <sys/types.h>
+
+namespace tizen_cpp {
+
+class SuspendEvent {
+ public:
+ class IEventListener {
+ public:
+ virtual ~IEventListener() = default;
+ virtual void OnSuspend(pid_t pid, int status) = 0;
+ };
+
+ explicit SuspendEvent(IEventListener* listener);
+ ~SuspendEvent();
+
+ private:
+ static void GAsyncReadyCb(GObject* source_object, GAsyncResult* res,
+ gpointer user_data);
+ static void GDBusSignalCb(GDBusConnection* conn, const gchar* sender_name,
+ const gchar* object_path,
+ const gchar* interface_name,
+ const gchar* signal_name, GVariant* parameters,
+ gpointer user_data);
+
+ private:
+ IEventListener* listener_;
+ GDBusConnection* conn_ = nullptr;
+ GCancellable* cancellable_ = nullptr;
+ guint source_ = 0;
+};
+
+} // namespace tizen_cpp
+
+#endif // TIZEN_CPP_APP_CORE_CPP_SUSPEND_EVENT_PRIVATE_HH_
APPLY_PKG_CONFIG(${TARGET_UNIT_TEST} PUBLIC
AUL_DEPS
BUNDLE_DEPS
- CAPI_SYSTEM_INFO_DEPS
DLOG_DEPS
ECORE_WL2_DEPS
ELEMENTARY_DEPS
#include "mock/test_fixture.h"
extern "C" GDBusConnection* g_bus_get_sync(GBusType bus_type,
- GCancellable* cancellable, GError** error) {
+ GCancellable* cancellable,
+ GError** error) {
return MOCK_HOOK_P3(DbusMock, g_bus_get_sync, bus_type, cancellable, error);
}
-extern "C" guint g_dbus_connection_signal_subscribe(GDBusConnection* arg0,
- const gchar* arg1, const gchar* arg2, const gchar* arg3, const gchar* arg4,
- const gchar* arg5, GDBusSignalFlags arg6, GDBusSignalCallback arg7,
- gpointer arg8, GDestroyNotify arg9) {
- return MOCK_HOOK_P10(DbusMock, g_dbus_connection_signal_subscribe,
- arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
+extern "C" guint g_dbus_connection_signal_subscribe(
+ GDBusConnection* arg0, const gchar* arg1, const gchar* arg2,
+ const gchar* arg3, const gchar* arg4, const gchar* arg5,
+ GDBusSignalFlags arg6, GDBusSignalCallback arg7, gpointer arg8,
+ GDestroyNotify arg9) {
+ return MOCK_HOOK_P10(DbusMock, g_dbus_connection_signal_subscribe, arg0, arg1,
+ arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
+}
+
+extern "C" void g_bus_get(GBusType bus_type, GCancellable* cancellable,
+ GAsyncReadyCallback callback, gpointer user_data) {
+ MOCK_HOOK_P4(DbusMock, g_bus_get, bus_type, cancellable, callback, user_data);
+}
+
+extern "C" GDBusConnection* g_bus_get_finish(GAsyncResult* res,
+ GError** error) {
+ return MOCK_HOOK_P2(DbusMock, g_bus_get_finish, res, error);
+}
+
+extern "C" void g_dbus_connection_signal_unsubscribe(GDBusConnection* conn,
+ guint subscription_id) {
+ MOCK_HOOK_P2(DbusMock, g_dbus_connection_signal_unsubscribe, conn,
+ subscription_id);
+}
+
+extern "C" GCancellable* g_cancellable_new(void) {
+ return MOCK_HOOK_P0(DbusMock, g_cancellable_new);
+}
+
+extern "C" void g_cancellable_cancel(GCancellable* cancellable) {
+ MOCK_HOOK_P1(DbusMock, g_cancellable_cancel, cancellable);
+}
+
+extern "C" void g_object_unref(gpointer object) {
+ MOCK_HOOK_P1(DbusMock, g_object_unref, object);
}
public:
DbusMock() {
using ::testing::_;
- using ::testing::Return;
using ::testing::Invoke;
+ using ::testing::Return;
static int dummy;
- conn_ = (GDBusConnection*)&dummy;
+ conn_ = reinterpret_cast<GDBusConnection*>(&dummy);
- ON_CALL(*this, g_bus_get_sync(_, _, _))
- .WillByDefault(Return(conn_));
+ ON_CALL(*this, g_bus_get_sync(_, _, _)).WillByDefault(Return(conn_));
}
- MOCK_METHOD3(g_bus_get_sync, GDBusConnection* (GBusType, GCancellable*, GError**));
+ MOCK_METHOD3(g_bus_get_sync,
+ GDBusConnection*(GBusType, GCancellable*, GError**));
+ MOCK_METHOD4(g_bus_get,
+ void(GBusType, GCancellable*, GAsyncReadyCallback, gpointer));
MOCK_METHOD10(g_dbus_connection_signal_subscribe,
guint(GDBusConnection*, const gchar*, const gchar*, const gchar*,
const gchar*, const gchar*, GDBusSignalFlags, GDBusSignalCallback,
gpointer, GDestroyNotify));
-
- private:
- GDBusConnection* conn_ = nullptr;
+ MOCK_METHOD2(g_dbus_connection_signal_unsubscribe,
+ void(GDBusConnection*, guint));
+ MOCK_METHOD0(g_cancellable_new, GCancellable*());
+ MOCK_METHOD1(g_cancellable_cancel, void(GCancellable*));
+ MOCK_METHOD1(g_object_unref, void(gpointer));
+ MOCK_METHOD2(g_bus_get_finish, GDBusConnection*(GAsyncResult*, GError**));
+
+ private:
+ GDBusConnection* conn_ = nullptr;
};
#endif // UNIT_TESTS_MOCK_DBUS_MOCK_H_
-