Revert "[4.0] Support Widget Application"
[platform/core/uifw/dali-adaptor.git] / adaptors / tizen / framework-tizen.cpp
1 /*
2  * Copyright (c) 2017 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 "framework.h"
20
21 // EXTERNAL INCLUDES
22 #include <appcore_ui_base.h>
23 #include <app_control_internal.h>
24 #include <app_common.h>
25 #include <bundle.h>
26 #include <Ecore.h>
27
28 #include <system_info.h>
29 #include <system_settings.h>
30 #include <bundle_internal.h>
31
32 // CONDITIONAL INCLUDES
33 #ifdef APPCORE_WATCH_AVAILABLE
34 #include <appcore-watch/watch_app.h>
35 #endif
36 #ifdef DALI_ELDBUS_AVAILABLE
37 #include <Eldbus.h>
38 #endif // DALI_ELDBUS_AVAILABLE
39
40 #if defined( TIZEN_PLATFORM_CONFIG_SUPPORTED ) && TIZEN_PLATFORM_CONFIG_SUPPORTED
41 #include <tzplatform_config.h>
42 #endif // TIZEN_PLATFORM_CONFIG_SUPPORTED
43
44 #include <dali/integration-api/debug.h>
45
46 // INTERNAL INCLUDES
47 #include <callback-manager.h>
48
49 namespace Dali
50 {
51
52 namespace Internal
53 {
54
55 namespace Adaptor
56 {
57
58 #if defined(DEBUG_ENABLED)
59 namespace
60 {
61 Integration::Log::Filter* gDBusLogging = Integration::Log::Filter::New( Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_DBUS" );
62 } // anonymous namespace
63 #endif
64
65 namespace AppCore
66 {
67
68 typedef enum
69 {
70   LOW_MEMORY,                 //< The low memory event
71   LOW_BATTERY,                //< The low battery event
72   LANGUAGE_CHANGED,           //< The system language changed event
73   DEVICE_ORIENTATION_CHANGED, //< The device orientation changed event
74   REGION_FORMAT_CHANGED,      //< The region format changed event
75   SUSPENDED_STATE_CHANGED,    //< The suspended state changed event of the application
76   UPDATE_REQUESTED,           //< The update requested event. This event can occur when an app needs to be updated. It is dependent on target devices.
77 } AppEventType;
78
79 static int AppEventConverter[APPCORE_BASE_EVENT_MAX] =
80 {
81   [LOW_MEMORY] = APPCORE_BASE_EVENT_LOW_MEMORY,
82   [LOW_BATTERY] = APPCORE_BASE_EVENT_LOW_BATTERY,
83   [LANGUAGE_CHANGED] = APPCORE_BASE_EVENT_LANG_CHANGE,
84   [DEVICE_ORIENTATION_CHANGED] = APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED,
85   [REGION_FORMAT_CHANGED] = APPCORE_BASE_EVENT_REGION_CHANGE,
86   [SUSPENDED_STATE_CHANGED] = APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE,
87 };
88
89 struct AppEventInfo
90 {
91   AppEventType type;
92   void *value;
93 };
94
95 typedef struct AppEventInfo *AppEventInfoPtr;
96
97 typedef void (*AppEventCallback)(AppEventInfoPtr eventInfo, void *userData);
98
99 struct AppEventHandler
100 {
101   AppEventType type;
102   AppEventCallback cb;
103   void *data;
104   void *raw;
105 };
106
107 typedef struct AppEventHandler *AppEventHandlerPtr;
108
109 int EventCallback(void *event, void *data)
110 {
111   AppEventHandlerPtr handler = static_cast<AppEventHandlerPtr>(data);
112
113   struct AppEventInfo appEvent;
114
115   appEvent.type = handler->type;
116   appEvent.value = event;
117
118   if (handler->cb)
119     handler->cb(&appEvent, handler->data);
120
121   return 0;
122 }
123
124 int AppAddEventHandler(AppEventHandlerPtr *eventHandler, AppEventType eventType, AppEventCallback callback, void *userData)
125 {
126   AppEventHandlerPtr handler;
127
128   handler = static_cast<AppEventHandlerPtr>( calloc(1, sizeof(struct AppEventHandler)) );
129   if (!handler)
130   {
131     DALI_LOG_ERROR( "failed to create handler" );
132     return TIZEN_ERROR_UNKNOWN;
133   }
134   else
135   {
136     handler->type = eventType;
137     handler->cb = callback;
138     handler->data = userData;
139     handler->raw = appcore_base_add_event( static_cast<appcore_base_event>(AppEventConverter[static_cast<int>(eventType)]), EventCallback, handler);
140
141     *eventHandler = handler;
142
143     return TIZEN_ERROR_NONE;
144   }
145 }
146
147 } // namespace Appcore
148
149 /**
150  * Impl to hide EFL data members
151  */
152 struct Framework::Impl
153 {
154 // Constructor
155   Impl(void* data, Type type )
156   : mAbortCallBack( NULL ),
157     mCallbackManager( NULL )
158 #ifdef APPCORE_WATCH_AVAILABLE
159     , mWatchCallback()
160 #endif
161   {
162     mFramework = static_cast<Framework*>(data);
163
164 #ifndef APPCORE_WATCH_AVAILABLE
165     if ( type == WATCH )
166     {
167       throw Dali::DaliException( "", "Watch Application is not supported." );
168     }
169 #endif
170     mApplicationType = type;
171     mCallbackManager = CallbackManager::New();
172
173     char* region;
174     char* language;
175     system_settings_get_value_string( SYSTEM_SETTINGS_KEY_LOCALE_COUNTRY, &region );
176     system_settings_get_value_string( SYSTEM_SETTINGS_KEY_LOCALE_LANGUAGE, &language );
177     mRegion = std::string( region );
178     mLanguage = std::string( language );
179   }
180
181   ~Impl()
182   {
183     delete mAbortCallBack;
184
185     // we're quiting the main loop so
186     // mCallbackManager->RemoveAllCallBacks() does not need to be called
187     // to delete our abort handler
188     delete mCallbackManager;
189   }
190
191   int AppMain()
192   {
193     int ret;
194
195     if (mApplicationType == NORMAL)
196     {
197       ret = AppNormalMain();
198     }
199     else
200     {
201       ret = AppWatchMain();
202     }
203     return ret;
204   }
205
206   void AppExit()
207   {
208     if (mApplicationType == NORMAL)
209     {
210       AppNormalExit();
211     }
212     else
213     {
214       AppWatchExit();
215     }
216   }
217
218   void SetLanguage( const std::string& language )
219   {
220     mLanguage = language;
221   }
222
223   void SetRegion( const std::string& region )
224   {
225     mRegion = region;
226   }
227
228   std::string GetLanguage() const
229   {
230     return mLanguage;
231   }
232
233   std::string GetRegion() const
234   {
235     return mRegion;
236   }
237
238   // Data
239   Type mApplicationType;
240   CallbackBase* mAbortCallBack;
241   CallbackManager *mCallbackManager;
242   std::string mLanguage;
243   std::string mRegion;
244
245   Framework* mFramework;
246   AppCore::AppEventHandlerPtr handlers[5];
247 #ifdef APPCORE_WATCH_AVAILABLE
248   watch_app_lifecycle_callback_s mWatchCallback;
249   app_event_handler_h watchHandlers[5];
250 #endif
251
252   static int AppCreate(void *data)
253   {
254     appcore_ui_base_on_create();
255     return static_cast<int>( static_cast<Framework*>(data)->Create() );
256   }
257
258   static int AppTerminate(void *data)
259   {
260     appcore_ui_base_on_terminate();
261     Observer *observer = &static_cast<Framework*>(data)->mObserver;
262
263     observer->OnTerminate();
264
265     return 0;
266   }
267
268   static int AppPause(void *data)
269   {
270     appcore_ui_base_on_pause();
271     Observer *observer = &static_cast<Framework*>(data)->mObserver;
272
273     observer->OnPause();
274
275     return 0;
276   }
277
278   static int AppResume(void *data)
279   {
280     appcore_ui_base_on_resume();
281     Observer *observer = &static_cast<Framework*>(data)->mObserver;
282
283     observer->OnResume();
284
285     return 0;
286   }
287
288   static void ProcessBundle(Framework* framework, bundle *bundleData)
289   {
290     if(bundleData == NULL)
291     {
292       return;
293     }
294
295     // get bundle name
296     char* bundleName = const_cast<char*>(bundle_get_val(bundleData, "name"));
297     if(bundleName != NULL)
298     {
299       framework->SetBundleName(bundleName);
300     }
301
302     // get bundle? id
303     char* bundleId = const_cast<char*>(bundle_get_val(bundleData, "id"));
304     if(bundleId != NULL)
305     {
306       framework->SetBundleId(bundleId);
307     }
308   }
309
310   /**
311    * Called by AppCore when the application is launched from another module (e.g. homescreen).
312    * @param[in] b the bundle data which the launcher module sent
313    */
314   static int AppControl(bundle* bundleData, void *data)
315   {
316     app_control_h appControl = NULL;
317
318     appcore_ui_base_on_control(bundleData);
319
320     if (bundleData)
321     {
322       if (app_control_create_event(bundleData, &appControl) != TIZEN_ERROR_NONE)
323       {
324         DALI_LOG_ERROR("Failed to create an app_control handle");
325       }
326     }
327     else
328     {
329       if (app_control_create(&appControl) != TIZEN_ERROR_NONE)
330       {
331         DALI_LOG_ERROR("Failed to create an app_control handle");
332       }
333     }
334
335     Framework* framework = static_cast<Framework*>(data);
336     Observer *observer = &framework->mObserver;
337
338     ProcessBundle(framework, bundleData);
339
340     observer->OnReset();
341     observer->OnAppControl(appControl);
342
343     app_control_destroy(appControl);
344
345     return 0;
346   }
347
348   static void AppInit(int argc, char **argv, void *data)
349   {
350 #pragma GCC diagnostic push
351 #pragma GCC diagnostic ignored "-Wold-style-cast"
352
353     ecore_init();
354     ecore_app_args_set( argc, (const char **)argv );
355
356 #pragma GCC diagnostic pop
357   }
358
359   static void AppFinish(void)
360   {
361     ecore_shutdown();
362
363     if(getenv("AUL_LOADER_INIT"))
364     {
365       unsetenv("AUL_LOADER_INIT");
366       ecore_shutdown();
367     }
368   }
369
370   static void AppRun(void *data)
371   {
372     ecore_main_loop_begin();
373   }
374
375   static void AppExit(void *data)
376   {
377     ecore_main_loop_quit();
378   }
379
380   static void AppLanguageChanged(AppCore::AppEventInfoPtr event, void *data)
381   {
382     Framework* framework = static_cast<Framework*>(data);
383     Observer *observer = &framework->mObserver;
384
385     if( event && event->value )
386     {
387       framework->SetLanguage( std::string( static_cast<const char *>(event->value) ) );
388       observer->OnLanguageChanged();
389     }
390     else
391     {
392       DALI_LOG_ERROR( "NULL pointer in Language changed event\n" );
393     }
394   }
395
396   static void AppDeviceRotated(AppCore::AppEventInfoPtr event_info, void *data)
397   {
398   }
399
400   static void AppRegionChanged(AppCore::AppEventInfoPtr event, void *data)
401   {
402     Framework* framework = static_cast<Framework*>(data);
403     Observer *observer = &framework->mObserver;
404
405     if( event && event->value )
406     {
407       framework->SetRegion( std::string( static_cast<const char *>(event->value) ) );
408       observer->OnRegionChanged();
409     }
410     else
411     {
412       DALI_LOG_ERROR( "NULL pointer in Region changed event\n" );
413     }
414   }
415
416   static void AppBatteryLow(AppCore::AppEventInfoPtr event, void *data)
417   {
418     Observer *observer = &static_cast<Framework*>(data)->mObserver;
419     int status = *static_cast<int *>(event->value);
420     Dali::DeviceStatus::Battery::Status result = Dali::DeviceStatus::Battery::NORMAL;
421
422     // convert to dali battery status
423     switch( status )
424     {
425       case 1:
426       {
427         result = Dali::DeviceStatus::Battery::POWER_OFF;
428         break;
429       }
430       case 2:
431       {
432         result = Dali::DeviceStatus::Battery::CRITICALLY_LOW;
433         break;
434       }
435       default :
436         break;
437     }
438     observer->OnBatteryLow(result);
439   }
440
441   static void AppMemoryLow(AppCore::AppEventInfoPtr event, void *data)
442   {
443     Observer *observer = &static_cast<Framework*>(data)->mObserver;
444     int status = *static_cast<int *>(event->value);
445     Dali::DeviceStatus::Memory::Status result = Dali::DeviceStatus::Memory::NORMAL;
446
447     // convert to dali memmory status
448     switch( status )
449     {
450       case 1:
451       {
452         result = Dali::DeviceStatus::Memory::NORMAL;
453         break;
454       }
455       case 2:
456       {
457         result = Dali::DeviceStatus::Memory::LOW;
458         break;
459       }
460       case 4:
461       {
462         result = Dali::DeviceStatus::Memory::CRITICALLY_LOW;
463         break;
464       }
465       default :
466         break;
467     }
468     observer->OnMemoryLow(result);
469   }
470
471
472   int AppNormalMain()
473   {
474     int ret;
475
476     AppCore::AppAddEventHandler(&handlers[AppCore::LOW_BATTERY], AppCore::LOW_BATTERY, AppBatteryLow, mFramework);
477     AppCore::AppAddEventHandler(&handlers[AppCore::LOW_MEMORY], AppCore::LOW_MEMORY, AppMemoryLow, mFramework);
478     AppCore::AppAddEventHandler(&handlers[AppCore::DEVICE_ORIENTATION_CHANGED], AppCore::DEVICE_ORIENTATION_CHANGED, AppDeviceRotated, mFramework);
479     AppCore::AppAddEventHandler(&handlers[AppCore::LANGUAGE_CHANGED], AppCore::LANGUAGE_CHANGED, AppLanguageChanged, mFramework);
480     AppCore::AppAddEventHandler(&handlers[AppCore::REGION_FORMAT_CHANGED], AppCore::REGION_FORMAT_CHANGED, AppRegionChanged, mFramework);
481
482     appcore_ui_base_ops ops = appcore_ui_base_get_default_ops();
483
484     /* override methods */
485     ops.base.create = AppCreate;
486     ops.base.control = AppControl;
487     ops.base.terminate = AppTerminate;
488     ops.pause = AppPause;
489     ops.resume = AppResume;
490     ops.base.init = AppInit;
491     ops.base.finish = AppFinish;
492     ops.base.run = AppRun;
493     ops.base.exit = AppExit;
494
495     ret = appcore_ui_base_init(ops, *mFramework->mArgc, *mFramework->mArgv, mFramework, APPCORE_UI_BASE_HINT_WINDOW_GROUP_CONTROL |
496                                                                                         APPCORE_UI_BASE_HINT_WINDOW_STACK_CONTROL |
497                                                                                         APPCORE_UI_BASE_HINT_BG_LAUNCH_CONTROL |
498                                                                                         APPCORE_UI_BASE_HINT_HW_ACC_CONTROL |
499                                                                                         APPCORE_UI_BASE_HINT_WINDOW_AUTO_CONTROL );
500
501     if (ret != TIZEN_ERROR_NONE)
502       return ret;
503
504     appcore_ui_base_fini();
505
506     return TIZEN_ERROR_NONE;
507   }
508
509   void AppNormalExit()
510   {
511     appcore_ui_base_exit();
512   }
513
514 #ifdef APPCORE_WATCH_AVAILABLE
515   static bool WatchAppCreate(int width, int height, void *data)
516   {
517     return static_cast<Framework*>(data)->Create();
518   }
519
520   static void WatchAppTimeTick(watch_time_h time, void *data)
521   {
522     Observer *observer = &static_cast<Framework*>(data)->mObserver;
523     WatchTime curTime(time);
524
525     observer->OnTimeTick(curTime);
526   }
527
528   static void WatchAppAmbientTick(watch_time_h time, void *data)
529   {
530     Observer *observer = &static_cast<Framework*>(data)->mObserver;
531     WatchTime curTime(time);
532
533     observer->OnAmbientTick(curTime);
534   }
535
536   static void WatchAppAmbientChanged(bool ambient, void *data)
537   {
538     Observer *observer = &static_cast<Framework*>(data)->mObserver;
539
540     observer->OnAmbientChanged(ambient);
541   }
542
543   static void WatchAppControl(app_control_h app_control, void *data)
544   {
545     Framework* framework = static_cast<Framework*>(data);
546     Observer *observer = &framework->mObserver;
547     bundle *bundleData = NULL;
548
549     app_control_to_bundle(app_control, &bundleData);
550     ProcessBundle(framework, bundleData);
551
552     observer->OnReset();
553     observer->OnAppControl(app_control);
554   }
555
556   static void WatchAppTerminate(void *data)
557   {
558     Observer *observer = &static_cast<Framework*>(data)->mObserver;
559
560     observer->OnTerminate();
561   }
562
563   static void WatchAppPause(void *data)
564   {
565     Observer *observer = &static_cast<Framework*>(data)->mObserver;
566
567     observer->OnPause();
568   }
569
570   static void WatchAppResume(void *data)
571   {
572     Observer *observer = &static_cast<Framework*>(data)->mObserver;
573
574     observer->OnResume();
575   }
576
577 #endif
578
579   int AppWatchMain()
580   {
581     int ret = true;
582
583 #ifdef APPCORE_WATCH_AVAILABLE
584     mWatchCallback.create = WatchAppCreate;
585     mWatchCallback.app_control = WatchAppControl;
586     mWatchCallback.terminate = WatchAppTerminate;
587     mWatchCallback.pause = WatchAppPause;
588     mWatchCallback.resume = WatchAppResume;
589     mWatchCallback.time_tick = WatchAppTimeTick;
590     mWatchCallback.ambient_tick = WatchAppAmbientTick;
591     mWatchCallback.ambient_changed = WatchAppAmbientChanged;
592
593     AppCore::AppAddEventHandler(&handlers[AppCore::LOW_BATTERY], AppCore::LOW_BATTERY, AppBatteryLow, mFramework);
594     AppCore::AppAddEventHandler(&handlers[AppCore::LOW_MEMORY], AppCore::LOW_MEMORY, AppMemoryLow, mFramework);
595     AppCore::AppAddEventHandler(&handlers[AppCore::LANGUAGE_CHANGED], AppCore::LANGUAGE_CHANGED, AppLanguageChanged, mFramework);
596     AppCore::AppAddEventHandler(&handlers[AppCore::REGION_FORMAT_CHANGED], AppCore::REGION_FORMAT_CHANGED, AppRegionChanged, mFramework);
597
598     ret = watch_app_main(*mFramework->mArgc, *mFramework->mArgv, &mWatchCallback, mFramework);
599 #endif
600     return ret;
601   }
602
603   void AppWatchExit()
604   {
605 #ifdef APPCORE_WATCH_AVAILABLE
606     watch_app_exit();
607 #endif
608   }
609
610 private:
611   // Undefined
612   Impl( const Impl& impl );
613
614   // Undefined
615   Impl& operator=( const Impl& impl );
616 };
617
618 Framework::Framework( Framework::Observer& observer, int *argc, char ***argv, Type type )
619 : mObserver(observer),
620   mInitialised(false),
621   mRunning(false),
622   mArgc(argc),
623   mArgv(argv),
624   mBundleName(""),
625   mBundleId(""),
626   mAbortHandler( MakeCallback( this, &Framework::AbortCallback ) ),
627   mImpl(NULL)
628 {
629   bool featureFlag = true;
630   system_info_get_platform_bool( "tizen.org/feature/opengles.version.2_0", &featureFlag );
631
632   if( featureFlag == false )
633   {
634     set_last_result( TIZEN_ERROR_NOT_SUPPORTED );
635   }
636 #ifdef DALI_ELDBUS_AVAILABLE
637   // Initialize ElDBus.
638   DALI_LOG_INFO( gDBusLogging, Debug::General, "Starting DBus Initialization\n" );
639   eldbus_init();
640 #endif
641   InitThreads();
642
643   mImpl = new Impl(this, type);
644 }
645
646 Framework::~Framework()
647 {
648   if (mRunning)
649   {
650     Quit();
651   }
652
653 #ifdef DALI_ELDBUS_AVAILABLE
654   // Shutdown ELDBus.
655   DALI_LOG_INFO( gDBusLogging, Debug::General, "Shutting down DBus\n" );
656   eldbus_shutdown();
657 #endif
658
659   delete mImpl;
660 }
661
662 bool Framework::Create()
663 {
664   mInitialised = true;
665   mObserver.OnInit();
666   return true;
667 }
668
669 void Framework::Run()
670 {
671   mRunning = true;
672   int ret;
673
674   ret = mImpl->AppMain();
675   if (ret != APP_ERROR_NONE)
676   {
677     DALI_LOG_ERROR("Framework::Run(), ui_app_main() is failed. err = %d\n", ret);
678   }
679   mRunning = false;
680 }
681
682 void Framework::Quit()
683 {
684   mImpl->AppExit();
685 }
686
687 bool Framework::IsMainLoopRunning()
688 {
689   return mRunning;
690 }
691
692 void Framework::AddAbortCallback( CallbackBase* callback )
693 {
694   mImpl->mAbortCallBack = callback;
695 }
696
697 std::string Framework::GetBundleName() const
698 {
699   return mBundleName;
700 }
701
702 void Framework::SetBundleName(const std::string& name)
703 {
704   mBundleName = name;
705 }
706
707 std::string Framework::GetBundleId() const
708 {
709   return mBundleId;
710 }
711
712 std::string Framework::GetResourcePath()
713 {
714   std::string resourcePath = "";
715 #if defined( TIZEN_PLATFORM_CONFIG_SUPPORTED ) && TIZEN_PLATFORM_CONFIG_SUPPORTED
716   resourcePath = app_get_resource_path();
717 #else // For backwards compatibility with older Tizen versions
718
719   // "DALI_APPLICATION_PACKAGE" is used to get the already configured Application package path.
720   const char* environmentVariable = "DALI_APPLICATION_PACKAGE";
721   char* value = getenv( environmentVariable );
722   if ( value != NULL )
723   {
724     resourcePath = value;
725   }
726 #endif //TIZEN_PLATFORM_CONFIG_SUPPORTED
727
728   return resourcePath;
729 }
730
731 void Framework::SetBundleId(const std::string& id)
732 {
733   mBundleId = id;
734 }
735
736 void Framework::AbortCallback( )
737 {
738   // if an abort call back has been installed run it.
739   if (mImpl->mAbortCallBack)
740   {
741     CallbackBase::Execute( *mImpl->mAbortCallBack );
742   }
743   else
744   {
745     Quit();
746   }
747 }
748
749 void Framework::SetLanguage( const std::string& language )
750 {
751   mImpl->SetLanguage( language );
752 }
753
754 void Framework::SetRegion( const std::string& region )
755 {
756   mImpl->SetRegion( region );
757 }
758
759 std::string Framework::GetLanguage() const
760 {
761   return mImpl->GetLanguage();
762 }
763
764 std::string Framework::GetRegion() const
765 {
766   return mImpl->GetRegion();
767 }
768
769 } // namespace Adaptor
770
771 } // namespace Internal
772
773 } // namespace Dali