[Tizen] Change the return type of the init function
[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 <aul.h>
23 #include <aul_app_com.h>
24 #include <appcore_ui_base.h>
25 #include <appcore_multiwindow_base.h>
26 #include <app_control_internal.h>
27 #include <app_common.h>
28 #include <bundle.h>
29 #include <bundle_internal.h>
30 #include <Ecore.h>
31 #include <screen_connector_provider.h>
32 #include <system_info.h>
33 #include <string.h>
34 #include <unistd.h>
35 #include <vconf.h>
36 #include <vconf-internal-keys.h>
37
38 #pragma GCC diagnostic push
39 #pragma GCC diagnostic ignored "-Wold-style-cast"
40 #include <glib.h>
41 #pragma GCC diagnostic pop
42
43 // CONDITIONAL INCLUDES
44 #ifdef APPCORE_WATCH_AVAILABLE
45 #include <appcore-watch/watch_app.h>
46 #endif
47 #ifdef DALI_ELDBUS_AVAILABLE
48 #include <Eldbus.h>
49 #endif // DALI_ELDBUS_AVAILABLE
50
51 #if defined( TIZEN_PLATFORM_CONFIG_SUPPORTED ) && TIZEN_PLATFORM_CONFIG_SUPPORTED
52 #include <tzplatform_config.h>
53 #endif // TIZEN_PLATFORM_CONFIG_SUPPORTED
54
55 #include <dali/integration-api/debug.h>
56
57 // INTERNAL INCLUDES
58 #include <callback-manager.h>
59 #include <window.h>
60 #include <widget-impl.h>
61 #include <widget-data.h>
62
63 namespace Dali
64 {
65
66 namespace Internal
67 {
68
69 namespace Adaptor
70 {
71
72 namespace
73 {
74 #if defined(DEBUG_ENABLED)
75 Integration::Log::Filter* gDBusLogging = Integration::Log::Filter::New( Debug::NoLogging, false, "LOG_ADAPTOR_EVENTS_DBUS" );
76 #endif
77
78 // TODO: remove these global variables
79 static bool gForegroundState;
80 static char* gAppId;
81 static char* gPackageId;
82 static char* gViewerEndpoint;
83
84 } // anonymous namespace
85
86 namespace AppCore
87 {
88
89 typedef enum
90 {
91   LOW_MEMORY,                 //< The low memory event
92   LOW_BATTERY,                //< The low battery event
93   LANGUAGE_CHANGED,           //< The system language changed event
94   DEVICE_ORIENTATION_CHANGED, //< The device orientation changed event
95   REGION_FORMAT_CHANGED,      //< The region format changed event
96   SUSPENDED_STATE_CHANGED,    //< The suspended state changed event of the application
97   UPDATE_REQUESTED,           //< The update requested event. This event can occur when an app needs to be updated. It is dependent on target devices.
98 } AppEventType;
99
100 static int AppEventConverter[APPCORE_BASE_EVENT_MAX] =
101 {
102   [LOW_MEMORY] = APPCORE_BASE_EVENT_LOW_MEMORY,
103   [LOW_BATTERY] = APPCORE_BASE_EVENT_LOW_BATTERY,
104   [LANGUAGE_CHANGED] = APPCORE_BASE_EVENT_LANG_CHANGE,
105   [DEVICE_ORIENTATION_CHANGED] = APPCORE_BASE_EVENT_DEVICE_ORIENTATION_CHANGED,
106   [REGION_FORMAT_CHANGED] = APPCORE_BASE_EVENT_REGION_CHANGE,
107   [SUSPENDED_STATE_CHANGED] = APPCORE_BASE_EVENT_SUSPENDED_STATE_CHANGE,
108 };
109
110 struct AppEventInfo
111 {
112   AppEventType type;
113   void *value;
114 };
115
116 typedef struct AppEventInfo *AppEventInfoPtr;
117
118 typedef void (*AppEventCallback)(AppEventInfoPtr eventInfo, void *userData);
119
120 struct AppEventHandler
121 {
122   AppEventType type;
123   AppEventCallback cb;
124   void *data;
125   void *raw;
126 };
127
128 typedef struct AppEventHandler *AppEventHandlerPtr;
129
130 int EventCallback(void *event, void *data)
131 {
132   AppEventHandlerPtr handler = static_cast<AppEventHandlerPtr>(data);
133
134   struct AppEventInfo appEvent;
135
136   appEvent.type = handler->type;
137   appEvent.value = event;
138
139   if (handler->cb)
140     handler->cb(&appEvent, handler->data);
141
142   return 0;
143 }
144
145 int AppAddEventHandler(AppEventHandlerPtr *eventHandler, AppEventType eventType, AppEventCallback callback, void *userData)
146 {
147   AppEventHandlerPtr handler;
148
149   handler = static_cast<AppEventHandlerPtr>( calloc(1, sizeof(struct AppEventHandler)) );
150   if (!handler)
151   {
152     DALI_LOG_ERROR( "failed to create handler" );
153     return TIZEN_ERROR_UNKNOWN;
154   }
155   else
156   {
157     handler->type = eventType;
158     handler->cb = callback;
159     handler->data = userData;
160     handler->raw = appcore_base_add_event( static_cast<appcore_base_event>(AppEventConverter[static_cast<int>(eventType)]), EventCallback, handler);
161
162     *eventHandler = handler;
163
164     return TIZEN_ERROR_NONE;
165   }
166 }
167
168 } // namespace Appcore
169
170 /**
171  * Impl to hide EFL data members
172  */
173 struct Framework::Impl
174 {
175 // Constructor
176   Impl(void* data, Type type )
177   : mAbortCallBack( NULL ),
178     mCallbackManager( NULL )
179 #ifdef APPCORE_WATCH_AVAILABLE
180     , mWatchCallback()
181 #endif
182   {
183     mFramework = static_cast<Framework*>(data);
184     gForegroundState = false;
185
186 #ifndef APPCORE_WATCH_AVAILABLE
187     if ( type == WATCH )
188     {
189       throw Dali::DaliException( "", "Watch Application is not supported." );
190     }
191 #endif
192     mApplicationType = type;
193     mCallbackManager = CallbackManager::New();
194   }
195
196   ~Impl()
197   {
198     delete mAbortCallBack;
199
200     // we're quiting the main loop so
201     // mCallbackManager->RemoveAllCallBacks() does not need to be called
202     // to delete our abort handler
203     delete mCallbackManager;
204   }
205
206   int AppMain()
207   {
208     int ret;
209
210     if (mApplicationType == NORMAL)
211     {
212       ret = AppNormalMain();
213     }
214     else if(mApplicationType == WIDGET)
215     {
216       ret = AppWidgetMain();
217     }
218     else
219     {
220       ret = AppWatchMain();
221     }
222     return ret;
223   }
224
225   void AppExit()
226   {
227     if (mApplicationType == NORMAL)
228     {
229       AppNormalExit();
230     }
231     else if(mApplicationType == WIDGET)
232     {
233       AppWidgetExit();
234     }
235     else
236     {
237       AppWatchExit();
238     }
239   }
240
241
242   // Data
243   Type mApplicationType;
244   CallbackBase* mAbortCallBack;
245   CallbackManager *mCallbackManager;
246
247   Framework* mFramework;
248   AppCore::AppEventHandlerPtr handlers[5];
249
250 #ifdef APPCORE_WATCH_AVAILABLE
251   watch_app_lifecycle_callback_s mWatchCallback;
252   app_event_handler_h watchHandlers[5];
253 #endif
254
255   static int AppCreate(void *data)
256   {
257     appcore_ui_base_on_create();
258     return static_cast<int>( static_cast<Framework*>(data)->Create() );
259   }
260
261   static int AppTerminate(void *data)
262   {
263     appcore_ui_base_on_terminate();
264     Observer *observer = &static_cast<Framework*>(data)->mObserver;
265
266     observer->OnTerminate();
267
268     return 0;
269   }
270
271   static int AppPause(void *data)
272   {
273     appcore_ui_base_on_pause();
274     Observer *observer = &static_cast<Framework*>(data)->mObserver;
275
276     observer->OnPause();
277
278     return 0;
279   }
280
281   static int AppResume(void *data)
282   {
283     appcore_ui_base_on_resume();
284     Observer *observer = &static_cast<Framework*>(data)->mObserver;
285
286     observer->OnResume();
287
288     return 0;
289   }
290
291   static void ProcessBundle(Framework* framework, bundle *bundleData)
292   {
293     if(bundleData == NULL)
294     {
295       return;
296     }
297
298     // get bundle name
299     char* bundleName = const_cast<char*>(bundle_get_val(bundleData, "name"));
300     if(bundleName != NULL)
301     {
302       framework->SetBundleName(bundleName);
303     }
304
305     // get bundle? id
306     char* bundleId = const_cast<char*>(bundle_get_val(bundleData, "id"));
307     if(bundleId != NULL)
308     {
309       framework->SetBundleId(bundleId);
310     }
311   }
312
313   /**
314    * Called by AppCore when the application is launched from another module (e.g. homescreen).
315    * @param[in] b the bundle data which the launcher module sent
316    */
317   static int AppControl(bundle* bundleData, void *data)
318   {
319     app_control_h appControl = NULL;
320
321     appcore_ui_base_on_control(bundleData);
322
323     if (bundleData)
324     {
325       if (app_control_create_event(bundleData, &appControl) != TIZEN_ERROR_NONE)
326       {
327         DALI_LOG_ERROR("Failed to create an app_control handle");
328       }
329     }
330     else
331     {
332       if (app_control_create(&appControl) != TIZEN_ERROR_NONE)
333       {
334         DALI_LOG_ERROR("Failed to create an app_control handle");
335       }
336     }
337
338     Framework* framework = static_cast<Framework*>(data);
339     Observer *observer = &framework->mObserver;
340
341     ProcessBundle(framework, bundleData);
342
343     observer->OnReset();
344     observer->OnAppControl(appControl);
345
346     app_control_destroy(appControl);
347
348     return 0;
349   }
350
351   static void AppInit(int argc, char **argv, void *data)
352   {
353 #pragma GCC diagnostic push
354 #pragma GCC diagnostic ignored "-Wold-style-cast"
355
356     ecore_init();
357     ecore_app_args_set( argc, (const char **)argv );
358
359 #pragma GCC diagnostic pop
360   }
361
362   static void AppFinish(void)
363   {
364     ecore_shutdown();
365
366     if(getenv("AUL_LOADER_INIT"))
367     {
368       unsetenv("AUL_LOADER_INIT");
369       ecore_shutdown();
370     }
371   }
372
373   static void AppRun(void *data)
374   {
375     ecore_main_loop_begin();
376   }
377
378   static void AppExit(void *data)
379   {
380     ecore_main_loop_quit();
381   }
382
383   static void AppLanguageChanged(AppCore::AppEventInfoPtr event, void *data)
384   {
385     Observer *observer = &static_cast<Framework*>(data)->mObserver;
386
387     observer->OnLanguageChanged();
388   }
389
390   static void AppDeviceRotated(AppCore::AppEventInfoPtr event_info, void *data)
391   {
392   }
393
394   static void AppRegionChanged(AppCore::AppEventInfoPtr event, void *data)
395   {
396     Observer *observer = &static_cast<Framework*>(data)->mObserver;
397
398     observer->OnRegionChanged();
399   }
400
401   static void AppBatteryLow(AppCore::AppEventInfoPtr event, void *data)
402   {
403     Observer *observer = &static_cast<Framework*>(data)->mObserver;
404
405     observer->OnBatteryLow();
406   }
407
408   static void AppMemoryLow(AppCore::AppEventInfoPtr event, void *data)
409   {
410     Observer *observer = &static_cast<Framework*>(data)->mObserver;
411
412     observer->OnMemoryLow();
413   }
414
415
416   int AppNormalMain()
417   {
418     int ret;
419
420     AppCore::AppAddEventHandler(&handlers[AppCore::LOW_BATTERY], AppCore::LOW_BATTERY, AppBatteryLow, mFramework);
421     AppCore::AppAddEventHandler(&handlers[AppCore::LOW_MEMORY], AppCore::LOW_MEMORY, AppMemoryLow, mFramework);
422     AppCore::AppAddEventHandler(&handlers[AppCore::DEVICE_ORIENTATION_CHANGED], AppCore::DEVICE_ORIENTATION_CHANGED, AppDeviceRotated, mFramework);
423     AppCore::AppAddEventHandler(&handlers[AppCore::LANGUAGE_CHANGED], AppCore::LANGUAGE_CHANGED, AppLanguageChanged, mFramework);
424     AppCore::AppAddEventHandler(&handlers[AppCore::REGION_FORMAT_CHANGED], AppCore::REGION_FORMAT_CHANGED, AppRegionChanged, mFramework);
425
426     appcore_ui_base_ops ops = appcore_ui_base_get_default_ops();
427
428     /* override methods */
429     ops.base.create = AppCreate;
430     ops.base.control = AppControl;
431     ops.base.terminate = AppTerminate;
432     ops.pause = AppPause;
433     ops.resume = AppResume;
434     ops.base.init = AppInit;
435     ops.base.finish = AppFinish;
436     ops.base.run = AppRun;
437     ops.base.exit = AppExit;
438
439     ret = appcore_ui_base_init(ops, *mFramework->mArgc, *mFramework->mArgv, mFramework, APPCORE_UI_BASE_HINT_WINDOW_GROUP_CONTROL |
440                                                                                         APPCORE_UI_BASE_HINT_WINDOW_STACK_CONTROL |
441                                                                                         APPCORE_UI_BASE_HINT_BG_LAUNCH_CONTROL |
442                                                                                         APPCORE_UI_BASE_HINT_HW_ACC_CONTROL |
443                                                                                         APPCORE_UI_BASE_HINT_WINDOW_AUTO_CONTROL );
444
445     if (ret != TIZEN_ERROR_NONE)
446       return ret;
447
448     appcore_ui_base_fini();
449
450     return TIZEN_ERROR_NONE;
451   }
452
453   void AppNormalExit()
454   {
455     appcore_ui_base_exit();
456   }
457
458   void AppWidgetExit()
459   {
460     if( !IsWidgetFeatureEnabled() )
461     {
462       DALI_LOG_ERROR("widget feature is not supported");
463       return;
464     }
465
466     appcore_multiwindow_base_exit();
467     aul_widget_notify_exit();
468   }
469
470   int AppWidgetMain()
471   {
472     if( !IsWidgetFeatureEnabled() )
473     {
474       DALI_LOG_ERROR("widget feature is not supported");
475       return 0;
476     }
477
478     AppCore::AppAddEventHandler(&handlers[AppCore::LOW_BATTERY], AppCore::LOW_BATTERY, AppBatteryLow, mFramework);
479     AppCore::AppAddEventHandler(&handlers[AppCore::LOW_MEMORY], AppCore::LOW_MEMORY, AppMemoryLow, mFramework);
480     AppCore::AppAddEventHandler(&handlers[AppCore::DEVICE_ORIENTATION_CHANGED], AppCore::DEVICE_ORIENTATION_CHANGED, AppDeviceRotated, mFramework);
481     AppCore::AppAddEventHandler(&handlers[AppCore::LANGUAGE_CHANGED], AppCore::LANGUAGE_CHANGED, AppLanguageChanged, mFramework);
482     AppCore::AppAddEventHandler(&handlers[AppCore::REGION_FORMAT_CHANGED], AppCore::REGION_FORMAT_CHANGED, AppRegionChanged, mFramework);
483
484     appcore_multiwindow_base_ops ops = appcore_multiwindow_base_get_default_ops();
485
486     /* override methods */
487     ops.base.create = WidgetAppCreate;
488     ops.base.control = WidgetAppControl;
489     ops.base.terminate = WidgetAppTerminate;
490     ops.base.receive = WidgetAppReceive;
491     ops.base.init = AppInit;
492     ops.base.finish = AppFinish;
493     ops.base.run = AppRun;
494     ops.base.exit = AppExit;
495
496     bundle *bundleFromArgv = bundle_import_from_argv(*mFramework->mArgc, *mFramework->mArgv);
497
498     char* viewerEndpoint = NULL;
499
500     if (bundleFromArgv)
501     {
502       bundle_get_str(bundleFromArgv, "__WIDGET_ENDPOINT__", &viewerEndpoint);
503       if (viewerEndpoint)
504       {
505         gViewerEndpoint = strdup(viewerEndpoint);
506       }
507       else
508       {
509         DALI_LOG_ERROR("endpoint is missing");
510         return 0;
511       }
512
513       bundle_free(bundleFromArgv);
514     }
515     else
516     {
517       DALI_LOG_ERROR("failed to get launch argv");
518       return 0;
519     }
520
521     appcore_multiwindow_base_init(ops, *mFramework->mArgc, *mFramework->mArgv, mFramework);
522     appcore_multiwindow_base_fini();
523     return TIZEN_ERROR_NONE;
524   }
525
526   static void WidgetAppPoweroff(keynode_t *key, void *data)
527   {
528     int val;
529
530     val = vconf_keynode_get_int(key);
531     switch (val) {
532       case VCONFKEY_SYSMAN_POWER_OFF_DIRECT:
533       case VCONFKEY_SYSMAN_POWER_OFF_RESTART:
534       {
535         static_cast<Internal::Adaptor::Framework::Impl*>(data)->AppWidgetExit();
536         break;
537       }
538       case VCONFKEY_SYSMAN_POWER_OFF_NONE:
539       case VCONFKEY_SYSMAN_POWER_OFF_POPUP:
540       default:
541         break;
542     }
543   }
544
545   static int WidgetAppCreate(void *data)
546   {
547     char pkgid[256] = {0, };
548
549     appcore_multiwindow_base_on_create();
550     app_get_id(&gAppId);
551
552     if(aul_app_get_pkgid_bypid(getpid(), pkgid, sizeof(pkgid)) == 0)
553     {
554       gPackageId = strdup(pkgid);
555     }
556
557     if(!gPackageId || !gAppId)
558     {
559       DALI_LOG_ERROR("package_id is NULL");
560       return -1;
561     }
562
563     screen_connector_provider_init();
564     vconf_notify_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, WidgetAppPoweroff, data);
565
566     return static_cast<int>( static_cast<Framework*>(data)->Create() );
567   }
568
569   static int WidgetAppTerminate(void *data)
570   {
571     Observer *observer = &static_cast<Framework*>(data)->mObserver;
572
573     observer->OnTerminate();
574
575     vconf_ignore_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, WidgetAppPoweroff);
576     screen_connector_provider_fini();
577
578     appcore_multiwindow_base_on_terminate();
579     return 0;
580   }
581
582   static void WidgetAppInstResume(const char* classId, const char* id, appcore_multiwindow_base_instance_h context, void* data)
583   {
584     WidgetInstanceResume(classId, id, static_cast<bundle*>(data));
585   }
586
587   static void WidgetInstanceResume(const char* classId, const char* id, bundle* bundleData)
588   {
589     appcore_multiwindow_base_instance_h context;
590
591     context = appcore_multiwindow_base_instance_find(id);
592
593     if(!context)
594     {
595       DALI_LOG_ERROR("context not found: %s", id);
596       return;
597     }
598
599     appcore_multiwindow_base_instance_resume(context);
600
601     SendUpdateStatus(classId, id, AUL_WIDGET_INSTANCE_EVENT_RESUME, NULL);
602
603     if(!gForegroundState)
604     {
605       aul_send_app_status_change_signal( getpid(), gAppId, gPackageId, "fg", "widgetapp" );
606       gForegroundState = true;
607     }
608
609     return;
610   }
611
612   static int SendUpdateStatus(const char* classId, const char* instanceId, int status, bundle* extra )
613   {
614     bundle* bundleData;
615     int lifecycle = -1;
616     bundle_raw *raw = NULL;
617     int length;
618
619     bundleData = bundle_create();
620     if(!bundleData)
621     {
622       DALI_LOG_ERROR("out of memory");
623       return -1;
624     }
625
626     bundle_add_str(bundleData, AUL_K_WIDGET_ID, classId);
627     bundle_add_str(bundleData, AUL_K_WIDGET_INSTANCE_ID, instanceId);
628     bundle_add_byte(bundleData, AUL_K_WIDGET_STATUS, &status, sizeof(int));
629
630     if(extra)
631     {
632       bundle_encode(extra, &raw, &length);
633 #pragma GCC diagnostic push
634 #pragma GCC diagnostic ignored "-Wold-style-cast"
635       bundle_add_str(bundleData, "__WIDGET_CONTENT_INFO__", (const char*)raw);
636 #pragma GCC diagnostic pop
637
638       aul_widget_instance_add(classId, instanceId);
639     }
640
641     aul_app_com_send(gViewerEndpoint, bundleData);
642
643     switch(status)
644     {
645       case AUL_WIDGET_INSTANCE_EVENT_CREATE:
646         lifecycle = Dali::Widget::WidgetLifecycleEventType::CREATE;
647         break;
648       case AUL_WIDGET_INSTANCE_EVENT_DESTROY:
649         lifecycle = Dali::Widget::WidgetLifecycleEventType::DESTROY;
650         break;
651       case AUL_WIDGET_INSTANCE_EVENT_PAUSE:
652         lifecycle = Dali::Widget::WidgetLifecycleEventType::PAUSE;
653         break;
654       case AUL_WIDGET_INSTANCE_EVENT_RESUME:
655         lifecycle = Dali::Widget::WidgetLifecycleEventType::RESUME;
656         break;
657     }
658
659     if (lifecycle > -1)
660       SendLifecycleEvent(classId, instanceId, lifecycle);
661
662     bundle_free(bundleData);
663     if (raw)
664       free(raw);
665
666     return 0;
667   }
668
669   static int SendLifecycleEvent(const char* classId, const char* instanceId, int status)
670   {
671     bundle* bundleData = bundle_create();
672     int ret;
673
674     if (bundleData == NULL)
675     {
676       DALI_LOG_ERROR("out of memory");
677       return -1;
678     }
679
680     bundle_add_str(bundleData, AUL_K_WIDGET_ID, classId);
681     bundle_add_str(bundleData, AUL_K_WIDGET_INSTANCE_ID, instanceId);
682     bundle_add_byte(bundleData, AUL_K_WIDGET_STATUS, &status, sizeof(int));
683     bundle_add_str(bundleData, AUL_K_PKGID, gPackageId);
684
685     ret = aul_app_com_send("widget.status", bundleData);
686
687     if (ret < 0)
688       DALI_LOG_ERROR("send lifecycle error:%d", ret);
689
690     bundle_free(bundleData);
691
692     return ret;
693   }
694
695   static int WidgetAppReceive(aul_type type, bundle *bundleData, void *data)
696   {
697     appcore_multiwindow_base_on_receive(type, bundleData);
698
699     switch(type)
700     {
701       case AUL_RESUME:
702       {
703         appcore_multiwindow_base_instance_foreach_full(WidgetAppInstResume, bundleData);
704         break;
705       }
706       case AUL_TERMINATE:
707       {
708         static_cast<Internal::Adaptor::Framework::Impl*>(data)->AppWidgetExit();
709         break;
710       }
711       case AUL_WIDGET_CONTENT:
712       {
713         GetContent(bundleData);
714         break;
715       }
716       default:
717         break;
718     }
719     return 0;
720   }
721
722   static void GetContent( bundle* bundleData )
723   {
724     char* instanceId = NULL;
725     appcore_multiwindow_base_instance_h context;
726     const appcore_multiwindow_base_class *cls;
727     Internal::Adaptor::Widget *widgetInstance;
728
729     bundle_get_str(bundleData, AUL_K_WIDGET_INSTANCE_ID, &instanceId);
730     if(!instanceId)
731     {
732       DALI_LOG_ERROR("instance id is NULL");
733       return;
734     }
735
736     context = static_cast<appcore_multiwindow_base_instance_h>(appcore_multiwindow_base_instance_find(instanceId));
737     if(!context)
738     {
739       DALI_LOG_ERROR("could not find widget obj: %s", instanceId);
740       return;
741     }
742
743     cls = appcore_multiwindow_base_instance_get_class(context);
744     if(!cls)
745     {
746       DALI_LOG_ERROR("widget class is NULL");
747       return;
748     }
749
750     widgetInstance = static_cast<Internal::Adaptor::Widget*>(cls->data);
751     if(!widgetInstance)
752     {
753       DALI_LOG_ERROR("widget instance is NULL");
754       return;
755     }
756
757     Dali::WidgetData *widgetData = widgetInstance->FindWidgetData( instanceId );
758     if(!widgetData)
759     {
760       DALI_LOG_ERROR("widget extra is NULL");
761       return;
762     }
763
764     char* widgetContent = widgetData->GetContent();
765     if(widgetContent)
766     {
767       bundle_add_str(bundleData, AUL_K_WIDGET_CONTENT_INFO, widgetContent);
768     }
769     else
770     {
771       bundle_add_str(bundleData, AUL_K_WIDGET_CONTENT_INFO, "");
772     }
773   }
774
775   /**
776    * Called by AppCore when the application is launched from another module (e.g. homescreen).
777    * @param[in] b the bundle data which the launcher module sent
778    */
779   static int WidgetAppControl(bundle* bundleData, void *data)
780   {
781     char *classId = NULL;
782     char *id = NULL;
783     char *operation = NULL;
784
785     appcore_multiwindow_base_on_control(bundleData);
786
787     bundle_get_str(bundleData, AUL_K_WIDGET_ID, &classId);
788     bundle_get_str(bundleData, AUL_K_WIDGET_INSTANCE_ID, &id);
789     bundle_get_str(bundleData, "__WIDGET_OP__", &operation);
790
791     if(!operation)
792     {
793       DALI_LOG_ERROR("operation is NULL");
794       return 0;
795     }
796
797     if(strcmp(operation, "create") == 0)
798     {
799       InstanceCreate( classId, id, bundleData );
800     }
801     else if (strcmp(operation, "resize") == 0)
802     {
803       InstanceResize( classId, id, bundleData );
804     }
805     else if (strcmp(operation, "update") == 0)
806     {
807       InstanceUpdate( classId, id, bundleData );
808     }
809     else if (strcmp(operation, "destroy") == 0)
810     {
811       InstanceDestroy( classId, id, bundleData, data );
812     }
813     else if (strcmp(operation, "resume") == 0)
814     {
815       InstanceResume( classId, id, bundleData );
816     }
817     else if (strcmp(operation, "pause") == 0)
818     {
819       InstancePause( classId, id, bundleData );
820     }
821     else if (strcmp(operation, "terminate") == 0)
822     {
823       InstanceDestroy( classId, id, bundleData, data );
824     }
825
826     return 0;
827   }
828
829   static void InstanceCreate(const char* classId, const char* id, bundle* bundleData)
830   {
831     appcore_multiwindow_base_instance_run(classId, id, bundle_dup(bundleData));
832   }
833
834   static void InstanceResize(const char *classId, const char *id, bundle *bundleData)
835   {
836     appcore_multiwindow_base_instance_h context;
837     Internal::Adaptor::Widget *widgetInstance;
838     const appcore_multiwindow_base_class *cls;
839     char *remain = NULL;
840     char *widthStr = NULL;
841     char *heightStr = NULL;
842     uint32_t width = 0;
843     uint32_t height = 0;
844
845     context = appcore_multiwindow_base_instance_find(id);
846
847     if(!context)
848     {
849       DALI_LOG_ERROR("context not found: %s", id);
850       return;
851     }
852
853     cls = appcore_multiwindow_base_instance_get_class(context);
854     if(!cls)
855     {
856       DALI_LOG_ERROR("widget class is NULL");
857       return;
858     }
859
860     widgetInstance = static_cast<Internal::Adaptor::Widget*>(cls->data);
861     if(!widgetInstance)
862     {
863       DALI_LOG_ERROR("widget instance is NULL");
864       return;
865     }
866
867     bundle_get_str(bundleData, "__WIDGET_WIDTH__", &widthStr);
868     bundle_get_str(bundleData, "__WIDGET_HEIGHT__", &heightStr);
869
870     if(widthStr)
871       width = static_cast<uint32_t>(g_ascii_strtoll(widthStr, &remain, 10));
872
873     if(heightStr)
874       height = static_cast<uint32_t>(g_ascii_strtoll(heightStr, &remain, 10));
875
876     widgetInstance->OnResize( context, Dali::Widget::WindowSize(width,height) );
877   }
878
879   static void InstanceUpdate(const char* classId, const char* id, bundle* bundleData)
880   {
881     appcore_multiwindow_base_instance_h context;
882
883     if(!id)
884     {
885       appcore_multiwindow_base_instance_foreach(classId, UpdateCallback, bundleData);
886       return;
887     }
888
889     context = appcore_multiwindow_base_instance_find(id);
890
891     if(!context)
892     {
893       DALI_LOG_ERROR("context not found: %s", id);
894       return;
895     }
896
897     UpdateCallback(classId, id, context, bundleData);
898   }
899
900   static void UpdateCallback(const char* classId, const char* id, appcore_multiwindow_base_instance_h context, void* data)
901   {
902     Internal::Adaptor::Widget *widgetInstance;
903     const appcore_multiwindow_base_class *cls;
904     bundle* content = NULL;
905     char* contentRaw = NULL;
906     char* forceStr = NULL;
907     int force;
908     bundle* bundleData = static_cast<bundle*>(data);
909
910     if(!bundleData)
911     {
912       DALI_LOG_ERROR("bundle is NULL");
913       return;
914     }
915
916     cls = appcore_multiwindow_base_instance_get_class(context);
917     if(!cls)
918     {
919       DALI_LOG_ERROR("class is NULL");
920       return;
921     }
922
923     widgetInstance = static_cast<Internal::Adaptor::Widget*>(cls->data);
924     if(!widgetInstance)
925     {
926       DALI_LOG_ERROR("widget instance is NULL");
927       return;
928     }
929
930     bundle_get_str(bundleData, "__WIDGET_FORCE__", &forceStr);
931
932     if(forceStr && strcmp(forceStr, "true") == 0)
933     {
934       force = 1;
935     }
936     else
937     {
938       force = 0;
939     }
940
941     bundle_get_str(bundleData, "__WIDGET_CONTENT_INFO__", &contentRaw);
942
943     if(contentRaw)
944     {
945 #pragma GCC diagnostic push
946 #pragma GCC diagnostic ignored "-Wold-style-cast"
947       content = bundle_decode((const bundle_raw *)contentRaw, strlen(contentRaw));
948 #pragma GCC diagnostic pop
949
950     }
951
952     widgetInstance->OnUpdate(context, content, force);
953
954     if(content)
955     {
956       bundle_free(content);
957     }
958   }
959
960   static void InstanceDestroy(const char* classId, const char* id, bundle* bundleData, void* data)
961   {
962     appcore_multiwindow_base_instance_h context;
963
964     Internal::Adaptor::Widget *widgetInstance;
965     const appcore_multiwindow_base_class *cls;
966
967     context = appcore_multiwindow_base_instance_find(id);
968
969     if(!context)
970     {
971       DALI_LOG_ERROR("could not find widget obj: %s, clear amd info", id);
972       aul_widget_instance_del(classId, id);
973       return;
974     }
975
976     cls = appcore_multiwindow_base_instance_get_class(context);
977     if(!cls)
978     {
979       DALI_LOG_ERROR("widget class is NULL");
980       return;
981     }
982
983     widgetInstance = static_cast<Internal::Adaptor::Widget*>(cls->data);
984     if(!widgetInstance)
985     {
986       DALI_LOG_ERROR("widget instance is NULL");
987       return;
988     }
989
990     Dali::WidgetData *widgetData  = widgetInstance->FindWidgetData(id);
991
992     widgetData->SetArgs( bundleData );
993     appcore_multiwindow_base_instance_exit(context);
994     CheckEmptyInstance(data);
995   }
996
997   static void CheckEmptyInstance(void* data)
998   {
999     int cnt = appcore_multiwindow_base_instance_get_cnt();
1000
1001     if(cnt == 0)
1002     {
1003       static_cast<Internal::Adaptor::Framework::Impl*>(data)->AppWidgetExit();
1004     }
1005   }
1006
1007   static void InstanceResume(const char* classId, const char* id, bundle* bundleData)
1008   {
1009     appcore_multiwindow_base_instance_h context;
1010
1011     context = appcore_multiwindow_base_instance_find(id);
1012
1013     if(!context)
1014     {
1015       DALI_LOG_ERROR("context not found: %s", id);
1016       return;
1017     }
1018
1019     appcore_multiwindow_base_instance_resume(context);
1020
1021     SendUpdateStatus(classId, id, AUL_WIDGET_INSTANCE_EVENT_RESUME, NULL);
1022     if(!gForegroundState)
1023     {
1024       aul_send_app_status_change_signal(getpid(), gAppId, gPackageId, "fg", "widgetapp" );
1025       gForegroundState = true;
1026     }
1027   }
1028
1029   static void InstancePause(const char* classId, const char* id, bundle* bundleData)
1030   {
1031     appcore_multiwindow_base_instance_h context;
1032
1033     context = appcore_multiwindow_base_instance_find(id);
1034
1035     if(!context)
1036     {
1037       DALI_LOG_ERROR("context not found: %s", id);
1038       return;
1039     }
1040
1041     appcore_multiwindow_base_instance_pause(context);
1042
1043     if(gForegroundState)
1044     {
1045       aul_send_app_status_change_signal(getpid(), gAppId, gPackageId, "bg", "widgetapp" );
1046       gForegroundState = false;
1047     }
1048   }
1049
1050   static bool IsWidgetFeatureEnabled()
1051   {
1052     static bool feature = false;
1053     static bool retrieved = false;
1054     int ret;
1055
1056     if(retrieved == true)
1057       return feature;
1058
1059     ret = system_info_get_platform_bool("http://tizen.org/feature/shell.appwidget", &feature);
1060     if(ret != SYSTEM_INFO_ERROR_NONE)
1061     {
1062       DALI_LOG_ERROR("failed to get system info"); /* LCOV_EXCL_LINE */
1063       return false; /* LCOV_EXCL_LINE */
1064     }
1065
1066     retrieved = true;
1067     return feature;
1068   }
1069
1070
1071 #ifdef APPCORE_WATCH_AVAILABLE
1072   static bool WatchAppCreate(int width, int height, void *data)
1073   {
1074     return static_cast<Framework*>(data)->Create();
1075   }
1076
1077   static void WatchAppTimeTick(watch_time_h time, void *data)
1078   {
1079     Observer *observer = &static_cast<Framework*>(data)->mObserver;
1080     WatchTime curTime(time);
1081
1082     observer->OnTimeTick(curTime);
1083   }
1084
1085   static void WatchAppAmbientTick(watch_time_h time, void *data)
1086   {
1087     Observer *observer = &static_cast<Framework*>(data)->mObserver;
1088     WatchTime curTime(time);
1089
1090     observer->OnAmbientTick(curTime);
1091   }
1092
1093   static void WatchAppAmbientChanged(bool ambient, void *data)
1094   {
1095     Observer *observer = &static_cast<Framework*>(data)->mObserver;
1096
1097     observer->OnAmbientChanged(ambient);
1098   }
1099
1100   static void WatchAppLanguageChanged(app_event_info_h event, void *data)
1101   {
1102     Observer *observer = &static_cast<Framework*>(data)->mObserver;
1103
1104     observer->OnLanguageChanged();
1105   }
1106
1107   static void WatchAppRegionChanged(app_event_info_h event, void *data)
1108   {
1109     Observer *observer = &static_cast<Framework*>(data)->mObserver;
1110
1111     observer->OnRegionChanged();
1112   }
1113
1114   static void WatchAppBatteryLow(app_event_info_h event, void *data)
1115   {
1116     Observer *observer = &static_cast<Framework*>(data)->mObserver;
1117
1118     observer->OnBatteryLow();
1119   }
1120
1121   static void WatchAppMemoryLow(app_event_info_h event, void *data)
1122   {
1123     Observer *observer = &static_cast<Framework*>(data)->mObserver;
1124
1125     observer->OnMemoryLow();
1126   }
1127
1128   static void WatchAppControl(app_control_h app_control, void *data)
1129   {
1130     Framework* framework = static_cast<Framework*>(data);
1131     Observer *observer = &framework->mObserver;
1132     bundle *bundleData = NULL;
1133
1134     app_control_to_bundle(app_control, &bundleData);
1135     ProcessBundle(framework, bundleData);
1136
1137     observer->OnReset();
1138     observer->OnAppControl(app_control);
1139   }
1140
1141   static void WatchAppTerminate(void *data)
1142   {
1143     Observer *observer = &static_cast<Framework*>(data)->mObserver;
1144
1145     observer->OnTerminate();
1146   }
1147
1148   static void WatchAppPause(void *data)
1149   {
1150     Observer *observer = &static_cast<Framework*>(data)->mObserver;
1151
1152     observer->OnPause();
1153   }
1154
1155   static void WatchAppResume(void *data)
1156   {
1157     Observer *observer = &static_cast<Framework*>(data)->mObserver;
1158
1159     observer->OnResume();
1160   }
1161 #endif
1162
1163   int AppWatchMain()
1164   {
1165     int ret = true;
1166
1167 #ifdef APPCORE_WATCH_AVAILABLE
1168     mWatchCallback.create = WatchAppCreate;
1169     mWatchCallback.app_control = WatchAppControl;
1170     mWatchCallback.terminate = WatchAppTerminate;
1171     mWatchCallback.pause = WatchAppPause;
1172     mWatchCallback.resume = WatchAppResume;
1173     mWatchCallback.time_tick = WatchAppTimeTick;
1174     mWatchCallback.ambient_tick = WatchAppAmbientTick;
1175     mWatchCallback.ambient_changed = WatchAppAmbientChanged;
1176
1177     watch_app_add_event_handler(&watchHandlers[APP_EVENT_LOW_BATTERY], APP_EVENT_LOW_BATTERY, WatchAppBatteryLow, mFramework);
1178     watch_app_add_event_handler(&watchHandlers[APP_EVENT_LOW_MEMORY], APP_EVENT_LOW_MEMORY, WatchAppMemoryLow, mFramework);
1179     watch_app_add_event_handler(&watchHandlers[APP_EVENT_LANGUAGE_CHANGED], APP_EVENT_LANGUAGE_CHANGED, WatchAppLanguageChanged, mFramework);
1180     watch_app_add_event_handler(&watchHandlers[APP_EVENT_REGION_FORMAT_CHANGED], APP_EVENT_REGION_FORMAT_CHANGED, WatchAppRegionChanged, mFramework);
1181
1182     ret = watch_app_main(*mFramework->mArgc, *mFramework->mArgv, &mWatchCallback, mFramework);
1183 #endif
1184     return ret;
1185   }
1186
1187   void AppWatchExit()
1188   {
1189 #ifdef APPCORE_WATCH_AVAILABLE
1190     watch_app_exit();
1191 #endif
1192   }
1193
1194
1195 private:
1196   // Undefined
1197   Impl( const Impl& impl );
1198
1199   // Undefined
1200   Impl& operator=( const Impl& impl );
1201 };
1202
1203 Framework::Framework( Framework::Observer& observer, int *argc, char ***argv, Type type )
1204 : mObserver(observer),
1205   mInitialised(false),
1206   mRunning(false),
1207   mArgc(argc),
1208   mArgv(argv),
1209   mBundleName(""),
1210   mBundleId(""),
1211   mAbortHandler( MakeCallback( this, &Framework::AbortCallback ) ),
1212   mImpl(NULL)
1213 {
1214   bool featureFlag = true;
1215   system_info_get_platform_bool( "tizen.org/feature/opengles.version.2_0", &featureFlag );
1216
1217   if( featureFlag == false )
1218   {
1219     set_last_result( TIZEN_ERROR_NOT_SUPPORTED );
1220   }
1221 #ifdef DALI_ELDBUS_AVAILABLE
1222   // Initialize ElDBus.
1223   eldbus_init();
1224 #endif
1225   InitThreads();
1226
1227   mImpl = new Impl(this, type);
1228 }
1229
1230 Framework::~Framework()
1231 {
1232   if (mRunning)
1233   {
1234     Quit();
1235   }
1236
1237 #ifdef DALI_ELDBUS_AVAILABLE
1238   // Shutdown ELDBus.
1239   eldbus_shutdown();
1240 #endif
1241
1242   delete mImpl;
1243 }
1244
1245 bool Framework::Create()
1246 {
1247   mInitialised = true;
1248   mObserver.OnInit();
1249   return true;
1250 }
1251
1252 void Framework::Run()
1253 {
1254   mRunning = true;
1255   int ret;
1256
1257   ret = mImpl->AppMain();
1258   if (ret != APP_ERROR_NONE)
1259   {
1260     DALI_LOG_ERROR("Framework::Run(), ui_app_main() is failed. err = %d\n", ret);
1261   }
1262   mRunning = false;
1263 }
1264
1265 void Framework::Quit()
1266 {
1267   mImpl->AppExit();
1268 }
1269
1270 bool Framework::IsMainLoopRunning()
1271 {
1272   return mRunning;
1273 }
1274
1275 void Framework::AddAbortCallback( CallbackBase* callback )
1276 {
1277   mImpl->mAbortCallBack = callback;
1278 }
1279
1280 std::string Framework::GetBundleName() const
1281 {
1282   return mBundleName;
1283 }
1284
1285 void Framework::SetBundleName(const std::string& name)
1286 {
1287   mBundleName = name;
1288 }
1289
1290 std::string Framework::GetBundleId() const
1291 {
1292   return mBundleId;
1293 }
1294
1295 std::string Framework::GetResourcePath()
1296 {
1297   std::string resourcePath = "";
1298 #if defined( TIZEN_PLATFORM_CONFIG_SUPPORTED ) && TIZEN_PLATFORM_CONFIG_SUPPORTED
1299   resourcePath = app_get_resource_path();
1300 #else // For backwards compatibility with older Tizen versions
1301
1302   // "DALI_APPLICATION_PACKAGE" is used to get the already configured Application package path.
1303   const char* environmentVariable = "DALI_APPLICATION_PACKAGE";
1304   char* value = getenv( environmentVariable );
1305   if ( value != NULL )
1306   {
1307     resourcePath = value;
1308   }
1309 #endif //TIZEN_PLATFORM_CONFIG_SUPPORTED
1310
1311   return resourcePath;
1312 }
1313
1314 void Framework::SetBundleId(const std::string& id)
1315 {
1316   mBundleId = id;
1317 }
1318
1319 void Framework::AbortCallback( )
1320 {
1321   // if an abort call back has been installed run it.
1322   if (mImpl->mAbortCallBack)
1323   {
1324     CallbackBase::Execute( *mImpl->mAbortCallBack );
1325   }
1326   else
1327   {
1328     Quit();
1329   }
1330 }
1331
1332 } // namespace Adaptor
1333
1334 } // namespace Internal
1335
1336 } // namespace Dali