Support UI Thread
[platform/core/appfw/app-core.git] / tizen-cpp / app-core-efl-cpp / app_core_efl_base.cc
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <Elementary.h>
18 #include <glib.h>
19 #include <stdlib.h>
20
21 #include <condition_variable>
22 #include <memory>
23 #include <mutex>
24 #include <string>
25 #include <thread>
26
27 #include "app-core-efl-cpp/app_core_efl_base.hh"
28 #include "app-core-efl-cpp/voice_elm_private.hh"
29 #include "common/log_private.hh"
30 #include "common/glib_private.hh"
31
32 namespace tizen_cpp {
33
34 class AppCoreEflBase::Impl {
35  public:
36   Impl(AppCoreEflBase* parent);
37   ~Impl();
38
39   void Init(int argc, char** argv);
40   void Finish();
41   void LoopRun();
42   void LoopExit();
43   void TrimMemory();
44
45  private:
46   friend class AppCoreEflBase;
47   AppCoreEflBase* parent_;
48
49   std::thread thread_;
50   bool thread_started_ = false;
51   std::condition_variable cond_;
52   std::unique_ptr<VoiceElm> vc_elm_;
53   guint source_id_ = 0;
54   std::mutex mutex_;
55   bool initialized_ = false;
56 };
57
58 AppCoreEflBase::Impl::Impl(AppCoreEflBase* parent) : parent_(parent) {}
59
60 AppCoreEflBase::Impl::~Impl() {
61   if (thread_.joinable())
62     thread_.join();
63
64   if (source_id_ != 0)
65     GLib::SourceRemove(source_id_);
66 }
67
68 void AppCoreEflBase::Impl::Init(int argc, char** argv) {
69   if (initialized_)
70     return;
71
72   elm_init(argc, argv);
73   unsigned int hint = parent_->GetHint();
74   if ((hint & HINT_HW_ACC_CONTROL) && !getenv("AUL_HWACC")) {
75     const char* hwacc = getenv("HWACC");
76     if (hwacc == nullptr) {
77       _D("elm_config_accel_preference_set is not called");
78     } else if (strcmp(hwacc, "USE") == 0) {
79       elm_config_accel_preference_set("hw");
80       _D("elm_config_accel_preference_set : hw");
81     } else if (strcmp(hwacc, "NOT_USE") == 0) {
82       elm_config_accel_preference_set("none");
83       _D("elm_config_accel_preference_set : none");
84     } else {
85       _D("elm_config_accel_preference_set is not called");
86     }
87   }
88
89   if (VoiceElm::IsVtAutoMode()) {
90     std::unique_lock<std::mutex> lock(mutex_);
91     thread_ = std::thread([&] {
92         std::unique_lock<std::mutex> lock(mutex_);
93         thread_started_ = true;
94         cond_.notify_one();
95
96         int retry_count = 3;
97         do {
98           if (vc_elm_.get() == nullptr)
99               vc_elm_.reset(VoiceElm::Load());
100
101           if (vc_elm_.get() != nullptr) {
102             source_id_ = GLib::IdleAdd([](gpointer user_data) {
103                   auto* impl = static_cast<AppCoreEflBase::Impl*>(user_data);
104                   if (impl->vc_elm_.get() != nullptr)
105                     impl->vc_elm_->Init();
106
107                   impl->source_id_ = 0;
108                   return G_SOURCE_REMOVE;
109                 }, this);
110             break;
111           }
112         } while (retry_count--);
113     });
114     cond_.wait(lock, [&] { return thread_started_; });
115   }
116
117   initialized_ = true;
118 }
119
120 void AppCoreEflBase::Impl::Finish() {
121   if (!initialized_)
122     return;
123
124   if (thread_.joinable())
125     thread_.join();
126
127   thread_started_ = false;
128
129   if (source_id_ != 0) {
130     GLib::SourceRemove(source_id_);
131     source_id_ = 0;
132   }
133
134   elm_shutdown();
135
136   // Check loader case
137   const char* env = getenv("AUL_LOADER_INIT");
138   if (env && env[0] == '1') {
139     setenv("AUL_LOADER_INIT", "0", 1);
140     elm_shutdown();
141   }
142
143   initialized_ = false;
144 }
145
146 void AppCoreEflBase::Impl::LoopRun() {
147   elm_run();
148 }
149
150 void AppCoreEflBase::Impl::LoopExit() {
151   elm_exit();
152 }
153
154 void AppCoreEflBase::Impl::TrimMemory() {
155   elm_cache_all_flush();
156 }
157
158 AppCoreEflBase::AppCoreEflBase(unsigned int hint)
159     : AppCoreUiBase(hint),
160       impl_(new Impl(this)) {
161 }
162
163 AppCoreEflBase::~AppCoreEflBase() = default;
164
165 void AppCoreEflBase::OnLoopInit(int argc, char** argv) {
166   impl_->Init(argc, argv);
167 }
168
169 void AppCoreEflBase::OnLoopFinish() {
170   impl_->Finish();
171 }
172
173 void AppCoreEflBase::OnLoopRun() {
174   impl_->LoopRun();
175 }
176
177 void AppCoreEflBase::OnLoopExit() {
178   impl_->LoopExit();
179 }
180
181 int AppCoreEflBase::OnTrimMemory() {
182   _D("Trim memory");
183   impl_->TrimMemory();
184   return AppCoreUiBase::OnTrimMemory();
185 }
186
187 }  // namespace tizen_cpp