/* * Copyright (c) 2011 - 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 #include #include #include #include #include #include #include #include #include #include "app_internal.h" #include "common_private.hh" #include "log_private.hh" namespace { using namespace tizen_cpp; class UiAppContext : public AppCoreEflBase { public: enum AppState { APP_STATE_NOT_RUNNING, APP_STATE_CREATING, APP_STATE_RUNNING, }; UiAppContext(ui_app_lifecycle_callback_s callback, void* data, unsigned int hint) : AppCoreEflBase(hint), callback_(callback), data_(data) { SetAppState(APP_STATE_CREATING); } void Run(int argc, char** argv) override { SetAppState(APP_STATE_RUNNING); AppCoreEflBase::Run(argc, argv); SetAppState(APP_STATE_NOT_RUNNING); } int OnCreate() override { LOGW("ui_app_create()"); AppCoreEflBase::OnCreate(); if (callback_.create == nullptr || callback_.create(data_) == false) { return app_error(APP_ERROR_INVALID_CONTEXT, __FUNCTION__, "app_create_cb() returns false"); } return APP_ERROR_NONE; } int OnControl(tizen_base::Bundle b) override { app_control_h app_control = nullptr; LOGW("ui_app_control()"); AppCoreEflBase::OnControl(b); if (b.GetHandle()) { int ret = app_control_create_event(b.GetHandle(), &app_control); if (ret != APP_ERROR_NONE) { // LCOV_EXCL_START _E("Failed to create an app_control handle"); return APP_ERROR_INVALID_PARAMETER; // LCOV_EXCL_STOp } } else { // LCOV_EXCL_START if (app_control_create(&app_control) != APP_ERROR_NONE) { _E("Failed to create an app_control handle"); return APP_ERROR_OUT_OF_MEMORY; } // LCOV_EXCL_STOP } if (callback_.app_control) callback_.app_control(app_control, data_); app_control_destroy(app_control); return APP_ERROR_NONE; } int OnTerminate() override { LOGW("ui_app_terminate()"); AppCoreEflBase::OnTerminate(); if (callback_.terminate) callback_.terminate(data_); return APP_ERROR_NONE; } int OnPause() override { LOGW("ui_app_pause()"); AppCoreEflBase::OnPause(); if (callback_.pause) callback_.pause(data_); return APP_ERROR_NONE; } int OnResume() override { LOGW("ui_app_resume"); AppCoreEflBase::OnResume(); if (callback_.resume) callback_.resume(data_); return APP_ERROR_NONE; } AppState GetAppState() const { return state_; } void SetAppState(AppState state) { state_ = state; } private: ui_app_lifecycle_callback_s callback_; void* data_; AppState state_ = APP_STATE_NOT_RUNNING; }; constexpr int UI_APP_EVENT_MAX = 8; constexpr IAppCore::IEvent::Type __app_event_converter[UI_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, [APP_EVENT_UPDATE_REQUESTED] = IAppCore::IEvent::Type::UPDATE_REQUESTED, [APP_EVENT_TIME_ZONE_CHANGED] = IAppCore::IEvent::Type::TIME_ZONE_CHANGED, }; std::unique_ptr __context; std::list> __pending_app_events; } // namespace API int ui_app_main(int argc, char** argv, ui_app_lifecycle_callback_s* callback, void* user_data) { if (argc < 1 || argv == nullptr || callback == nullptr) { _E("Invalid parameter"); return APP_ERROR_INVALID_PARAMETER; } if (callback->create == nullptr) { // LCOV_EXCL_START _E("app_create_cb() callback MUST be registerted"); return APP_ERROR_INVALID_PARAMETER; // LCOV_EXCL_STOP } // LCOV_EXCL_START if (__context.get() != nullptr && __context->GetAppState() != UiAppContext::APP_STATE_NOT_RUNNING) { _E("Already running"); return APP_ERROR_ALREADY_RUNNING; } // LCOV_EXCL_STOP unsigned int hint = AppCoreEflBase::HINT_WINDOW_GROUP_CONTROL | AppCoreEflBase::HINT_WINDOW_STACK_CONTROL | AppCoreEflBase::HINT_BG_LAUNCH_CONTROL | AppCoreEflBase::HINT_HW_ACC_CONTROL | AppCoreEflBase::HINT_WINDOW_AUTO_CONTROL | AppCoreEflBase::HINT_LEGACY_CONTROL | AppCoreEflBase::HINT_WINDOW_ID_CONTROL; LOGW("ui_app_main()"); try { __context = std::make_unique(*callback, user_data, hint); for (auto i : __pending_app_events) __context->AddEvent(std::move(i)); __context->Run(argc, argv); } catch (std::runtime_error& e) { __context->SetAppState(UiAppContext::APP_STATE_NOT_RUNNING); // LCOV_EXCL_LINE } return APP_ERROR_NONE; } API void ui_app_exit(void) { LOGW("ui_app_exit()"); if (__context.get() && __context->GetAppState() == UiAppContext::APP_STATE_RUNNING) __context->Exit(); } API int ui_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) { _E("Invalid parameter"); return APP_ERROR_INVALID_PARAMETER; } if (event_type < APP_EVENT_LOW_MEMORY || event_type > APP_EVENT_TIME_ZONE_CHANGED) { _E("Invalid event type"); return APP_ERROR_INVALID_PARAMETER; } auto* ae = new (std::nothrow) AppEvent(__app_event_converter[event_type], callback, user_data); if (ae == nullptr) { // LCOV_EXCL_START _E("Out of memory"); return APP_ERROR_OUT_OF_MEMORY; // LCOV_EXCL_STOP } auto* h = new (std::nothrow) std::shared_ptr(ae); if (h == nullptr) { // LCOV_EXCL_START _E("Out of memory"); delete ae; return APP_ERROR_OUT_OF_MEMORY; // LCOV_EXCL_STOP } if (__context.get() && __context->GetAppState() == UiAppContext::APP_STATE_RUNNING) { __context->AddEvent(*h); } else { __pending_app_events.push_back(*h); } *event_handler = reinterpret_cast(h); return APP_ERROR_NONE; } API int ui_app_remove_event_handler(app_event_handler_h event_handler) { if (event_handler == nullptr) { _E("Invalid parameter"); return APP_ERROR_INVALID_PARAMETER; } auto* eb = reinterpret_cast*>(event_handler); auto type = (*eb)->GetType(); if (type < IAppCore::IEvent::Type::LOW_MEMORY || type > IAppCore::IEvent::Type::TIME_ZONE_CHANGED) { // LCOV_EXCL_START _E("invalid parameter"); return APP_ERROR_INVALID_PARAMETER; // LCOV_EXCL_STOP } if (__context.get() && __context->GetAppState() == UiAppContext::APP_STATE_RUNNING) { if (!__context->RemoveEvent(*eb)) { // LCOV_EXCL_START _E("Invalid handle"); return APP_ERROR_INVALID_PARAMETER; // LCOV_EXCL_STOP } } else { __pending_app_events.remove(*eb); } delete eb; return APP_ERROR_NONE; } API int ui_app_get_window_position(int *x, int *y, int *w, int *h) { if (x == nullptr || y == nullptr || w == nullptr || h == nullptr) return APP_ERROR_INVALID_PARAMETER; if (__context.get() == nullptr || __context->GetWindowPosition(x, y, w, h) < 0) return APP_ERROR_NOT_SUPPORTED; return APP_ERROR_NONE; }