Merge "Direct Rendering" into devel/master
[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           {
300             auto* task      = static_cast<Task*>(userData);
301             auto* framework = static_cast<Framework*>(task->mFramework);
302             framework->mObserver.OnMemoryLow(task->mNewMemoryStatus);
303             return G_SOURCE_REMOVE;
304           });
305         mFramework->mTaskObserver.OnTaskMemoryLow(mNewMemoryStatus);
306         AppCoreTaskBase::OnLowMemory(state);
307       }
308
309       void OnLowBattery(AppCoreTaskBase::LowBatteryState state) override
310       {
311         print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnLowBattery() emitted", __MODULE__, __func__, __LINE__);
312         mNewBatteryStatus = AppCore::GetBatteryStatus(static_cast<app_event_low_battery_status_e>(state));
313
314         PostToUiThread(
315           [](gpointer userData) -> gboolean
316           {
317             auto* task      = static_cast<Task*>(userData);
318             auto* framework = static_cast<Framework*>(task->mFramework);
319             framework->mObserver.OnBatteryLow(task->mNewBatteryStatus);
320             return G_SOURCE_REMOVE;
321           });
322         mFramework->mTaskObserver.OnTaskBatteryLow(mNewBatteryStatus);
323         AppCoreTaskBase::OnLowBattery(state);
324       }
325
326       void OnLangChanged(const std::string& lang) override
327       {
328         print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnLangChanged() emitted", __MODULE__, __func__, __LINE__);
329         mNewLanguage = lang;
330         mFramework->SetLanguage(mNewLanguage);
331
332         PostToUiThread(
333           [](gpointer userData) -> gboolean
334           {
335             auto* task      = static_cast<Task*>(userData);
336             auto* framework = static_cast<Framework*>(task->mFramework);
337             framework->mObserver.OnLanguageChanged();
338             return G_SOURCE_REMOVE;
339           });
340
341         mFramework->mTaskObserver.OnTaskLanguageChanged();
342         AppCoreTaskBase::OnLangChanged(lang);
343       }
344
345       void OnRegionChanged(const std::string& region) override
346       {
347         print_log(DLOG_INFO, "DALI", "%s: %s(%d) > nRegionChanged() emitted", __MODULE__, __func__, __LINE__);
348         mNewRegion = region;
349         mFramework->SetRegion(mNewRegion);
350
351         PostToUiThread(
352           [](gpointer userData) -> gboolean
353           {
354             auto* task      = static_cast<Task*>(userData);
355             auto* framework = static_cast<Framework*>(task->mFramework);
356             framework->mObserver.OnRegionChanged();
357             return G_SOURCE_REMOVE;
358           });
359
360         mFramework->mTaskObserver.OnTaskRegionChanged();
361         AppCoreTaskBase::OnRegionChanged(mNewRegion);
362       }
363
364       void OnDeviceOrientationChanged(AppCoreTaskBase::DeviceOrientationState state) override
365       {
366         print_log(DLOG_INFO, "DALI", "%s: %s(%d) > OnDeviceOrientationChanged() emitted", __MODULE__, __func__, __LINE__);
367         // Note: This isn't emitted to the App.
368         AppCoreTaskBase::OnDeviceOrientationChanged(state);
369       }
370
371     private:
372       GMainContext* GetTizenGlibContext()
373       {
374         GMainContext* context;
375         const char*   env = getenv("TIZEN_GLIB_CONTEXT");
376         if(env)
377         {
378           context = (GMainContext*)strtoul(env, nullptr, 10);
379         }
380         else
381         {
382           context = nullptr;
383         }
384
385         return context;
386       }
387
388       void PostToUiThread(GSourceFunc func)
389       {
390         GSource* source = g_idle_source_new();
391         g_source_set_callback(source, func, this, nullptr);
392         g_source_attach(source, GetTizenGlibContext());
393         g_source_unref(source);
394       }
395
396     private:
397       Framework*                          mFramework;
398       std::string                         mNewLanguage;
399       std::string                         mNewRegion;
400       Dali::DeviceStatus::Battery::Status mNewBatteryStatus;
401       Dali::DeviceStatus::Memory::Status  mNewMemoryStatus;
402     };
403
404     explicit UiAppContext(unsigned int hint, Framework* framework)
405     : AppCoreUiBase(hint),
406       mFramework(framework),
407       mUseUiThread(false)
408     {
409       if(hint & AppCoreUiBase::HINT_DUAL_THREAD)
410       {
411         mUseUiThread = true;
412       }
413
414       if(!mUseUiThread)
415       {
416         mLanguageChanged = std::make_shared<AppEvent>(IAppCore::IEvent::Type::LANG_CHANGE, OnLanguageChanged, this);
417         AddEvent(mLanguageChanged);
418
419         mDeviceOrientationChanged = std::make_shared<AppEvent>(IAppCore::IEvent::Type::DEVICE_ORIENTATION_CHANGED, OnDeviceOrientationChanged, this);
420         AddEvent(mDeviceOrientationChanged);
421
422         mRegionFormatChanged = std::make_shared<AppEvent>(IAppCore::IEvent::Type::REGION_CHANGE, OnRegionFormatChanged, this);
423         AddEvent(mRegionFormatChanged);
424
425         mLowMemory = std::make_shared<AppEvent>(IAppCore::IEvent::Type::LOW_MEMORY, OnLowMemory, this);
426         AddEvent(mLowMemory);
427
428         mLowBattery = std::make_shared<AppEvent>(IAppCore::IEvent::Type::LOW_BATTERY, OnLowBattery, this);
429         AddEvent(mLowBattery);
430       }
431     }
432
433     virtual ~UiAppContext()
434     {
435       if(!mUseUiThread)
436       {
437         RemoveEvent(mLowBattery);
438         RemoveEvent(mLowMemory);
439         RemoveEvent(mRegionFormatChanged);
440         RemoveEvent(mDeviceOrientationChanged);
441         RemoveEvent(mLanguageChanged);
442       }
443     }
444
445     std::unique_ptr<AppCoreTaskBase> CreateTask() override
446     {
447       return std::unique_ptr<AppCoreTaskBase>(
448         new Task(mFramework));
449     }
450
451     int OnCreate() override
452     {
453       AppCoreUiBase::OnCreate();
454       mFramework->Create();
455       return 0;
456     }
457
458     int OnTerminate() override
459     {
460       AppCoreUiBase::OnTerminate();
461       auto* observer = &mFramework->mObserver;
462       observer->OnTerminate();
463       return 0;
464     }
465
466     int OnPause() override
467     {
468       AppCoreUiBase::OnPause();
469       auto* observer = &mFramework->mObserver;
470       observer->OnPause();
471       return 0;
472     }
473
474     int OnResume() override
475     {
476       AppCoreUiBase::OnResume();
477       auto* observer = &mFramework->mObserver;
478       observer->OnResume();
479       return 0;
480     }
481
482     int OnControl(tizen_base::Bundle b) override
483     {
484       AppCoreUiBase::OnControl(b);
485
486       app_control_h appControl = nullptr;
487
488       auto* bundleData = b.GetHandle();
489       if(bundleData)
490       {
491         if(app_control_create_event(bundleData, &appControl) != TIZEN_ERROR_NONE)
492         {
493           DALI_LOG_ERROR("Failed to create an app_control handle");
494           return 0;
495         }
496       }
497       else
498       {
499         if(app_control_create(&appControl) != TIZEN_ERROR_NONE)
500         {
501           DALI_LOG_ERROR("Failed to create an app_control handle");
502           return 0;
503         }
504       }
505
506       auto* observer = &mFramework->mObserver;
507       ProcessBundle(mFramework, bundleData);
508       observer->OnReset();
509       observer->OnAppControl(appControl);
510       app_control_destroy(appControl);
511       return 0;
512     }
513
514     void OnLoopInit(int argc, char** argv) override
515     {
516 #pragma GCC diagnostic push
517 #pragma GCC diagnostic ignored "-Wold-style-cast"
518       ecore_init();
519       ecore_app_args_set(argc, (const char**)argv);
520 #pragma GCC diagnostic pop
521
522 #ifdef DALI_ELDBUS_AVAILABLE
523       // Initialize ElDBus.
524       DALI_LOG_INFO(gDBusLogging, Debug::General, "Starting DBus Initialization\n");
525       eldbus_init();
526 #endif
527     }
528
529     void OnLoopFinish() override
530     {
531       ecore_shutdown();
532
533       if(getenv("AUL_LOADER_INIT"))
534       {
535         setenv("AUL_LOADER_INIT", "0", 1);
536         ecore_shutdown();
537       }
538
539 #ifdef DALI_ELDBUS_AVAILABLE
540       // Shutdown ELDBus.
541       DALI_LOG_INFO(gDBusLogging, Debug::General, "Shutting down DBus\n");
542       eldbus_shutdown();
543 #endif
544     }
545
546     void OnLoopRun() override
547     {
548       ecore_main_loop_begin();
549     }
550
551     void OnLoopExit() override
552     {
553       ecore_main_loop_quit();
554     }
555
556   private:
557     static void OnLanguageChanged(app_event_info_h event_info, void* user_data)
558     {
559       auto*     context   = static_cast<UiAppContext*>(user_data);
560       auto*     framework = context->mFramework;
561       Observer* observer  = &framework->mObserver;
562
563       char* lang = nullptr;
564       app_event_get_language(event_info, &lang);
565       if(lang)
566       {
567         framework->SetLanguage(std::string(lang));
568         observer->OnLanguageChanged();
569         free(lang);
570       }
571       else
572       {
573         DALI_LOG_ERROR("NULL pointer in Language changed event\n");
574       }
575     }
576
577     static void OnDeviceOrientationChanged(app_event_info_h event_info, void* user_data)
578     {
579     }
580
581     static void OnRegionFormatChanged(app_event_info_h event_info, void* user_data)
582     {
583       auto*     context   = static_cast<UiAppContext*>(user_data);
584       auto*     framework = context->mFramework;
585       Observer* observer  = &framework->mObserver;
586
587       char* region = nullptr;
588       app_event_get_region_format(event_info, &region);
589       if(region)
590       {
591         framework->SetRegion(std::string(region));
592         observer->OnRegionChanged();
593         free(region);
594       }
595       else
596       {
597         DALI_LOG_ERROR("NULL pointer in Region changed event\n");
598       }
599     }
600
601     static void OnLowBattery(app_event_info_h event_info, void* user_data)
602     {
603       auto*     context   = static_cast<UiAppContext*>(user_data);
604       auto*     framework = context->mFramework;
605       Observer* observer  = &framework->mObserver;
606
607       app_event_low_battery_status_e status;
608       app_event_get_low_battery_status(event_info, &status);
609       Dali::DeviceStatus::Battery::Status result = AppCore::GetBatteryStatus(status);
610       observer->OnBatteryLow(result);
611     }
612
613     static void OnLowMemory(app_event_info_h event_info, void* user_data)
614     {
615       auto*     context   = static_cast<UiAppContext*>(user_data);
616       auto*     framework = context->mFramework;
617       Observer* observer  = &framework->mObserver;
618
619       app_event_low_memory_status_e status;
620       app_event_get_low_memory_status(event_info, &status);
621       Dali::DeviceStatus::Memory::Status result = AppCore::GetMemoryStatus(status);
622       observer->OnMemoryLow(result);
623     }
624
625     void ProcessBundle(Framework* framework, bundle* bundleData)
626     {
627       if(bundleData == nullptr)
628       {
629         return;
630       }
631
632       // get bundle name
633       char* bundleName = const_cast<char*>(bundle_get_val(bundleData, "name"));
634       if(bundleName != nullptr)
635       {
636         framework->SetBundleName(bundleName);
637       }
638
639       // get bundle? id
640       char* bundleId = const_cast<char*>(bundle_get_val(bundleData, "id"));
641       if(bundleId != nullptr)
642       {
643         framework->SetBundleId(bundleId);
644       }
645     }
646
647   private:
648     Framework*                mFramework;
649     std::shared_ptr<AppEvent> mLanguageChanged;
650     std::shared_ptr<AppEvent> mDeviceOrientationChanged;
651     std::shared_ptr<AppEvent> mRegionFormatChanged;
652     std::shared_ptr<AppEvent> mLowBattery;
653     std::shared_ptr<AppEvent> mLowMemory;
654     bool                      mUseUiThread;
655   };
656
657   // Constructor
658   Impl(void* data, Type type, bool useUiThread)
659   : mAbortCallBack(NULL),
660     mCallbackManager(NULL),
661     mUseUiThread(useUiThread)
662 #ifdef APPCORE_WATCH_AVAILABLE
663     ,
664     mWatchCallback()
665 #endif
666   {
667     mFramework = static_cast<Framework*>(data);
668
669 #ifndef APPCORE_WATCH_AVAILABLE
670     if(type == WATCH)
671     {
672       throw Dali::DaliException("", "Watch Application is not supported.");
673     }
674 #endif
675     mApplicationType = type;
676     mCallbackManager = CallbackManager::New();
677   }
678
679   ~Impl()
680   {
681     delete mAbortCallBack;
682
683     // we're quiting the main loop so
684     // mCallbackManager->RemoveAllCallBacks() does not need to be called
685     // to delete our abort handler
686     delete mCallbackManager;
687   }
688
689   int AppMain()
690   {
691     // TODO: The app-core-cpp has to be applied to the other app types.
692     int ret;
693     switch(mApplicationType)
694     {
695       case NORMAL:
696       {
697         ret = AppNormalMain();
698         break;
699       }
700       case WIDGET:
701       {
702         ret = AppWidgetMain();
703         break;
704       }
705       case WATCH:
706       {
707         ret = AppWatchMain();
708         break;
709       }
710 #ifdef COMPONENT_APPLICATION_SUPPORT
711       case COMPONENT:
712       {
713         ret = AppComponentMain();
714         break;
715       }
716 #endif
717     }
718     return ret;
719   }
720
721   void AppExit()
722   {
723     switch(mApplicationType)
724     {
725       case NORMAL:
726       {
727         AppNormalExit();
728         break;
729       }
730       case WIDGET:
731       {
732         AppWidgetExit();
733         break;
734       }
735       case WATCH:
736       {
737         AppWatchExit();
738         break;
739       }
740 #ifdef COMPONENT_APPLICATION_SUPPORT
741       case COMPONENT:
742       {
743         AppComponentExit();
744         break;
745       }
746 #endif
747     }
748   }
749
750   void SetLanguage(const std::string& language)
751   {
752     mLanguage = language;
753   }
754
755   void SetRegion(const std::string& region)
756   {
757     mRegion = region;
758   }
759
760   std::string GetLanguage()
761   {
762     if(mLanguage.empty())
763     {
764       char* language = nullptr;
765       system_settings_get_value_string(SYSTEM_SETTINGS_KEY_LOCALE_LANGUAGE, &language);
766
767       if(language != nullptr)
768       {
769         mLanguage = std::string(language);
770         free(language);
771       }
772     }
773     return mLanguage;
774   }
775
776   std::string GetRegion()
777   {
778     if(mRegion.empty())
779     {
780       char* region = nullptr;
781       system_settings_get_value_string(SYSTEM_SETTINGS_KEY_LOCALE_COUNTRY, &region);
782
783       if(region != nullptr)
784       {
785         mRegion = std::string(region);
786         free(region);
787       }
788     }
789     return mRegion;
790   }
791
792   // Data
793   Type             mApplicationType;
794   CallbackBase*    mAbortCallBack;
795   CallbackManager* mCallbackManager;
796   std::string      mLanguage{};
797   std::string      mRegion{};
798
799   Framework*                    mFramework;
800   AppCore::AppEventHandlerPtr   handlers[5];
801   std::unique_ptr<UiAppContext> mUiAppContext;
802   bool                          mUseUiThread;
803 #ifdef APPCORE_WATCH_AVAILABLE
804   watch_app_lifecycle_callback_s mWatchCallback;
805   app_event_handler_h            watchHandlers[5];
806 #endif
807
808   static void ProcessBundle(Framework* framework, bundle* bundleData)
809   {
810     if(bundleData == NULL)
811     {
812       return;
813     }
814
815     // get bundle name
816     char* bundleName = const_cast<char*>(bundle_get_val(bundleData, "name"));
817     if(bundleName != NULL)
818     {
819       framework->SetBundleName(bundleName);
820     }
821
822     // get bundle? id
823     char* bundleId = const_cast<char*>(bundle_get_val(bundleData, "id"));
824     if(bundleId != NULL)
825     {
826       framework->SetBundleId(bundleId);
827     }
828   }
829
830   static void AppInit(int argc, char** argv, void* data)
831   {
832 #pragma GCC diagnostic push
833 #pragma GCC diagnostic ignored "-Wold-style-cast"
834     ecore_init();
835     ecore_app_args_set(argc, (const char**)argv);
836 #pragma GCC diagnostic pop
837
838 #ifdef DALI_ELDBUS_AVAILABLE
839     // Initialize ElDBus.
840     DALI_LOG_INFO(gDBusLogging, Debug::General, "Starting DBus Initialization\n");
841     eldbus_init();
842 #endif
843   }
844
845   static void AppFinish(void)
846   {
847     ecore_shutdown();
848
849     if(getenv("AUL_LOADER_INIT"))
850     {
851       setenv("AUL_LOADER_INIT", "0", 1);
852       ecore_shutdown();
853     }
854
855 #ifdef DALI_ELDBUS_AVAILABLE
856     // Shutdown ELDBus.
857     DALI_LOG_INFO(gDBusLogging, Debug::General, "Shutting down DBus\n");
858     eldbus_shutdown();
859 #endif
860   }
861
862   static void AppRun(void* data)
863   {
864     ecore_main_loop_begin();
865   }
866
867   static void AppExit(void* data)
868   {
869     ecore_main_loop_quit();
870   }
871
872   static void AppLanguageChanged(AppCore::AppEventInfoPtr event, void* data)
873   {
874     Framework* framework = static_cast<Framework*>(data);
875     Observer*  observer  = &framework->mObserver;
876
877     if(event && event->value)
878     {
879       framework->SetLanguage(std::string(static_cast<const char*>(event->value)));
880       observer->OnLanguageChanged();
881     }
882     else
883     {
884       DALI_LOG_ERROR("NULL pointer in Language changed event\n");
885     }
886   }
887
888   static void AppDeviceRotated(AppCore::AppEventInfoPtr event_info, void* data)
889   {
890   }
891
892   static void AppRegionChanged(AppCore::AppEventInfoPtr event, void* data)
893   {
894     Framework* framework = static_cast<Framework*>(data);
895     Observer*  observer  = &framework->mObserver;
896
897     if(event && event->value)
898     {
899       framework->SetRegion(std::string(static_cast<const char*>(event->value)));
900       observer->OnRegionChanged();
901     }
902     else
903     {
904       DALI_LOG_ERROR("NULL pointer in Region changed event\n");
905     }
906   }
907
908   static void AppBatteryLow(AppCore::AppEventInfoPtr event, void* data)
909   {
910     Observer*                           observer = &static_cast<Framework*>(data)->mObserver;
911     int                                 status   = *static_cast<int*>(event->value);
912     Dali::DeviceStatus::Battery::Status result   = Dali::DeviceStatus::Battery::NORMAL;
913
914     // convert to dali battery status
915     switch(status)
916     {
917       case 1:
918       {
919         result = Dali::DeviceStatus::Battery::POWER_OFF;
920         break;
921       }
922       case 2:
923       {
924         result = Dali::DeviceStatus::Battery::CRITICALLY_LOW;
925         break;
926       }
927       default:
928         break;
929     }
930     observer->OnBatteryLow(result);
931   }
932
933   static void AppMemoryLow(AppCore::AppEventInfoPtr event, void* data)
934   {
935     Observer*                          observer = &static_cast<Framework*>(data)->mObserver;
936     int                                status   = *static_cast<int*>(event->value);
937     Dali::DeviceStatus::Memory::Status result   = Dali::DeviceStatus::Memory::NORMAL;
938
939     // convert to dali memmory status
940     switch(status)
941     {
942       case 1:
943       {
944         result = Dali::DeviceStatus::Memory::NORMAL;
945         break;
946       }
947       case 2:
948       {
949         result = Dali::DeviceStatus::Memory::LOW;
950         break;
951       }
952       case 4:
953       {
954         result = Dali::DeviceStatus::Memory::CRITICALLY_LOW;
955         break;
956       }
957       default:
958         break;
959     }
960     observer->OnMemoryLow(result);
961   }
962
963   int AppNormalMain()
964   {
965     if(mUiAppContext.get() == nullptr)
966     {
967       unsigned int hint = AppCoreUiBase::HINT_WINDOW_GROUP_CONTROL |
968                           AppCoreUiBase::HINT_WINDOW_STACK_CONTROL |
969                           AppCoreUiBase::HINT_BG_LAUNCH_CONTROL |
970                           AppCoreUiBase::HINT_HW_ACC_CONTROL |
971                           AppCoreUiBase::HINT_WINDOW_AUTO_CONTROL;
972
973       // For testing UIThread model, This code turns on the UI Thread feature forcibly.
974       //  ex) app_launcher -e [APPID] __K_UI_THREAD enable
975       // This code doesn't change mUseUiThread in Internal::Application
976       bundle* b = bundle_import_from_argv(*mFramework->mArgc, *mFramework->mArgv);
977       if(b != nullptr)
978       {
979         const char* val = bundle_get_val(b, "__K_UI_THREAD");
980         if(val != nullptr && strcmp(val, "enable") == 0)
981         {
982           mUseUiThread = true;
983         }
984
985         bundle_free(b);
986       }
987
988       if(mUseUiThread)
989       {
990         hint |= AppCoreUiBase::HINT_DUAL_THREAD;
991       }
992
993       mUiAppContext = std::make_unique<UiAppContext>(hint, mFramework);
994     }
995
996     mUiAppContext->Run(*mFramework->mArgc, *mFramework->mArgv);
997     return TIZEN_ERROR_NONE;
998   }
999
1000   void AppNormalExit()
1001   {
1002     if(mUiAppContext.get() == nullptr)
1003     {
1004       return;
1005     }
1006
1007     mUiAppContext->Exit();
1008   }
1009
1010   void AppWidgetExit()
1011   {
1012     widget_base_exit();
1013   }
1014
1015   static int WidgetAppCreate(void* data)
1016   {
1017     widget_base_on_create();
1018     return static_cast<int>(static_cast<Framework*>(data)->Create());
1019   }
1020
1021   static int WidgetAppTerminate(void* data)
1022   {
1023     Observer* observer = &static_cast<Framework*>(data)->mObserver;
1024     observer->OnTerminate();
1025
1026     widget_base_on_terminate();
1027     return 0;
1028   }
1029
1030   int AppWidgetMain()
1031   {
1032     if(!IsWidgetFeatureEnabled())
1033     {
1034       DALI_LOG_ERROR("widget feature is not supported");
1035       return 0;
1036     }
1037
1038     AppCore::AppAddEventHandler(&handlers[AppCore::LOW_BATTERY], AppCore::LOW_BATTERY, AppBatteryLow, mFramework);
1039     AppCore::AppAddEventHandler(&handlers[AppCore::LOW_MEMORY], AppCore::LOW_MEMORY, AppMemoryLow, mFramework);
1040     AppCore::AppAddEventHandler(&handlers[AppCore::DEVICE_ORIENTATION_CHANGED], AppCore::DEVICE_ORIENTATION_CHANGED, AppDeviceRotated, mFramework);
1041     AppCore::AppAddEventHandler(&handlers[AppCore::LANGUAGE_CHANGED], AppCore::LANGUAGE_CHANGED, AppLanguageChanged, mFramework);
1042     AppCore::AppAddEventHandler(&handlers[AppCore::REGION_FORMAT_CHANGED], AppCore::REGION_FORMAT_CHANGED, AppRegionChanged, mFramework);
1043
1044     widget_base_ops ops = widget_base_get_default_ops();
1045
1046     /* override methods */
1047     ops.create    = WidgetAppCreate;
1048     ops.terminate = WidgetAppTerminate;
1049     ops.init      = AppInit;
1050     ops.finish    = AppFinish;
1051     ops.run       = AppRun;
1052     ops.exit      = AppExit;
1053
1054     int result = widget_base_init(ops, *mFramework->mArgc, *mFramework->mArgv, mFramework);
1055
1056     widget_base_fini();
1057
1058     return result;
1059   }
1060
1061 #ifdef APPCORE_WATCH_AVAILABLE
1062   static bool WatchAppCreate(int width, int height, void* data)
1063   {
1064     return static_cast<Framework*>(data)->Create();
1065   }
1066
1067   static void WatchAppTimeTick(watch_time_h time, void* data)
1068   {
1069     Observer* observer = &static_cast<Framework*>(data)->mObserver;
1070     WatchTime curTime(time);
1071
1072     observer->OnTimeTick(curTime);
1073   }
1074
1075   static void WatchAppAmbientTick(watch_time_h time, void* data)
1076   {
1077     Observer* observer = &static_cast<Framework*>(data)->mObserver;
1078     WatchTime curTime(time);
1079
1080     observer->OnAmbientTick(curTime);
1081   }
1082
1083   static void WatchAppAmbientChanged(bool ambient, void* data)
1084   {
1085     Observer* observer = &static_cast<Framework*>(data)->mObserver;
1086
1087     observer->OnAmbientChanged(ambient);
1088   }
1089
1090   static void WatchAppControl(app_control_h app_control, void* data)
1091   {
1092     Framework* framework  = static_cast<Framework*>(data);
1093     Observer*  observer   = &framework->mObserver;
1094     bundle*    bundleData = NULL;
1095
1096     app_control_to_bundle(app_control, &bundleData);
1097     ProcessBundle(framework, bundleData);
1098
1099     observer->OnReset();
1100     observer->OnAppControl(app_control);
1101   }
1102
1103   static void WatchAppTerminate(void* data)
1104   {
1105     Observer* observer = &static_cast<Framework*>(data)->mObserver;
1106
1107     observer->OnTerminate();
1108   }
1109
1110   static void WatchAppPause(void* data)
1111   {
1112     Observer* observer = &static_cast<Framework*>(data)->mObserver;
1113
1114     observer->OnPause();
1115   }
1116
1117   static void WatchAppResume(void* data)
1118   {
1119     Observer* observer = &static_cast<Framework*>(data)->mObserver;
1120
1121     observer->OnResume();
1122   }
1123
1124 #endif
1125
1126   int AppWatchMain()
1127   {
1128     int ret = true;
1129
1130 #ifdef APPCORE_WATCH_AVAILABLE
1131     mWatchCallback.create          = WatchAppCreate;
1132     mWatchCallback.app_control     = WatchAppControl;
1133     mWatchCallback.terminate       = WatchAppTerminate;
1134     mWatchCallback.pause           = WatchAppPause;
1135     mWatchCallback.resume          = WatchAppResume;
1136     mWatchCallback.time_tick       = WatchAppTimeTick;
1137     mWatchCallback.ambient_tick    = WatchAppAmbientTick;
1138     mWatchCallback.ambient_changed = WatchAppAmbientChanged;
1139
1140     AppCore::AppAddEventHandler(&handlers[AppCore::LOW_BATTERY], AppCore::LOW_BATTERY, AppBatteryLow, mFramework);
1141     AppCore::AppAddEventHandler(&handlers[AppCore::LOW_MEMORY], AppCore::LOW_MEMORY, AppMemoryLow, mFramework);
1142     AppCore::AppAddEventHandler(&handlers[AppCore::LANGUAGE_CHANGED], AppCore::LANGUAGE_CHANGED, AppLanguageChanged, mFramework);
1143     AppCore::AppAddEventHandler(&handlers[AppCore::REGION_FORMAT_CHANGED], AppCore::REGION_FORMAT_CHANGED, AppRegionChanged, mFramework);
1144
1145     ret = watch_app_main(*mFramework->mArgc, *mFramework->mArgv, &mWatchCallback, mFramework);
1146 #endif
1147     return ret;
1148   }
1149
1150   void AppWatchExit()
1151   {
1152 #ifdef APPCORE_WATCH_AVAILABLE
1153     watch_app_exit();
1154 #endif
1155   }
1156
1157 #ifdef COMPONENT_APPLICATION_SUPPORT
1158   int AppComponentMain()
1159   {
1160     /*Crate component_based_app_base_lifecycle_callback*/
1161     component_based_app_base_lifecycle_callback_s callback;
1162     callback.init      = AppInit;
1163     callback.run       = AppRun;
1164     callback.exit      = AppExit;
1165     callback.create    = ComponentAppCreate;
1166     callback.terminate = ComponentAppTerminate;
1167     callback.fini      = ComponentAppFinish;
1168
1169     return component_based_app_base_main(*mFramework->mArgc, *mFramework->mArgv, &callback, mFramework);
1170     ;
1171   }
1172
1173   static void* ComponentAppCreate(void* data)
1174   {
1175     Framework* framework = static_cast<Framework*>(data);
1176     Observer*  observer  = &framework->mObserver;
1177     observer->OnInit();
1178
1179     return Dali::AnyCast<void*>(observer->OnCreate());
1180   }
1181
1182   static void ComponentAppTerminate(void* data)
1183   {
1184     Observer* observer = &static_cast<Framework*>(data)->mObserver;
1185     observer->OnTerminate();
1186   }
1187
1188   static void ComponentAppFinish(void* data)
1189   {
1190     ecore_shutdown();
1191
1192     if(getenv("AUL_LOADER_INIT"))
1193     {
1194       setenv("AUL_LOADER_INIT", "0", 1);
1195       ecore_shutdown();
1196     }
1197   }
1198
1199   void AppComponentExit()
1200   {
1201     component_based_app_base_exit();
1202   }
1203
1204 #endif
1205
1206 private:
1207   // Undefined
1208   Impl(const Impl& impl);
1209
1210   // Undefined
1211   Impl& operator=(const Impl& impl);
1212 };
1213
1214 Framework::Framework(Framework::Observer& observer, Framework::TaskObserver& taskObserver, int* argc, char*** argv, Type type, bool useUiThread)
1215 : mObserver(observer),
1216   mTaskObserver(taskObserver),
1217   mInitialised(false),
1218   mPaused(false),
1219   mRunning(false),
1220   mArgc(argc),
1221   mArgv(argv),
1222   mBundleName(""),
1223   mBundleId(""),
1224   mAbortHandler(MakeCallback(this, &Framework::AbortCallback)),
1225   mImpl(NULL)
1226 {
1227   bool featureFlag = true;
1228   system_info_get_platform_bool("tizen.org/feature/opengles.version.2_0", &featureFlag);
1229
1230   if(featureFlag == false)
1231   {
1232     set_last_result(TIZEN_ERROR_NOT_SUPPORTED);
1233   }
1234
1235   InitThreads();
1236
1237   mImpl = new Impl(this, type, useUiThread);
1238 }
1239
1240 Framework::~Framework()
1241 {
1242   if(mRunning)
1243   {
1244     Quit();
1245   }
1246
1247   delete mImpl;
1248 }
1249
1250 bool Framework::Create()
1251 {
1252   mInitialised = true;
1253   mObserver.OnInit();
1254   return true;
1255 }
1256
1257 void Framework::Run()
1258 {
1259   mRunning = true;
1260   int ret;
1261
1262   DALI_TRACE_BEGIN(gTraceFilter, "DALI_APPMAIN");
1263   ret = mImpl->AppMain();
1264   DALI_TRACE_END(gTraceFilter, "DALI_APPMAIN");
1265   if(ret != APP_ERROR_NONE)
1266   {
1267     DALI_LOG_ERROR("Framework::Run(), ui_app_main() is failed. err = %d\n", ret);
1268   }
1269   mRunning = false;
1270 }
1271
1272 void Framework::Quit()
1273 {
1274   mImpl->AppExit();
1275 }
1276
1277 bool Framework::IsMainLoopRunning()
1278 {
1279   return mRunning;
1280 }
1281
1282 void Framework::AddAbortCallback(CallbackBase* callback)
1283 {
1284   mImpl->mAbortCallBack = callback;
1285 }
1286
1287 std::string Framework::GetBundleName() const
1288 {
1289   return mBundleName;
1290 }
1291
1292 void Framework::SetBundleName(const std::string& name)
1293 {
1294   mBundleName = name;
1295 }
1296
1297 std::string Framework::GetBundleId() const
1298 {
1299   return mBundleId;
1300 }
1301
1302 std::string Framework::GetResourcePath()
1303 {
1304   std::string resourcePath = "";
1305 #if defined(TIZEN_PLATFORM_CONFIG_SUPPORTED) && TIZEN_PLATFORM_CONFIG_SUPPORTED
1306   char* app_rsc_path = app_get_resource_path();
1307   if(app_rsc_path)
1308   {
1309     resourcePath = app_rsc_path;
1310     free(app_rsc_path);
1311   }
1312 #else // For backwards compatibility with older Tizen versions
1313
1314   // "DALI_APPLICATION_PACKAGE" is used to get the already configured Application package path.
1315   const char* environmentVariable = "DALI_APPLICATION_PACKAGE";
1316   char*       value               = getenv(environmentVariable);
1317   if(value != NULL)
1318   {
1319     resourcePath = value;
1320   }
1321
1322   if(resourcePath.back() != '/')
1323   {
1324     resourcePath += "/";
1325   }
1326
1327 #endif // TIZEN_PLATFORM_CONFIG_SUPPORTED
1328
1329   return resourcePath;
1330 }
1331
1332 std::string Framework::GetDataPath()
1333 {
1334   std::string result;
1335   char*       dataPath = app_get_data_path();
1336   if(dataPath)
1337   {
1338     result = dataPath;
1339     free(dataPath);
1340   }
1341   return result;
1342 }
1343
1344 void Framework::SetBundleId(const std::string& id)
1345 {
1346   mBundleId = id;
1347 }
1348
1349 void Framework::AbortCallback()
1350 {
1351   // if an abort call back has been installed run it.
1352   if(mImpl->mAbortCallBack)
1353   {
1354     CallbackBase::Execute(*mImpl->mAbortCallBack);
1355   }
1356   else
1357   {
1358     Quit();
1359   }
1360 }
1361
1362 void Framework::InitThreads()
1363 {
1364 }
1365
1366 void Framework::SetLanguage(const std::string& language)
1367 {
1368   mImpl->SetLanguage(language);
1369 }
1370
1371 void Framework::SetRegion(const std::string& region)
1372 {
1373   mImpl->SetRegion(region);
1374 }
1375
1376 std::string Framework::GetLanguage() const
1377 {
1378   return mImpl->GetLanguage();
1379 }
1380
1381 std::string Framework::GetRegion() const
1382 {
1383   return mImpl->GetRegion();
1384 }
1385
1386 } // namespace Adaptor
1387
1388 } // namespace Internal
1389
1390 } // namespace Dali