e9c3ac15dfffee49e4752e3699bd23b3a8228a13
[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 int 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     return 0;
361   }
362
363   static void AppFinish(void)
364   {
365     ecore_shutdown();
366
367     if(getenv("AUL_LOADER_INIT"))
368     {
369       unsetenv("AUL_LOADER_INIT");
370       ecore_shutdown();
371     }
372   }
373
374   static void AppRun(void *data)
375   {
376     ecore_main_loop_begin();
377   }
378
379   static void AppExit(void *data)
380   {
381     ecore_main_loop_quit();
382   }
383
384   static void AppLanguageChanged(AppCore::AppEventInfoPtr event, void *data)
385   {
386     Observer *observer = &static_cast<Framework*>(data)->mObserver;
387
388     observer->OnLanguageChanged();
389   }
390
391   static void AppDeviceRotated(AppCore::AppEventInfoPtr event_info, void *data)
392   {
393   }
394
395   static void AppRegionChanged(AppCore::AppEventInfoPtr event, void *data)
396   {
397     Observer *observer = &static_cast<Framework*>(data)->mObserver;
398
399     observer->OnRegionChanged();
400   }
401
402   static void AppBatteryLow(AppCore::AppEventInfoPtr event, void *data)
403   {
404     Observer *observer = &static_cast<Framework*>(data)->mObserver;
405
406     observer->OnBatteryLow();
407   }
408
409   static void AppMemoryLow(AppCore::AppEventInfoPtr event, void *data)
410   {
411     Observer *observer = &static_cast<Framework*>(data)->mObserver;
412
413     observer->OnMemoryLow();
414   }
415
416
417   int AppNormalMain()
418   {
419     int ret;
420
421     AppCore::AppAddEventHandler(&handlers[AppCore::LOW_BATTERY], AppCore::LOW_BATTERY, AppBatteryLow, mFramework);
422     AppCore::AppAddEventHandler(&handlers[AppCore::LOW_MEMORY], AppCore::LOW_MEMORY, AppMemoryLow, mFramework);
423     AppCore::AppAddEventHandler(&handlers[AppCore::DEVICE_ORIENTATION_CHANGED], AppCore::DEVICE_ORIENTATION_CHANGED, AppDeviceRotated, mFramework);
424     AppCore::AppAddEventHandler(&handlers[AppCore::LANGUAGE_CHANGED], AppCore::LANGUAGE_CHANGED, AppLanguageChanged, mFramework);
425     AppCore::AppAddEventHandler(&handlers[AppCore::REGION_FORMAT_CHANGED], AppCore::REGION_FORMAT_CHANGED, AppRegionChanged, mFramework);
426
427     appcore_ui_base_ops ops = appcore_ui_base_get_default_ops();
428
429     /* override methods */
430     ops.base.create = AppCreate;
431     ops.base.control = AppControl;
432     ops.base.terminate = AppTerminate;
433     ops.pause = AppPause;
434     ops.resume = AppResume;
435     ops.base.init = AppInit;
436     ops.base.finish = AppFinish;
437     ops.base.run = AppRun;
438     ops.base.exit = AppExit;
439
440     ret = appcore_ui_base_init(ops, *mFramework->mArgc, *mFramework->mArgv, mFramework, APPCORE_UI_BASE_HINT_WINDOW_GROUP_CONTROL |
441                                                                                         APPCORE_UI_BASE_HINT_WINDOW_STACK_CONTROL |
442                                                                                         APPCORE_UI_BASE_HINT_BG_LAUNCH_CONTROL |
443                                                                                         APPCORE_UI_BASE_HINT_HW_ACC_CONTROL |
444                                                                                         APPCORE_UI_BASE_HINT_WINDOW_AUTO_CONTROL );
445
446     if (ret != TIZEN_ERROR_NONE)
447       return ret;
448
449     appcore_ui_base_fini();
450
451     return TIZEN_ERROR_NONE;
452   }
453
454   void AppNormalExit()
455   {
456     appcore_ui_base_exit();
457   }
458
459   void AppWidgetExit()
460   {
461     if( !IsWidgetFeatureEnabled() )
462     {
463       DALI_LOG_ERROR("widget feature is not supported");
464       return;
465     }
466
467     appcore_multiwindow_base_exit();
468     aul_widget_notify_exit();
469   }
470
471   int AppWidgetMain()
472   {
473     if( !IsWidgetFeatureEnabled() )
474     {
475       DALI_LOG_ERROR("widget feature is not supported");
476       return 0;
477     }
478
479     AppCore::AppAddEventHandler(&handlers[AppCore::LOW_BATTERY], AppCore::LOW_BATTERY, AppBatteryLow, mFramework);
480     AppCore::AppAddEventHandler(&handlers[AppCore::LOW_MEMORY], AppCore::LOW_MEMORY, AppMemoryLow, mFramework);
481     AppCore::AppAddEventHandler(&handlers[AppCore::DEVICE_ORIENTATION_CHANGED], AppCore::DEVICE_ORIENTATION_CHANGED, AppDeviceRotated, mFramework);
482     AppCore::AppAddEventHandler(&handlers[AppCore::LANGUAGE_CHANGED], AppCore::LANGUAGE_CHANGED, AppLanguageChanged, mFramework);
483     AppCore::AppAddEventHandler(&handlers[AppCore::REGION_FORMAT_CHANGED], AppCore::REGION_FORMAT_CHANGED, AppRegionChanged, mFramework);
484
485     appcore_multiwindow_base_ops ops = appcore_multiwindow_base_get_default_ops();
486
487     /* override methods */
488     ops.base.create = WidgetAppCreate;
489     ops.base.control = WidgetAppControl;
490     ops.base.terminate = WidgetAppTerminate;
491     ops.base.receive = WidgetAppReceive;
492     ops.base.init = AppInit;
493     ops.base.finish = AppFinish;
494     ops.base.run = AppRun;
495     ops.base.exit = AppExit;
496
497     bundle *bundleFromArgv = bundle_import_from_argv(*mFramework->mArgc, *mFramework->mArgv);
498
499     char* viewerEndpoint = NULL;
500
501     if (bundleFromArgv)
502     {
503       bundle_get_str(bundleFromArgv, "__WIDGET_ENDPOINT__", &viewerEndpoint);
504       if (viewerEndpoint)
505       {
506         gViewerEndpoint = strdup(viewerEndpoint);
507       }
508       else
509       {
510         DALI_LOG_ERROR("endpoint is missing");
511         return 0;
512       }
513
514       bundle_free(bundleFromArgv);
515     }
516     else
517     {
518       DALI_LOG_ERROR("failed to get launch argv");
519       return 0;
520     }
521
522     appcore_multiwindow_base_init(ops, *mFramework->mArgc, *mFramework->mArgv, mFramework);
523     appcore_multiwindow_base_fini();
524     return TIZEN_ERROR_NONE;
525   }
526
527   static void WidgetAppPoweroff(keynode_t *key, void *data)
528   {
529     int val;
530
531     val = vconf_keynode_get_int(key);
532     switch (val) {
533       case VCONFKEY_SYSMAN_POWER_OFF_DIRECT:
534       case VCONFKEY_SYSMAN_POWER_OFF_RESTART:
535       {
536         static_cast<Internal::Adaptor::Framework::Impl*>(data)->AppWidgetExit();
537         break;
538       }
539       case VCONFKEY_SYSMAN_POWER_OFF_NONE:
540       case VCONFKEY_SYSMAN_POWER_OFF_POPUP:
541       default:
542         break;
543     }
544   }
545
546   static int WidgetAppCreate(void *data)
547   {
548     char pkgid[256] = {0, };
549
550     appcore_multiwindow_base_on_create();
551     app_get_id(&gAppId);
552
553     if(aul_app_get_pkgid_bypid(getpid(), pkgid, sizeof(pkgid)) == 0)
554     {
555       gPackageId = strdup(pkgid);
556     }
557
558     if(!gPackageId || !gAppId)
559     {
560       DALI_LOG_ERROR("package_id is NULL");
561       return -1;
562     }
563
564     screen_connector_provider_init();
565     vconf_notify_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, WidgetAppPoweroff, data);
566
567     return static_cast<int>( static_cast<Framework*>(data)->Create() );
568   }
569
570   static int WidgetAppTerminate(void *data)
571   {
572     Observer *observer = &static_cast<Framework*>(data)->mObserver;
573
574     observer->OnTerminate();
575
576     vconf_ignore_key_changed(VCONFKEY_SYSMAN_POWER_OFF_STATUS, WidgetAppPoweroff);
577     screen_connector_provider_fini();
578
579     appcore_multiwindow_base_on_terminate();
580     return 0;
581   }
582
583   static void WidgetAppInstResume(const char* classId, const char* id, appcore_multiwindow_base_instance_h context, void* data)
584   {
585     WidgetInstanceResume(classId, id, static_cast<bundle*>(data));
586   }
587
588   static void WidgetInstanceResume(const char* classId, const char* id, bundle* bundleData)
589   {
590     appcore_multiwindow_base_instance_h context;
591
592     context = appcore_multiwindow_base_instance_find(id);
593
594     if(!context)
595     {
596       DALI_LOG_ERROR("context not found: %s", id);
597       return;
598     }
599
600     appcore_multiwindow_base_instance_resume(context);
601
602     SendUpdateStatus(classId, id, AUL_WIDGET_INSTANCE_EVENT_RESUME, NULL);
603
604     if(!gForegroundState)
605     {
606       aul_send_app_status_change_signal( getpid(), gAppId, gPackageId, "fg", "widgetapp" );
607       gForegroundState = true;
608     }
609
610     return;
611   }
612
613   static int SendUpdateStatus(const char* classId, const char* instanceId, int status, bundle* extra )
614   {
615     bundle* bundleData;
616     int lifecycle = -1;
617     bundle_raw *raw = NULL;
618     int length;
619
620     bundleData = bundle_create();
621     if(!bundleData)
622     {
623       DALI_LOG_ERROR("out of memory");
624       return -1;
625     }
626
627     bundle_add_str(bundleData, AUL_K_WIDGET_ID, classId);
628     bundle_add_str(bundleData, AUL_K_WIDGET_INSTANCE_ID, instanceId);
629     bundle_add_byte(bundleData, AUL_K_WIDGET_STATUS, &status, sizeof(int));
630
631     if(extra)
632     {
633       bundle_encode(extra, &raw, &length);
634 #pragma GCC diagnostic push
635 #pragma GCC diagnostic ignored "-Wold-style-cast"
636       bundle_add_str(bundleData, "__WIDGET_CONTENT_INFO__", (const char*)raw);
637 #pragma GCC diagnostic pop
638
639       aul_widget_instance_add(classId, instanceId);
640     }
641
642     aul_app_com_send(gViewerEndpoint, bundleData);
643
644     switch(status)
645     {
646       case AUL_WIDGET_INSTANCE_EVENT_CREATE:
647         lifecycle = Dali::Widget::WidgetLifecycleEventType::CREATE;
648         break;
649       case AUL_WIDGET_INSTANCE_EVENT_DESTROY:
650         lifecycle = Dali::Widget::WidgetLifecycleEventType::DESTROY;
651         break;
652       case AUL_WIDGET_INSTANCE_EVENT_PAUSE:
653         lifecycle = Dali::Widget::WidgetLifecycleEventType::PAUSE;
654         break;
655       case AUL_WIDGET_INSTANCE_EVENT_RESUME:
656         lifecycle = Dali::Widget::WidgetLifecycleEventType::RESUME;
657         break;
658     }
659
660     if (lifecycle > -1)
661       SendLifecycleEvent(classId, instanceId, lifecycle);
662
663     bundle_free(bundleData);
664     if (raw)
665       free(raw);
666
667     return 0;
668   }
669
670   static int SendLifecycleEvent(const char* classId, const char* instanceId, int status)
671   {
672     bundle* bundleData = bundle_create();
673     int ret;
674
675     if (bundleData == NULL)
676     {
677       DALI_LOG_ERROR("out of memory");
678       return -1;
679     }
680
681     bundle_add_str(bundleData, AUL_K_WIDGET_ID, classId);
682     bundle_add_str(bundleData, AUL_K_WIDGET_INSTANCE_ID, instanceId);
683     bundle_add_byte(bundleData, AUL_K_WIDGET_STATUS, &status, sizeof(int));
684     bundle_add_str(bundleData, AUL_K_PKGID, gPackageId);
685
686     ret = aul_app_com_send("widget.status", bundleData);
687
688     if (ret < 0)
689       DALI_LOG_ERROR("send lifecycle error:%d", ret);
690
691     bundle_free(bundleData);
692
693     return ret;
694   }
695
696   static int WidgetAppReceive(aul_type type, bundle *bundleData, void *data)
697   {
698     appcore_multiwindow_base_on_receive(type, bundleData);
699
700     switch(type)
701     {
702       case AUL_RESUME:
703       {
704         appcore_multiwindow_base_instance_foreach_full(WidgetAppInstResume, bundleData);
705         break;
706       }
707       case AUL_TERMINATE:
708       {
709         static_cast<Internal::Adaptor::Framework::Impl*>(data)->AppWidgetExit();
710         break;
711       }
712       case AUL_WIDGET_CONTENT:
713       {
714         GetContent(bundleData);
715         break;
716       }
717       default:
718         break;
719     }
720     return 0;
721   }
722
723   static void GetContent( bundle* bundleData )
724   {
725     char* instanceId = NULL;
726     appcore_multiwindow_base_instance_h context;
727     const appcore_multiwindow_base_class *cls;
728     Internal::Adaptor::Widget *widgetInstance;
729
730     bundle_get_str(bundleData, AUL_K_WIDGET_INSTANCE_ID, &instanceId);
731     if(!instanceId)
732     {
733       DALI_LOG_ERROR("instance id is NULL");
734       return;
735     }
736
737     context = static_cast<appcore_multiwindow_base_instance_h>(appcore_multiwindow_base_instance_find(instanceId));
738     if(!context)
739     {
740       DALI_LOG_ERROR("could not find widget obj: %s", instanceId);
741       return;
742     }
743
744     cls = appcore_multiwindow_base_instance_get_class(context);
745     if(!cls)
746     {
747       DALI_LOG_ERROR("widget class is NULL");
748       return;
749     }
750
751     widgetInstance = static_cast<Internal::Adaptor::Widget*>(cls->data);
752     if(!widgetInstance)
753     {
754       DALI_LOG_ERROR("widget instance is NULL");
755       return;
756     }
757
758     Dali::WidgetData *widgetData = widgetInstance->FindWidgetData( instanceId );
759     if(!widgetData)
760     {
761       DALI_LOG_ERROR("widget extra is NULL");
762       return;
763     }
764
765     char* widgetContent = widgetData->GetContent();
766     if(widgetContent)
767     {
768       bundle_add_str(bundleData, AUL_K_WIDGET_CONTENT_INFO, widgetContent);
769     }
770     else
771     {
772       bundle_add_str(bundleData, AUL_K_WIDGET_CONTENT_INFO, "");
773     }
774   }
775
776   /**
777    * Called by AppCore when the application is launched from another module (e.g. homescreen).
778    * @param[in] b the bundle data which the launcher module sent
779    */
780   static int WidgetAppControl(bundle* bundleData, void *data)
781   {
782     char *classId = NULL;
783     char *id = NULL;
784     char *operation = NULL;
785
786     appcore_multiwindow_base_on_control(bundleData);
787
788     bundle_get_str(bundleData, AUL_K_WIDGET_ID, &classId);
789     bundle_get_str(bundleData, AUL_K_WIDGET_INSTANCE_ID, &id);
790     bundle_get_str(bundleData, "__WIDGET_OP__", &operation);
791
792     if(!operation)
793     {
794       DALI_LOG_ERROR("operation is NULL");
795       return 0;
796     }
797
798     if(strcmp(operation, "create") == 0)
799     {
800       InstanceCreate( classId, id, bundleData );
801     }
802     else if (strcmp(operation, "resize") == 0)
803     {
804       InstanceResize( classId, id, bundleData );
805     }
806     else if (strcmp(operation, "update") == 0)
807     {
808       InstanceUpdate( classId, id, bundleData );
809     }
810     else if (strcmp(operation, "destroy") == 0)
811     {
812       InstanceDestroy( classId, id, bundleData, data );
813     }
814     else if (strcmp(operation, "resume") == 0)
815     {
816       InstanceResume( classId, id, bundleData );
817     }
818     else if (strcmp(operation, "pause") == 0)
819     {
820       InstancePause( classId, id, bundleData );
821     }
822     else if (strcmp(operation, "terminate") == 0)
823     {
824       InstanceDestroy( classId, id, bundleData, data );
825     }
826
827     return 0;
828   }
829
830   static void InstanceCreate(const char* classId, const char* id, bundle* bundleData)
831   {
832     appcore_multiwindow_base_instance_run(classId, id, bundle_dup(bundleData));
833   }
834
835   static void InstanceResize(const char *classId, const char *id, bundle *bundleData)
836   {
837     appcore_multiwindow_base_instance_h context;
838     Internal::Adaptor::Widget *widgetInstance;
839     const appcore_multiwindow_base_class *cls;
840     char *remain = NULL;
841     char *widthStr = NULL;
842     char *heightStr = NULL;
843     uint32_t width = 0;
844     uint32_t height = 0;
845
846     context = appcore_multiwindow_base_instance_find(id);
847
848     if(!context)
849     {
850       DALI_LOG_ERROR("context not found: %s", id);
851       return;
852     }
853
854     cls = appcore_multiwindow_base_instance_get_class(context);
855     if(!cls)
856     {
857       DALI_LOG_ERROR("widget class is NULL");
858       return;
859     }
860
861     widgetInstance = static_cast<Internal::Adaptor::Widget*>(cls->data);
862     if(!widgetInstance)
863     {
864       DALI_LOG_ERROR("widget instance is NULL");
865       return;
866     }
867
868     bundle_get_str(bundleData, "__WIDGET_WIDTH__", &widthStr);
869     bundle_get_str(bundleData, "__WIDGET_HEIGHT__", &heightStr);
870
871     if(widthStr)
872       width = static_cast<uint32_t>(g_ascii_strtoll(widthStr, &remain, 10));
873
874     if(heightStr)
875       height = static_cast<uint32_t>(g_ascii_strtoll(heightStr, &remain, 10));
876
877     widgetInstance->OnResize( context, Dali::Widget::WindowSize(width,height) );
878   }
879
880   static void InstanceUpdate(const char* classId, const char* id, bundle* bundleData)
881   {
882     appcore_multiwindow_base_instance_h context;
883
884     if(!id)
885     {
886       appcore_multiwindow_base_instance_foreach(classId, UpdateCallback, bundleData);
887       return;
888     }
889
890     context = appcore_multiwindow_base_instance_find(id);
891
892     if(!context)
893     {
894       DALI_LOG_ERROR("context not found: %s", id);
895       return;
896     }
897
898     UpdateCallback(classId, id, context, bundleData);
899   }
900
901   static void UpdateCallback(const char* classId, const char* id, appcore_multiwindow_base_instance_h context, void* data)
902   {
903     Internal::Adaptor::Widget *widgetInstance;
904     const appcore_multiwindow_base_class *cls;
905     bundle* content = NULL;
906     char* contentRaw = NULL;
907     char* forceStr = NULL;
908     int force;
909     bundle* bundleData = static_cast<bundle*>(data);
910
911     if(!bundleData)
912     {
913       DALI_LOG_ERROR("bundle is NULL");
914       return;
915     }
916
917     cls = appcore_multiwindow_base_instance_get_class(context);
918     if(!cls)
919     {
920       DALI_LOG_ERROR("class is NULL");
921       return;
922     }
923
924     widgetInstance = static_cast<Internal::Adaptor::Widget*>(cls->data);
925     if(!widgetInstance)
926     {
927       DALI_LOG_ERROR("widget instance is NULL");
928       return;
929     }
930
931     bundle_get_str(bundleData, "__WIDGET_FORCE__", &forceStr);
932
933     if(forceStr && strcmp(forceStr, "true") == 0)
934     {
935       force = 1;
936     }
937     else
938     {
939       force = 0;
940     }
941
942     bundle_get_str(bundleData, "__WIDGET_CONTENT_INFO__", &contentRaw);
943
944     if(contentRaw)
945     {
946 #pragma GCC diagnostic push
947 #pragma GCC diagnostic ignored "-Wold-style-cast"
948       content = bundle_decode((const bundle_raw *)contentRaw, strlen(contentRaw));
949 #pragma GCC diagnostic pop
950
951     }
952
953     widgetInstance->OnUpdate(context, content, force);
954
955     if(content)
956     {
957       bundle_free(content);
958     }
959   }
960
961   static void InstanceDestroy(const char* classId, const char* id, bundle* bundleData, void* data)
962   {
963     appcore_multiwindow_base_instance_h context;
964
965     Internal::Adaptor::Widget *widgetInstance;
966     const appcore_multiwindow_base_class *cls;
967
968     context = appcore_multiwindow_base_instance_find(id);
969
970     if(!context)
971     {
972       DALI_LOG_ERROR("could not find widget obj: %s, clear amd info", id);
973       aul_widget_instance_del(classId, id);
974       return;
975     }
976
977     cls = appcore_multiwindow_base_instance_get_class(context);
978     if(!cls)
979     {
980       DALI_LOG_ERROR("widget class is NULL");
981       return;
982     }
983
984     widgetInstance = static_cast<Internal::Adaptor::Widget*>(cls->data);
985     if(!widgetInstance)
986     {
987       DALI_LOG_ERROR("widget instance is NULL");
988       return;
989     }
990
991     Dali::WidgetData *widgetData  = widgetInstance->FindWidgetData(id);
992
993     widgetData->SetArgs( bundleData );
994     appcore_multiwindow_base_instance_exit(context);
995     CheckEmptyInstance(data);
996   }
997
998   static void CheckEmptyInstance(void* data)
999   {
1000     int cnt = appcore_multiwindow_base_instance_get_cnt();
1001
1002     if(cnt == 0)
1003     {
1004       static_cast<Internal::Adaptor::Framework::Impl*>(data)->AppWidgetExit();
1005     }
1006   }
1007
1008   static void InstanceResume(const char* classId, const char* id, bundle* bundleData)
1009   {
1010     appcore_multiwindow_base_instance_h context;
1011
1012     context = appcore_multiwindow_base_instance_find(id);
1013
1014     if(!context)
1015     {
1016       DALI_LOG_ERROR("context not found: %s", id);
1017       return;
1018     }
1019
1020     appcore_multiwindow_base_instance_resume(context);
1021
1022     SendUpdateStatus(classId, id, AUL_WIDGET_INSTANCE_EVENT_RESUME, NULL);
1023     if(!gForegroundState)
1024     {
1025       aul_send_app_status_change_signal(getpid(), gAppId, gPackageId, "fg", "widgetapp" );
1026       gForegroundState = true;
1027     }
1028   }
1029
1030   static void InstancePause(const char* classId, const char* id, bundle* bundleData)
1031   {
1032     appcore_multiwindow_base_instance_h context;
1033
1034     context = appcore_multiwindow_base_instance_find(id);
1035
1036     if(!context)
1037     {
1038       DALI_LOG_ERROR("context not found: %s", id);
1039       return;
1040     }
1041
1042     appcore_multiwindow_base_instance_pause(context);
1043
1044     if(gForegroundState)
1045     {
1046       aul_send_app_status_change_signal(getpid(), gAppId, gPackageId, "bg", "widgetapp" );
1047       gForegroundState = false;
1048     }
1049   }
1050
1051   static bool IsWidgetFeatureEnabled()
1052   {
1053     static bool feature = false;
1054     static bool retrieved = false;
1055     int ret;
1056
1057     if(retrieved == true)
1058       return feature;
1059
1060     ret = system_info_get_platform_bool("http://tizen.org/feature/shell.appwidget", &feature);
1061     if(ret != SYSTEM_INFO_ERROR_NONE)
1062     {
1063       DALI_LOG_ERROR("failed to get system info"); /* LCOV_EXCL_LINE */
1064       return false; /* LCOV_EXCL_LINE */
1065     }
1066
1067     retrieved = true;
1068     return feature;
1069   }
1070
1071
1072 #ifdef APPCORE_WATCH_AVAILABLE
1073   static bool WatchAppCreate(int width, int height, void *data)
1074   {
1075     return static_cast<Framework*>(data)->Create();
1076   }
1077
1078   static void WatchAppTimeTick(watch_time_h time, void *data)
1079   {
1080     Observer *observer = &static_cast<Framework*>(data)->mObserver;
1081     WatchTime curTime(time);
1082
1083     observer->OnTimeTick(curTime);
1084   }
1085
1086   static void WatchAppAmbientTick(watch_time_h time, void *data)
1087   {
1088     Observer *observer = &static_cast<Framework*>(data)->mObserver;
1089     WatchTime curTime(time);
1090
1091     observer->OnAmbientTick(curTime);
1092   }
1093
1094   static void WatchAppAmbientChanged(bool ambient, void *data)
1095   {
1096     Observer *observer = &static_cast<Framework*>(data)->mObserver;
1097
1098     observer->OnAmbientChanged(ambient);
1099   }
1100
1101   static void WatchAppLanguageChanged(app_event_info_h event, void *data)
1102   {
1103     Observer *observer = &static_cast<Framework*>(data)->mObserver;
1104
1105     observer->OnLanguageChanged();
1106   }
1107
1108   static void WatchAppRegionChanged(app_event_info_h event, void *data)
1109   {
1110     Observer *observer = &static_cast<Framework*>(data)->mObserver;
1111
1112     observer->OnRegionChanged();
1113   }
1114
1115   static void WatchAppBatteryLow(app_event_info_h event, void *data)
1116   {
1117     Observer *observer = &static_cast<Framework*>(data)->mObserver;
1118
1119     observer->OnBatteryLow();
1120   }
1121
1122   static void WatchAppMemoryLow(app_event_info_h event, void *data)
1123   {
1124     Observer *observer = &static_cast<Framework*>(data)->mObserver;
1125
1126     observer->OnMemoryLow();
1127   }
1128
1129   static void WatchAppControl(app_control_h app_control, void *data)
1130   {
1131     Framework* framework = static_cast<Framework*>(data);
1132     Observer *observer = &framework->mObserver;
1133     bundle *bundleData = NULL;
1134
1135     app_control_to_bundle(app_control, &bundleData);
1136     ProcessBundle(framework, bundleData);
1137
1138     observer->OnReset();
1139     observer->OnAppControl(app_control);
1140   }
1141
1142   static void WatchAppTerminate(void *data)
1143   {
1144     Observer *observer = &static_cast<Framework*>(data)->mObserver;
1145
1146     observer->OnTerminate();
1147   }
1148
1149   static void WatchAppPause(void *data)
1150   {
1151     Observer *observer = &static_cast<Framework*>(data)->mObserver;
1152
1153     observer->OnPause();
1154   }
1155
1156   static void WatchAppResume(void *data)
1157   {
1158     Observer *observer = &static_cast<Framework*>(data)->mObserver;
1159
1160     observer->OnResume();
1161   }
1162 #endif
1163
1164   int AppWatchMain()
1165   {
1166     int ret = true;
1167
1168 #ifdef APPCORE_WATCH_AVAILABLE
1169     mWatchCallback.create = WatchAppCreate;
1170     mWatchCallback.app_control = WatchAppControl;
1171     mWatchCallback.terminate = WatchAppTerminate;
1172     mWatchCallback.pause = WatchAppPause;
1173     mWatchCallback.resume = WatchAppResume;
1174     mWatchCallback.time_tick = WatchAppTimeTick;
1175     mWatchCallback.ambient_tick = WatchAppAmbientTick;
1176     mWatchCallback.ambient_changed = WatchAppAmbientChanged;
1177
1178     watch_app_add_event_handler(&watchHandlers[APP_EVENT_LOW_BATTERY], APP_EVENT_LOW_BATTERY, WatchAppBatteryLow, mFramework);
1179     watch_app_add_event_handler(&watchHandlers[APP_EVENT_LOW_MEMORY], APP_EVENT_LOW_MEMORY, WatchAppMemoryLow, mFramework);
1180     watch_app_add_event_handler(&watchHandlers[APP_EVENT_LANGUAGE_CHANGED], APP_EVENT_LANGUAGE_CHANGED, WatchAppLanguageChanged, mFramework);
1181     watch_app_add_event_handler(&watchHandlers[APP_EVENT_REGION_FORMAT_CHANGED], APP_EVENT_REGION_FORMAT_CHANGED, WatchAppRegionChanged, mFramework);
1182
1183     ret = watch_app_main(*mFramework->mArgc, *mFramework->mArgv, &mWatchCallback, mFramework);
1184 #endif
1185     return ret;
1186   }
1187
1188   void AppWatchExit()
1189   {
1190 #ifdef APPCORE_WATCH_AVAILABLE
1191     watch_app_exit();
1192 #endif
1193   }
1194
1195
1196 private:
1197   // Undefined
1198   Impl( const Impl& impl );
1199
1200   // Undefined
1201   Impl& operator=( const Impl& impl );
1202 };
1203
1204 Framework::Framework( Framework::Observer& observer, int *argc, char ***argv, Type type )
1205 : mObserver(observer),
1206   mInitialised(false),
1207   mRunning(false),
1208   mArgc(argc),
1209   mArgv(argv),
1210   mBundleName(""),
1211   mBundleId(""),
1212   mAbortHandler( MakeCallback( this, &Framework::AbortCallback ) ),
1213   mImpl(NULL)
1214 {
1215   bool featureFlag = true;
1216   system_info_get_platform_bool( "tizen.org/feature/opengles.version.2_0", &featureFlag );
1217
1218   if( featureFlag == false )
1219   {
1220     set_last_result( TIZEN_ERROR_NOT_SUPPORTED );
1221   }
1222 #ifdef DALI_ELDBUS_AVAILABLE
1223   // Initialize ElDBus.
1224   eldbus_init();
1225 #endif
1226   InitThreads();
1227
1228   mImpl = new Impl(this, type);
1229 }
1230
1231 Framework::~Framework()
1232 {
1233   if (mRunning)
1234   {
1235     Quit();
1236   }
1237
1238 #ifdef DALI_ELDBUS_AVAILABLE
1239   // Shutdown ELDBus.
1240   eldbus_shutdown();
1241 #endif
1242
1243   delete mImpl;
1244 }
1245
1246 bool Framework::Create()
1247 {
1248   mInitialised = true;
1249   mObserver.OnInit();
1250   return true;
1251 }
1252
1253 void Framework::Run()
1254 {
1255   mRunning = true;
1256   int ret;
1257
1258   ret = mImpl->AppMain();
1259   if (ret != APP_ERROR_NONE)
1260   {
1261     DALI_LOG_ERROR("Framework::Run(), ui_app_main() is failed. err = %d\n", ret);
1262   }
1263   mRunning = false;
1264 }
1265
1266 void Framework::Quit()
1267 {
1268   mImpl->AppExit();
1269 }
1270
1271 bool Framework::IsMainLoopRunning()
1272 {
1273   return mRunning;
1274 }
1275
1276 void Framework::AddAbortCallback( CallbackBase* callback )
1277 {
1278   mImpl->mAbortCallBack = callback;
1279 }
1280
1281 std::string Framework::GetBundleName() const
1282 {
1283   return mBundleName;
1284 }
1285
1286 void Framework::SetBundleName(const std::string& name)
1287 {
1288   mBundleName = name;
1289 }
1290
1291 std::string Framework::GetBundleId() const
1292 {
1293   return mBundleId;
1294 }
1295
1296 std::string Framework::GetResourcePath()
1297 {
1298   std::string resourcePath = "";
1299 #if defined( TIZEN_PLATFORM_CONFIG_SUPPORTED ) && TIZEN_PLATFORM_CONFIG_SUPPORTED
1300   resourcePath = app_get_resource_path();
1301 #else // For backwards compatibility with older Tizen versions
1302
1303   // "DALI_APPLICATION_PACKAGE" is used to get the already configured Application package path.
1304   const char* environmentVariable = "DALI_APPLICATION_PACKAGE";
1305   char* value = getenv( environmentVariable );
1306   if ( value != NULL )
1307   {
1308     resourcePath = value;
1309   }
1310 #endif //TIZEN_PLATFORM_CONFIG_SUPPORTED
1311
1312   return resourcePath;
1313 }
1314
1315 void Framework::SetBundleId(const std::string& id)
1316 {
1317   mBundleId = id;
1318 }
1319
1320 void Framework::AbortCallback( )
1321 {
1322   // if an abort call back has been installed run it.
1323   if (mImpl->mAbortCallBack)
1324   {
1325     CallbackBase::Execute( *mImpl->mAbortCallBack );
1326   }
1327   else
1328   {
1329     Quit();
1330   }
1331 }
1332
1333 } // namespace Adaptor
1334
1335 } // namespace Internal
1336
1337 } // namespace Dali