SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -g -Wall")
SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Werror")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS}")
SET(CMAKE_SKIP_BUILD_RPATH TRUE)
SET(APPCORE_AGENT "appcore-agent")
INCLUDE(FindPkgConfig)
-pkg_check_modules(pkg_agent REQUIRED aul dlog capi-appfw-app-control capi-appfw-app-common vconf ecore-core vconf-internal-keys appcore-common capi-system-info)
+pkg_check_modules(pkg_agent REQUIRED aul dlog capi-appfw-app-control capi-appfw-app-common vconf ecore-core vconf-internal-keys app-core-cpp capi-system-info)
FOREACH(flag ${pkg_agent_CFLAGS})
SET(EXTRA_CFLAGS_agent "${EXTRA_CFLAGS_agent} ${flag}")
ENDFOREACH(flag)
PATTERN "*.h*"
)
-ADD_SUBDIRECTORY(unittests)
\ No newline at end of file
+ADD_SUBDIRECTORY(unittests)
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* @since_tizen 4.0
* @remarks This is for App Framework internally.
*/
-typedef struct service_app_job_s *service_app_job_h;
+typedef void *service_app_job_h;
/**
* @brief Adds the job handler.
BuildRequires: pkgconfig(capi-appfw-app-control)
BuildRequires: pkgconfig(capi-appfw-app-common)
BuildRequires: pkgconfig(capi-system-info)
-BuildRequires: pkgconfig(appcore-common)
+BuildRequires: pkgconfig(app-core-cpp)
BuildRequires: pkgconfig(dlog)
BuildRequires: pkgconfig(ecore-core)
BuildRequires: pkgconfig(gmock)
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 "job-handler.hh"
+#include "log-private.hh"
+
+namespace tizen_cpp {
+
+JobHandler::JobHandler(std::string job_id, service_app_job_cb cb,
+ void* user_data)
+ : job_id_(std::move(job_id)),
+ cb_(cb),
+ user_data_(user_data) {
+}
+
+const std::string& JobHandler::GetJobId() const {
+ return job_id_;
+}
+
+void JobHandler::Do(const Job* job) {
+ if (cb_)
+ cb_(job->GetStatus(), job->GetId().c_str(), job->GetData(), user_data_);
+}
+
+} // namespace tizen_cpp
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 JOB_HANDLER_HH_
+#define JOB_HANDLER_HH_
+
+#include <string>
+
+#include "job.hh"
+#include "service_app_internal.h"
+
+namespace tizen_cpp {
+
+class JobHandler {
+ public:
+ JobHandler(std::string job_id, service_app_job_cb cb, void* user_data);
+
+ const std::string& GetJobId() const;
+ void Do(const Job* job);
+
+ private:
+ std::string job_id_;
+ service_app_job_cb cb_;
+ void* user_data_;
+};
+
+} // namespace tizen_cpp
+
+#endif // JOB_HANDLER_HH_
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 <aul.h>
+#include <aul_job_scheduler.h>
+
+#include <algorithm>
+
+#include "job-manager.hh"
+#include "log-private.hh"
+
+namespace tizen_cpp {
+
+void JobManager::AddJobHandler(JobHandler* handler) {
+ handlers_.push_back(handler);
+}
+
+void JobManager::RemoveJobHandler(JobHandler* handler) {
+ auto found = std::find(handlers_.begin(), handlers_.end(), handler);
+ if (found == handlers_.end())
+ return;
+
+ handlers_.erase(found);
+}
+
+bool JobManager::ExistJobHandler(const std::string& job_id) {
+ for (auto* h : handlers_) {
+ if (h->GetJobId() == job_id)
+ return true;
+ }
+
+ return false;
+}
+
+bool JobManager::ExistJobHandler(JobHandler* handler) {
+ for (auto* h : handlers_) {
+ if (h == handler)
+ return true;
+ }
+
+ return false;
+}
+
+void JobManager::Do(std::shared_ptr<Job> job) {
+ job->SetEventListener(this);
+ if (!ExistJobHandler(job->GetId())) {
+ job->SetTimer();
+ AddPendingJob(job);
+ } else {
+ job->SetIdler();
+ AddRunningJob(job);
+ }
+}
+
+int JobManager::Finish(const std::string& job_id) {
+ RemoveRunningJob(job_id);
+ int ret = aul_job_scheduler_update_job_status(job_id.c_str(),
+ JOB_STATUS_FINISHED);
+ if (ret != AUL_R_OK) {
+ _E("aul_job_scheduler_update_job_status() is failed. error(%d)", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+void JobManager::FinishAllJobs() {
+ running_jobs_.clear();
+ pending_jobs_.clear();
+}
+
+void JobManager::FlushPendingJob(const std::string& job_id) {
+ auto iter = pending_jobs_.begin();
+ while (iter != pending_jobs_.end()) {
+ if ((*iter)->GetId() == job_id) {
+ auto job = *iter;
+ iter = pending_jobs_.erase(iter);
+ job->UnsetTimer();
+ AddPendingJob(job);
+ job->SetIdler();
+ } else {
+ iter++;
+ }
+ }
+}
+
+void JobManager::AddRunningJob(std::shared_ptr<Job> job) {
+ running_jobs_.push_back(job);
+}
+
+void JobManager::RemoveRunningJob(const std::string& job_id) {
+ auto iter = running_jobs_.begin();
+ while (iter != running_jobs_.end()) {
+ if ((*iter)->GetId() == job_id)
+ iter = running_jobs_.erase(iter);
+ else
+ iter++;
+ }
+}
+
+void JobManager::AddPendingJob(std::shared_ptr<Job> job) {
+ pending_jobs_.push_back(job);
+}
+
+void JobManager::RemovePendingJob(const std::string& job_id) {
+ auto iter = pending_jobs_.begin();
+ while (iter != pending_jobs_.end()) {
+ if ((*iter)->GetId() == job_id)
+ iter = pending_jobs_.erase(iter);
+ else
+ iter++;
+ }
+}
+
+void JobManager::OnTimedOut(const Job* job) {
+ _E("[__TIMEDOUT__] Job(%s), Status(%d)",
+ job->GetId().c_str(), job->GetStatus());
+ RemovePendingJob(job->GetId());
+}
+
+void JobManager::OnRun(const Job* job) {
+ _D("[__JOB__] START. Job(%s), Status(%d)",
+ job->GetId().c_str(), job->GetStatus());
+ if (job->GetStatus() == SERVICE_APP_JOB_STATUS_START) {
+ aul_job_scheduler_update_job_status(job->GetId().c_str(), JOB_STATUS_START);
+ for (auto* h : handlers_) {
+ if (h->GetJobId() == job->GetId())
+ h->Do(job);
+ }
+ } else {
+ for (auto* h : handlers_) {
+ if (h->GetJobId() == job->GetId())
+ h->Do(job);
+ }
+ aul_job_scheduler_update_job_status(job->GetId().c_str(),
+ JOB_STATUS_STOPPED);
+ }
+ _D("[__JOB__] END. Job(%s), Status(%d)",
+ job->GetId().c_str(), job->GetStatus());
+ RemoveRunningJob(job->GetId());
+}
+
+} // namespace tizen_cpp
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 JOB_MANAGER_HH_
+#define JOB_MANAGER_HH_
+
+#include <list>
+#include <memory>
+#include <string>
+
+#include "job.hh"
+#include "job-handler.hh"
+
+namespace tizen_cpp {
+
+class JobManager : public Job::IEvent {
+ public:
+ void AddJobHandler(JobHandler* handler);
+ void RemoveJobHandler(JobHandler* handler);
+ bool ExistJobHandler(JobHandler* handler);
+ void Do(std::shared_ptr<Job> job);
+ int Finish(const std::string& job_id);
+ void FinishAllJobs();
+ void FlushPendingJob(const std::string& job_id);
+
+ private:
+ bool ExistJobHandler(const std::string& job_id);
+ void AddPendingJob(std::shared_ptr<Job> job);
+ void RemovePendingJob(const std::string& job_id);
+ void AddRunningJob(std::shared_ptr<Job> job);
+ void RemoveRunningJob(const std::string& job_id);
+
+ void OnTimedOut(const Job* job) override;
+ void OnRun(const Job* job) override;
+
+ private:
+ std::list<JobHandler*> handlers_;
+ std::list<std::shared_ptr<Job>> pending_jobs_;
+ std::list<std::shared_ptr<Job>> running_jobs_;
+};
+
+} // namespace tizen_cpp
+
+#endif // JOB_MANAGER_HH_
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 "job.hh"
+#include "log-private.hh"
+
+namespace tizen_cpp {
+
+Job::Job(int status, std::string id, tizen_base::Bundle data)
+ : status_(status), id_(std::move(id)), data_(std::move(data)) {
+}
+
+Job::~Job() {
+ UnsetIdler();
+ UnsetTimer();
+}
+
+int Job::GetStatus() const {
+ return status_;
+}
+
+const std::string& Job::GetId() const {
+ return id_;
+}
+
+bundle* Job::GetData() const {
+ return data_.GetHandle();
+}
+
+void Job::SetEventListener(IEvent* listener) {
+ listener_ = listener;
+}
+
+void Job::SetTimer() {
+ if (timer_ == 0) {
+ timer_ = g_timeout_add(5000, TimedOutCb, this);
+ if (timer_ == 0)
+ _E("g_timeout_add() is failed");
+ }
+}
+
+void Job::UnsetTimer() {
+ if (timer_ != 0) {
+ g_source_remove(timer_);
+ timer_ = 0;
+ }
+}
+
+void Job::SetIdler() {
+ if (idler_ == 0) {
+ idler_ = g_idle_add(IdleCb, this);
+ if (idler_ == 0)
+ _E("g_idle_add() is failed");
+ }
+}
+
+void Job::UnsetIdler() {
+ if (idler_ != 0) {
+ g_source_remove(idler_);
+ idler_ = 0;
+ }
+}
+
+gboolean Job::TimedOutCb(gpointer data) {
+ auto* handle = static_cast<Job*>(data);
+ handle->timer_ = 0;
+
+ auto* listener = handle->listener_;
+ if (listener != nullptr)
+ listener->OnTimedOut(handle);
+
+ return G_SOURCE_REMOVE;
+}
+
+gboolean Job::IdleCb(gpointer data) {
+ auto* handle = static_cast<Job*>(data);
+ handle->idler_ = 0;
+ auto* listener = handle->listener_;
+ if (listener != nullptr)
+ listener->OnRun(handle);
+
+ return G_SOURCE_REMOVE;
+}
+
+} // namespace tizen_cpp
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 JOB_HH_
+#define JOB_HH_
+
+#include <bundle_cpp.h>
+#include <glib.h>
+
+#include <string>
+
+namespace tizen_cpp {
+
+class Job {
+ public:
+ class IEvent {
+ public:
+ virtual void OnTimedOut(const Job* job) = 0;
+ virtual void OnRun(const Job* job) = 0;
+ };
+
+ Job(int status, std::string id, tizen_base::Bundle data);
+ virtual ~Job();
+
+ int GetStatus() const;
+ const std::string& GetId() const;
+ bundle* GetData() const;
+ void SetEventListener(IEvent* listener);
+ void SetTimer();
+ void UnsetTimer();
+ void SetIdler();
+ void UnsetIdler();
+
+ private:
+ static gboolean TimedOutCb(gpointer data);
+ static gboolean IdleCb(gpointer data);
+
+ private:
+ int status_;
+ std::string id_;
+ tizen_base::Bundle data_;
+ IEvent* listener_ = nullptr;
+ guint timer_ = 0;
+ guint idler_ = 0;
+};
+
+} // namespace tizen_cpp
+
+#endif // JOB_HH_
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 LOG_PRIVATE_HH_
+#define LOG_PRIVATE_HH_
+
+#include <dlog.h>
+
+#undef LOG_TAG
+#define LOG_TAG "CAPI_APPFW_APPLICATION"
+
+#undef _E
+#define _E LOGE
+
+#undef _W
+#define _W LOGW
+
+#undef _I
+#define _I LOGI
+
+#undef _D
+#define _D LOGD
+
+#endif // LOG_PRIVATE_HH_
+++ /dev/null
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * 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 <stdlib.h>
-#include <unistd.h>
-#include <bundle.h>
-#include <aul.h>
-#include <dlog.h>
-#include <vconf-internal-keys.h>
-#include <app_common.h>
-#include <Ecore.h>
-#include <appcore_base.h>
-#include <service_app.h>
-#include <aul_job_scheduler.h>
-#include <bundle_internal.h>
-#include <glib.h>
-#include <app_control_internal.h>
-
-#include "service_app_extension.h"
-#include "service_app_internal.h"
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-
-#define LOG_TAG "CAPI_APPFW_APPLICATION"
-
-typedef enum {
- APP_STATE_NOT_RUNNING,
- APP_STATE_CREATING,
- APP_STATE_RUNNING,
-} app_state_e;
-
-struct app_event_handler {
- app_event_type_e type;
- app_event_cb cb;
- void *data;
- void* raw;
-};
-
-struct app_event_info {
- app_event_type_e type;
- void *value;
-};
-
-struct service_app_context {
- service_app_lifecycle_callback_s callback;
- void *data;
- GList *running_jobs;
- GList *pending_jobs;
- GList *job_handlers;
-};
-
-struct service_app_job_s {
- char *job_id;
- service_app_job_cb callback;
- void *user_data;
-};
-
-struct job_s {
- int job_status;
- char *job_id;
- bundle *job_data;
- guint timer;
- guint idler;
-};
-
-static struct service_app_context __context;
-static app_state_e __app_state = APP_STATE_NOT_RUNNING;
-
-static int __app_event_converter[APPCORE_BASE_EVENT_MAX] = {
- [APP_EVENT_LOW_MEMORY] = APPCORE_BASE_EVENT_LOW_MEMORY,
- [APP_EVENT_LOW_BATTERY] = APPCORE_BASE_EVENT_LOW_BATTERY,
- [APP_EVENT_LANGUAGE_CHANGED] = APPCORE_BASE_EVENT_LANG_CHANGE,
- [APP_EVENT_DEVICE_ORIENTATION_CHANGED] = APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED,
- [APP_EVENT_REGION_FORMAT_CHANGED] = APPCORE_BASE_EVENT_REGION_CHANGE,
- [APP_EVENT_SUSPENDED_STATE_CHANGED] = APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE,
-};
-
-static int __on_error(app_error_e error, const char *function, const char *description);
-static void __destroy_job_handler(gpointer data);
-static bool __exist_job_handler(const char *job_id);
-
-static struct job_s *__create_job(int job_status, const char *job_id,
- bundle *job_data)
-{
- struct job_s *job;
-
- job = calloc(1, sizeof(struct job_s));
- if (job == NULL) {
- /* LCOV_EXCL_START */
- LOGE("Out of memory");
- return NULL;
- /* LCOV_EXCL_STOP */
- }
-
- job->job_id = strdup(job_id);
- if (job->job_id == NULL) {
- /* LCOV_EXCL_START */
- LOGE("Out of memory");
- free(job);
- return NULL;
- /* LCOV_EXCL_STOP */
- }
-
- job->job_data = bundle_dup(job_data);
- if (job->job_data == NULL) {
- /* LCOV_EXCL_START */
- LOGE("Out of memory");
- free(job->job_id);
- free(job);
- return NULL;
- /* LCOV_EXCL_STOP */
- }
-
- job->job_status = job_status;
-
- return job;
-}
-
-static void __destroy_job(gpointer data)
-{
- struct job_s *job = (struct job_s *)data;
-
- if (job == NULL)
- return;
-
- if (job->idler)
- g_source_remove(job->idler); /* LCOV_EXCL_LINE */
- if (job->timer)
- g_source_remove(job->timer); /* LCOV_EXCL_LINE */
- if (job->job_data)
- bundle_free(job->job_data);
- if (job->job_id)
- free(job->job_id);
- free(job);
-}
-
-/* LCOV_EXCL_START */
-static gboolean __pending_job_timeout_handler(gpointer data)
-{
- struct job_s *job = (struct job_s *)data;
-
- LOGE("[__TIMEOUT__] Job(%s) Status(%d)", job->job_id, job->job_status);
- __context.pending_jobs = g_list_remove(__context.pending_jobs, job);
- job->timer = 0;
- __destroy_job(job);
-
- return G_SOURCE_REMOVE;
-}
-/* LCOV_EXCL_STOP */
-
-static void __job_finish(void)
-{
- if (__context.running_jobs) {
- /* LCOV_EXCL_START */
- g_list_free_full(__context.running_jobs, __destroy_job);
- __context.running_jobs = NULL;
- /* LCOV_EXCL_STOP */
- }
-
- if (__context.pending_jobs) {
- /* LCOV_EXCL_START */
- g_list_free_full(__context.pending_jobs, __destroy_job);
- __context.pending_jobs = NULL;
- /* LCOV_EXCL_STOP */
- }
-
- if (__context.job_handlers) {
- g_list_free_full(__context.job_handlers, __destroy_job_handler);
- __context.job_handlers = NULL;
- }
-}
-
-static int __service_app_create(void *data)
-{
- LOGW("service_app_create()");
- appcore_base_on_create();
-
- if (__context.callback.create == NULL ||
- __context.callback.create(__context.data) == false)
- return __on_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "service_app_create_cb() returns false");
-
- return APP_ERROR_NONE;
-}
-
-static int __service_app_terminate(void *data)
-{
- LOGW("service_app_terminate()");
- if (__context.callback.terminate)
- __context.callback.terminate(__context.data);
-
- appcore_base_on_terminate();
-
- return APP_ERROR_NONE;
-}
-
-static int __service_app_control(bundle *b, void *data)
-{
- app_control_h app_control = NULL;
- const char *job_id;
-
- LOGW("service_app_control()");
- appcore_base_on_control(b);
-
- job_id = bundle_get_val(b, AUL_K_JOB_ID);
- if (job_id) {
- LOGD("[__JOB__] Job(%s)", job_id);
- return 0;
- }
-
- if (app_control_create_event(b, &app_control) != 0)
- return -1;
-
- if (__context.callback.app_control)
- __context.callback.app_control(app_control, __context.data);
-
- app_control_destroy(app_control);
-
- return 0;
-}
-
-static int __service_app_receive(aul_type type, bundle *b, void *data)
-{
- appcore_base_on_receive(type, b);
-
- if (type == AUL_TERMINATE_BGAPP) {
- appcore_base_exit();
- return 0;
- }
-
- return 0;
-}
-
-static void __loop_init(int argc, char **argv, void *data)
-{
- ecore_init();
-}
-
-static void __loop_fini(void)
-{
- ecore_shutdown();
-}
-
-static void __loop_run(void *data)
-{
- ecore_main_loop_begin();
-}
-
-static void __exit_main_loop(void *data)
-{
- ecore_main_loop_quit();
-}
-
-static void __loop_exit(void *data)
-{
- ecore_main_loop_thread_safe_call_sync((Ecore_Data_Cb)__exit_main_loop, NULL);
-}
-
-static const char *__error_to_string(app_error_e error)
-{
- switch (error) {
- case APP_ERROR_NONE:
- return "NONE";
- case APP_ERROR_INVALID_PARAMETER:
- return "INVALID_PARAMETER";
- case APP_ERROR_OUT_OF_MEMORY:
- return "OUT_OF_MEMORY";
- case APP_ERROR_INVALID_CONTEXT:
- return "INVALID_CONTEXT";
- case APP_ERROR_NO_SUCH_FILE:
- return "NO_SUCH_FILE";
- case APP_ERROR_ALREADY_RUNNING:
- return "ALREADY_RUNNING";
- default:
- return "UNKNOWN";
- }
-}
-
-static int __on_error(app_error_e error, const char *function, const char *description)
-{
- if (description)
- LOGE("[%s] %s(0x%08x) : %s", function, __error_to_string(error), error, description);
- else
- LOGE("[%s] %s(0x%08x)", function, __error_to_string(error), error);
-
- return error;
-}
-
-EXPORT_API int service_app_main_ext(int argc, char **argv, service_app_lifecycle_callback_s *callback,
- service_app_loop_method_s *method, void *user_data)
-{
- int ret;
- appcore_base_ops ops = appcore_base_get_default_ops();
-
- if (argc < 1 || argv == NULL || callback == NULL || method == NULL)
- return __on_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- if (callback->create == NULL)
- return __on_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "service_app_create_cb() callback must be registered");
-
- if (__app_state != APP_STATE_NOT_RUNNING)
- return __on_error(APP_ERROR_ALREADY_RUNNING, __FUNCTION__, NULL); /* LCOV_EXCL_LINE */
-
- /* override methods */
- ops.create = __service_app_create;
- ops.terminate = __service_app_terminate;
- ops.control = __service_app_control;
- ops.receive = __service_app_receive;
- ops.run = method->run;
- ops.exit = method->exit;
- ops.init = method->init;
- ops.finish = method->fini;
-
- __context.callback = *callback;
- __context.data = user_data;
-
- __app_state = APP_STATE_CREATING;
- ret = appcore_base_init(ops, argc, argv, NULL);
- if (ret < 0) {
- /* LCOV_EXCL_START */
- __app_state = APP_STATE_NOT_RUNNING;
- return __on_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, NULL);
- /* LCOV_EXCL_STOP */
- }
-
- appcore_base_fini();
- __job_finish();
- __app_state = APP_STATE_NOT_RUNNING;
- return APP_ERROR_NONE;
-}
-
-EXPORT_API int service_app_main(int argc, char **argv, service_app_lifecycle_callback_s *callback, void *user_data)
-{
- service_app_loop_method_s method = {
- .init = __loop_init,
- .fini = __loop_fini,
- .run = __loop_run,
- .exit = __loop_exit,
- };
-
- LOGW("service_app_main()");
- return service_app_main_ext(argc, argv, callback, &method, user_data);
-}
-
-EXPORT_API void service_app_exit(void)
-{
- LOGW("service_app_exit()");
- appcore_base_exit();
-}
-
-static int __event_cb(void *event, void *data)
-{
- app_event_handler_h handler = data;
-
- struct app_event_info app_event;
-
- app_event.type = handler->type;
- app_event.value = event;
-
- if (handler->cb)
- handler->cb(&app_event, handler->data);
- return 0;
-}
-
-EXPORT_API int service_app_add_event_handler(app_event_handler_h *event_handler, app_event_type_e event_type, app_event_cb callback, void *user_data)
-{
- app_event_handler_h handler;
-
- if (event_handler == NULL || callback == NULL)
- return __on_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "null parameter");
-
- if (event_type < APP_EVENT_LOW_MEMORY || event_type > APP_EVENT_SUSPENDED_STATE_CHANGED ||
- event_type == APP_EVENT_DEVICE_ORIENTATION_CHANGED)
- return __on_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, "invalid event type");
-
- handler = calloc(1, sizeof(struct app_event_handler));
- if (!handler)
- return __on_error(APP_ERROR_OUT_OF_MEMORY, __FUNCTION__, "insufficient memory"); /* LCOV_EXCL_LINE */
-
- handler->type = event_type;
- handler->cb = callback;
- handler->data = user_data;
- handler->raw = appcore_base_add_event(__app_event_converter[event_type], __event_cb, handler);
-
- *event_handler = handler;
-
- return APP_ERROR_NONE;
-}
-
-EXPORT_API int service_app_remove_event_handler(app_event_handler_h event_handler)
-{
- int ret;
- app_event_type_e type;
-
- if (event_handler == NULL)
- return __on_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL);
-
- type = event_handler->type;
- if (type < APP_EVENT_LOW_MEMORY ||
- type > APP_EVENT_SUSPENDED_STATE_CHANGED ||
- type == APP_EVENT_DEVICE_ORIENTATION_CHANGED)
- return __on_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); /* LCOV_EXCL_LINE */
-
- ret = appcore_base_remove_event(event_handler->raw);
- free(event_handler);
-
- if (ret < 0)
- return __on_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, NULL); /* LCOV_EXCL_LINE */
-
- return APP_ERROR_NONE;
-}
-
-EXPORT_API void service_app_exit_without_restart(void)
-{
- aul_status_update_v2(STATUS_NORESTART);
- appcore_base_exit();
-}
-
-static void __invoke_job_callback(int status, const char *job_id,
- bundle *job_data)
-{
- struct service_app_job_s *handle;
- GList *iter;
-
- iter = __context.job_handlers;
- while (iter) {
- handle = (struct service_app_job_s *)iter->data;
- iter = iter->next;
- if (strcmp(handle->job_id, job_id) == 0) {
- handle->callback(status, job_id, job_data,
- handle->user_data);
- }
- }
-}
-
-static gboolean __handle_job(gpointer data)
-{
- struct job_s *job = (struct job_s *)data;
-
- __context.running_jobs = g_list_remove(__context.running_jobs, job);
-
- LOGD("[__JOB___] Job(%s) Status(%d) START",
- job->job_id, job->job_status);
- if (job->job_status == SERVICE_APP_JOB_STATUS_START) {
- aul_job_scheduler_update_job_status(job->job_id,
- JOB_STATUS_START);
- __invoke_job_callback(job->job_status, job->job_id,
- job->job_data);
- } else {
- __invoke_job_callback(job->job_status, job->job_id,
- job->job_data);
- aul_job_scheduler_update_job_status(job->job_id,
- JOB_STATUS_STOPPED);
- }
- LOGD("[__JOB__] Job(%s) Status(%d) END",
- job->job_id, job->job_status);
-
- job->idler = 0;
- __destroy_job(job);
-
- return G_SOURCE_REMOVE;
-}
-
-static void __flush_pending_job(const char *job_id)
-{
- struct job_s *job;
- GList *iter;
-
- iter = __context.pending_jobs;
- while (iter) {
- /* LCOV_EXCL_START */
- job = (struct job_s *)iter->data;
- iter = iter->next;
- if (strcmp(job->job_id, job_id) == 0) {
- __context.pending_jobs = g_list_remove(
- __context.pending_jobs, job);
-
- if (job->timer) {
- g_source_remove(job->timer);
- job->timer = 0;
- }
-
- job->idler = g_idle_add(__handle_job, job);
- __context.running_jobs = g_list_append(
- __context.running_jobs, job);
- }
- /* LCOV_EXCL_STOP */
- }
-}
-
-static bool __exist_job_handler(const char *job_id)
-{
- struct service_app_job_s *handle;
- GList *iter;
-
- iter = __context.job_handlers;
- while (iter) {
- handle = (struct service_app_job_s *)iter->data;
- if (strcmp(handle->job_id, job_id) == 0)
- return true;
-
- iter = iter->next;
- }
-
- return false;
-}
-
-static struct service_app_job_s *__create_job_handler(const char *job_id,
- service_app_job_cb callback, void *user_data)
-{
- struct service_app_job_s *handle;
-
- handle = calloc(1, sizeof(struct service_app_job_s));
- if (handle == NULL) {
- /* LCOV_EXCL_START */
- LOGE("Out of memory");
- return NULL;
- /* LCOV_EXCL_STOP */
- }
-
- handle->job_id = strdup(job_id);
- if (handle->job_id == NULL) {
- /* LCOV_EXCL_START */
- LOGE("Out of memory");
- free(handle);
- return NULL;
- /* LCOV_EXCL_STOP */
- }
-
- handle->callback = callback;
- handle->user_data = user_data;
-
- return handle;
-}
-
-static void __destroy_job_handler(gpointer data)
-{
- struct service_app_job_s *handle = (struct service_app_job_s *)data;
-
- if (handle == NULL)
- return;
-
- if (handle->job_id)
- free(handle->job_id);
- free(handle);
-}
-
-EXPORT_API service_app_job_h service_app_add_job_handler(const char *job_id,
- service_app_job_cb callback, void *user_data)
-{
- struct service_app_job_s *handle;
-
- if (job_id == NULL || callback == NULL) {
- /* LCOV_EXCL_START */
- LOGE("Invalid parameter");
- return NULL;
- /* LCOV_EXCL_STOP */
- }
-
- handle = __create_job_handler(job_id, callback, user_data);
- if (handle == NULL)
- return NULL;
-
- __context.job_handlers = g_list_append(__context.job_handlers, handle);
-
- __flush_pending_job(job_id);
-
- return handle;
-}
-
-EXPORT_API int service_app_remove_job_handler(service_app_job_h handle)
-{
- if (handle == NULL ||
- g_list_index(__context.job_handlers, handle) < 0) {
- /* LCOV_EXCL_START */
- return __on_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__,
- NULL);
- /* LCOV_EXCL_STOP */
- }
-
- __context.job_handlers = g_list_remove(__context.job_handlers, handle);
-
- __destroy_job_handler(handle);
-
- return APP_ERROR_NONE;
-}
-
-EXPORT_API int service_app_job_raise(int job_status, const char *job_id,
- bundle *job_data)
-{
- struct job_s *job;
-
- if (job_status < SERVICE_APP_JOB_STATUS_START ||
- job_status > SERVICE_APP_JOB_STATUS_STOP ||
- job_id == NULL || job_data == NULL) {
- /* LCOV_EXCL_START */
- return __on_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__,
- NULL);
- /* LCOV_EXCL_STOP */
- }
-
- job = __create_job(job_status, job_id, job_data);
- if (job == NULL)
- return __on_error(APP_ERROR_OUT_OF_MEMORY, __FUNCTION__, NULL); /* LCOV_EXCL_LINE */
-
- if (!__exist_job_handler(job_id)) {
- /* LCOV_EXCL_START */
- job->timer = g_timeout_add(5000, __pending_job_timeout_handler,
- job);
- __context.pending_jobs = g_list_append(__context.pending_jobs,
- job);
- /* LCOV_EXCL_STOP */
- } else {
- job->idler = g_idle_add(__handle_job, job);
- __context.running_jobs = g_list_append(__context.running_jobs,
- job);
- }
-
- return APP_ERROR_NONE;
-}
-
-static void __remove_running_job(const char *job_id)
-{
- struct job_s *job;
- GList *iter;
-
- iter = __context.running_jobs;
- while (iter) {
- /* LCOV_EXCL_START */
- job = (struct job_s *)iter->data;
- iter = iter->next;
- if (strcmp(job->job_id, job_id) == 0) {
- __context.running_jobs = g_list_remove(
- __context.running_jobs, job);
- __destroy_job(job);
- }
- /* LCOV_EXCL_STOP */
- }
-}
-
-EXPORT_API int service_app_job_finished(const char *job_id)
-{
- int r;
-
- if (job_id == NULL) {
- /* LCOV_EXCL_START */
- return __on_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__,
- NULL);
- /* LCOV_EXCL_STOP */
- }
-
- __remove_running_job(job_id);
-
- r = aul_job_scheduler_update_job_status(job_id, JOB_STATUS_FINISHED);
- if (r != AUL_R_OK) {
- /* LCOV_EXCL_START */
- return __on_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__,
- NULL);
- /* LCOV_EXCL_STOP */
- }
-
- return APP_ERROR_NONE;
-}
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 <Ecore.h>
+#include <app_control_internal.h>
+#include <aul.h>
+#include <aul_job_scheduler.h>
+#include <dlog.h>
+#include <glib.h>
+#include <service_app.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <vconf-internal-keys.h>
+
+#include <app_core_base.hh>
+#include <app_event_internal.hh>
+
+#include <list>
+#include <memory>
+#include <type_traits>
+
+#include "service_app_extension.h"
+#include "service_app_internal.h"
+
+#include "job-manager.hh"
+#include "log-private.hh"
+
+using namespace tizen_cpp;
+
+namespace {
+
+const char* __error_to_string(app_error_e error) {
+ switch (error) {
+ case APP_ERROR_NONE:
+ return "NONE";
+ case APP_ERROR_INVALID_PARAMETER:
+ return "INVALID_PARAMETER";
+ case APP_ERROR_OUT_OF_MEMORY:
+ return "OUT_OF_MEMORY";
+ case APP_ERROR_INVALID_CONTEXT:
+ return "INVALID_CONTEXT";
+ case APP_ERROR_NO_SUCH_FILE:
+ return "NO_SUCH_FILE";
+ case APP_ERROR_ALREADY_RUNNING:
+ return "ALREADY_RUNNING";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+int __on_error(app_error_e error, const char* function,
+ const char* description) {
+ if (description) {
+ _E("[%s] %s(0x%08x) : %s",
+ function, __error_to_string(error), error, description);
+ } else {
+ _E("[%s] %s(0x%08x)", function, __error_to_string(error), error);
+ }
+
+ return error;
+}
+
+constexpr int APP_EVENT_MAX = 7;
+constexpr IAppCore::IEvent::Type __app_event_converter[APP_EVENT_MAX] = {
+ [APP_EVENT_LOW_MEMORY] = IAppCore::IEvent::Type::LOW_MEMORY,
+ [APP_EVENT_LOW_BATTERY] = IAppCore::IEvent::Type::LOW_BATTERY,
+ [APP_EVENT_LANGUAGE_CHANGED] = IAppCore::IEvent::Type::LANG_CHANGE,
+ [APP_EVENT_DEVICE_ORIENTATION_CHANGED] = IAppCore::IEvent::Type::DEVICE_ORIENTATION_CHANGED,
+ [APP_EVENT_REGION_FORMAT_CHANGED] = IAppCore::IEvent::Type::REGION_CHANGE,
+ [APP_EVENT_SUSPENDED_STATE_CHANGED] = IAppCore::IEvent::Type::SUSPENDED_STATE_CHANGE,
+};
+
+class AppContext : public AppCoreBase {
+ public:
+ enum AppState {
+ APP_STATE_NOT_RUNNING,
+ APP_STATE_CREATING,
+ APP_STATE_RUNNING,
+ };
+
+ AppContext(service_app_lifecycle_callback_s callback,
+ service_app_loop_method_s method, void* data)
+ : callback_(callback), method_(method), data_(data) {
+ state_ = APP_STATE_CREATING;
+ }
+
+ void Run(int argc, char** argv) override {
+ SetAppState(APP_STATE_RUNNING);
+ AppCoreBase::Run(argc, argv);
+ SetAppState(APP_STATE_NOT_RUNNING);
+ }
+
+ int OnReceive(aul_type type, tizen_base::Bundle b) override {
+ AppCoreBase::OnReceive(type, b);
+
+ if (type == AUL_TERMINATE_BGAPP) {
+ Exit();
+ return 0;
+ }
+
+ return 0;
+ }
+
+ int OnCreate() override {
+ _W("service_app_create()");
+ AppCoreBase::OnCreate();
+
+ if (callback_.create == nullptr || callback_.create(data_) == false) {
+ return __on_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__,
+ "service_app_create_cb() returns false");
+ }
+
+ return APP_ERROR_NONE;
+ }
+
+ int OnControl(tizen_base::Bundle b) override {
+ _W("service_app_control()");
+ AppCoreBase::OnControl(b);
+
+ std::string job_id = b.GetString(AUL_K_JOB_ID);
+ if (!job_id.empty()) {
+ _D("[__JOB__] Job(%s)", job_id.c_str());
+ return 0;
+ }
+
+ app_control_h app_control = nullptr;
+ if (app_control_create_event(b.GetHandle(), &app_control) != 0)
+ return -1;
+
+ if (callback_.app_control)
+ callback_.app_control(app_control, data_);
+
+ app_control_destroy(app_control);
+
+ return 0;
+ }
+
+ int OnTerminate() override {
+ _W("service_app_terminate()");
+ if (callback_.terminate)
+ callback_.terminate(data_);
+
+ AppCoreBase::OnTerminate();
+
+ return APP_ERROR_NONE;
+ }
+
+ void OnLoopInit(int argc, char** argv) override {
+ if (method_.init)
+ method_.init(argc, argv, data_);
+ else
+ ecore_init();
+ }
+
+ void OnLoopFinish() override {
+ if (method_.fini)
+ method_.fini();
+ else
+ ecore_shutdown();
+ }
+
+ void OnLoopRun() override {
+ if (method_.run)
+ method_.run(data_);
+ else
+ ecore_main_loop_begin();
+ }
+
+ void OnLoopExit() override {
+ if (method_.exit) {
+ method_.exit(data_);
+ } else {
+ ecore_main_loop_thread_safe_call_sync([](void* data) -> void* {
+ ecore_main_loop_quit();
+ return nullptr;
+ }, nullptr);
+ }
+ }
+
+ AppState GetAppState() const {
+ return state_;
+ }
+
+ void SetAppState(AppState state) {
+ state_ = state;
+ }
+
+ private:
+ service_app_lifecycle_callback_s callback_;
+ service_app_loop_method_s method_;
+ void* data_;
+ AppState state_ = APP_STATE_NOT_RUNNING;
+};
+
+std::unique_ptr<AppContext> __context;
+std::list<std::shared_ptr<AppEvent>> __pending_app_events;
+JobManager __job_manager;
+
+} // namespace
+
+extern "C" EXPORT_API int service_app_main_ext(int argc, char** argv,
+ service_app_lifecycle_callback_s* callback,
+ service_app_loop_method_s* method, void* user_data) {
+ if (argc < 1 || argv == nullptr || callback == nullptr || method == nullptr)
+ return __on_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, nullptr);
+
+ if (callback->create == nullptr) {
+ return __on_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__,
+ "service_app_create_cb() callback must be registered");
+ }
+
+ if (__context.get() != nullptr &&
+ __context->GetAppState() != AppContext::APP_STATE_NOT_RUNNING)
+ return __on_error(APP_ERROR_ALREADY_RUNNING, __FUNCTION__, nullptr);
+
+ try {
+ __context = std::make_unique<AppContext>(*callback, *method, user_data);
+ for (auto& i : __pending_app_events) {
+ __context->AddEvent(i);
+ }
+ __context->Run(argc, argv);
+ } catch(std::runtime_error& e) {
+ __context->SetAppState(AppContext::APP_STATE_NOT_RUNNING);
+ return __on_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, nullptr);
+ }
+
+ __job_manager.FinishAllJobs();
+ return APP_ERROR_NONE;
+}
+
+extern "C" EXPORT_API int service_app_main(int argc, char** argv,
+ service_app_lifecycle_callback_s* callback, void* user_data) {
+ service_app_loop_method_s method = { nullptr, };
+ _W("service_app_main()");
+ return service_app_main_ext(argc, argv, callback, &method, user_data);
+}
+
+extern "C" EXPORT_API void service_app_exit(void) {
+ _W("service_app_exit()");
+ if (__context.get() &&
+ __context->GetAppState() == AppContext::APP_STATE_RUNNING)
+ __context->Exit();
+}
+
+extern "C" EXPORT_API int service_app_add_event_handler(
+ app_event_handler_h* event_handler, app_event_type_e event_type,
+ app_event_cb callback, void *user_data) {
+ if (event_handler == nullptr || callback == nullptr) {
+ return __on_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__,
+ "null parameter");
+ }
+
+ if (event_type < APP_EVENT_LOW_MEMORY ||
+ event_type > APP_EVENT_SUSPENDED_STATE_CHANGED ||
+ event_type == APP_EVENT_DEVICE_ORIENTATION_CHANGED) {
+ return __on_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__,
+ "invalid event type");
+ }
+
+ auto* ae = new (std::nothrow) AppEvent(__app_event_converter[event_type],
+ callback, user_data);
+ if (!ae) {
+ return __on_error(APP_ERROR_OUT_OF_MEMORY, __FUNCTION__,
+ "failed to create handler");
+ }
+
+ auto* h = new (std::nothrow) std::shared_ptr<AppEvent>(ae);
+ if (!h) {
+ delete ae;
+ return __on_error(APP_ERROR_OUT_OF_MEMORY, __FUNCTION__,
+ "failed to create handler");
+ }
+
+ if (__context.get() &&
+ __context->GetAppState() == AppContext::APP_STATE_RUNNING) {
+ __context->AddEvent(*h);
+ } else {
+ __pending_app_events.push_back(*h);
+ }
+
+ *event_handler = reinterpret_cast<app_event_handler_h>(h);
+
+ return APP_ERROR_NONE;
+}
+
+extern "C" EXPORT_API int service_app_remove_event_handler(
+ app_event_handler_h event_handler) {
+ if (event_handler == nullptr)
+ return __on_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, nullptr);
+
+ auto* eb = reinterpret_cast<std::shared_ptr<AppEvent>*>(event_handler);
+ auto type = (*eb)->GetType();
+
+ if (type < IAppCore::IEvent::Type::LOW_MEMORY ||
+ type > IAppCore::IEvent::Type::SUSPENDED_STATE_CHANGE ||
+ type == IAppCore::IEvent::Type::DEVICE_ORIENTATION_CHANGED)
+ return __on_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__, nullptr);
+
+ if (__context.get() &&
+ __context->GetAppState() == AppContext::APP_STATE_RUNNING) {
+ if (!__context->RemoveEvent(*eb)) {
+ return __on_error(APP_ERROR_INVALID_PARAMETER, __FUNCTION__,
+ "invalid raw handler");
+ }
+ } else {
+ __pending_app_events.remove(*eb);
+ }
+
+ delete eb;
+
+ return APP_ERROR_NONE;
+}
+
+extern "C" EXPORT_API void service_app_exit_without_restart(void) {
+ if (__context.get() &&
+ __context->GetAppState() == AppContext::APP_STATE_RUNNING) {
+ aul_status_update_v2(STATUS_NORESTART);
+ __context->Exit();
+ }
+}
+
+extern "C" EXPORT_API service_app_job_h service_app_add_job_handler(
+ const char* job_id, service_app_job_cb callback, void* user_data) {
+ if (job_id == nullptr || callback == nullptr) {
+ _E("Invalid parameter");
+ return nullptr;
+ }
+
+ auto* handle = new (std::nothrow) JobHandler(job_id, callback, user_data);
+ if (handle == nullptr) {
+ _E("Out of memory");
+ return nullptr;
+ }
+
+ __job_manager.AddJobHandler(handle);
+ __job_manager.FlushPendingJob(job_id);
+ return handle;
+}
+
+extern "C" EXPORT_API int service_app_remove_job_handler(
+ service_app_job_h handle) {
+ if (handle == nullptr) {
+ _E("Invalid parameter");
+ return APP_ERROR_INVALID_PARAMETER;
+ }
+
+ auto* h = static_cast<JobHandler*>(handle);
+ if (!__job_manager.ExistJobHandler(h)) {
+ _E("Invalid parameter");
+ return APP_ERROR_INVALID_PARAMETER;
+ }
+
+ __job_manager.RemoveJobHandler(h);
+ delete h;
+ return APP_ERROR_NONE;
+}
+
+extern "C" EXPORT_API int service_app_job_raise(int job_status,
+ const char* job_id, bundle* job_data) {
+ if (job_status < SERVICE_APP_JOB_STATUS_START ||
+ job_status > SERVICE_APP_JOB_STATUS_STOP ||
+ job_id == nullptr || job_data == nullptr) {
+ _E("Invalid parameter");
+ return APP_ERROR_INVALID_PARAMETER;
+ }
+
+ auto job = std::make_shared<Job>(job_status, job_id,
+ tizen_base::Bundle(job_data, true, true));
+ if (job == nullptr) {
+ _E("Out of memory");
+ return APP_ERROR_OUT_OF_MEMORY;
+ }
+
+ __job_manager.Do(job);
+ return APP_ERROR_NONE;
+}
+
+extern "C" EXPORT_API int service_app_job_finished(const char* job_id) {
+ if (job_id == nullptr) {
+ _E("Invalid parameter");
+ return APP_ERROR_INVALID_PARAMETER;
+ }
+
+ if (__job_manager.Finish(job_id) != 0)
+ return APP_ERROR_INVALID_CONTEXT;
+
+ return APP_ERROR_NONE;
+}
-AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} TEST_SRCS)
-AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/mock MOCK_SRCS)
-INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../include/)
+SET(TARGET_TEST "appcore-agent-test")
ENABLE_TESTING()
-SET(TARGET_TEST "appcore-agent-test")
-ADD_EXECUTABLE(${TARGET_TEST} ${TEST_SRCS} ${MOCK_SRCS})
-ADD_TEST(${TARGET_TEST} ${TARGET_TEST})
+INCLUDE(FindPkgConfig)
+LINK_DIRECTORIES(${CMAKE_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../include/)
-pkg_check_modules(gtest_pkgs REQUIRED gmock)
-INCLUDE_DIRECTORIES(${gtest_pkgs_INCLUDE_DIRS})
-LINK_DIRECTORIES(${gtest_pkgs_LIBRARY_DIRS})
+pkg_check_modules(test REQUIRED
+ aul
+ dlog
+ capi-appfw-app-control
+ vconf
+ ecore-core
+ vconf-internal-keys
+ app-core-cpp
+ capi-system-info
+ )
-INCLUDE(FindPkgConfig)
-pkg_check_modules(test REQUIRED aul dlog capi-appfw-app-control capi-appfw-app-common vconf ecore-core vconf-internal-keys appcore-common capi-system-info)
FOREACH(flag ${test_CFLAGS})
SET(EXTRA_CXXFLAGS_test "${EXTRA_CXXFLAGS_test} ${flag}")
ENDFOREACH(flag)
-SET(${EXTRA_CXXFLAGS_test} "${EXTRA_CXXFLAGS_test} --std=c++14")
-SET_TARGET_PROPERTIES(${TARGET_TEST} PROPERTIES COMPILE_FLAGS ${EXTRA_CXXFLAGS_test})
+pkg_check_modules(gtest_pkgs REQUIRED gmock)
+INCLUDE_DIRECTORIES(${gtest_pkgs_INCLUDE_DIRS})
+LINK_DIRECTORIES(${gtest_pkgs_LIBRARY_DIRS})
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CXXFLAGS_test}")
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS_test}")
-TARGET_LINK_LIBRARIES(${TARGET_TEST} ${gtest_pkgs_LIBRARIES} appcore-agent)
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../src/ LIB_SRCS)
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} TEST_SRCS)
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/mock/ MOCK_SRCS)
+
+ADD_EXECUTABLE(${TARGET_TEST} ${MOCK_SRCS} ${TEST_SRCS} ${LIB_SRCS})
+TARGET_LINK_LIBRARIES(${TARGET_TEST} ${test_LDFLAGS} ${gtest_pkgs_LIBRARIES})
+
+ADD_TEST(${TARGET_TEST} ${TARGET_TEST})
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 - 2021 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.
#include "mock_hook.h"
#include "test_fixture.h"
-extern "C" int appcore_base_init(appcore_base_ops ops, int argc, char **argv, void* data) {
- return MOCK_HOOK_P4(AppCoreMock, appcore_base_init, ops, argc, argv, data);
+namespace tizen_cpp {
+
+void AppCoreBase::Run(int argc, char** argv) {
+ TestFixture::GetMock<AppCoreMock>().Run(argc, argv);
+ TestFixture::GetMock<AppCoreMock>().OnLoopInit(argc, argv, this);
+ TestFixture::GetMock<AppCoreMock>().OnCreate();
+ TestFixture::GetMock<AppCoreMock>().OnLoopRun();
+ TestFixture::GetMock<AppCoreMock>().OnLoopFinish();
+ TestFixture::GetMock<AppCoreMock>().OnTerminate();
}
-extern "C" void appcore_base_fini() {
- return MOCK_HOOK_P0(AppCoreMock, appcore_base_fini);
+void AppCoreBase::Exit() {
+ TestFixture::GetMock<AppCoreMock>().Exit();
+ TestFixture::GetMock<AppCoreMock>().OnLoopExit();
}
-extern "C" void appcore_base_exit() {
- return MOCK_HOOK_P0(AppCoreMock, appcore_base_exit);
-}
\ No newline at end of file
+} // namespace tizen_cpp
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 - 2021 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.
#ifndef MOCK_APPCORE_MOCK_H_
#define MOCK_APPCORE_MOCK_H_
+
#include <gmock/gmock.h>
-#include <appcore_base.h>
+#include <app_core_base.hh>
#include "module_mock.h"
class AppCoreMock : public virtual ModuleMock {
public:
- virtual ~AppCoreMock() {}
-
- MOCK_METHOD4(appcore_base_init, int(appcore_base_ops, int, char**, void*));
- MOCK_METHOD0(appcore_base_fini, void());
- MOCK_METHOD0(appcore_base_exit, void());
+ MOCK_METHOD2(Run, void(int, char**));
+ MOCK_METHOD0(Exit, void());
+ MOCK_METHOD0(OnCreate, void());
+ MOCK_METHOD0(OnTerminate, void());
+ MOCK_METHOD3(OnLoopInit, void(int, char**, void*));
+ MOCK_METHOD0(OnLoopFinish, void());
+ MOCK_METHOD0(OnLoopRun, void());
+ MOCK_METHOD0(OnLoopExit, void());
};
-#endif // MOCK_APPCORE_HOOK_H_
\ No newline at end of file
+#endif // MOCK_APPCORE_MOCK_H_
\ No newline at end of file
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2020 - 2021 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.
#include <service_app.h>
#include <service_app_extension.h>
#include <service_app_internal.h>
-#include <appcore_base.h>
#include <app_common.h>
#include <aul_job_scheduler.h>
#include <glib.h>
virtual void TearDown() {}
};
-extern "C" int __dlog_print(log_id_t log_id, int prio, const char *tag, const char *fmt, ...) {
- printf("%s:", tag);
- va_list ap;
- va_start(ap, fmt);
- vprintf(fmt, ap);
- va_end(ap);
- printf("\n");
-
+extern "C" int __dlog_print(log_id_t log_id, int prio, const char* tag,
+ const char* fmt, ...) {
return 0;
}
}
bool __service_app_create_cb(void* user_data) {
- return false;
-}
-
-bool __service_app_create_cb_loop(void* user_data) {
- bool* loop = reinterpret_cast<bool*>(user_data);
-
- while (*loop) {
- std::cout << "wait..." << std::endl;
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
- }
-
return true;
}
void __service_app_terminate_cb(void* user_data) {
-
}
void __service_app_control_cb(app_control_h app_control, void* user_data) {
-
}
TEST_F(ServiceAppTest, Basic) {
char** argv;
int argc = bundle_export_to_argv(b.GetHandle(), &argv);
- std::unique_ptr<char**, std::function<void(char***)>> ptr(&argv, [argc](char*** ptr){
+ std::unique_ptr<char**, std::function<void(char***)>> ptr(&argv,
+ [argc](char*** ptr) {
bundle_free_exported_argv(argc, ptr);
});
- ASSERT_TRUE(argc > 0);
-
- ret = service_app_main(argc, argv, &callback, nullptr);
- EXPECT_THAT(ret, testing::Eq(APP_ERROR_NONE));
+ ASSERT_GT(argc, 0);
+ using testing::_;
ret = service_app_main(0, nullptr, &callback, nullptr);
EXPECT_THAT(ret, testing::Eq(APP_ERROR_INVALID_PARAMETER));
ret = service_app_main(argc, argv, &callback, nullptr);
EXPECT_THAT(ret, testing::Eq(APP_ERROR_INVALID_PARAMETER));
- using testing::_;
-
- EXPECT_CALL(GetMock<AppCoreMock>(), appcore_base_init(_,_,_,_))
- .WillOnce(testing::Invoke([&](appcore_base_ops ops, int argc, char** argv,
- void* data) {
- ops.create(data);
- return 0;
- }));
-
+ EXPECT_CALL(GetMock<AppCoreMock>(), Run(_, _)).Times(1);
bool loop = true;
+ EXPECT_CALL(GetMock<AppCoreMock>(), OnLoopRun())
+ .WillOnce(testing::Invoke([&]() {
+ while (loop) {
+ std::cout << "wait..." << std::endl;
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+ }
+ }));
+
std::thread t([&]() {
- callback.create = __service_app_create_cb_loop;
+ callback.create = __service_app_create_cb;
service_app_main(argc, argv, &callback, reinterpret_cast<void*>(&loop));
});
std::this_thread::sleep_for(std::chrono::milliseconds(50));
- callback.create = __service_app_create_cb;
- ret = service_app_main(1, argv, &callback, &loop);
+ ret = service_app_main(argc, argv, &callback, &loop);
EXPECT_THAT(ret, testing::Eq(APP_ERROR_ALREADY_RUNNING));
- loop = false;
- t.join();
-
// test service_app_exit
- EXPECT_CALL(GetMock<AppCoreMock>(), appcore_base_exit()).Times(testing::AtLeast(1));
+ EXPECT_CALL(GetMock<AppCoreMock>(), Exit()).Times(1);
+ EXPECT_CALL(GetMock<AppCoreMock>(), OnLoopExit())
+ .WillOnce(testing::Invoke([&]() {
+ loop = false;
+ t.join();
+ }));
service_app_exit();
}
handle = service_app_add_job_handler(nullptr, nullptr, nullptr);
EXPECT_TRUE(handle == nullptr);
- handle = service_app_add_job_handler("temp", [] (int status, const char* job_id,
- bundle* job_data, void* user_data) -> int {
- int* calledCnt = reinterpret_cast<int*>(user_data);
- *calledCnt = *calledCnt + 1;
- return 0;
- }, reinterpret_cast<void*>(&calledCnt));
+ handle = service_app_add_job_handler("temp",
+ [] (int status, const char* job_id, bundle* job_data,
+ void* user_data) -> int {
+ int* calledCnt = reinterpret_cast<int*>(user_data);
+ *calledCnt = *calledCnt + 1;
+ return 0;
+ }, reinterpret_cast<void*>(&calledCnt));
EXPECT_TRUE(handle != nullptr);
EXPECT_THAT(calledCnt, testing::Eq(0));
ret = service_app_job_raise(0, nullptr, nullptr);
EXPECT_THAT(ret, testing::Eq(APP_ERROR_INVALID_PARAMETER));
- ret = service_app_job_raise(SERVICE_APP_JOB_STATUS_START, "temp", b.GetHandle());
+ ret = service_app_job_raise(SERVICE_APP_JOB_STATUS_START, "temp",
+ b.GetHandle());
g_main_context_iteration(g_main_context_default(), 0);
EXPECT_THAT(ret, testing::Eq(APP_ERROR_NONE));
EXPECT_THAT(ret, testing::Eq(APP_ERROR_NONE));
EXPECT_THAT(calledCnt, testing::Eq(0));
- appcore_base_raise_event(&calledCnt, APPCORE_BASE_EVENT_LOW_MEMORY);
+ //appcore_base_raise_event(&calledCnt, APPCORE_BASE_EVENT_LOW_MEMORY);
- EXPECT_THAT(calledCnt, testing::Eq(1));
+ //EXPECT_THAT(calledCnt, testing::Eq(1));
ret = service_app_remove_event_handler(nullptr);
EXPECT_THAT(ret, testing::Eq(APP_ERROR_INVALID_PARAMETER));
ret = service_app_remove_event_handler(handle);
EXPECT_THAT(ret, testing::Eq(APP_ERROR_NONE));
- appcore_base_raise_event(&calledCnt, APPCORE_BASE_EVENT_LOW_MEMORY);
- EXPECT_THAT(calledCnt, testing::Eq(1));
+ //appcore_base_raise_event(&calledCnt, APPCORE_BASE_EVENT_LOW_MEMORY);
+ //EXPECT_THAT(calledCnt, testing::Eq(1));
}
-} // namespace appcore_agent
+} // namespace appcore_agent
int main(int argc, char* argv[]) {
int ret = 0;