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