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