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