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