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