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