Add window position
[platform/core/appfw/app-core.git] / tizen-cpp / app-core-ui-cpp / app_core_ui_base.cc
1 /*
2  * Copyright (c) 2021 - 2022 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 "app-core-ui-cpp/app_core_ui_base.hh"
18
19 #include <Ecore_Wl2.h>
20 #include <aul_app_lifecycle.h>
21 #include <aul_rpc_port.h>
22 #include <aul_svc.h>
23 #include <bundle_internal.h>
24 #include <fcntl.h>
25 #include <sys/stat.h>
26 #include <sys/syscall.h>
27 #include <sys/types.h>
28 #include <ttrace.h>
29 #include <unistd.h>
30
31 #include <list>
32 #include <memory>
33 #include <string>
34 #include <thread>
35
36 #include "app-core-cpp/app_core_base.hh"
37 #include "app-core-ui-cpp/api/app_core_ui_base.h"
38 #include "app-core-ui-cpp/app_core_task_base.hh"
39 #include "app-core-ui-cpp/app_core_ui_delegator_private.hh"
40 #include "app-core-ui-cpp/app_core_ui_plugin_private.hh"
41 #include "app-core-ui-cpp/wayland_handler_private.hh"
42 #include "common/ecore_handler.hh"
43 #include "common/glib_private.hh"
44 #include "common/log_private.hh"
45
46 namespace tizen_cpp {
47
48 constexpr const char K_SERVICE_THREAD[] = "__K_SERVICE_THREAD";
49
50 void SetComm(const std::string& name) {
51   pid_t tid = syscall(__NR_gettid);
52   std::string path = "/proc/" + std::to_string(tid) + "/comm";
53   int fd = open(path.c_str(), O_WRONLY);
54   if (fd < 0) {
55     _E("open(%s) is failed. errno(%d)", path.c_str(), errno);
56     return;
57   }
58
59   ssize_t bytes_written = write(fd, name.c_str(), name.length() + 1);
60   if (bytes_written < 0)
61     _E("write(%d) is failed. errno(%d)", fd, errno);
62
63   close(fd);
64 }
65
66 class AppCoreUiBase::Impl {
67  public:
68   Impl(AppCoreUiBase* parent, unsigned int hint)
69       : parent_(parent),
70         hint_(hint),
71         handler_(std::make_shared<EcoreHandler>(parent)),
72         wl_handler_(new WaylandHandler()) {
73   }
74
75  private:
76   friend class AppCoreUiBase;
77   AppCoreUiBase* parent_;
78
79   enum AppState {
80     AS_NONE,
81     AS_CREATED,
82     AS_RUNNING,
83     AS_PAUSED,
84     AS_DYING,
85   };
86
87   enum VisibilityType {
88     VT_NONE,
89     VT_UNOBSCURED,
90     VT_FULLY_OBSCURED,
91   };
92
93   enum WinStatus {
94     WS_NONE,
95     WS_PAUSE,
96     WS_RESUME,
97   };
98
99   struct WinNode {
100     unsigned int win_;
101     unsigned int surf_;
102     int vis_;
103     WinNode(unsigned int win, unsigned int surf)
104         : win_(win), surf_(surf), vis_(VT_NONE) {
105     }
106   };
107
108   class WindowPosition {
109    public:
110     WindowPosition(int x, int y, int w, int h)
111       : x_(x), y_(y), w_(w), h_(h){
112     }
113
114     int GetPositionX() const { return x_; }
115     int GetPositionY() const { return y_; }
116     int GetScreenWidth() const { return w_; }
117     int GetScreenHeight() const { return h_; }
118
119    private:
120     int x_;
121     int y_;
122     int w_;
123     int h_;
124   };
125
126   void ExitFromSuspend();
127   void PrepareToSuspend();
128   void DoStart(tizen_base::Bundle b);
129   void DoResume();
130   void DoPause();
131   bool CheckVisible();
132   int IsLegacyLifecycle();
133   std::shared_ptr<struct WinNode> FindWin(unsigned int win);
134   bool AddWin(unsigned int win, unsigned int surf);
135   bool DeleteWin(unsigned int win);
136   bool UpdateWin(unsigned int win, unsigned int surf, int vis);
137   void RaiseWin();
138   void PauseWin();
139   void ApplyBgState(bool bg_state);
140   void SetAppId();
141   int InitWl();
142   int FiniWl();
143   void PluginInit(int argc, char** argv);
144   void PluginFini();
145   void Run(int argc, char** argv);
146   void Exit();
147
148   std::list<std::shared_ptr<WinNode>> winnode_list_;
149   unsigned int hint_;
150   std::string below_app_;
151   bool first_launch_ = true;
152   bool bg_state_ = false;
153   bool resource_reclaiming_ = true;
154   std::string appid_;
155   AppState state_ = AS_NONE;
156   WinStatus w_status_ = WS_NONE;
157   std::shared_ptr<EcoreHandler> handler_;
158   std::unique_ptr<WaylandHandler> wl_handler_;
159   IAppCoreUi* core_ui_delegator_ = nullptr;
160   std::unique_ptr<AppCoreUiDelegator> plugin_delegator_;
161   std::unique_ptr<AppCoreUiPlugin> plugin_;
162   std::unique_ptr<AppCoreTaskBase> service_;
163   GMainContext* context_ = nullptr;
164   std::thread thread_;
165   std::unique_ptr<WindowPosition> position_;
166 };
167
168 AppCoreUiBase::AppCoreUiBase(unsigned int hint)
169     : impl_(new Impl(this, hint)) {
170 }
171
172 AppCoreUiBase::~AppCoreUiBase() = default;
173
174 std::shared_ptr<AppCoreUiBase::Impl::WinNode> AppCoreUiBase::Impl::FindWin(
175     unsigned int win) {
176   for (auto& i : winnode_list_) {
177     if (i->win_ == win)
178       return i;
179   }
180
181   return nullptr;
182 }
183
184 bool AppCoreUiBase::Impl::AddWin(unsigned int win, unsigned int surf) {
185   _D("[EVENT_TEST][EVENT] __add_win WIN: %u", win);
186   std::shared_ptr<AppCoreUiBase::Impl::WinNode> node = FindWin(win);
187   if (node != nullptr) {
188     _D("[EVENT_TEST][EVENT] ERROR There is already window: %u", win);
189     return false;
190   }
191
192   winnode_list_.emplace_back(new WinNode(win, surf));
193   return true;
194 }
195
196 bool AppCoreUiBase::Impl::DeleteWin(unsigned int win) {
197   std::shared_ptr<struct AppCoreUiBase::Impl::WinNode> node = FindWin(win);
198   if (node == nullptr) {
199     _D("[EVENT_TEST][EVENT] ERROR There is no window: %u", win);
200     return false;
201   }
202
203   winnode_list_.remove_if(
204       [win](std::shared_ptr<struct AppCoreUiBase::Impl::WinNode> node) {
205         return node->win_ == win;
206       });
207   return true;
208 }
209
210 bool AppCoreUiBase::Impl::UpdateWin(unsigned int win, unsigned int surf,
211     int vis) {
212   std::shared_ptr<AppCoreUiBase::Impl::WinNode> node = FindWin(win);
213   if (node == nullptr) {
214     _D("[EVENT_TEST][EVENT] ERROR There is no window: %u", win);
215     return false;
216   }
217
218   node->win_ = win;
219   if (surf != 0)
220     node->surf_ = surf;
221   if (vis != VT_NONE)
222     node->vis_ = vis;
223
224   return true;
225 }
226
227 void AppCoreUiBase::Impl::RaiseWin() {
228   if (!(hint_ & HINT_WINDOW_STACK_CONTROL))
229     return;
230
231   unsigned int win_id = parent_->GetMainWindow();
232   _I("Raise window: %u", win_id);
233   handler_->RaiseWin(win_id);
234 }
235
236 void AppCoreUiBase::Impl::PauseWin() {
237   if (!(hint_ & HINT_WINDOW_STACK_CONTROL))
238     return;
239
240   _D("Pause window");
241   for (auto& i : winnode_list_) {
242     _D("Pause window: %u", i->win_);
243     handler_->PauseWin(i->win_);
244   }
245 }
246
247 unsigned int AppCoreUiBase::GetMainWindow() {
248   if (impl_->winnode_list_.empty())
249     return 0;
250
251   return impl_->winnode_list_.begin()->get()->win_;
252 }
253
254 unsigned int AppCoreUiBase::GetMainSurface() {
255   if (impl_->winnode_list_.empty())
256     return 0;
257
258   return impl_->winnode_list_.begin()->get()->surf_;
259 }
260
261 void AppCoreUiBase::SetCoreUiDelegator(IAppCoreUi* delegator) {
262   impl_->core_ui_delegator_ = delegator;
263 }
264
265 void AppCoreUiBase::SetWindowDelegator(IWindow* delegator) {
266   impl_->handler_->SetWindow(delegator);
267 }
268
269 int AppCoreUiBase::Impl::InitWl() {
270   return wl_handler_->Init();
271 }
272
273 int AppCoreUiBase::Impl::FiniWl() {
274   wl_handler_->Fini();
275   return 0;
276 }
277
278 void AppCoreUiBase::Impl::ApplyBgState(bool bg_state) {
279   if (wl_handler_->Init() < 0)
280     return;
281
282   if (bg_state)
283     wl_handler_->SetBgState();
284   else
285     wl_handler_->UnsetBgState();
286
287   parent_->SetBgState(bg_state);
288 }
289
290 void AppCoreUiBase::Impl::SetAppId() {
291   if (wl_handler_->Init() < 0)
292     return;
293
294   wl_handler_->SetAppId(appid_);
295 }
296
297 void AppCoreUiBase::Impl::PluginInit(int argc, char** argv) {
298   plugin_.reset(AppCoreUiPlugin::Load());
299   if (plugin_ == nullptr)
300     return;
301
302   app_core_ui_base_ops ops;
303   ops.base.create = [](void* data) -> int {
304     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
305     return base->OnCreate();
306   };
307
308   ops.base.control = [](bundle* b, void* data) -> int {
309     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
310     return base->OnControl(tizen_base::Bundle(b));
311   };
312
313   ops.base.terminate = [](void* data) -> int {
314     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
315     return base->OnTerminate();
316   };
317
318   ops.base.receive = [](aul_type type, bundle* b, void* data) -> int {
319     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
320     return base->OnReceive(type, tizen_base::Bundle(b));
321   };
322
323   ops.base.set_i18n = [](void* data) -> int {
324     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
325     return base->OnSetI18n();
326   };
327
328   ops.base.init = [](int argc, char** argv, void* data) {
329     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
330     base->OnLoopInit(argc, argv);
331   };
332
333   ops.base.finish = [](void* data) {
334     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
335     base->OnLoopFinish();
336   };
337
338   ops.base.run = [](void* data) {
339     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
340     base->OnLoopRun();
341   };
342
343   ops.base.exit = [](void* data) {
344     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
345     base->OnLoopExit();
346   };
347
348   ops.base.set_event = [](app_core_ui_base_event_e event, void* data) {
349     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
350     base->OnSetEvent(static_cast<IAppCore::IEvent::Type>(event));
351   };
352
353   ops.base.unset_event = [](app_core_ui_base_event_e event, void* data) {
354     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
355     base->OnUnsetEvent(static_cast<IAppCore::IEvent::Type>(event));
356   };
357
358   ops.base.trim_memory = [](void* data) {
359     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
360     base->OnTrimMemory();
361   };
362
363   ops.pause = [](void* data) -> int {
364     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
365     return base->OnPause();
366   };
367
368   ops.resume = [](void* data) -> int {
369     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
370     return base->OnResume();
371   };
372
373   ops.window.show = [](int type, void* event, void* data) {
374     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
375     base->OnShow(type, event);
376   };
377
378   ops.window.hide = [](int type, void* event, void* data) {
379     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
380     base->OnHide(type, event);
381   };
382
383   ops.window.lower = [](int type, void* event, void* data) {
384     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
385     base->OnLower(type, event);
386   };
387
388   ops.window.visibility = [](int type, void* event, void* data) {
389     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
390     base->OnVisibility(type, event);
391   };
392
393   ops.window.pre_visibility = [](int type, void* event, void* data) {
394     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
395     base->OnPreVisibility(type, event);
396   };
397
398   ops.window.aux_message = [](int type, void* event, void* data) {
399     auto* base = reinterpret_cast<AppCoreUiBase*>(data);
400     base->OnAuxMessage(type, event);
401   };
402
403   plugin_->Init(parent_, &ops, argc, argv, &hint_);
404   plugin_delegator_.reset(new AppCoreUiDelegator(ops, parent_));
405   parent_->SetCoreDelegator(plugin_delegator_.get());
406   parent_->SetLoopDelegator(plugin_delegator_.get());
407   parent_->SetCoreUiDelegator(plugin_delegator_.get());
408   parent_->SetWindowDelegator(plugin_delegator_.get());
409 }
410
411 void AppCoreUiBase::Impl::PluginFini() {
412   if (plugin_ == nullptr)
413     return;
414
415   plugin_->Fini(parent_);
416 }
417
418 void AppCoreUiBase::DoRun(int argc, char** argv) {
419   SetCoreDelegator(nullptr);
420   SetLoopDelegator(nullptr);
421   SetCoreUiDelegator(nullptr);
422   SetWindowDelegator(this);
423   impl_->plugin_delegator_.reset();
424
425   impl_->handler_->Init();
426   impl_->PluginInit(argc, argv);
427
428   char appid[PATH_MAX] = {0, };
429   int ret = aul_app_get_appid_bypid(getpid(), appid, sizeof(appid));
430   if (ret != 0)
431     _E("Fail to get appid. pid(%d)", getpid());
432
433   impl_->state_ = Impl::AS_NONE;
434   impl_->w_status_ = Impl::WS_NONE;
435   impl_->appid_ = std::string(appid);
436   LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:main:done]", appid);
437
438   tizen_base::Bundle b(bundle_import_from_argv(argc, argv), false, true);
439   if (!b.IsEmpty()) {
440     if (impl_->hint_ & HINT_BG_LAUNCH_CONTROL) {
441       std::string bg_launch = b.GetString(AUL_SVC_K_BG_LAUNCH);
442       if (bg_launch.compare("enable") == 0)
443         impl_->ApplyBgState(true);
444     }
445
446     std::string x_str = b.GetString(AUL_K_HINT_SCREEN_POS_X);
447     if (!x_str.empty()) {
448       std::string y_str = b.GetString(AUL_K_HINT_SCREEN_POS_Y);
449       std::string w_str = b.GetString(AUL_K_HINT_SCREEN_WIDTH);
450       std::string h_str = b.GetString(AUL_K_HINT_SCREEN_HEIGHT);
451       if (!y_str.empty() && !w_str.empty() && !h_str.empty()) {
452         int x = atoi(x_str.c_str());
453         int y = atoi(y_str.c_str());
454         int w = atoi(w_str.c_str());
455         int h = atoi(h_str.c_str());
456
457         impl_->position_ =
458           std::make_unique<AppCoreUiBase::Impl::WindowPosition>(x, y, w, h);
459       }
460     }
461   }
462
463   if (impl_->hint_ & HINT_WINDOW_ID_CONTROL)
464     impl_->SetAppId();
465
466   AppCoreBase::Run(argc, argv);
467 }
468
469 void AppCoreUiBase::DoExit() {
470   AppCoreBase::Exit();
471 }
472
473 void AppCoreUiBase::Impl::Run(int argc, char** argv) {
474   if (hint_ & HINT_DUAL_THREAD) {
475     // For the loader case
476     while (ecore_shutdown() != 0);
477
478     service_ = parent_->CreateTask();
479     context_ = g_main_context_new();
480     std::string env = std::to_string(
481         reinterpret_cast<unsigned long int>(context_));
482     setenv("TIZEN_GLIB_CONTEXT", env.c_str(), 1);
483
484     thread_ = std::thread([&] {
485           SetComm("UIThread+");
486           parent_->DoRun(argc, argv);
487         });
488
489     service_->Run(argc, argv);
490
491     if (thread_.joinable())
492       thread_.join();
493
494     setenv("TIZEN_GLIB_CONTEXT", "0", 1);
495     g_main_context_unref(context_);
496     context_ = nullptr;
497     return;
498   }
499
500   parent_->DoRun(argc, argv);
501 }
502
503 void AppCoreUiBase::Impl::Exit() {
504   if (hint_ & HINT_DUAL_THREAD) {
505     GLib::IdleAdd(context_, [](gpointer user_data) {
506           auto* impl = static_cast<AppCoreUiBase::Impl*>(user_data);
507           impl->parent_->DoExit();
508           return G_SOURCE_REMOVE;
509         }, this);
510
511     service_->Exit();
512     return;
513   }
514
515   parent_->DoExit();
516 }
517
518 void AppCoreUiBase::Run(int argc, char** argv) {
519   impl_->Run(argc, argv);
520 }
521
522 void AppCoreUiBase::Exit() {
523   impl_->Exit();
524 }
525
526 void AppCoreUiBase::Dispose() {
527   impl_->handler_->UnsetEvents();
528   impl_->FiniWl();
529
530   impl_->appid_.clear();
531
532   AppCoreBase::Dispose();
533   impl_->PluginFini();
534   impl_->handler_->Fini();
535 }
536
537 std::unique_ptr<AppCoreTaskBase> AppCoreUiBase::CreateTask() {
538   return std::make_unique<AppCoreTaskBase>();
539 }
540
541 void AppCoreUiBase::Impl::PrepareToSuspend() {
542   if (parent_->IsBgAllowed() && !parent_->IsSuspended()) {
543     SuspendedState suspend = SUSPENDED_STATE_WILL_ENTER_SUSPEND;
544     parent_->RaiseEvent(suspend, IEvent::Type::SUSPENDED_STATE_CHANGE);
545     parent_->ToggleSuspendedState();
546   }
547 }
548
549 void AppCoreUiBase::Impl::ExitFromSuspend() {
550   if (parent_->IsSuspended()) {
551     SuspendedState suspend = SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND;
552     parent_->RaiseEvent(suspend, IEvent::Type::SUSPENDED_STATE_CHANGE);
553     parent_->ToggleSuspendedState();
554   }
555 }
556
557 void AppCoreUiBase::Impl::DoPause() {
558   if (state_ == AS_RUNNING) {
559     aul_app_lifecycle_update_state(AUL_APP_LIFECYCLE_STATE_PAUSED);
560     state_ = AS_PAUSED;
561     traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:PAUSE");
562     _D("Call pause callback");
563     if (parent_->GetHint() & HINT_DUAL_THREAD)
564       service_->Post(AppCoreTaskBase::UiState::PAUSED);
565
566     int ret;
567     if (core_ui_delegator_)
568       ret = core_ui_delegator_->OnPause();
569     else
570       ret = parent_->OnPause();
571
572     traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
573     if (ret >= 0 && resource_reclaiming_)
574       parent_->AddSuspendTimer();
575
576     PrepareToSuspend();
577   }
578
579   aul_status_update(STATUS_BG);
580 }
581
582 void AppCoreUiBase::Impl::DoResume() {
583   if (state_ == AS_PAUSED || state_ == AS_CREATED) {
584     aul_app_lifecycle_update_state(AUL_APP_LIFECYCLE_STATE_RESUMED);
585     ExitFromSuspend();
586     state_ = AS_RUNNING;
587     LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:start]", appid_.c_str());
588     traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:RESUME");
589     _D("Call resume callback");
590     if (parent_->GetHint() & HINT_DUAL_THREAD)
591       service_->Post(AppCoreTaskBase::UiState::RESUMED);
592
593     parent_->RemoveSuspendTimer();
594     if (core_ui_delegator_)
595       core_ui_delegator_->OnResume();
596     else
597       parent_->OnResume();
598
599     traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
600     LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:done]", appid_.c_str());
601   }
602
603   aul_status_update(STATUS_VISIBLE);
604 }
605
606 void AppCoreUiBase::Impl::DoStart(tizen_base::Bundle b) {
607   if (parent_->GetHint() & HINT_WINDOW_STACK_CONTROL)
608     below_app_ = b.GetString(AUL_SVC_K_RELOCATE_BELOW);
609
610   if (first_launch_) {
611     first_launch_ = false;
612     return;
613   }
614
615   std::string rpc_port = b.GetString(AUL_K_RPC_PORT);
616   if (parent_->GetHint() & HINT_BG_LAUNCH_CONTROL) {
617     std::string bg_launch = b.GetString(AUL_SVC_K_BG_LAUNCH);
618     if (!bg_launch.empty() && bg_launch.compare("enable") == 0) {
619       if (!bg_state_ && state_ != AS_RUNNING)
620         ApplyBgState(true);
621     } else {
622       if (bg_state_ && rpc_port.empty())
623         ApplyBgState(false);
624     }
625   }
626
627   if (parent_->GetHint() & HINT_WINDOW_AUTO_CONTROL) {
628     if (!bg_state_ && rpc_port.empty())
629       RaiseWin();
630   }
631 }
632
633 int AppCoreUiBase::Impl::IsLegacyLifecycle() {
634   static int is_legacy = -1;
635   if (__builtin_expect(is_legacy != -1, 1))
636     return is_legacy;
637
638   const char* api_version = getenv("TIZEN_API_VERSION");
639   if (api_version) {
640     if (strverscmp("2.4", api_version) > 0 &&
641         strverscmp("2.2.1", api_version) < 0)
642       is_legacy = 1;
643     else
644       is_legacy = 0;
645   } else {
646     is_legacy = 0;
647   }
648
649   return is_legacy;
650 }
651
652 int AppCoreUiBase::OnPause() {
653   return 0;
654 }
655
656 int AppCoreUiBase::OnResume() {
657   return 0;
658 }
659
660 int AppCoreUiBase::OnReceive(aul_type type, tizen_base::Bundle b) {
661   if (impl_->state_ == Impl::AS_DYING) {
662     _E("Skip the event in dying state");
663     return 0;
664   }
665
666   if ((type == AUL_TERMINATE_BGAPP || type == AUL_TERMINATE_BG_INST) &&
667       impl_->state_ != Impl::AS_PAUSED)
668     return 0;
669
670   if (type == AUL_START) {
671     impl_->ExitFromSuspend();
672
673     if (!b.GetString(K_SERVICE_THREAD).empty()) {
674       impl_->service_->OnReceive(type, std::move(b));
675       return 0;
676     }
677   }
678
679   AppCoreBase::OnReceive(type, b);
680
681   switch (type) {
682   case AUL_START:
683     impl_->DoStart(b);
684     if (GetHint() & HINT_LEGACY_CONTROL) {
685       if (impl_->bg_state_ && impl_->IsLegacyLifecycle()) {
686         _D("Legacy lifecycle");
687         impl_->DoResume();
688       }
689     }
690     break;
691   case AUL_RESUME:
692     if (impl_->bg_state_)
693       impl_->ApplyBgState(false);
694
695     impl_->RaiseWin();
696     break;
697   case AUL_TERMINATE:
698     if (impl_->state_ == Impl::AS_RUNNING) {
699       _D("Call pause callback");
700       if (impl_->core_ui_delegator_)
701         impl_->core_ui_delegator_->OnPause();
702       else
703         OnPause();
704     }
705     impl_->state_ = Impl::AS_DYING;
706     break;
707   case AUL_TERMINATE_BGAPP:
708   case AUL_TERMINATE_BG_INST:
709   case AUL_TERMINATE_INST:
710     _D("[APP %d] TERMINATE", getpid());
711     if (impl_->state_ == Impl::AS_RUNNING) {
712       _D("Call pause callback");
713       if (impl_->core_ui_delegator_)
714         impl_->core_ui_delegator_->OnPause();
715       else
716         OnPause();
717     }
718     impl_->state_ = Impl::AS_DYING;
719     aul_status_update(STATUS_DYING);
720     Exit();
721     break;
722   case AUL_PAUSE:
723     impl_->PauseWin();
724     break;
725   default:
726     break;
727   }
728
729   return 0;
730 }
731
732 int AppCoreUiBase::OnControl(tizen_base::Bundle b) {
733   LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:start]",
734       impl_->appid_.c_str());
735   AppCoreBase::OnControl(std::move(b));
736   LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:done]",
737       impl_->appid_.c_str());
738   return 0;
739 }
740
741 int AppCoreUiBase::OnCreate() {
742   impl_->handler_->SetEvents();
743   AppCoreBase::OnCreate();
744   impl_->state_ = Impl::AS_CREATED;
745   LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:create:done]",
746       impl_->appid_.c_str());
747   return 0;
748 }
749
750 int AppCoreUiBase::OnTerminate() {
751   if (impl_->state_ == Impl::AS_RUNNING) {
752     _D("Call pause callback");
753     OnPause();
754   }
755
756   impl_->state_ = Impl::AS_DYING;
757   AppCoreBase::OnTerminate();
758   return 0;
759 }
760
761 int AppCoreUiBase::OnTrimMemory() {
762   return AppCoreBase::OnTrimMemory();
763 }
764
765 int AppCoreUiBase::GroupAdd() {
766   _D("Group attach");
767   static bool attached = false;
768   if (attached)
769     return 0;
770
771   int wid = GetMainSurface();
772   if (wid == 0) {
773     _E("window wasn't ready");
774     return -1;
775   }
776
777   int ret = aul_app_group_set_window(wid);
778   if (ret < 0) {
779     _E("Failed to set app group window. error(%d)", ret);
780     return ret;
781   }
782
783   attached = true;
784   return 0;
785 }
786
787 void AppCoreUiBase::GroupRemove() {
788   _D("Group lower");
789   int exit = 0;
790   aul_app_group_lower(&exit);
791   if (exit) {
792     _W("Sub App");
793     Exit();
794   }
795 }
796
797 void AppCoreUiBase::OnShow(int type, void* event) {
798   auto* ev = reinterpret_cast<Ecore_Wl2_Event_Window_Show*>(event);
799   if (ev->parent_win != 0)
800     return;
801
802   unsigned int win = static_cast<unsigned int>(ev->win);
803   unsigned int surf = static_cast<unsigned int>(ev->data[0]);
804   _D("[EVENT_TEST][EVENT] GET SHOW EVENT!!!. WIN: %u, %u", win, surf);
805
806   if (!impl_->FindWin(win))
807     impl_->AddWin(win, surf);
808   else
809     impl_->UpdateWin(win, surf, Impl::VT_NONE);
810
811   if (surf != 0)
812     GroupAdd();
813 }
814
815 bool AppCoreUiBase::Impl::CheckVisible() {
816   _D("[EVENT_TEST][EVENT] __check_visible");
817   for (auto& i : winnode_list_) {
818     _D("win : %u visibility : %d", i->win_, i->vis_);
819     if (i->vis_ == VT_UNOBSCURED)
820       return true;
821   }
822
823   return false;
824 }
825
826 void AppCoreUiBase::OnHide(int type, void* event) {
827   auto* ev = reinterpret_cast<Ecore_Wl2_Event_Window_Hide*>(event);
828   _D("[EVENT_TEST][EVENT] GET HIDE EVENT!!!. WIN :%d", ev->win);
829   if (impl_->FindWin((unsigned int)ev->win)) {
830     impl_->DeleteWin((unsigned int)ev->win);
831     bool bvisibility = impl_->CheckVisible();
832     if (!bvisibility && impl_->w_status_ != Impl::WS_PAUSE) {
833       _D("Go to Pasue state");
834       impl_->w_status_ = Impl::WS_PAUSE;
835       impl_->DoPause();
836     }
837   }
838 }
839
840 void AppCoreUiBase::OnLower(int type, void* event) {
841   auto* ev = reinterpret_cast<Ecore_Wl2_Event_Window_Lower*>(event);
842   if (!ev)
843     return;
844
845   _D("ECORE_WL2_EVENT_WINDOW_LOWER window id: %u", ev->win);
846   if (!(impl_->hint_ & HINT_WINDOW_GROUP_CONTROL))
847     return;
848
849   GroupRemove();
850 }
851
852 void AppCoreUiBase::OnVisibility(int type, void* event) {
853   auto* ev = reinterpret_cast<Ecore_Wl2_Event_Window_Visibility_Change*>(event);
854   impl_->UpdateWin((unsigned int)ev->win, 0,
855       ev->fully_obscured ? Impl::VT_FULLY_OBSCURED : Impl::VT_UNOBSCURED);
856   bool bvisibility = impl_->CheckVisible();
857   _D("bvisibility %d, w_status_ %d", bvisibility, impl_->w_status_);
858
859   if (bvisibility && (impl_->hint_ & HINT_WINDOW_STACK_CONTROL) &&
860       !impl_->below_app_.empty()) {
861     aul_app_group_activate_below(impl_->below_app_.c_str());
862     impl_->below_app_.clear();
863   }
864
865   if (bvisibility && impl_->w_status_ != Impl::WS_RESUME) {
866     _D("Go to Resume state");
867     impl_->w_status_ = Impl::WS_RESUME;
868     impl_->DoResume();
869   } else if (!bvisibility && impl_->w_status_ != Impl::WS_PAUSE) {
870     _D("Go to Pasue state");
871     impl_->w_status_ = Impl::WS_PAUSE;
872     impl_->DoPause();
873   } else {
874     _D("No change state");
875   }
876 }
877
878 void AppCoreUiBase::OnPreVisibility(int type, void* event) {
879   auto* ev = reinterpret_cast<Ecore_Wl2_Event_Window_Pre_Visibility_Change*>(
880       event);
881   if (ev && ev->type == ECORE_WL2_WINDOW_VISIBILITY_TYPE_PRE_UNOBSCURED) {
882     impl_->UpdateWin((unsigned int)ev->win, 0, Impl::VT_UNOBSCURED);
883     bool bvisibility = impl_->CheckVisible();
884
885     _D("bvisibility %d, w_status_ %d", bvisibility, impl_->w_status_);
886     if (bvisibility && impl_->w_status_ != Impl::WS_RESUME) {
887       _D(" Go to Resume state");
888       impl_->w_status_ = Impl::WS_RESUME;
889       impl_->DoResume();
890     }
891   }
892 }
893
894 void AppCoreUiBase::OnAuxMessage(int type, void* event) {
895   auto* ev = reinterpret_cast<Ecore_Wl2_Event_Aux_Message*>(event);
896   if (ev->key && !strcmp(ev->key, "dpms_wm")) {
897     if (ev->val && !strcmp(ev->val, "on")) {
898       _D("Display state: on");
899       SetDisplayState(DISPLAY_STATE_ON);
900     } else if (ev->val && !strcmp(ev->val, "off")) {
901       _D("Display state: off");
902       SetDisplayState(DISPLAY_STATE_OFF);
903     } else {
904       _E("Unknown state: %s", ev->val);
905     }
906   }
907 }
908
909 void AppCoreUiBase::Pause() {
910   impl_->DoPause();
911 }
912
913 void AppCoreUiBase::Resume() {
914   impl_->DoResume();
915 }
916
917 bool AppCoreUiBase::IsResumed() {
918   return impl_->state_ == Impl::AS_RUNNING;
919 }
920
921 int AppCoreUiBase::GetHint() {
922   return impl_->hint_;
923 }
924
925 bool AppCoreUiBase::GetBgState() {
926   return impl_->bg_state_;
927 }
928
929 void AppCoreUiBase::SetBgState(bool bg_state) {
930   impl_->bg_state_ = bg_state;
931 }
932
933 void AppCoreUiBase::SetSystemResourceReclaiming(bool enable) {
934   impl_->resource_reclaiming_ = enable;
935 }
936
937 int AppCoreUiBase::GetWindowPosition(int* x, int* y, int* w, int* h) {
938   if (!impl_->position_ ||
939       x == nullptr ||
940       y == nullptr ||
941       w == nullptr ||
942       h == nullptr)
943     return -1;
944
945   *x = impl_->position_->GetPositionX();
946   *y = impl_->position_->GetPositionY();
947   *w = impl_->position_->GetScreenWidth();
948   *h = impl_->position_->GetScreenHeight();
949
950   return 0;
951 }
952
953 }  // namespace tizen_cpp