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