d0b25e17b9c71d334df581e6cffd650b52851b66
[platform/core/uifw/dali-adaptor.git] / dali / internal / adaptor / tizen-wayland / framework-tizen.cpp
1 /*
2  * Copyright (c) 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
18 // CLASS HEADER
19 #include <dali/internal/adaptor/common/framework.h>
20
21 // EXTERNAL INCLUDES
22 #include <app_common.h>
23 #include <app_control_internal.h>
24 #include <bundle.h>
25 #include <bundle_internal.h>
26 #include <dlog.h>
27 #include <glib.h>
28 #include <system_info.h>
29 #include <system_settings.h>
30 #include <widget_base.h>
31 #include <app_core_ui_base.hh>
32 #include <app_event_internal.hh>
33
34 // CONDITIONAL INCLUDES
35 #ifdef APPCORE_WATCH_AVAILABLE
36 #include <appcore-watch/watch_app.h>
37 #endif
38 #ifdef DALI_ELDBUS_AVAILABLE
39 #include <Eldbus.h>
40 #endif // DALI_ELDBUS_AVAILABLE
41
42 #if defined(TIZEN_PLATFORM_CONFIG_SUPPORTED) && TIZEN_PLATFORM_CONFIG_SUPPORTED
43 #include <tzplatform_config.h>
44 #endif // TIZEN_PLATFORM_CONFIG_SUPPORTED
45
46 #ifdef COMPONENT_APPLICATION_SUPPORT
47 #include <component_based_app_base.h>
48 #endif
49
50 #include <dali/integration-api/debug.h>
51 #include <dali/integration-api/trace.h>
52
53 // INTERNAL INCLUDES
54 #include <dali/internal/system/common/callback-manager.h>
55 #include <dali/internal/system/linux/dali-ecore.h>
56
57 using namespace tizen_cpp;
58
59 namespace Dali
60 {
61 namespace Internal
62 {
63 namespace Adaptor
64 {
65 namespace
66 {
67 #if defined(DEBUG_ENABLED)
68 Integration::Log::Filter* gDBusLogging = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_DBUS");
69 #endif
70 DALI_INIT_TRACE_FILTER(gTraceFilter, DALI_TRACE_FRAMEWORK, true);
71
72 bool IsWidgetFeatureEnabled()
73 {
74   static bool feature   = false;
75   static bool retrieved = false;
76   int         ret;
77
78   if(retrieved == true)
79   {
80     return feature;
81   }
82
83   ret = system_info_get_platform_bool("http://tizen.org/feature/shell.appwidget", &feature);
84   if(ret != SYSTEM_INFO_ERROR_NONE)
85   {
86     DALI_LOG_ERROR("failed to get system info");
87     return false;
88   }
89
90   retrieved = true;
91   return feature;
92 }
93
94 } // anonymous namespace
95
96 namespace AppCore
97 {
98 typedef enum
99 {
100   LOW_MEMORY,                 //< The low memory event
101   LOW_BATTERY,                //< The low battery event
102   LANGUAGE_CHANGED,           //< The system language changed event
103   DEVICE_ORIENTATION_CHANGED, //< The device orientation changed event
104   REGION_FORMAT_CHANGED,      //< The region format changed event
105   SUSPENDED_STATE_CHANGED,    //< The suspended state changed event of the application
106   UPDATE_REQUESTED,           //< The update requested event. This event can occur when an app needs to be updated. It is dependent on target devices.
107 } AppEventType;
108
109 static int AppEventConverter[APPCORE_BASE_EVENT_MAX] =
110   {
111     [LOW_MEMORY]                 = APPCORE_BASE_EVENT_LOW_MEMORY,
112     [LOW_BATTERY]                = APPCORE_BASE_EVENT_LOW_BATTERY,
113     [LANGUAGE_CHANGED]           = APPCORE_BASE_EVENT_LANG_CHANGE,
114     [DEVICE_ORIENTATION_CHANGED] = APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED,
115     [REGION_FORMAT_CHANGED]      = APPCORE_BASE_EVENT_REGION_CHANGE,
116     [SUSPENDED_STATE_CHANGED]    = APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE,
117 };
118
119 struct AppEventInfo
120 {
121   AppEventType type;
122   void*        value;
123 };
124
125 typedef struct AppEventInfo* AppEventInfoPtr;
126
127 typedef void (*AppEventCallback)(AppEventInfoPtr eventInfo, void* userData);
128
129 struct AppEventHandler
130 {
131   AppEventType     type;
132   AppEventCallback cb;
133   void*            data;
134   void*            raw;
135 };
136
137 typedef struct AppEventHandler* AppEventHandlerPtr;
138
139 int EventCallback(void* event, void* data)
140 {
141   AppEventHandlerPtr handler = static_cast<AppEventHandlerPtr>(data);
142
143   struct AppEventInfo appEvent;
144
145   appEvent.type  = handler->type;
146   appEvent.value = event;
147
148   if(handler->cb)
149     handler->cb(&appEvent, handler->data);
150
151   return 0;
152 }
153
154 int AppAddEventHandler(AppEventHandlerPtr* eventHandler, AppEventType eventType, AppEventCallback callback, void* userData)
155 {
156   AppEventHandlerPtr handler;
157
158   handler = static_cast<AppEventHandlerPtr>(calloc(1, sizeof(struct AppEventHandler)));
159   if(!handler)
160   {
161     DALI_LOG_ERROR("failed to create handler");
162     return TIZEN_ERROR_UNKNOWN;
163   }
164   else
165   {
166     handler->type = eventType;
167     handler->cb   = callback;
168     handler->data = userData;
169     handler->raw  = appcore_base_add_event(static_cast<appcore_base_event>(AppEventConverter[static_cast<int>(eventType)]), EventCallback, handler);
170
171     *eventHandler = handler;
172
173     return TIZEN_ERROR_NONE;
174   }
175 }
176
177 DeviceStatus::Memory::Status GetMemoryStatus(app_event_low_memory_status_e memoryStatus)
178 {
179   switch(memoryStatus)
180   {
181     case APP_EVENT_LOW_MEMORY_SOFT_WARNING: // 0x02
182     {
183       return Dali::DeviceStatus::Memory::Status::LOW;
184     }
185     case APP_EVENT_LOW_MEMORY_HARD_WARNING: // 0x04
186     {
187       return Dali::DeviceStatus::Memory::Status::CRITICALLY_LOW;
188     }
189     default: // APP_EVENT_LOW_MEMORY_NORMAL 0x01
190     {
191       return Dali::DeviceStatus::Memory::Status::NORMAL;
192     }
193   }
194 }
195
196 DeviceStatus::Battery::Status GetBatteryStatus(app_event_low_battery_status_e batteryStatus)
197 {
198   switch(batteryStatus)
199   {
200     case APP_EVENT_LOW_BATTERY_POWER_OFF: // 1
201     {
202       return Dali::DeviceStatus::Battery::Status::POWER_OFF;
203     }
204     case APP_EVENT_LOW_BATTERY_CRITICAL_LOW: // 2
205     {
206       return Dali::DeviceStatus::Battery::Status::CRITICALLY_LOW;
207     }
208     default:
209     {
210       return Dali::DeviceStatus::Battery::Status::NORMAL;
211     }
212   }
213 }
214
215 } // namespace AppCore
216
217 /**
218  * Impl to hide EFL data members
219  */
220 struct Framework::Impl
221 {
222   class UiAppContext : public AppCoreUiBase
223   {
224   public:
225     class Task : public AppCoreTaskBase
226     {
227     public:
228       explicit Task(Framework* framework)
229       : mFramework(framework),
230         mNewBatteryStatus(Dali::DeviceStatus::Battery::Status::NORMAL),
231         mNewMemoryStatus(Dali::DeviceStatus::Memory::NORMAL)
232       {
233       }
234
235       virtual ~Task()
236       {
237       }
238
239       int OnCreate() override
240       {
241         // On the main thread, the log functions are not set. So print_log() is used directly.
242         print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnCreate() emitted", __MODULE__, __func__, __LINE__);
243         mFramework->mTaskObserver.OnTaskInit();
244         return AppCoreTaskBase::OnCreate();
245       }
246
247       int OnTerminate() override
248       {
249         print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnTerminate() emitted", __MODULE__, __func__, __LINE__);
250         mFramework->mTaskObserver.OnTaskTerminate();
251         return AppCoreTaskBase::OnTerminate();
252       }
253
254       int OnControl(tizen_base::Bundle b) override
255       {
256         print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnControl() emitted", __MODULE__, __func__, __LINE__);
257         AppCoreTaskBase::OnControl(b);
258
259         app_control_h appControl = nullptr;
260
261         auto* bundleData = b.GetHandle();
262         if(bundleData)
263         {
264           if(app_control_create_event(bundleData, &appControl) != TIZEN_ERROR_NONE)
265           {
266             print_log(DLOG_ERROR, "DALI", "%s: %s(%d) > Failed to create an app_control handle with Bundle", __MODULE__, __func__, __LINE__);
267           }
268         }
269         else
270         {
271           if(app_control_create(&appControl) != TIZEN_ERROR_NONE)
272           {
273             print_log(DLOG_ERROR, "DALI", "%s: %s(%d) > Failed to create an app_control handle", __MODULE__, __func__, __LINE__);
274           }
275         }
276         mFramework->mTaskObserver.OnTaskAppControl(appControl);
277
278         app_control_destroy(appControl);
279         return 0;
280       }
281
282       void OnUiEvent(AppCoreTaskBase::UiState state) override
283       {
284         // This event is emitted when the UI thread is paused or resumed.
285         print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnUiEvent() emitted", __MODULE__, __func__, __LINE__);
286
287         // Note: This isn't implemented.
288         AppCoreTaskBase::OnUiEvent(state);
289       }
290
291       void OnLowMemory(AppCoreTaskBase::LowMemoryState state) override
292       {
293         print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnLowMemory() emitted", __MODULE__, __func__, __LINE__);
294
295         mNewMemoryStatus = AppCore::GetMemoryStatus(static_cast<app_event_low_memory_status_e>(state));
296
297         PostToUiThread(
298           [](gpointer userData) -> gboolean {
299             auto* task      = static_cast<Task*>(userData);
300             auto* framework = static_cast<Framework*>(task->mFramework);
301             framework->mObserver.OnMemoryLow(task->mNewMemoryStatus);
302             return G_SOURCE_REMOVE;
303           });
304         mFramework->mTaskObserver.OnTaskMemoryLow(mNewMemoryStatus);
305         AppCoreTaskBase::OnLowMemory(state);
306       }
307
308       void OnLowBattery(AppCoreTaskBase::LowBatteryState state) override
309       {
310         print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnLowBattery() emitted", __MODULE__, __func__, __LINE__);
311         mNewBatteryStatus = AppCore::GetBatteryStatus(static_cast<app_event_low_battery_status_e>(state));
312
313         PostToUiThread(
314           [](gpointer userData) -> gboolean {
315             auto* task      = static_cast<Task*>(userData);
316             auto* framework = static_cast<Framework*>(task->mFramework);
317             framework->mObserver.OnBatteryLow(task->mNewBatteryStatus);
318             return G_SOURCE_REMOVE;
319           });
320         mFramework->mTaskObserver.OnTaskBatteryLow(mNewBatteryStatus);
321         AppCoreTaskBase::OnLowBattery(state);
322       }
323
324       void OnLangChanged(const std::string& lang) override
325       {
326         print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnLangChanged() emitted", __MODULE__, __func__, __LINE__);
327         mNewLanguage = lang;
328         mFramework->SetLanguage(mNewLanguage);
329
330         PostToUiThread(
331           [](gpointer userData) -> gboolean {
332             auto* task      = static_cast<Task*>(userData);
333             auto* framework = static_cast<Framework*>(task->mFramework);
334             framework->mObserver.OnLanguageChanged();
335             return G_SOURCE_REMOVE;
336           });
337
338         mFramework->mTaskObserver.OnTaskLanguageChanged();
339         AppCoreTaskBase::OnLangChanged(lang);
340       }
341
342       void OnRegionChanged(const std::string& region) override
343       {
344         print_log(DLOG_INFO, "DALI", "%s: %s(%d) > nRegionChanged() emitted", __MODULE__, __func__, __LINE__);
345         mNewRegion = region;
346         mFramework->SetRegion(mNewRegion);
347
348         PostToUiThread(
349           [](gpointer userData) -> gboolean {
350             auto* task      = static_cast<Task*>(userData);
351             auto* framework = static_cast<Framework*>(task->mFramework);
352             framework->mObserver.OnRegionChanged();
353             return G_SOURCE_REMOVE;
354           });
355
356         mFramework->mTaskObserver.OnTaskRegionChanged();
357         AppCoreTaskBase::OnRegionChanged(mNewRegion);
358       }
359
360       void OnDeviceOrientationChanged(AppCoreTaskBase::DeviceOrientationState state) override
361       {
362         print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnDeviceOrientationChanged() emitted", __MODULE__, __func__, __LINE__);
363         // Note: This isn't emitted to the App.
364         AppCoreTaskBase::OnDeviceOrientationChanged(state);
365       }
366
367     private:
368       GMainContext* GetTizenGlibContext()
369       {
370         GMainContext* context;
371         const char*   env = getenv("TIZEN_GLIB_CONTEXT");
372         if(env)
373         {
374           context = (GMainContext*)strtoul(env, nullptr, 10);
375         }
376         else
377         {
378           context = nullptr;
379         }
380
381         return context;
382       }
383
384       void PostToUiThread(GSourceFunc func)
385       {
386         GSource* source = g_idle_source_new();
387         g_source_set_callback(source, func, this, nullptr);
388         g_source_attach(source, GetTizenGlibContext());
389         g_source_unref(source);
390       }
391
392     private:
393       Framework*                          mFramework;
394       std::string                         mNewLanguage;
395       std::string                         mNewRegion;
396       Dali::DeviceStatus::Battery::Status mNewBatteryStatus;
397       Dali::DeviceStatus::Memory::Status  mNewMemoryStatus;
398     };
399
400     explicit UiAppContext(unsigned int hint, Framework* framework)
401     : AppCoreUiBase(hint),
402       mFramework(framework),
403       mUseUiThread(false)
404     {
405       if(hint & AppCoreUiBase::HINT_DUAL_THREAD)
406       {
407         mUseUiThread = true;
408       }
409
410       if(!mUseUiThread)
411       {
412         mLanguageChanged = std::make_shared<AppEvent>(IAppCore::IEvent::Type::LANG_CHANGE, OnLanguageChanged, this);
413         AddEvent(mLanguageChanged);
414
415         mDeviceOrientationChanged = std::make_shared<AppEvent>(IAppCore::IEvent::Type::DEVICE_ORIENTATION_CHANGED, OnDeviceOrientationChanged, this);
416         AddEvent(mDeviceOrientationChanged);
417
418         mRegionFormatChanged = std::make_shared<AppEvent>(IAppCore::IEvent::Type::REGION_CHANGE, OnRegionFormatChanged, this);
419         AddEvent(mRegionFormatChanged);
420
421         mLowMemory = std::make_shared<AppEvent>(IAppCore::IEvent::Type::LOW_MEMORY, OnLowMemory, this);
422         AddEvent(mLowMemory);
423
424         mLowBattery = std::make_shared<AppEvent>(IAppCore::IEvent::Type::LOW_BATTERY, OnLowBattery, this);
425         AddEvent(mLowBattery);
426       }
427     }
428
429     virtual ~UiAppContext()
430     {
431       if(!mUseUiThread)
432       {
433         RemoveEvent(mLowBattery);
434         RemoveEvent(mLowMemory);
435         RemoveEvent(mRegionFormatChanged);
436         RemoveEvent(mDeviceOrientationChanged);
437         RemoveEvent(mLanguageChanged);
438       }
439     }
440
441     std::unique_ptr<AppCoreTaskBase> CreateTask() override
442     {
443       return std::unique_ptr<AppCoreTaskBase>(
444         new Task(mFramework));
445     }
446
447     int OnCreate() override
448     {
449       AppCoreUiBase::OnCreate();
450       mFramework->Create();
451       return 0;
452     }
453
454     int OnTerminate() override
455     {
456       AppCoreUiBase::OnTerminate();
457       auto* observer = &mFramework->mObserver;
458       observer->OnTerminate();
459       return 0;
460     }
461
462     int OnPause() override
463     {
464       AppCoreUiBase::OnPause();
465       auto* observer = &mFramework->mObserver;
466       observer->OnPause();
467       return 0;
468     }
469
470     int OnResume() override
471     {
472       AppCoreUiBase::OnResume();
473       auto* observer = &mFramework->mObserver;
474       observer->OnResume();
475       return 0;
476     }
477
478     int OnControl(tizen_base::Bundle b) override
479     {
480       AppCoreUiBase::OnControl(b);
481
482       app_control_h appControl = nullptr;
483
484       auto* bundleData = b.GetHandle();
485       if(bundleData)
486       {
487         if(app_control_create_event(bundleData, &appControl) != TIZEN_ERROR_NONE)
488         {
489           DALI_LOG_ERROR("Failed to create an app_control handle");
490           return 0;
491         }
492       }
493       else
494       {
495         if(app_control_create(&appControl) != TIZEN_ERROR_NONE)
496         {
497           DALI_LOG_ERROR("Failed to create an app_control handle");
498           return 0;
499         }
500       }
501
502       auto* observer = &mFramework->mObserver;
503       ProcessBundle(mFramework, bundleData);
504       observer->OnReset();
505       observer->OnAppControl(appControl);
506       app_control_destroy(appControl);
507       return 0;
508     }
509
510     void OnLoopInit(int argc, char** argv) override
511     {
512 #pragma GCC diagnostic push
513 #pragma GCC diagnostic ignored "-Wold-style-cast"
514       ecore_init();
515       ecore_app_args_set(argc, (const char**)argv);
516 #pragma GCC diagnostic pop
517
518 #ifdef DALI_ELDBUS_AVAILABLE
519       // Initialize ElDBus.
520       DALI_LOG_INFO(gDBusLogging, Debug::General, "Starting DBus Initialization\n");
521       eldbus_init();
522 #endif
523     }
524
525     void OnLoopFinish() override
526     {
527       ecore_shutdown();
528
529       if(getenv("AUL_LOADER_INIT"))
530       {
531         setenv("AUL_LOADER_INIT", "0", 1);
532         ecore_shutdown();
533       }
534
535 #ifdef DALI_ELDBUS_AVAILABLE
536       // Shutdown ELDBus.
537       DALI_LOG_INFO(gDBusLogging, Debug::General, "Shutting down DBus\n");
538       eldbus_shutdown();
539 #endif
540     }
541
542     void OnLoopRun() override
543     {
544       ecore_main_loop_begin();
545     }
546
547     void OnLoopExit() override
548     {
549       ecore_main_loop_quit();
550     }
551
552   private:
553     static void OnLanguageChanged(app_event_info_h event_info, void* user_data)
554     {
555       auto*     context   = static_cast<UiAppContext*>(user_data);
556       auto*     framework = context->mFramework;
557       Observer* observer  = &framework->mObserver;
558
559       char* lang = nullptr;
560       app_event_get_language(event_info, &lang);
561       if(lang)
562       {
563         framework->SetLanguage(std::string(lang));
564         observer->OnLanguageChanged();
565         free(lang);
566       }
567       else
568       {
569         DALI_LOG_ERROR("NULL pointer in Language changed event\n");
570       }
571     }
572
573     static void OnDeviceOrientationChanged(app_event_info_h event_info, void* user_data)
574     {
575     }
576
577     static void OnRegionFormatChanged(app_event_info_h event_info, void* user_data)
578     {
579       auto*     context   = static_cast<UiAppContext*>(user_data);
580       auto*     framework = context->mFramework;
581       Observer* observer  = &framework->mObserver;
582
583       char* region = nullptr;
584       app_event_get_region_format(event_info, &region);
585       if(region)
586       {
587         framework->SetRegion(std::string(region));
588         observer->OnRegionChanged();
589         free(region);
590       }
591       else
592       {
593         DALI_LOG_ERROR("NULL pointer in Region changed event\n");
594       }
595     }
596
597     static void OnLowBattery(app_event_info_h event_info, void* user_data)
598     {
599       auto*     context   = static_cast<UiAppContext*>(user_data);
600       auto*     framework = context->mFramework;
601       Observer* observer  = &framework->mObserver;
602
603       app_event_low_battery_status_e status;
604       app_event_get_low_battery_status(event_info, &status);
605       Dali::DeviceStatus::Battery::Status result = AppCore::GetBatteryStatus(status);
606       observer->OnBatteryLow(result);
607     }
608
609     static void OnLowMemory(app_event_info_h event_info, void* user_data)
610     {
611       auto*     context   = static_cast<UiAppContext*>(user_data);
612       auto*     framework = context->mFramework;
613       Observer* observer  = &framework->mObserver;
614
615       app_event_low_memory_status_e status;
616       app_event_get_low_memory_status(event_info, &status);
617       Dali::DeviceStatus::Memory::Status result = AppCore::GetMemoryStatus(status);
618       observer->OnMemoryLow(result);
619     }
620
621     void ProcessBundle(Framework* framework, bundle* bundleData)
622     {
623       if(bundleData == nullptr)
624       {
625         return;
626       }
627
628       // get bundle name
629       char* bundleName = const_cast<char*>(bundle_get_val(bundleData, "name"));
630       if(bundleName != nullptr)
631       {
632         framework->SetBundleName(bundleName);
633       }
634
635       // get bundle? id
636       char* bundleId = const_cast<char*>(bundle_get_val(bundleData, "id"));
637       if(bundleId != nullptr)
638       {
639         framework->SetBundleId(bundleId);
640       }
641     }
642
643   private:
644     Framework*                mFramework;
645     std::shared_ptr<AppEvent> mLanguageChanged;
646     std::shared_ptr<AppEvent> mDeviceOrientationChanged;
647     std::shared_ptr<AppEvent> mRegionFormatChanged;
648     std::shared_ptr<AppEvent> mLowBattery;
649     std::shared_ptr<AppEvent> mLowMemory;
650     bool                      mUseUiThread;
651   };
652
653   // Constructor
654   Impl(void* data, Type type, bool useUiThread)
655   : mAbortCallBack(NULL),
656     mCallbackManager(NULL),
657     mUseUiThread(useUiThread)
658 #ifdef APPCORE_WATCH_AVAILABLE
659     ,
660     mWatchCallback()
661 #endif
662   {
663     mFramework = static_cast<Framework*>(data);
664
665 #ifndef APPCORE_WATCH_AVAILABLE
666     if(type == WATCH)
667     {
668       throw Dali::DaliException("", "Watch Application is not supported.");
669     }
670 #endif
671     mApplicationType = type;
672     mCallbackManager = CallbackManager::New();
673   }
674
675   ~Impl()
676   {
677     delete mAbortCallBack;
678
679     // we're quiting the main loop so
680     // mCallbackManager->RemoveAllCallBacks() does not need to be called
681     // to delete our abort handler
682     delete mCallbackManager;
683   }
684
685   int AppMain()
686   {
687     // TODO: The app-core-cpp has to be applied to the other app types.
688     int ret;
689     switch(mApplicationType)
690     {
691       case NORMAL:
692       {
693         ret = AppNormalMain();
694         break;
695       }
696       case WIDGET:
697       {
698         ret = AppWidgetMain();
699         break;
700       }
701       case WATCH:
702       {
703         ret = AppWatchMain();
704         break;
705       }
706 #ifdef COMPONENT_APPLICATION_SUPPORT
707       case COMPONENT:
708       {
709         ret = AppComponentMain();
710         break;
711       }
712 #endif
713     }
714     return ret;
715   }
716
717   void AppExit()
718   {
719     switch(mApplicationType)
720     {
721       case NORMAL:
722       {
723         AppNormalExit();
724         break;
725       }
726       case WIDGET:
727       {
728         AppWidgetExit();
729         break;
730       }
731       case WATCH:
732       {
733         AppWatchExit();
734         break;
735       }
736 #ifdef COMPONENT_APPLICATION_SUPPORT
737       case COMPONENT:
738       {
739         AppComponentExit();
740         break;
741       }
742 #endif
743     }
744   }
745
746   void SetLanguage(const std::string& language)
747   {
748     mLanguage = language;
749   }
750
751   void SetRegion(const std::string& region)
752   {
753     mRegion = region;
754   }
755
756   std::string GetLanguage()
757   {
758     if(mLanguage.empty())
759     {
760       char* language = nullptr;
761       system_settings_get_value_string(SYSTEM_SETTINGS_KEY_LOCALE_LANGUAGE, &language);
762
763       if(language != nullptr)
764       {
765         mLanguage = std::string(language);
766         free(language);
767       }
768     }
769     return mLanguage;
770   }
771
772   std::string GetRegion()
773   {
774     if(mRegion.empty())
775     {
776       char* region = nullptr;
777       system_settings_get_value_string(SYSTEM_SETTINGS_KEY_LOCALE_COUNTRY, &region);
778
779       if(region != nullptr)
780       {
781         mRegion = std::string(region);
782         free(region);
783       }
784     }
785     return mRegion;
786   }
787
788   // Data
789   Type             mApplicationType;
790   CallbackBase*    mAbortCallBack;
791   CallbackManager* mCallbackManager;
792   std::string      mLanguage{};
793   std::string      mRegion{};
794
795   Framework*                    mFramework;
796   AppCore::AppEventHandlerPtr   handlers[5];
797   std::unique_ptr<UiAppContext> mUiAppContext;
798   bool                          mUseUiThread;
799 #ifdef APPCORE_WATCH_AVAILABLE
800   watch_app_lifecycle_callback_s mWatchCallback;
801 #endif
802
803   static void ProcessBundle(Framework* framework, bundle* bundleData)
804   {
805     if(bundleData == NULL)
806     {
807       return;
808     }
809
810     // get bundle name
811     char* bundleName = const_cast<char*>(bundle_get_val(bundleData, "name"));
812     if(bundleName != NULL)
813     {
814       framework->SetBundleName(bundleName);
815     }
816
817     // get bundle? id
818     char* bundleId = const_cast<char*>(bundle_get_val(bundleData, "id"));
819     if(bundleId != NULL)
820     {
821       framework->SetBundleId(bundleId);
822     }
823   }
824
825   static void AppInit(int argc, char** argv, void* data)
826   {
827 #pragma GCC diagnostic push
828 #pragma GCC diagnostic ignored "-Wold-style-cast"
829     ecore_init();
830     ecore_app_args_set(argc, (const char**)argv);
831 #pragma GCC diagnostic pop
832
833 #ifdef DALI_ELDBUS_AVAILABLE
834     // Initialize ElDBus.
835     DALI_LOG_INFO(gDBusLogging, Debug::General, "Starting DBus Initialization\n");
836     eldbus_init();
837 #endif
838   }
839
840   static void AppFinish(void)
841   {
842     ecore_shutdown();
843
844     if(getenv("AUL_LOADER_INIT"))
845     {
846       setenv("AUL_LOADER_INIT", "0", 1);
847       ecore_shutdown();
848     }
849
850 #ifdef DALI_ELDBUS_AVAILABLE
851     // Shutdown ELDBus.
852     DALI_LOG_INFO(gDBusLogging, Debug::General, "Shutting down DBus\n");
853     eldbus_shutdown();
854 #endif
855   }
856
857   static void AppRun(void* data)
858   {
859     ecore_main_loop_begin();
860   }
861
862   static void AppExit(void* data)
863   {
864     ecore_main_loop_quit();
865   }
866
867   static void AppLanguageChanged(AppCore::AppEventInfoPtr event, void* data)
868   {
869     Framework* framework = static_cast<Framework*>(data);
870     Observer*  observer  = &framework->mObserver;
871
872     if(event && event->value)
873     {
874       framework->SetLanguage(std::string(static_cast<const char*>(event->value)));
875       observer->OnLanguageChanged();
876     }
877     else
878     {
879       DALI_LOG_ERROR("NULL pointer in Language changed event\n");
880     }
881   }
882
883   static void AppDeviceRotated(AppCore::AppEventInfoPtr event_info, void* data)
884   {
885   }
886
887   static void AppRegionChanged(AppCore::AppEventInfoPtr event, void* data)
888   {
889     Framework* framework = static_cast<Framework*>(data);
890     Observer*  observer  = &framework->mObserver;
891
892     if(event && event->value)
893     {
894       framework->SetRegion(std::string(static_cast<const char*>(event->value)));
895       observer->OnRegionChanged();
896     }
897     else
898     {
899       DALI_LOG_ERROR("NULL pointer in Region changed event\n");
900     }
901   }
902
903   static void AppBatteryLow(AppCore::AppEventInfoPtr event, void* data)
904   {
905     Observer*                           observer = &static_cast<Framework*>(data)->mObserver;
906     int                                 status   = *static_cast<int*>(event->value);
907     Dali::DeviceStatus::Battery::Status result   = Dali::DeviceStatus::Battery::NORMAL;
908
909     // convert to dali battery status
910     switch(status)
911     {
912       case 1:
913       {
914         result = Dali::DeviceStatus::Battery::POWER_OFF;
915         break;
916       }
917       case 2:
918       {
919         result = Dali::DeviceStatus::Battery::CRITICALLY_LOW;
920         break;
921       }
922       default:
923         break;
924     }
925     observer->OnBatteryLow(result);
926   }
927
928   static void AppMemoryLow(AppCore::AppEventInfoPtr event, void* data)
929   {
930     Observer*                          observer = &static_cast<Framework*>(data)->mObserver;
931     int                                status   = *static_cast<int*>(event->value);
932     Dali::DeviceStatus::Memory::Status result   = Dali::DeviceStatus::Memory::NORMAL;
933
934     // convert to dali memmory status
935     switch(status)
936     {
937       case 1:
938       {
939         result = Dali::DeviceStatus::Memory::NORMAL;
940         break;
941       }
942       case 2:
943       {
944         result = Dali::DeviceStatus::Memory::LOW;
945         break;
946       }
947       case 4:
948       {
949         result = Dali::DeviceStatus::Memory::CRITICALLY_LOW;
950         break;
951       }
952       default:
953         break;
954     }
955     observer->OnMemoryLow(result);
956   }
957
958   int AppNormalMain()
959   {
960     if(mUiAppContext.get() == nullptr)
961     {
962       unsigned int hint = AppCoreUiBase::HINT_WINDOW_GROUP_CONTROL |
963                           AppCoreUiBase::HINT_WINDOW_STACK_CONTROL |
964                           AppCoreUiBase::HINT_BG_LAUNCH_CONTROL |
965                           AppCoreUiBase::HINT_HW_ACC_CONTROL |
966                           AppCoreUiBase::HINT_WINDOW_AUTO_CONTROL;
967
968       // For testing UIThread model, This code turns on the UI Thread feature forcibly.
969       //  ex) app_launcher -e [APPID] __K_UI_THREAD enable
970       // This code doesn't change mUseUiThread in Internal::Application
971       bundle* b = bundle_import_from_argv(*mFramework->mArgc, *mFramework->mArgv);
972       if(b != nullptr)
973       {
974         const char* val = bundle_get_val(b, "__K_UI_THREAD");
975         if(val != nullptr && strcmp(val, "enable") == 0)
976         {
977           mUseUiThread = true;
978         }
979
980         bundle_free(b);
981       }
982
983       if(mUseUiThread)
984       {
985         hint |= AppCoreUiBase::HINT_DUAL_THREAD;
986       }
987
988       mUiAppContext = std::make_unique<UiAppContext>(hint, mFramework);
989     }
990
991     mUiAppContext->Run(*mFramework->mArgc, *mFramework->mArgv);
992     return TIZEN_ERROR_NONE;
993   }
994
995   void AppNormalExit()
996   {
997     if(mUiAppContext.get() == nullptr)
998     {
999       return;
1000     }
1001
1002     mUiAppContext->Exit();
1003   }
1004
1005   void AppWidgetExit()
1006   {
1007     widget_base_exit();
1008   }
1009
1010   static int WidgetAppCreate(void* data)
1011   {
1012     widget_base_on_create();
1013     return static_cast<int>(static_cast<Framework*>(data)->Create());
1014   }
1015
1016   static int WidgetAppTerminate(void* data)
1017   {
1018     Observer* observer = &static_cast<Framework*>(data)->mObserver;
1019     observer->OnTerminate();
1020
1021     widget_base_on_terminate();
1022     return 0;
1023   }
1024
1025   int AppWidgetMain()
1026   {
1027     if(!IsWidgetFeatureEnabled())
1028     {
1029       DALI_LOG_ERROR("widget feature is not supported");
1030       return 0;
1031     }
1032
1033     AppCore::AppAddEventHandler(&handlers[AppCore::LOW_BATTERY], AppCore::LOW_BATTERY, AppBatteryLow, mFramework);
1034     AppCore::AppAddEventHandler(&handlers[AppCore::LOW_MEMORY], AppCore::LOW_MEMORY, AppMemoryLow, mFramework);
1035     AppCore::AppAddEventHandler(&handlers[AppCore::DEVICE_ORIENTATION_CHANGED], AppCore::DEVICE_ORIENTATION_CHANGED, AppDeviceRotated, mFramework);
1036     AppCore::AppAddEventHandler(&handlers[AppCore::LANGUAGE_CHANGED], AppCore::LANGUAGE_CHANGED, AppLanguageChanged, mFramework);
1037     AppCore::AppAddEventHandler(&handlers[AppCore::REGION_FORMAT_CHANGED], AppCore::REGION_FORMAT_CHANGED, AppRegionChanged, mFramework);
1038
1039     widget_base_ops ops = widget_base_get_default_ops();
1040
1041     /* override methods */
1042     ops.create    = WidgetAppCreate;
1043     ops.terminate = WidgetAppTerminate;
1044     ops.init      = AppInit;
1045     ops.finish    = AppFinish;
1046     ops.run       = AppRun;
1047     ops.exit      = AppExit;
1048
1049     int result = widget_base_init(ops, *mFramework->mArgc, *mFramework->mArgv, mFramework);
1050
1051     widget_base_fini();
1052
1053     return result;
1054   }
1055
1056 #ifdef APPCORE_WATCH_AVAILABLE
1057   static bool WatchAppCreate(int width, int height, void* data)
1058   {
1059     return static_cast<Framework*>(data)->Create();
1060   }
1061
1062   static void WatchAppTimeTick(watch_time_h time, void* data)
1063   {
1064     Observer* observer = &static_cast<Framework*>(data)->mObserver;
1065     WatchTime curTime(time);
1066
1067     observer->OnTimeTick(curTime);
1068   }
1069
1070   static void WatchAppAmbientTick(watch_time_h time, void* data)
1071   {
1072     Observer* observer = &static_cast<Framework*>(data)->mObserver;
1073     WatchTime curTime(time);
1074
1075     observer->OnAmbientTick(curTime);
1076   }
1077
1078   static void WatchAppAmbientChanged(bool ambient, void* data)
1079   {
1080     Observer* observer = &static_cast<Framework*>(data)->mObserver;
1081
1082     observer->OnAmbientChanged(ambient);
1083   }
1084
1085   static void WatchAppControl(app_control_h app_control, void* data)
1086   {
1087     Framework* framework  = static_cast<Framework*>(data);
1088     Observer*  observer   = &framework->mObserver;
1089     bundle*    bundleData = NULL;
1090
1091     app_control_to_bundle(app_control, &bundleData);
1092     ProcessBundle(framework, bundleData);
1093
1094     observer->OnReset();
1095     observer->OnAppControl(app_control);
1096   }
1097
1098   static void WatchAppTerminate(void* data)
1099   {
1100     Observer* observer = &static_cast<Framework*>(data)->mObserver;
1101
1102     observer->OnTerminate();
1103   }
1104
1105   static void WatchAppPause(void* data)
1106   {
1107     Observer* observer = &static_cast<Framework*>(data)->mObserver;
1108
1109     observer->OnPause();
1110   }
1111
1112   static void WatchAppResume(void* data)
1113   {
1114     Observer* observer = &static_cast<Framework*>(data)->mObserver;
1115
1116     observer->OnResume();
1117   }
1118
1119 #endif
1120
1121   int AppWatchMain()
1122   {
1123     int ret = true;
1124
1125 #ifdef APPCORE_WATCH_AVAILABLE
1126     mWatchCallback.create          = WatchAppCreate;
1127     mWatchCallback.app_control     = WatchAppControl;
1128     mWatchCallback.terminate       = WatchAppTerminate;
1129     mWatchCallback.pause           = WatchAppPause;
1130     mWatchCallback.resume          = WatchAppResume;
1131     mWatchCallback.time_tick       = WatchAppTimeTick;
1132     mWatchCallback.ambient_tick    = WatchAppAmbientTick;
1133     mWatchCallback.ambient_changed = WatchAppAmbientChanged;
1134
1135     AppCore::AppAddEventHandler(&handlers[AppCore::LOW_BATTERY], AppCore::LOW_BATTERY, AppBatteryLow, mFramework);
1136     AppCore::AppAddEventHandler(&handlers[AppCore::LOW_MEMORY], AppCore::LOW_MEMORY, AppMemoryLow, mFramework);
1137     AppCore::AppAddEventHandler(&handlers[AppCore::LANGUAGE_CHANGED], AppCore::LANGUAGE_CHANGED, AppLanguageChanged, mFramework);
1138     AppCore::AppAddEventHandler(&handlers[AppCore::REGION_FORMAT_CHANGED], AppCore::REGION_FORMAT_CHANGED, AppRegionChanged, mFramework);
1139
1140     ret = watch_app_main(*mFramework->mArgc, *mFramework->mArgv, &mWatchCallback, mFramework);
1141 #endif
1142     return ret;
1143   }
1144
1145   void AppWatchExit()
1146   {
1147 #ifdef APPCORE_WATCH_AVAILABLE
1148     watch_app_exit();
1149 #endif
1150   }
1151
1152 #ifdef COMPONENT_APPLICATION_SUPPORT
1153   int AppComponentMain()
1154   {
1155     /*Crate component_based_app_base_lifecycle_callback*/
1156     component_based_app_base_lifecycle_callback_s callback;
1157     callback.init      = AppInit;
1158     callback.run       = AppRun;
1159     callback.exit      = AppExit;
1160     callback.create    = ComponentAppCreate;
1161     callback.terminate = ComponentAppTerminate;
1162     callback.fini      = ComponentAppFinish;
1163
1164     return component_based_app_base_main(*mFramework->mArgc, *mFramework->mArgv, &callback, mFramework);
1165     ;
1166   }
1167
1168   static void* ComponentAppCreate(void* data)
1169   {
1170     Framework* framework = static_cast<Framework*>(data);
1171     Observer*  observer  = &framework->mObserver;
1172     observer->OnInit();
1173
1174     return Dali::AnyCast<void*>(observer->OnCreate());
1175   }
1176
1177   static void ComponentAppTerminate(void* data)
1178   {
1179     Observer* observer = &static_cast<Framework*>(data)->mObserver;
1180     observer->OnTerminate();
1181   }
1182
1183   static void ComponentAppFinish(void* data)
1184   {
1185     ecore_shutdown();
1186
1187     if(getenv("AUL_LOADER_INIT"))
1188     {
1189       setenv("AUL_LOADER_INIT", "0", 1);
1190       ecore_shutdown();
1191     }
1192   }
1193
1194   void AppComponentExit()
1195   {
1196     component_based_app_base_exit();
1197   }
1198
1199 #endif
1200
1201 private:
1202   // Undefined
1203   Impl(const Impl& impl);
1204
1205   // Undefined
1206   Impl& operator=(const Impl& impl);
1207 };
1208
1209 Framework::Framework(Framework::Observer& observer, Framework::TaskObserver& taskObserver, int* argc, char*** argv, Type type, bool useUiThread)
1210 : mObserver(observer),
1211   mTaskObserver(taskObserver),
1212   mInitialised(false),
1213   mPaused(false),
1214   mRunning(false),
1215   mArgc(argc),
1216   mArgv(argv),
1217   mBundleName(""),
1218   mBundleId(""),
1219   mAbortHandler(MakeCallback(this, &Framework::AbortCallback)),
1220   mImpl(NULL)
1221 {
1222   bool featureFlag = true;
1223   system_info_get_platform_bool("tizen.org/feature/opengles.version.2_0", &featureFlag);
1224
1225   if(featureFlag == false)
1226   {
1227     set_last_result(TIZEN_ERROR_NOT_SUPPORTED);
1228   }
1229
1230   InitThreads();
1231
1232   mImpl = new Impl(this, type, useUiThread);
1233 }
1234
1235 Framework::~Framework()
1236 {
1237   if(mRunning)
1238   {
1239     Quit();
1240   }
1241
1242   delete mImpl;
1243 }
1244
1245 bool Framework::Create()
1246 {
1247   mInitialised = true;
1248   mObserver.OnInit();
1249   return true;
1250 }
1251
1252 void Framework::Run()
1253 {
1254   mRunning = true;
1255   int ret;
1256
1257   DALI_TRACE_BEGIN(gTraceFilter, "DALI_APPMAIN");
1258   ret = mImpl->AppMain();
1259   DALI_TRACE_END(gTraceFilter, "DALI_APPMAIN");
1260   if(ret != APP_ERROR_NONE)
1261   {
1262     DALI_LOG_ERROR("Framework::Run(), ui_app_main() is failed. err = %d\n", ret);
1263   }
1264   mRunning = false;
1265 }
1266
1267 void Framework::Quit()
1268 {
1269   mImpl->AppExit();
1270 }
1271
1272 bool Framework::IsMainLoopRunning()
1273 {
1274   return mRunning;
1275 }
1276
1277 void Framework::AddAbortCallback(CallbackBase* callback)
1278 {
1279   mImpl->mAbortCallBack = callback;
1280 }
1281
1282 std::string Framework::GetBundleName() const
1283 {
1284   return mBundleName;
1285 }
1286
1287 void Framework::SetBundleName(const std::string& name)
1288 {
1289   mBundleName = name;
1290 }
1291
1292 std::string Framework::GetBundleId() const
1293 {
1294   return mBundleId;
1295 }
1296
1297 std::string Framework::GetResourcePath()
1298 {
1299   std::string resourcePath = "";
1300 #if defined(TIZEN_PLATFORM_CONFIG_SUPPORTED) && TIZEN_PLATFORM_CONFIG_SUPPORTED
1301   char* app_rsc_path = app_get_resource_path();
1302   if(app_rsc_path)
1303   {
1304     resourcePath = app_rsc_path;
1305     free(app_rsc_path);
1306   }
1307 #else // For backwards compatibility with older Tizen versions
1308
1309   // "DALI_APPLICATION_PACKAGE" is used to get the already configured Application package path.
1310   const char* environmentVariable = "DALI_APPLICATION_PACKAGE";
1311   char*       value               = getenv(environmentVariable);
1312   if(value != NULL)
1313   {
1314     resourcePath = value;
1315   }
1316
1317   if(resourcePath.back() != '/')
1318   {
1319     resourcePath += "/";
1320   }
1321
1322 #endif // TIZEN_PLATFORM_CONFIG_SUPPORTED
1323
1324   return resourcePath;
1325 }
1326
1327 std::string Framework::GetDataPath()
1328 {
1329   std::string result;
1330   char*       dataPath = app_get_data_path();
1331   if(dataPath)
1332   {
1333     result = dataPath;
1334     free(dataPath);
1335   }
1336   return result;
1337 }
1338
1339 void Framework::SetBundleId(const std::string& id)
1340 {
1341   mBundleId = id;
1342 }
1343
1344 void Framework::AbortCallback()
1345 {
1346   // if an abort call back has been installed run it.
1347   if(mImpl->mAbortCallBack)
1348   {
1349     CallbackBase::Execute(*mImpl->mAbortCallBack);
1350   }
1351   else
1352   {
1353     Quit();
1354   }
1355 }
1356
1357 void Framework::InitThreads()
1358 {
1359 }
1360
1361 void Framework::SetLanguage(const std::string& language)
1362 {
1363   mImpl->SetLanguage(language);
1364 }
1365
1366 void Framework::SetRegion(const std::string& region)
1367 {
1368   mImpl->SetRegion(region);
1369 }
1370
1371 std::string Framework::GetLanguage() const
1372 {
1373   return mImpl->GetLanguage();
1374 }
1375
1376 std::string Framework::GetRegion() const
1377 {
1378   return mImpl->GetRegion();
1379 }
1380
1381 } // namespace Adaptor
1382
1383 } // namespace Internal
1384
1385 } // namespace Dali