Remove unnecessary function 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 <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     service_ = parent_->CreateTask();
440     context_ = g_main_context_new();
441     std::string env = std::to_string(
442         reinterpret_cast<unsigned long int>(context_));
443     setenv("TIZEN_GLIB_CONTEXT", env.c_str(), 1);
444
445     thread_ = std::thread([&] {
446           SetComm("UIThread+");
447           parent_->DoRun(argc, argv);
448         });
449
450     service_->Run(argc, argv);
451
452     if (thread_.joinable())
453       thread_.join();
454
455     setenv("TIZEN_GLIB_CONTEXT", "0", 1);
456     g_main_context_unref(context_);
457     context_ = nullptr;
458     return;
459   }
460
461   parent_->DoRun(argc, argv);
462 }
463
464 void AppCoreUiBase::Impl::Exit() {
465   if (hint_ & HINT_DUAL_THREAD) {
466     GLib::IdleAdd(context_, [](gpointer user_data) {
467           auto* impl = static_cast<AppCoreUiBase::Impl*>(user_data);
468           impl->parent_->DoExit();
469           return G_SOURCE_REMOVE;
470         }, this);
471
472     service_->Exit();
473     return;
474   }
475
476   parent_->DoExit();
477 }
478
479 void AppCoreUiBase::Run(int argc, char** argv) {
480   impl_->Run(argc, argv);
481 }
482
483 void AppCoreUiBase::Exit() {
484   impl_->Exit();
485 }
486
487 void AppCoreUiBase::Dispose() {
488   impl_->handler_->UnsetEvents();
489   impl_->FiniWl();
490
491   impl_->appid_.clear();
492
493   AppCoreBase::Dispose();
494   impl_->PluginFini();
495   impl_->handler_->Fini();
496 }
497
498 std::unique_ptr<AppCoreTaskBase> AppCoreUiBase::CreateTask() {
499   return std::make_unique<AppCoreTaskBase>();
500 }
501
502 void AppCoreUiBase::Impl::PrepareToSuspend() {
503   if (parent_->IsBgAllowed() && !parent_->IsSuspended()) {
504     SuspendedState suspend = SUSPENDED_STATE_WILL_ENTER_SUSPEND;
505     parent_->RaiseEvent(suspend, IEvent::Type::SUSPENDED_STATE_CHANGE);
506     parent_->ToggleSuspendedState();
507   }
508 }
509
510 void AppCoreUiBase::Impl::ExitFromSuspend() {
511   if (parent_->IsSuspended()) {
512     SuspendedState suspend = SUSPENDED_STATE_DID_EXIT_FROM_SUSPEND;
513     parent_->RaiseEvent(suspend, IEvent::Type::SUSPENDED_STATE_CHANGE);
514     parent_->ToggleSuspendedState();
515   }
516 }
517
518 void AppCoreUiBase::Impl::DoPause() {
519   if (state_ == AS_RUNNING) {
520     aul_app_lifecycle_update_state(AUL_APP_LIFECYCLE_STATE_PAUSED);
521     state_ = AS_PAUSED;
522     traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:PAUSE");
523     _D("Call pause callback");
524     if (parent_->GetHint() & HINT_DUAL_THREAD)
525       service_->Post(AppCoreTaskBase::UiState::PAUSED);
526
527     int ret;
528     if (core_ui_delegator_)
529       ret = core_ui_delegator_->OnPause();
530     else
531       ret = parent_->OnPause();
532
533     traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
534     if (ret >= 0 && resource_reclaiming_)
535       parent_->AddSuspendTimer();
536
537     PrepareToSuspend();
538   }
539
540   aul_status_update(STATUS_BG);
541 }
542
543 void AppCoreUiBase::Impl::DoResume() {
544   if (state_ == AS_PAUSED || state_ == AS_CREATED) {
545     aul_app_lifecycle_update_state(AUL_APP_LIFECYCLE_STATE_RESUMED);
546     ExitFromSuspend();
547     state_ = AS_RUNNING;
548     LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:start]", appid_.c_str());
549     traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "APPCORE:RESUME");
550     _D("Call resume callback");
551     if (parent_->GetHint() & HINT_DUAL_THREAD)
552       service_->Post(AppCoreTaskBase::UiState::RESUMED);
553
554     parent_->RemoveSuspendTimer();
555     if (core_ui_delegator_)
556       core_ui_delegator_->OnResume();
557     else
558       parent_->OnResume();
559
560     traceEnd(TTRACE_TAG_APPLICATION_MANAGER);
561     LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:resume:done]", appid_.c_str());
562   }
563
564   aul_status_update(STATUS_VISIBLE);
565 }
566
567 void AppCoreUiBase::Impl::DoStart(tizen_base::Bundle b) {
568   if (parent_->GetHint() & HINT_WINDOW_STACK_CONTROL)
569     below_app_ = b.GetString(AUL_SVC_K_RELOCATE_BELOW);
570
571   if (first_launch_) {
572     first_launch_ = false;
573     return;
574   }
575
576   if (parent_->GetHint() & HINT_BG_LAUNCH_CONTROL) {
577     std::string bg_launch = b.GetString(AUL_SVC_K_BG_LAUNCH);
578     if (!bg_launch.empty() && bg_launch.compare("enable") == 0) {
579       if (!bg_state_ && state_ != AS_RUNNING)
580         ApplyBgState(true);
581     } else {
582       if (bg_state_)
583         ApplyBgState(false);
584     }
585   }
586
587   if (parent_->GetHint() & HINT_WINDOW_AUTO_CONTROL) {
588     if (!bg_state_) {
589       std::string rpc_port = b.GetString(AUL_K_RPC_PORT);
590       if (rpc_port.empty())
591         RaiseWin();
592     }
593   }
594 }
595
596 int AppCoreUiBase::Impl::IsLegacyLifecycle() {
597   static int is_legacy = -1;
598   if (__builtin_expect(is_legacy != -1, 1))
599     return is_legacy;
600
601   const char* api_version = getenv("TIZEN_API_VERSION");
602   if (api_version) {
603     if (strverscmp("2.4", api_version) > 0 &&
604         strverscmp("2.2.1", api_version) < 0)
605       is_legacy = 1;
606     else
607       is_legacy = 0;
608   } else {
609     is_legacy = 0;
610   }
611
612   return is_legacy;
613 }
614
615 int AppCoreUiBase::OnPause() {
616   return 0;
617 }
618
619 int AppCoreUiBase::OnResume() {
620   return 0;
621 }
622
623 int AppCoreUiBase::OnReceive(aul_type type, tizen_base::Bundle b) {
624   if (impl_->state_ == Impl::AS_DYING) {
625     _E("Skip the event in dying state");
626     return 0;
627   }
628
629   if ((type == AUL_TERMINATE_BGAPP || type == AUL_TERMINATE_BG_INST) &&
630       impl_->state_ != Impl::AS_PAUSED)
631     return 0;
632
633   if (type == AUL_START) {
634     impl_->ExitFromSuspend();
635
636     if (!b.GetString(K_SERVICE_THREAD).empty()) {
637       impl_->service_->OnReceive(type, std::move(b));
638       return 0;
639     }
640   }
641
642   AppCoreBase::OnReceive(type, b);
643
644   switch (type) {
645   case AUL_START:
646     impl_->DoStart(b);
647     if (GetHint() & HINT_LEGACY_CONTROL) {
648       if (impl_->bg_state_ && impl_->IsLegacyLifecycle()) {
649         _D("Legacy lifecycle");
650         impl_->DoResume();
651       }
652     }
653     break;
654   case AUL_RESUME:
655     if (impl_->bg_state_)
656       impl_->ApplyBgState(false);
657
658     impl_->RaiseWin();
659     break;
660   case AUL_TERMINATE:
661     if (impl_->state_ == Impl::AS_RUNNING) {
662       _D("Call pause callback");
663       if (impl_->core_ui_delegator_)
664         impl_->core_ui_delegator_->OnPause();
665       else
666         OnPause();
667     }
668     impl_->state_ = Impl::AS_DYING;
669     break;
670   case AUL_TERMINATE_BGAPP:
671   case AUL_TERMINATE_BG_INST:
672   case AUL_TERMINATE_INST:
673     _D("[APP %d] TERMINATE", getpid());
674     if (impl_->state_ == Impl::AS_RUNNING) {
675       _D("Call pause callback");
676       if (impl_->core_ui_delegator_)
677         impl_->core_ui_delegator_->OnPause();
678       else
679         OnPause();
680     }
681     impl_->state_ = Impl::AS_DYING;
682     aul_status_update(STATUS_DYING);
683     Exit();
684     break;
685   case AUL_PAUSE:
686     impl_->PauseWin();
687     break;
688   default:
689     break;
690   }
691
692   return 0;
693 }
694
695 int AppCoreUiBase::OnControl(tizen_base::Bundle b) {
696   LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:start]",
697       impl_->appid_.c_str());
698   AppCoreBase::OnControl(std::move(b));
699   LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:reset:done]",
700       impl_->appid_.c_str());
701   return 0;
702 }
703
704 int AppCoreUiBase::OnCreate() {
705   impl_->handler_->SetEvents();
706   AppCoreBase::OnCreate();
707   impl_->state_ = Impl::AS_CREATED;
708   LOG(LOG_DEBUG, "LAUNCH", "[%s:Application:create:done]",
709       impl_->appid_.c_str());
710   return 0;
711 }
712
713 int AppCoreUiBase::OnTerminate() {
714   if (impl_->state_ == Impl::AS_RUNNING) {
715     _D("Call pause callback");
716     OnPause();
717   }
718
719   impl_->state_ = Impl::AS_DYING;
720   AppCoreBase::OnTerminate();
721   return 0;
722 }
723
724 int AppCoreUiBase::OnTrimMemory() {
725   return AppCoreBase::OnTrimMemory();
726 }
727
728 int AppCoreUiBase::GroupAdd() {
729   _D("Group attach");
730   static bool attached = false;
731   if (attached)
732     return 0;
733
734   int wid = GetMainSurface();
735   if (wid == 0) {
736     _E("window wasn't ready");
737     return -1;
738   }
739
740   int ret = aul_app_group_set_window(wid);
741   if (ret < 0) {
742     _E("Failed to set app group window. error(%d)", ret);
743     return ret;
744   }
745
746   attached = true;
747   return 0;
748 }
749
750 void AppCoreUiBase::GroupRemove() {
751   _D("Group lower");
752   int exit = 0;
753   aul_app_group_lower(&exit);
754   if (exit) {
755     _W("Sub App");
756     Exit();
757   }
758 }
759
760 void AppCoreUiBase::OnShow(int type, void* event) {
761   auto* ev = reinterpret_cast<Ecore_Wl2_Event_Window_Show*>(event);
762   if (ev->parent_win != 0)
763     return;
764
765   unsigned int win = static_cast<unsigned int>(ev->win);
766   unsigned int surf = static_cast<unsigned int>(ev->data[0]);
767   _D("[EVENT_TEST][EVENT] GET SHOW EVENT!!!. WIN: %u, %u", win, surf);
768
769   if (!impl_->FindWin(win))
770     impl_->AddWin(win, surf);
771   else
772     impl_->UpdateWin(win, surf, Impl::VT_NONE);
773
774   if (surf != 0)
775     GroupAdd();
776 }
777
778 bool AppCoreUiBase::Impl::CheckVisible() {
779   _D("[EVENT_TEST][EVENT] __check_visible");
780   for (auto& i : winnode_list_) {
781     _D("win : %u visibility : %d", i->win_, i->vis_);
782     if (i->vis_ == VT_UNOBSCURED)
783       return true;
784   }
785
786   return false;
787 }
788
789 void AppCoreUiBase::OnHide(int type, void* event) {
790   auto* ev = reinterpret_cast<Ecore_Wl2_Event_Window_Hide*>(event);
791   _D("[EVENT_TEST][EVENT] GET HIDE EVENT!!!. WIN :%d", ev->win);
792   if (impl_->FindWin((unsigned int)ev->win)) {
793     impl_->DeleteWin((unsigned int)ev->win);
794     bool bvisibility = impl_->CheckVisible();
795     if (!bvisibility && impl_->w_status_ != Impl::WS_PAUSE) {
796       _D("Go to Pasue state");
797       impl_->w_status_ = Impl::WS_PAUSE;
798       impl_->DoPause();
799     }
800   }
801 }
802
803 void AppCoreUiBase::OnLower(int type, void* event) {
804   auto* ev = reinterpret_cast<Ecore_Wl2_Event_Window_Lower*>(event);
805   if (!ev)
806     return;
807
808   _D("ECORE_WL2_EVENT_WINDOW_LOWER window id: %u", ev->win);
809   if (!(impl_->hint_ & HINT_WINDOW_GROUP_CONTROL))
810     return;
811
812   GroupRemove();
813 }
814
815 void AppCoreUiBase::OnVisibility(int type, void* event) {
816   auto* ev = reinterpret_cast<Ecore_Wl2_Event_Window_Visibility_Change*>(event);
817   impl_->UpdateWin((unsigned int)ev->win, 0,
818       ev->fully_obscured ? Impl::VT_FULLY_OBSCURED : Impl::VT_UNOBSCURED);
819   bool bvisibility = impl_->CheckVisible();
820   _D("bvisibility %d, w_status_ %d", bvisibility, impl_->w_status_);
821
822   if (bvisibility && (impl_->hint_ & HINT_WINDOW_STACK_CONTROL) &&
823       !impl_->below_app_.empty()) {
824     aul_app_group_activate_below(impl_->below_app_.c_str());
825     impl_->below_app_.clear();
826   }
827
828   if (bvisibility && impl_->w_status_ != Impl::WS_RESUME) {
829     _D("Go to Resume state");
830     impl_->w_status_ = Impl::WS_RESUME;
831     impl_->DoResume();
832   } else if (!bvisibility && impl_->w_status_ != Impl::WS_PAUSE) {
833     _D("Go to Pasue state");
834     impl_->w_status_ = Impl::WS_PAUSE;
835     impl_->DoPause();
836   } else {
837     _D("No change state");
838   }
839 }
840
841 void AppCoreUiBase::OnPreVisibility(int type, void* event) {
842   auto* ev = reinterpret_cast<Ecore_Wl2_Event_Window_Pre_Visibility_Change*>(
843       event);
844   if (ev && ev->type == ECORE_WL2_WINDOW_VISIBILITY_TYPE_PRE_UNOBSCURED) {
845     impl_->UpdateWin((unsigned int)ev->win, 0, Impl::VT_UNOBSCURED);
846     bool bvisibility = impl_->CheckVisible();
847
848     _D("bvisibility %d, w_status_ %d", bvisibility, impl_->w_status_);
849     if (bvisibility && impl_->w_status_ != Impl::WS_RESUME) {
850       _D(" Go to Resume state");
851       impl_->w_status_ = Impl::WS_RESUME;
852       impl_->DoResume();
853     }
854   }
855 }
856
857 void AppCoreUiBase::OnAuxMessage(int type, void* event) {
858   auto* ev = reinterpret_cast<Ecore_Wl2_Event_Aux_Message*>(event);
859   if (ev->key && !strcmp(ev->key, "dpms_wm")) {
860     if (ev->val && !strcmp(ev->val, "on")) {
861       _D("Display state: on");
862       SetDisplayState(DISPLAY_STATE_ON);
863     } else if (ev->val && !strcmp(ev->val, "off")) {
864       _D("Display state: off");
865       SetDisplayState(DISPLAY_STATE_OFF);
866     } else {
867       _E("Unknown state: %s", ev->val);
868     }
869   }
870 }
871
872 void AppCoreUiBase::Pause() {
873   impl_->DoPause();
874 }
875
876 void AppCoreUiBase::Resume() {
877   impl_->DoResume();
878 }
879
880 bool AppCoreUiBase::IsResumed() {
881   return impl_->state_ == Impl::AS_RUNNING;
882 }
883
884 int AppCoreUiBase::GetHint() {
885   return impl_->hint_;
886 }
887
888 bool AppCoreUiBase::GetBgState() {
889   return impl_->bg_state_;
890 }
891
892 void AppCoreUiBase::SetBgState(bool bg_state) {
893   impl_->bg_state_ = bg_state;
894 }
895
896 void AppCoreUiBase::SetSystemResourceReclaiming(bool enable) {
897   impl_->resource_reclaiming_ = enable;
898 }
899
900 }  // namespace tizen_cpp