Refactor appcore-widget
[platform/core/appfw/appcore-widget.git] / src / efl_base / widget_app.cc
1 /*
2 * Copyright (c) 2015 - 2021 Samsung Electronics Co., Ltd All Rights Reserved
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 #include <Elementary.h>
18 #include <app_event_internal.hh>
19 #include <aul.h>
20 #include <aul_app_com.h>
21 #include <aul_widget.h>
22 #include <dlog.h>
23 #include <glib.h>
24 #include <stdlib.h>
25 #include <system_info.h>
26 #include <widget_errno.h>
27 #include <widget_instance.h>
28
29 #include "common/export_private.hh"
30 #include "common/log_private.hh"
31 #include "include/widget_app.h"
32 #include "include/widget_app_internal.h"
33 #include "include/widget_base.hh"
34
35 using namespace tizen_cpp;
36 namespace {
37
38 constexpr const int kIconifyTimeout = 500;
39 constexpr const char kFeatureShellAppWidget[] =
40     "http://tizen.org/feature/shell.appwidget";
41 constexpr int APP_EVENT_MAX = 7;
42 constexpr IAppCore::IEvent::Type __app_event_converter[APP_EVENT_MAX] = {
43   [APP_EVENT_LOW_MEMORY] = IAppCore::IEvent::Type::LOW_MEMORY,
44   [APP_EVENT_LOW_BATTERY] = IAppCore::IEvent::Type::LOW_BATTERY,
45   [APP_EVENT_LANGUAGE_CHANGED] = IAppCore::IEvent::Type::LANG_CHANGE,
46   [APP_EVENT_DEVICE_ORIENTATION_CHANGED]
47       = IAppCore::IEvent::Type::DEVICE_ORIENTATION_CHANGED,
48   [APP_EVENT_REGION_FORMAT_CHANGED] = IAppCore::IEvent::Type::REGION_CHANGE,
49   [APP_EVENT_SUSPENDED_STATE_CHANGED]
50       = IAppCore::IEvent::Type::SUSPENDED_STATE_CHANGE,
51 };
52
53 class AppWidget : public WidgetBase {
54  public:
55   AppWidget(widget_app_lifecycle_callback_s* callback, void* user_data)
56       : callback_(callback), user_data_(user_data) {}
57
58   int OnCreate() override {
59     WidgetBase::OnCreate();
60     if (callback_ && callback_->create) {
61       if (callback_->create(user_data_) == nullptr) {
62         _E("Failed to create widget");
63         return -1;
64       }
65
66       _D("Widget app is created");
67       aul_widget_write_log(LOG_TAG, "[%s:%d]", __FUNCTION__, __LINE__);
68       return 0;
69     }
70
71     return -1;
72   }
73
74   int OnTerminate() override {
75     if (callback_ && callback_->terminate) {
76       callback_->terminate(user_data_);
77       WidgetBase::OnTerminate();
78       _D("Widget app is terminated");
79       aul_widget_write_log(LOG_TAG, "[%s:%d]", __FUNCTION__, __LINE__);
80       return 0;
81     }
82
83     WidgetBase::OnTerminate();
84     return -1;
85   }
86
87   void OnLoopInit(int argc, char** argv) override {
88     elm_init(argc, argv);
89   }
90
91   void OnLoopFinish() override {
92     elm_shutdown();
93   }
94
95   void OnLoopRun() override {
96     elm_run();
97   }
98
99   void OnLoopExit() override {
100     elm_exit();
101   }
102
103   int OnTrimMemory() override {
104     _D("Trim memory");
105     elm_cache_all_flush();
106     return WidgetBase::OnTrimMemory();
107   }
108
109  private:
110   widget_app_lifecycle_callback_s* callback_;
111   void* user_data_;
112 };
113
114 class AppWidgetContext : public WidgetContext {
115  public:
116   class Factory : public AppCoreMultiWindowBase::Context::IFactory {
117    public:
118     Factory(std::string widget_id,
119         widget_instance_lifecycle_callback_s callback, void* user_data)
120         : widget_id_(std::move(widget_id)),
121           callback_(callback),
122           user_data_(user_data) {
123     }
124
125     std::unique_ptr<Context> Create(std::string inst_id,
126         AppCoreMultiWindowBase* app) override {
127       return std::unique_ptr<Context>(
128           new AppWidgetContext(widget_id_, std::move(inst_id), app,
129               callback_, user_data_));
130     }
131
132    private:
133     std::string widget_id_;
134     widget_instance_lifecycle_callback_s callback_;
135     void* user_data_;
136   };
137
138   AppWidgetContext(std::string context_id, std::string inst_id,
139       AppCoreMultiWindowBase* app,
140       widget_instance_lifecycle_callback_s callback, void* user_data)
141       : WidgetContext(std::move(context_id), std::move(inst_id), app),
142           callback_(callback), user_data_(user_data) {}
143
144   bool OnCreate(const tizen_base::Bundle& contents, int w, int h) override {
145     int ret = -1;
146     if (callback_.create) {
147       ret = callback_.create(reinterpret_cast<widget_context_h>(this),
148           contents.GetHandle(), w, h, user_data_);
149       aul_widget_write_log(LOG_TAG, "[%s:%d]  ret : %d",
150           __FUNCTION__, __LINE__, ret);
151     }
152
153     return ret == 0;
154   }
155
156   void OnDestroy(DestroyType reason,
157       const tizen_base::Bundle& contents) override {
158     if (callback_.destroy) {
159       callback_.destroy(reinterpret_cast<widget_context_h>(this),
160           reason == DestroyType::PERMANENT ? WIDGET_APP_DESTROY_TYPE_PERMANENT :
161           WIDGET_APP_DESTROY_TYPE_TEMPORARY, contents.GetHandle(), user_data_);
162       aul_widget_write_log(LOG_TAG, "[%s:%d]", __FUNCTION__, __LINE__);
163     }
164
165     UnsetIconifyTimer();
166   }
167
168   void OnPause() override {
169     UnsetIconifyTimer();
170     SetIconifyTimer();
171
172     WidgetContext::OnPause();
173     if (callback_.pause) {
174       callback_.pause(reinterpret_cast<widget_context_h>(this), user_data_);
175     }
176   }
177
178   void OnResume() override {
179     UnsetIconifyTimer();
180
181     if (is_iconified_) {
182       Ecore_Wl2_Window* win = ecore_evas_wayland2_window_get(
183           ecore_evas_ecore_evas_get(evas_object_evas_get(win_)));
184       if (win) {
185         ecore_wl2_window_iconified_set(win, EINA_FALSE);
186         is_iconified_ = false;
187         _D("Set iconify false");
188       }
189     }
190
191     WidgetContext::OnResume();
192     if (callback_.resume) {
193       callback_.resume(reinterpret_cast<widget_context_h>(this), user_data_);
194     }
195   }
196
197   void OnResize(int w, int h) override {
198     WidgetContext::OnResize(w, h);
199
200     if (win_)
201       evas_object_resize(win_, w, h);
202     else
203       _E("Failed to find window");
204
205     if (callback_.resize) {
206       callback_.resize(reinterpret_cast<widget_context_h>(this),
207           w, h, user_data_);
208     }
209   }
210
211   void OnUpdate(const tizen_base::Bundle& contents, bool force) override {
212     WidgetContext::OnUpdate(contents, force);
213     if (callback_.update) {
214       callback_.update(reinterpret_cast<widget_context_h>(this),
215           contents.GetHandle(), force, user_data_);
216     }
217   }
218
219   void SetTag(void* tag) {
220     tag_ = tag;
221   }
222
223   void* GetTag() const {
224     return tag_;
225   }
226
227   Evas_Object* GetWindow() const {
228     return win_;
229   }
230
231   void SetWindow(Evas_Object* win) {
232     win_ = win;
233   }
234
235  private:
236   void SetIconifyTimer() {
237     if (iconify_timer_)
238       return;
239
240     iconify_timer_ = g_timeout_add(kIconifyTimeout,
241         [](gpointer user_data) -> gboolean{
242           AppWidgetContext* cxt = static_cast<AppWidgetContext*>(user_data);
243           Ecore_Wl2_Window* win = ecore_evas_wayland2_window_get(
244               ecore_evas_ecore_evas_get(evas_object_evas_get(cxt->win_)));
245           if (win) {
246             ecore_wl2_window_iconified_set(win, EINA_TRUE);
247             cxt->is_iconified_ = true;
248             _D("Set iconify true");
249           }
250
251           cxt->iconify_timer_ = 0;
252           return G_SOURCE_REMOVE;
253         }, this);
254   }
255
256   void UnsetIconifyTimer() {
257     if (iconify_timer_) {
258       g_source_remove(iconify_timer_);
259       iconify_timer_ = 0;
260     }
261   }
262
263  private:
264   widget_instance_lifecycle_callback_s callback_;
265   void* user_data_;
266   Evas_Object* win_ = nullptr;
267   guint iconify_timer_ = 0;
268   bool is_iconified_ = false;
269   void* tag_ = nullptr;
270 };
271
272 std::unique_ptr<AppWidget> __app_widget;
273 std::list<std::shared_ptr<AppEvent>> __pending_app_events;
274
275 }  // namespace
276
277 API int widget_app_main(int argc, char** argv,
278     widget_app_lifecycle_callback_s* callback, void* user_data) {
279   bool feature;
280   int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
281   if (ret < 0)
282     return WIDGET_ERROR_FAULT;
283
284   if (!feature)
285     return WIDGET_ERROR_NOT_SUPPORTED;
286
287   if (argc <= 0 || argv == nullptr || callback == nullptr) {
288     _E("Invalid parameter");
289     return WIDGET_ERROR_INVALID_PARAMETER;
290   }
291
292   if (callback->create == nullptr) {
293     _E("widget_app_create_cb() callback must be registered");
294     return WIDGET_ERROR_INVALID_PARAMETER;
295   }
296
297   try {
298     __app_widget = std::make_unique<AppWidget>(callback, user_data);
299     for (auto& i : __pending_app_events)
300       __app_widget->AddEvent(i);
301
302     __app_widget->Run(argc, argv);
303   } catch (std::runtime_error& e) {
304     return WIDGET_ERROR_FAULT;
305   }
306
307   return WIDGET_ERROR_NONE;
308 }
309
310 API int widget_app_exit(void) {
311   bool feature;
312   int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
313   if (ret < 0)
314     return WIDGET_ERROR_FAULT;
315
316   if (!feature)
317     return WIDGET_ERROR_NOT_SUPPORTED;
318
319   if (__app_widget.get() == nullptr)
320     return WIDGET_ERROR_FAULT;
321
322   __app_widget->Exit();
323   return WIDGET_ERROR_NONE;
324 }
325
326 API int widget_app_terminate_context(widget_context_h context) {
327   bool feature;
328   int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
329   if (ret < 0)
330     return WIDGET_ERROR_FAULT;
331
332   if (!feature)
333     return WIDGET_ERROR_NOT_SUPPORTED;
334
335   if (context == nullptr) {
336     _E("Invalid parameter");
337     return WIDGET_ERROR_INVALID_PARAMETER;
338   }
339
340   auto* cxt = reinterpret_cast<AppWidgetContext*>(context);
341   cxt->ExitAsync();
342   return WIDGET_ERROR_NONE;
343 }
344
345 API int widget_app_foreach_context(widget_context_cb cb, void* data) {
346   bool feature;
347   int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
348   if (ret < 0)
349     return WIDGET_ERROR_FAULT;
350
351   if (!feature)
352     return WIDGET_ERROR_NOT_SUPPORTED;
353
354   if (cb == nullptr) {
355     _E("Invalid parameter");
356     return WIDGET_ERROR_INVALID_PARAMETER;
357   }
358
359   if (__app_widget.get() == nullptr)
360     return WIDGET_ERROR_FAULT;
361
362   auto l = __app_widget->GetContexts();
363   for (auto& i : l) {
364     if (!cb(reinterpret_cast<widget_context_h>(i.get()), data))
365       break;
366   }
367
368   return WIDGET_ERROR_NONE;
369 }
370
371 API int widget_app_add_event_handler(app_event_handler_h* event_handler,
372     app_event_type_e event_type, app_event_cb callback, void* user_data) {
373   bool feature;
374   int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
375   if (ret < 0)
376     return WIDGET_ERROR_FAULT;
377
378   if (!feature)
379     return WIDGET_ERROR_NOT_SUPPORTED;
380
381   if (event_handler == nullptr || callback == nullptr)
382     return WIDGET_ERROR_INVALID_PARAMETER;
383
384   if (event_type < APP_EVENT_LOW_MEMORY ||
385       event_type > APP_EVENT_REGION_FORMAT_CHANGED)
386     return WIDGET_ERROR_INVALID_PARAMETER;
387
388   if (event_type == APP_EVENT_DEVICE_ORIENTATION_CHANGED)
389     return WIDGET_ERROR_NOT_SUPPORTED;
390
391   auto* app_event = new (std::nothrow) AppEvent(
392       ::__app_event_converter[event_type], callback, user_data);
393   if (app_event == nullptr) {
394     _E("Out of memory");
395     return WIDGET_ERROR_OUT_OF_MEMORY;
396   }
397
398   auto* h = new (std::nothrow) std::shared_ptr<AppEvent>(app_event);
399   if (h == nullptr) {
400     _E("Out of memory");
401     delete app_event;
402     return WIDGET_ERROR_OUT_OF_MEMORY;
403   }
404
405   if (__app_widget.get() != nullptr)
406     __app_widget->AddEvent(*h);
407   else
408     __pending_app_events.push_back(*h);
409
410   *event_handler = reinterpret_cast<app_event_handler_h>(h);
411   return WIDGET_ERROR_NONE;
412 }
413
414 API int widget_app_remove_event_handler(app_event_handler_h event_handler) {
415   bool feature;
416   int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
417   if (ret < 0)
418     return WIDGET_ERROR_FAULT;
419
420   if (!feature)
421     return WIDGET_ERROR_NOT_SUPPORTED;
422
423   if (event_handler == nullptr)
424     return WIDGET_ERROR_INVALID_PARAMETER;
425
426   auto* h = reinterpret_cast<std::shared_ptr<AppEvent>*>(event_handler);
427
428   if (__app_widget.get() != nullptr) {
429     if (!__app_widget->RemoveEvent(*h))
430       return WIDGET_ERROR_INVALID_PARAMETER;
431   } else {
432     __pending_app_events.remove(*h);
433   }
434
435   delete h;
436   return WIDGET_ERROR_NONE;
437 }
438
439 API const char* widget_app_get_id(widget_context_h context) {
440   bool feature;
441   int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
442   if (ret < 0) {
443     set_last_result(WIDGET_ERROR_FAULT);
444     return nullptr;
445   }
446
447   if (!feature) {
448     set_last_result(WIDGET_ERROR_NOT_SUPPORTED);
449     return nullptr;
450   }
451
452   if (context == nullptr) {
453     set_last_result(WIDGET_ERROR_INVALID_PARAMETER);
454     return nullptr;
455   }
456
457   auto* cxt = reinterpret_cast<AppWidgetContext*>(context);
458   const std::string& id = cxt->GetInstId();
459   set_last_result(WIDGET_ERROR_NONE);
460   return id.c_str();
461 }
462
463 API int widget_app_get_elm_win(widget_context_h context, Evas_Object** win) {
464   bool feature;
465   int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
466   if (ret < 0)
467     return WIDGET_ERROR_FAULT;
468
469   if (!feature)
470     return WIDGET_ERROR_NOT_SUPPORTED;
471
472   if (context == nullptr || win == nullptr) {
473     _E("Invalid parameter");
474     return WIDGET_ERROR_INVALID_PARAMETER;
475   }
476
477   auto* cxt = reinterpret_cast<AppWidgetContext*>(context);
478   const std::string& id = cxt->GetInstId();
479
480   Evas_Object* ret_win = elm_win_add(nullptr, id.c_str(), ELM_WIN_BASIC);
481   if (ret_win == nullptr) {
482     _E("Failed to create window");
483     return WIDGET_ERROR_FAULT;
484   }
485
486   elm_win_wm_rotation_preferred_rotation_set(ret_win, -1);
487   int rots[3] = { 0, };
488   elm_win_wm_rotation_available_rotations_set(ret_win, rots, 1);
489
490   Ecore_Wl2_Window* wl_win = ecore_evas_wayland2_window_get(
491       ecore_evas_ecore_evas_get(evas_object_evas_get(ret_win)));
492   if (wl_win == nullptr) {
493     _E("Failed to get wayland window");
494     evas_object_del(ret_win);
495     return WIDGET_ERROR_FAULT;
496   }
497
498   ecore_wl2_window_class_set(wl_win, id.c_str());
499   elm_win_aux_hint_add(ret_win, "wm.policy.win.user.geometry", "1");
500   cxt->WindowBind(id, wl_win);
501
502   /* Set data to use in accessibility */
503   std::string plug_id = id + ":" + std::to_string(getpid());
504   evas_object_data_set(ret_win, "___PLUGID", strdup(plug_id.c_str()));
505   evas_object_event_callback_add(ret_win, EVAS_CALLBACK_DEL,
506       [](void *data, Evas *e, Evas_Object *obj, void *event_info) {
507         char* plug_id = static_cast<char*>(
508             evas_object_data_del(obj, "___PLUGID"));
509         free(plug_id);
510       }, nullptr);
511
512   int win_id = ecore_wl2_window_id_get(wl_win);
513   _D("Window created: %d", win_id);
514
515   cxt->SetWindow(ret_win);
516   *win = ret_win;
517   return WIDGET_ERROR_NONE;
518 }
519
520 API widget_class_h widget_app_class_add(widget_class_h widget_class,
521     const char* class_id, widget_instance_lifecycle_callback_s callback,
522     void* user_data) {
523   bool feature;
524   int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
525   if (ret < 0) {
526     set_last_result(WIDGET_ERROR_FAULT);
527     return nullptr;
528   }
529
530   if (!feature) {
531     set_last_result(WIDGET_ERROR_NOT_SUPPORTED);
532     return nullptr;
533   }
534
535   if (class_id == nullptr || callback.create == nullptr) {
536     _E("Invalid parameter");
537     set_last_result(WIDGET_ERROR_INVALID_PARAMETER);
538     return nullptr;
539   }
540
541   if (__app_widget.get() == nullptr) {
542     set_last_result(WIDGET_ERROR_FAULT);
543     return nullptr;
544   }
545
546   auto factory = std::shared_ptr<AppCoreMultiWindowBase::Context::IFactory>(
547       new (std::nothrow) AppWidgetContext::Factory(
548           class_id, callback, user_data));
549   if (factory.get() == nullptr) {
550     set_last_result(WIDGET_ERROR_OUT_OF_MEMORY);
551     return nullptr;
552   }
553
554   __app_widget->AddContextFactory(std::move(factory), class_id);
555   set_last_result(WIDGET_ERROR_NONE);
556   int dummy;
557   widget_class_h cls = reinterpret_cast<widget_class_h>(&dummy);
558   return cls;
559 }
560
561 API widget_class_h widget_app_class_create(
562     widget_instance_lifecycle_callback_s callback, void* user_data) {
563   bool feature;
564   int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
565   if (ret < 0) {
566     set_last_result(WIDGET_ERROR_FAULT);
567     return nullptr;
568   }
569
570   if (!feature) {
571     set_last_result(WIDGET_ERROR_NOT_SUPPORTED);
572     return nullptr;
573   }
574
575   if (callback.create == nullptr) {
576     _E("Invalid parameter");
577     set_last_result(WIDGET_ERROR_INVALID_PARAMETER);
578     return nullptr;
579   }
580
581   char* appid = nullptr;
582   app_get_id(&appid);
583   if (appid == nullptr) {
584     LOGE("app_get_id() is failed");
585     return nullptr;
586   }
587   std::unique_ptr<char, decltype(std::free)*> ptr(appid, std::free);
588
589   return static_cast<widget_class_h>(
590       widget_app_class_add(nullptr, appid, callback, user_data));
591 }
592
593 API int widget_app_context_set_tag(widget_context_h context, void* tag) {
594   bool feature;
595   int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
596   if (ret < 0)
597     return WIDGET_ERROR_FAULT;
598
599   if (!feature)
600     return WIDGET_ERROR_NOT_SUPPORTED;
601
602   if (context == nullptr) {
603     _E("Invalid parameter");
604     return WIDGET_ERROR_INVALID_PARAMETER;
605   }
606
607   auto* cxt = reinterpret_cast<AppWidgetContext*>(context);
608   cxt->SetTag(tag);
609   return WIDGET_ERROR_NONE;
610 }
611
612 API int widget_app_context_get_tag(widget_context_h context, void** tag) {
613   bool feature;
614   int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
615   if (ret < 0)
616     return WIDGET_ERROR_FAULT;
617
618   if (!feature)
619     return WIDGET_ERROR_NOT_SUPPORTED;
620
621   if (context == nullptr || tag == nullptr) {
622     _E("Invalid parameter");
623     return WIDGET_ERROR_INVALID_PARAMETER;
624   }
625
626   auto* cxt = reinterpret_cast<AppWidgetContext*>(context);
627   *tag = cxt->GetTag();
628   return WIDGET_ERROR_NONE;
629 }
630
631 API int widget_app_context_set_content_info(widget_context_h context,
632     bundle* content_info) {
633   bool feature;
634   int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
635   if (ret < 0)
636     return WIDGET_ERROR_FAULT;
637
638   if (!feature)
639     return WIDGET_ERROR_NOT_SUPPORTED;
640
641   if (context == nullptr || content_info == nullptr) {
642     _E("Invalid parameter");
643     return WIDGET_ERROR_INVALID_PARAMETER;
644   }
645
646   auto* cxt = reinterpret_cast<AppWidgetContext*>(context);
647   ret = cxt->SetContents(tizen_base::Bundle(content_info));
648   if (ret != WIDGET_ERROR_NONE) {
649     _E("Failed to set content");
650     return static_cast<widget_error_e>(ret);
651   }
652
653   return WIDGET_ERROR_NONE;
654 }
655
656 API int widget_app_context_set_title(widget_context_h context,
657     const char* title) {
658   bool feature;
659   int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
660   if (ret < 0)
661     return WIDGET_ERROR_FAULT;
662
663   if (!feature)
664     return WIDGET_ERROR_NOT_SUPPORTED;
665
666   if (context == nullptr || title == nullptr) {
667     _E("Invalid parameter");
668     return WIDGET_ERROR_INVALID_PARAMETER;
669   }
670
671   auto* cxt = reinterpret_cast<AppWidgetContext*>(context);
672   if (cxt->GetWindow())
673     elm_win_title_set(cxt->GetWindow(), title);
674
675   return WIDGET_ERROR_NONE;
676 }
677
678 API int widget_app_restart(void) {
679   bool feature;
680   int ret = system_info_get_platform_bool(kFeatureShellAppWidget, &feature);
681   if (ret < 0)
682     return WIDGET_ERROR_FAULT;
683
684   if (!feature)
685     return WIDGET_ERROR_NOT_SUPPORTED;
686
687   if (__app_widget.get() == nullptr)
688     return WIDGET_ERROR_IO_ERROR;
689
690   std::string class_id;
691   auto l = __app_widget->GetContexts();
692   for (auto& i : l) {
693     class_id = i->GetContextId();
694     break;
695   }
696
697   if (class_id.empty())
698     return WIDGET_ERROR_IO_ERROR;
699
700   tizen_base::Bundle b;
701   int status = AUL_WIDGET_INSTANCE_EVENT_APP_RESTART_REQUEST;
702   std::vector<unsigned char> v;
703   auto* p = reinterpret_cast<const uint8_t*>(&status);
704   std::copy(p, p + sizeof(int), std::back_inserter(v));
705
706   b.Add(AUL_K_WIDGET_ID, class_id);
707   b.Add(AUL_K_WIDGET_STATUS, v);
708
709   std::string endpoint = __app_widget->GetViewerEndpoint();
710   ret = aul_app_com_send(endpoint.empty() ? nullptr : endpoint.c_str(),
711       b.GetHandle());
712   if (ret != AUL_R_OK) {
713     _E("Failed to send restart request");
714     return WIDGET_ERROR_IO_ERROR;
715   }
716
717   return WIDGET_ERROR_NONE;
718 }