From c7350e85e99d47686509c60e32d5ce062f84dd44 Mon Sep 17 00:00:00 2001 From: Mu-Woong Lee Date: Tue, 25 Jul 2017 19:02:59 +0900 Subject: [PATCH] Implement ActionState and ClosingState Change-Id: I5275369bde6068d285314e17f77003cdd1263d70 Signed-off-by: Mu-Woong Lee --- src/server/ActionDBusCaller.cpp | 67 ++++++++++++++++++++++ src/server/ActionDBusCaller.h | 46 ++++++++++++++++ src/server/ActionState.cpp | 107 +++++++++++++++++++++++++++++++++--- src/server/ActionState.h | 15 +++++ src/server/ClosingState.cpp | 26 ++++++--- src/server/ClosingState.h | 5 +- src/server/JobSchedulerService.cpp | 9 ++- src/server/ReqVerificationState.cpp | 28 ++++++++-- src/server/ReqVerificationState.h | 5 ++ src/shared/Conf.h | 3 + src/shared/JobAction.cpp | 24 ++++---- src/shared/JobAction.h | 2 +- 12 files changed, 298 insertions(+), 39 deletions(-) create mode 100644 src/server/ActionDBusCaller.cpp create mode 100644 src/server/ActionDBusCaller.h diff --git a/src/server/ActionDBusCaller.cpp b/src/server/ActionDBusCaller.cpp new file mode 100644 index 0000000..8ad0ce7 --- /dev/null +++ b/src/server/ActionDBusCaller.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2017 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 "ActionDBusCaller.h" + +using namespace ctx; + +GDBusConnection* ActionDBusCaller::__connection = NULL; + +static void __async_ready_cb(GObject* obj, GAsyncResult* res, gpointer data) +{ + GError *gerr = NULL; + GDBusConnection* conn = static_cast(data); + GVariant* param = g_dbus_connection_call_finish(conn, res, &gerr); + + if (param) + g_variant_unref(param); + + HANDLE_GERROR(gerr); +} + +ActionDBusCaller::ActionDBusCaller() +{ +} + +ActionDBusCaller::~ActionDBusCaller() +{ +} + +bool ActionDBusCaller::call(const std::string& busName, const std::string& objectPath, + const std::string& interface, const std::string& methodName, GVariant* param) +{ + IF_FAIL_RETURN(__connection, false); + + g_dbus_connection_call(__connection, busName.c_str(), + objectPath.c_str(), interface.c_str(), methodName.c_str(), param, + NULL, G_DBUS_CALL_FLAGS_NONE, CTX_DBUS_TIMEOUT, NULL, __async_ready_cb, __connection); + + return true; +} + +bool ActionDBusCaller::call(const std::string& busName, const std::string& objectPath, + const std::string& interface, const std::string& methodName, GVariant* param, uid_t uid) +{ + IF_FAIL_RETURN(__connection, false); + + //TODO + return false; +} + +void ActionDBusCaller::setConnection(GDBusConnection* conn) +{ + __connection = conn; +} diff --git a/src/server/ActionDBusCaller.h b/src/server/ActionDBusCaller.h new file mode 100644 index 0000000..2d2d29d --- /dev/null +++ b/src/server/ActionDBusCaller.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017 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 __CONTEXT_JOB_SCHEDULER_ACTION_DBUS_CALLER_H__ +#define __CONTEXT_JOB_SCHEDULER_ACTION_DBUS_CALLER_H__ + +#include +#include + +namespace ctx { + + class ActionDBusCaller { + public: + ActionDBusCaller(); + ~ActionDBusCaller(); + + bool call(const std::string& busName, const std::string& objectPath, + const std::string& interface, const std::string& methodName, + GVariant* param); + + bool call(const std::string& busName, const std::string& objectPath, + const std::string& interface, const std::string& methodName, + GVariant* param, uid_t uid); + + static void setConnection(GDBusConnection* conn); + + private: + static GDBusConnection* __connection; + }; + +} + +#endif /* __CONTEXT_JOB_SCHEDULER_ACTION_DBUS_CALLER_H__ */ diff --git a/src/server/ActionState.cpp b/src/server/ActionState.cpp index 968f25a..ffc919c 100644 --- a/src/server/ActionState.cpp +++ b/src/server/ActionState.cpp @@ -14,37 +14,128 @@ * limitations under the License. */ +#include +#include +#include +#include "ActionDBusCaller.h" #include "ActionState.h" +#include "ClosingState.h" + +#define SYSTEM_UID 0 using namespace ctx; ActionState::ActionState(JobState* prevState, bool timeout) : - JobState(prevState) + JobState(prevState), + __timeout(timeout), + __stopped(false), + __gSrcId(0), + __client(NULL) { _ENTER; - //TODO: Check whether the timeout expired. } ActionState::~ActionState() { _EXIT; + + if (__gSrcId != 0) + g_source_remove(__gSrcId); } bool ActionState::execute() { - //TODO: Set a timeout for waiting the client finishes the job. - // If the timeout expires, let the client know that the device is about to suspend. - // And goto ClosingState. + auto type = getJobInfo()->getAction()->getType(); + + if (type == JobAction::Type::DBUS_METHOD) { + __callDBusMethod(); + + } else if (type == JobAction::Type::APP_CONTROL) { + __sendAppControl(); + + } else if (type == JobAction::Type::NOTIFICATION) { + __postNotification(); + + } else { + return false; + } + + __gSrcId = g_timeout_add(CTX_ACTION_STOP_MARGIN, __stop, this); return true; } void ActionState::setClient(IClient* client) { - //TODO: Notify the client which job has been expired (once). - // Notify the client if the timeout already expired (once). + __client = client; + IF_FAIL_VOID(__client); + + std::string jobInfo = getJobInfo()->serialize(); + + __client->publish(SIGNAL_START_JOB, g_variant_new("(sb)", jobInfo.c_str(), __timeout)); + + if (__stopped) + __client->publish(SIGNAL_STOP_JOB, g_variant_new("(s)", jobInfo.c_str())); } void ActionState::jobFinished() { - //TODO: cancel the timeout and goto ClosingState. + transit(new ClosingState(this)); +} + +void ActionState::__callDBusMethod() +{ + ActionDBusCaller caller; + JobDBusCall* action = static_cast(getJobInfo()->getAction()); + bool success = false; + + if (getUid() == SYSTEM_UID) { + success = caller.call(action->getBusName(), action->getObjectPath(), + action->getInterface(), action->getMethodName(), action->getParameters()); + } else { + success = caller.call(action->getBusName(), action->getObjectPath(), + action->getInterface(), action->getMethodName(), action->getParameters(), + getUid()); + } + + IF_FAIL_VOID_TAG(success, _E, "DBus call failed"); +} + +void ActionState::__sendAppControl() +{ + //TODO +} + +void ActionState::__postNotification() +{ + //TODO +} + +void ActionState::__stop() +{ + __stopped = true; + + if (__client) { + std::string jobInfo = getJobInfo()->serialize(); + __client->publish(SIGNAL_STOP_JOB, g_variant_new("(s)", jobInfo.c_str())); + } + + __gSrcId = g_timeout_add(CTX_ACTION_EXIT_MARGIN, __exit, this); +} + +void ActionState::__exit() +{ + __gSrcId = 0; + transit(new ClosingState(this)); +} + +gboolean ActionState::__stop(gpointer data) +{ + static_cast(data)->__stop(); + return G_SOURCE_REMOVE; +} + +gboolean ActionState::__exit(gpointer data) +{ + static_cast(data)->__exit(); + return G_SOURCE_REMOVE; } diff --git a/src/server/ActionState.h b/src/server/ActionState.h index 0d8240e..30b9a33 100644 --- a/src/server/ActionState.h +++ b/src/server/ActionState.h @@ -33,6 +33,21 @@ namespace ctx { void jobFinished(); private: + void __callDBusMethod(); + void __sendAppControl(); + void __postNotification(); + + void __stop(); + void __exit(); + + static gboolean __stop(gpointer data); + static gboolean __exit(gpointer data); + + bool __timeout; + bool __stopped; + guint __gSrcId; + IClient* __client; + WakeLock __wakeLock; }; diff --git a/src/server/ClosingState.cpp b/src/server/ClosingState.cpp index 5b5514c..f189cb8 100644 --- a/src/server/ClosingState.cpp +++ b/src/server/ClosingState.cpp @@ -14,16 +14,11 @@ * limitations under the License. */ +#include "JobRunner.h" #include "ClosingState.h" using namespace ctx; -ClosingState::ClosingState(JobRunner* runner) : - JobState(runner) -{ - _ENTER; -} - ClosingState::ClosingState(JobState* prevState) : JobState(prevState) { @@ -37,6 +32,21 @@ ClosingState::~ClosingState() bool ClosingState::execute() { - //TODO: restart or terminate the job. - return false; + g_idle_add(__exit, this); + return true; +} + +void ClosingState::__exit() +{ + if (getJobInfo()->isOneTime()) { + getJobRunner()->terminate(); + } else { + getJobRunner()->restart(); + } +} + +gboolean ClosingState::__exit(gpointer data) +{ + static_cast(data)->__exit(); + return G_SOURCE_REMOVE; } diff --git a/src/server/ClosingState.h b/src/server/ClosingState.h index ba717d5..bf701b9 100644 --- a/src/server/ClosingState.h +++ b/src/server/ClosingState.h @@ -24,13 +24,16 @@ namespace ctx { class ClosingState : public JobState { public: - ClosingState(JobRunner* runner); ClosingState(JobState* prevState); ~ClosingState(); bool execute(); private: + void __exit(); + + static gboolean __exit(gpointer data); + WakeLock __wakeLock; }; diff --git a/src/server/JobSchedulerService.cpp b/src/server/JobSchedulerService.cpp index 81ea9cf..d720d16 100644 --- a/src/server/JobSchedulerService.cpp +++ b/src/server/JobSchedulerService.cpp @@ -22,8 +22,9 @@ #include "MethodCallHandler.h" #include "ContextManager.h" #include "SchedTimer.h" +#include "ActionDBusCaller.h" -#define ROOT_UID 0 +#define SYSTEM_UID 0 using namespace ctx; @@ -40,6 +41,7 @@ JobSchedulerService::~JobSchedulerService() void JobSchedulerService::setServiceRunner(IServiceRunner* runner) { + __serviceRunner = runner; } const char* JobSchedulerService::getServiceName() @@ -61,7 +63,8 @@ bool JobSchedulerService::prepare() { ContextManager::init(); SchedTimer::init(); - __jobManagers.emplace(ROOT_UID, new JobManager(ROOT_UID)); + ActionDBusCaller::setConnection(__serviceRunner->getConnection()); + __jobManagers.emplace(SYSTEM_UID, new JobManager(SYSTEM_UID)); return true; } @@ -92,7 +95,7 @@ void JobSchedulerService::onUserDeactivated(uid_t uid) JobManager* JobSchedulerService::getJobManager(uid_t uid) { if (util::is_system(uid)) - uid = ROOT_UID; + uid = SYSTEM_UID; auto it = __jobManagers.find(uid); IF_FAIL_RETURN_TAG(it != __jobManagers.end(), NULL, _W, "Unknown UID"); diff --git a/src/server/ReqVerificationState.cpp b/src/server/ReqVerificationState.cpp index dced5c5..707d0df 100644 --- a/src/server/ReqVerificationState.cpp +++ b/src/server/ReqVerificationState.cpp @@ -27,7 +27,9 @@ using namespace ctx; ReqVerificationState::ReqVerificationState(JobState* prevState) : - JobState(prevState) + JobState(prevState), + __startSrcId(0), + __timeoutSrcId(0) { _ENTER; } @@ -43,11 +45,6 @@ bool ReqVerificationState::execute() if (!__subscribe()) return false; - unsigned int timeout = std::max(getJobInfo()->getRequirementTimeout(), MIN_TIMEOUT); - - g_idle_add(__onStart, this); - g_timeout_add(timeout, __onTimeout, this); - return true; } @@ -80,11 +77,26 @@ bool ReqVerificationState::__subscribe() __reqInfos.emplace_back(req, pubs); } + unsigned int timeout = std::max(getJobInfo()->getRequirementTimeout(), MIN_TIMEOUT); + + __startSrcId = g_idle_add(__onStart, this); + __timeoutSrcId = g_timeout_add(timeout, __onTimeout, this); + return true; } void ReqVerificationState::__unsubscribe() { + if (__startSrcId != 0) { + g_source_remove(__startSrcId); + __startSrcId = 0; + } + + if (__timeoutSrcId != 0) { + g_source_remove(__timeoutSrcId); + __timeoutSrcId = 0; + } + for (auto& info : __reqInfos) { info.pubs->removeObserver(this); } @@ -139,6 +151,8 @@ bool ReqVerificationState::__inspectDisjunction() void ReqVerificationState::__onStart() { + __startSrcId = 0; + __readLatest(); if (__inspectAll()) @@ -147,6 +161,8 @@ void ReqVerificationState::__onStart() void ReqVerificationState::__onTimeout() { + __timeoutSrcId = 0; + if (__inspectMandatory()) { __unsubscribe(); transit(new ActionState(this, true)); diff --git a/src/server/ReqVerificationState.h b/src/server/ReqVerificationState.h index 7133147..008ae1a 100644 --- a/src/server/ReqVerificationState.h +++ b/src/server/ReqVerificationState.h @@ -54,7 +54,12 @@ namespace ctx { ContextPublisher* pubs; ReqInfo(JobRequirement* r, ContextPublisher* p); }; + std::list __reqInfos; + + guint __startSrcId; + guint __timeoutSrcId; + WakeLock __wakeLock; }; diff --git a/src/shared/Conf.h b/src/shared/Conf.h index 7b24cae..7c76ea4 100644 --- a/src/shared/Conf.h +++ b/src/shared/Conf.h @@ -23,4 +23,7 @@ #define CTX_PERIOD_MARGIN 0.25 // from 0 to 1 +#define CTX_ACTION_STOP_MARGIN 2000 // milli-seconds +#define CTX_ACTION_EXIT_MARGIN 500 // milli-seconds + #endif /* __CONTEXT_JOB_SCHEDULER_CONF_H__ */ diff --git a/src/shared/JobAction.cpp b/src/shared/JobAction.cpp index 47fdd68..745a2c0 100644 --- a/src/shared/JobAction.cpp +++ b/src/shared/JobAction.cpp @@ -85,9 +85,13 @@ JobDBusCall::JobDBusCall(const std::string& busName, const std::string& objPath, __busName(busName), __objectPath(objPath), __interface(interface), - __methodName(methodName), - __parameters(param) + __methodName(methodName) { + if (param) { + //TODO: escaping quotes? + char* paramStr = g_variant_print(param, TRUE); + __parameters = paramStr ? paramStr : EMPTY_STR; + } } JobDBusCall::JobDBusCall(Json::Value& jsonNode) @@ -96,13 +100,11 @@ JobDBusCall::JobDBusCall(Json::Value& jsonNode) __objectPath = jsonNode[KEY_OBJ_PATH].asString(); __interface = jsonNode[KEY_INTERFACE].asString(); __methodName = jsonNode[KEY_METHOD].asString(); - __parameters = g_variant_parse(NULL, jsonNode[KEY_PARAM].asString().c_str(), NULL, NULL, NULL); + __parameters = jsonNode[KEY_PARAM].asString(); } JobDBusCall::~JobDBusCall() { - if (__parameters) - g_variant_unref(__parameters); } JobAction::Type JobDBusCall::getType() const @@ -132,7 +134,10 @@ const std::string& JobDBusCall::getMethodName() const GVariant* JobDBusCall::getParameters() { - return __parameters; + if (__parameters.empty()) + return NULL; + + return g_variant_parse(NULL, __parameters.c_str(), NULL, NULL, NULL); } void JobDBusCall::toJson(Json::Value& jsonNode) const @@ -143,12 +148,7 @@ void JobDBusCall::toJson(Json::Value& jsonNode) const node[KEY_OBJ_PATH] = __objectPath; node[KEY_INTERFACE] = __interface; node[KEY_METHOD] = __methodName; - - if (__parameters) { - char* param = g_variant_print(__parameters, TRUE); - //TODO: escaping quotes? - node[KEY_PARAM] = param; - } + node[KEY_PARAM] = __parameters; } JobAppControl::JobAppControl(bundle* appCtrlBundle) : diff --git a/src/shared/JobAction.h b/src/shared/JobAction.h index ea68d88..45c0f1b 100644 --- a/src/shared/JobAction.h +++ b/src/shared/JobAction.h @@ -70,7 +70,7 @@ namespace ctx { std::string __objectPath; std::string __interface; std::string __methodName; - GVariant* __parameters; + std::string __parameters; }; -- 2.7.4