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