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