3e4ff8f00354883b918a1343b29701188a27d5f9
[apps/agl-service-homescreen.git] / src / homescreen.cpp
1 /*
2  * Copyright (c) 2017 TOYOTA MOTOR CORPORATION
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 #ifndef _GNU_SOURCE
18 #define _GNU_SOURCE
19 #endif
20 #include <memory>
21 #include <algorithm>
22 #include <unordered_map>
23 #include <list>
24 #include "hs-helper.h"
25 #include "hs-clientmanager.h"
26 #include "hs-appinfo.h"
27 #include "hs-config.h"
28 #include <unistd.h>
29
30
31 const char _error[] = "error";
32 const char _application_id[] = "application_id";
33 const char _display_message[] = "display_message";
34 const char _reply_message[] = "reply_message";
35 const char _keyData[] = "data";
36 const char _keyId[] = "id";
37
38 struct hs_handshake {
39     hs_handshake(int times, int sleep) : m_times(times), m_sleep(sleep) {}
40     void start(afb_api_t api) const;
41
42     enum HandshakeStatus {
43         Handshake_Idle = 0,
44         Handshake_Subscribing,
45         Handshake_Subscribe_Fail,
46         Handshake_WaitEvent,
47         Handshake_Over
48     };
49     static int hs_sts;
50
51 private:
52     const std::string sub_event = "windowmanager/handshake";
53     const int m_times;
54     const int m_sleep;
55 };
56
57 int hs_handshake::hs_sts = hs_handshake::Handshake_Idle;
58
59 void handshake_subscribe_callback(struct json_object *obj, const char *error, const char *info)
60 {
61     if(error == nullptr) {
62         hs_handshake::hs_sts =  hs_handshake::Handshake_WaitEvent;
63     }
64     else {
65         hs_handshake::hs_sts =  hs_handshake::Handshake_Subscribe_Fail;
66     }
67 }
68
69 int on_handshake_event(afb_api_t api, const char *event, struct json_object *object)
70 {
71     hs_handshake::hs_sts =  hs_handshake::Handshake_Over;
72     return 1;
73 }
74
75 void hs_handshake::start(afb_api_t api) const
76 {
77     setEventHook(sub_event.c_str(), on_handshake_event);
78     int count = 0;
79     do {
80         // try to subscribe handshake event
81         if(hs_handshake::hs_sts == hs_handshake::Handshake_Idle
82         || hs_handshake::hs_sts == hs_handshake::Handshake_Subscribe_Fail) {
83             hs_handshake::hs_sts = Handshake_Subscribing;
84             HS_WmProxy *wm_proxy = new HS_WmProxy();
85             wm_proxy->subscribe(api, HS_WmProxy::Event_Handshake, handshake_subscribe_callback);
86         }
87
88         // wait handshake event
89         if(hs_handshake::hs_sts == hs_handshake::Handshake_Over) {
90             break;
91         }
92
93         ++count;
94         usleep(m_sleep*1000);
95     } while(count < m_times);
96     AFB_WARNING("wait count is %d.", count);
97 }
98
99 struct hs_instance {
100     HS_ClientManager *client_manager;   // the connection session manager
101     HS_AppInfo *app_info;               // application info
102
103     hs_instance() : client_manager(HS_ClientManager::instance()), app_info(HS_AppInfo::instance()) {}
104     int init(afb_api_t api);
105     void setEventHook(const char *event, const event_hook_func f);
106     void onEvent(afb_api_t api, const char *event, struct json_object *object);
107 private:
108     std::unordered_map<std::string, std::list<event_hook_func>> event_hook_list;
109 };
110
111 /**
112  * init function
113  *
114  * #### Parameters
115  * - api : the api serving the request
116  *
117  * #### Return
118  * 0 : init success
119  * 1 : init fail
120  *
121  */
122 int hs_instance::init(afb_api_t api)
123 {
124     if(client_manager == nullptr) {
125         AFB_ERROR("client_manager is nullptr.");
126         return -1;
127     }
128     client_manager->init();
129
130     if(app_info == nullptr) {
131         AFB_ERROR("app_info is nullptr.");
132         return -1;
133     }
134     app_info->init(api);
135
136     HS_Config hs_config;
137     if(hs_config.readConfig() < 0) {
138         AFB_ERROR("read config file failed.");
139         return -1;
140     }
141
142     // const struct handshake_info *h = hs_config.getHandshakeInfo();
143     // struct hs_handshake handshake(h->times, h->sleep);
144     // handshake.start(api);
145
146     // recover application
147
148
149     return 0;
150 }
151
152 /**
153  * set event hook
154  *
155  * #### Parameters
156  *  - event  : event name
157  *  - f : hook function
158  *
159  * #### Return
160  * Nothing
161  */
162 void hs_instance::setEventHook(const char *event, const event_hook_func f)
163 {
164     if(event == nullptr || f == nullptr) {
165         AFB_WARNING("argument is null.");
166         return;
167     }
168
169     std::string ev(event);
170     auto it = event_hook_list.find(ev);
171     if(it != event_hook_list.end()) {
172         it->second.push_back(f);
173     }
174     else {
175         std::list<event_hook_func> l;
176         l.push_back(f);
177         event_hook_list[ev] = std::move(l);
178     }
179 }
180
181 /**
182  * onEvent function
183  *
184  * #### Parameters
185  *  - api : the api serving the request
186  *  - event  : event name
187  *  - object : event json object
188  *
189  * #### Return
190  * Nothing
191  */
192 void hs_instance::onEvent(afb_api_t api, const char *event, struct json_object *object)
193 {
194     std::string ev(event);
195     auto it = event_hook_list.find(ev);
196     if(it != event_hook_list.end()) {
197         for(auto &ref : it->second) {
198             if(ref(api, event, object))
199                 break;
200         }
201     }
202 }
203
204 static struct hs_instance *g_hs_instance;
205
206 /**
207  * set event hook
208  *
209  * #### Parameters
210  *  - event  : event name
211  *  - f : hook function pointer
212  *
213  * #### Return
214  * Nothing
215  */
216 void setEventHook(const char *event, const event_hook_func f)
217 {
218     if(g_hs_instance == nullptr) {
219         AFB_ERROR("g_hs_instance is null.");
220         return;
221     }
222
223     g_hs_instance->setEventHook(event, f);
224 }
225
226 /*
227 ********** Method of HomeScreen Service (API) **********
228 */
229
230 static void pingSample(afb_req_t request)
231 {
232    static int pingcount = 0;
233    afb_req_success_f(request, json_object_new_int(pingcount), "Ping count = %d", pingcount);
234    AFB_DEBUG("Verbosity macro at level notice invoked at ping invocation count = %d", pingcount);
235    pingcount++;
236 }
237
238 /**
239  * tap_shortcut notify for homescreen
240  * When Shortcut area is tapped,  notify these applciations
241  *
242  * #### Parameters
243  * Request key
244  * - application_id   : application id
245  *
246  * #### Return
247  * None
248  *
249  */
250 static void tap_shortcut (afb_req_t request)
251 {
252     AFB_DEBUG("called.");
253     int ret = 0;
254     const char* value = afb_req_value(request, _application_id);
255     if (value) {
256         AFB_INFO("request appid = %s.", value);
257         ret = g_hs_instance->client_manager->handleRequest(request, __FUNCTION__, value);
258         if(ret == AFB_REQ_NOT_STARTED_APPLICATION) {
259             std::string id = g_hs_instance->app_info->getAppProperty(value, _keyId);
260             HS_AfmMainProxy afm_proxy;
261             afm_proxy.start(request, id);
262             ret = 0;
263         }
264     }
265     else {
266         ret = AFB_EVENT_BAD_REQUEST;
267     }
268
269     if (ret) {
270         afb_req_fail_f(request, "failed", "called %s, Unknown parameter", __FUNCTION__);
271     }
272     else {
273         struct json_object *res = json_object_new_object();
274         hs_add_object_to_json_object_func(res, __FUNCTION__, 2,
275           _error,  ret);
276         afb_req_success(request, res, "afb_event_push event [tap_shortcut]");
277     }
278 }
279
280 /**
281  * HomeScreen OnScreen message
282  *
283  * #### Parameters
284  * Request key
285  * - display_message   : message for display
286  *
287  * #### Return
288  * None
289  *
290  */
291 static void on_screen_message (afb_req_t request)
292 {
293     AFB_DEBUG("called.");
294     int ret = g_hs_instance->client_manager->handleRequest(request, __FUNCTION__);
295     if (ret) {
296         afb_req_fail_f(request, "failed", "called %s, Unknown parameter", __FUNCTION__);
297     }
298     else {
299         struct json_object *res = json_object_new_object();
300         hs_add_object_to_json_object_func(res, __FUNCTION__, 2,
301           _error,  ret);
302         afb_req_success(request, res, "afb_event_push event [on_screen_message]");
303     }
304 }
305
306 /**
307  * HomeScreen OnScreen Reply
308  *
309  * #### Parameters
310  * Request key
311  * - reply_message   : message for reply
312  *
313  * #### Return
314  * None
315  *
316  */
317 static void on_screen_reply (afb_req_t request)
318 {
319     AFB_DEBUG("called.");
320     int ret = g_hs_instance->client_manager->handleRequest(request, __FUNCTION__);
321     if (ret) {
322         afb_req_fail_f(request, "failed", "called %s, Unknown parameter", __FUNCTION__);
323     }
324     else {
325         struct json_object *res = json_object_new_object();
326         hs_add_object_to_json_object_func(res, __FUNCTION__, 2,
327           _error,  ret);
328         afb_req_success(request, res, "afb_event_push event [on_screen_reply]");
329     }
330 }
331
332 /**
333  * Subscribe event
334  *
335  * #### Parameters
336  *  - event  : Event name. Event list is written in libhomescreen.cpp
337  *
338  * #### Return
339  * None
340  *
341  */
342 static void subscribe(afb_req_t request)
343 {
344     AFB_DEBUG("called.");
345     int ret = 0;
346     std::string req_appid = std::move(get_application_id(request));
347     if(!req_appid.empty()) {
348         ret = g_hs_instance->client_manager->handleRequest(request, __FUNCTION__, req_appid.c_str());
349     }
350     else {
351         ret = AFB_EVENT_BAD_REQUEST;
352     }
353
354     if(ret) {
355         afb_req_fail_f(request, "afb_req_subscribe failed", "called %s.", __FUNCTION__);
356     }
357     else {
358         struct json_object *res = json_object_new_object();
359         hs_add_object_to_json_object_func(res, __FUNCTION__, 2,
360             _error, ret);
361         afb_req_success_f(request, res, "homescreen binder subscribe.");
362     }
363 }
364
365 /**
366  * Unsubscribe event
367  *
368  * #### Parameters
369  *  - event  : Event name. Event list is written in libhomescreen.cpp
370  *
371  * #### Return
372  * None
373  *
374  */
375 static void unsubscribe(afb_req_t request)
376 {
377     AFB_DEBUG("called.");
378     int ret = 0;
379     std::string req_appid = std::move(get_application_id(request));
380     if(!req_appid.empty()) {
381         ret = g_hs_instance->client_manager->handleRequest(request, __FUNCTION__, req_appid.c_str());
382     }
383     else {
384         ret = AFB_EVENT_BAD_REQUEST;
385     }
386
387     if(ret) {
388         afb_req_fail_f(request, "afb_req_unsubscribe failed", "called %s.", __FUNCTION__);
389     }
390     else {
391         struct json_object *res = json_object_new_object();
392         hs_add_object_to_json_object_func(res, __FUNCTION__, 2,
393             _error, ret);
394         afb_req_success_f(request, res, "homescreen binder unsubscribe success.");
395     }
396 }
397
398 /**
399  * showWindow event
400  *
401  * #### Parameters
402  *  - request : the request
403  *
404  * #### Return
405  * None
406  *
407  */
408 static void showWindow(afb_req_t request)
409 {
410     AFB_DEBUG("called.");
411     int ret = 0;
412     const char* value = afb_req_value(request, _application_id);
413     if (value) {
414         ret = g_hs_instance->client_manager->handleRequest(request, __FUNCTION__, value);
415         if(ret == AFB_REQ_NOT_STARTED_APPLICATION) {
416             std::string id = g_hs_instance->app_info->getAppProperty(value, _keyId);
417             HS_AfmMainProxy afm_proxy;
418             afm_proxy.start(request, id);
419             ret = 0;
420         }
421     }
422     else {
423         ret = AFB_EVENT_BAD_REQUEST;
424     }
425
426     if (ret) {
427         afb_req_fail_f(request, "failed", "called %s, Unknown parameter", __FUNCTION__);
428     }
429     else {
430         struct json_object *res = json_object_new_object();
431         hs_add_object_to_json_object_func(res, __FUNCTION__, 2,
432           _error,  ret);
433         afb_req_success(request, res, "afb_event_push event [showWindow]");
434     }
435 }
436
437 /**
438  * hideWindow event
439  *
440  * #### Parameters
441  *  - request : the request
442  *
443  * #### Return
444  * None
445  *
446  */
447 static void hideWindow(afb_req_t request)
448 {
449     AFB_DEBUG("called.");
450     int ret = 0;
451     const char* value = afb_req_value(request, _application_id);
452     if (value) {
453         ret = g_hs_instance->client_manager->handleRequest(request, __FUNCTION__, value);
454     }
455     else {
456         ret = AFB_EVENT_BAD_REQUEST;
457     }
458
459     if (ret) {
460         afb_req_fail_f(request, "failed", "called %s, Unknown parameter", __FUNCTION__);
461     }
462     else {
463         struct json_object *res = json_object_new_object();
464         hs_add_object_to_json_object_func(res, __FUNCTION__, 2,
465           _error,  ret);
466         afb_req_success(request, res, "afb_event_push event [hideWindow]");
467     }
468 }
469
470 /**
471  * replyShowWindow event
472  *
473  * #### Parameters
474  *  - request : the request
475  *
476  * #### Return
477  *  None
478  *
479  */
480 static void replyShowWindow(afb_req_t request)
481 {
482     AFB_DEBUG("called.");
483     int ret = 0;
484     const char* value = afb_req_value(request, _application_id);
485     if (value) {
486         ret = g_hs_instance->client_manager->handleRequest(request, __FUNCTION__, value);
487     }
488     else {
489         ret = AFB_EVENT_BAD_REQUEST;
490     }
491
492     if (ret) {
493         afb_req_fail_f(request, "failed", "called %s, Unknown parameter", __FUNCTION__);
494     }
495     else {
496         struct json_object *res = json_object_new_object();
497         hs_add_object_to_json_object_func(res, __FUNCTION__, 2,
498           _error,  ret);
499         afb_req_success(request, res, "afb_event_push event [replyShowWindow]");
500     }
501 }
502
503 /**
504  * showNotification event
505  *
506  * the contents to homescreen which display at top area.
507  *
508  * #### Parameters
509  *  - request : the request
510  *
511  * #### Return
512  * None
513  *
514  */
515 static void showNotification(afb_req_t request)
516 {
517     AFB_DEBUG("called.");
518     int ret = g_hs_instance->client_manager->handleRequest(request, __FUNCTION__, "homescreen");
519     if (ret) {
520         afb_req_fail_f(request, "failed", "called %s, Unknown parameter", __FUNCTION__);
521     }
522     else {
523         struct json_object *res = json_object_new_object();
524         hs_add_object_to_json_object_func(res, __FUNCTION__, 2,
525           _error,  ret);
526         afb_req_success(request, res, "afb_event_push event [showNotification]");
527     }
528 }
529
530 /**
531  * showInformation event
532  *
533  * the contents to homescreen which display at bottom area.
534  *
535  * #### Parameters
536  *  - request : the request
537  *
538  * #### Return
539  * None
540  *
541  */
542 static void showInformation(afb_req_t request)
543 {
544     AFB_DEBUG("called.");
545     int ret = g_hs_instance->client_manager->handleRequest(request,  __FUNCTION__, "homescreen");
546     if (ret) {
547         afb_req_fail_f(request, "failed", "called %s, Unknown parameter", __FUNCTION__);
548     }
549     else {
550         struct json_object *res = json_object_new_object();
551         hs_add_object_to_json_object_func(res, __FUNCTION__, 2,
552           _error,  ret);
553         afb_req_success(request, res, "afb_event_push event [showInformation]");
554     }
555 }
556
557 /**
558  * get runnables list
559  *
560  * #### Parameters
561  *  - request : the request
562  *
563  * #### Return
564  * None
565  *
566  */
567 static void getRunnables(afb_req_t request)
568 {
569     AFB_DEBUG("called.");
570     struct json_object* j_runnable = json_object_new_array();
571     g_hs_instance->app_info->getRunnables(&j_runnable);
572
573     /*create response json object*/
574     struct json_object *res = json_object_new_object();
575     hs_add_object_to_json_object_func(res, __FUNCTION__, 2, _error, 0);
576     json_object_object_add(res, _keyData, j_runnable);
577     afb_req_success_f(request, res, "homescreen binder unsubscribe success.");
578 }
579
580 /*
581  * array of the verbs exported to afb-daemon
582  */
583 static const afb_verb_t verbs[]= {
584     /* VERB'S NAME                 FUNCTION TO CALL                  */
585     { .verb="ping",              .callback=pingSample             },
586     { .verb="tap_shortcut",      .callback=tap_shortcut           },
587     { .verb="showWindow",        .callback=showWindow             },
588     { .verb="hideWindow",        .callback=hideWindow             },
589     { .verb="replyShowWindow",   .callback=replyShowWindow        },
590     { .verb="on_screen_message", .callback=on_screen_message      },
591     { .verb="on_screen_reply",   .callback=on_screen_reply        },
592     { .verb="subscribe",         .callback=subscribe              },
593     { .verb="unsubscribe",       .callback=unsubscribe            },
594     { .verb="showNotification",  .callback=showNotification       },
595     { .verb="showInformation",   .callback=showInformation        },
596     { .verb="getRunnables",      .callback=getRunnables           },
597     {NULL } /* marker for end of the array */
598 };
599
600 /**
601  * homescreen binding preinit function
602  *
603  * #### Parameters
604  *  - api : the api serving the request
605  *
606  * #### Return
607  * None
608  *
609  */
610 static int preinit(afb_api_t api)
611 {
612     AFB_DEBUG("binding preinit (was register)");
613     return 0;
614 }
615
616 /**
617  * homescreen binding init function
618  *
619  * #### Parameters
620  *  - api : the api serving the request
621  *
622  * #### Return
623  * None
624  *
625  */
626 static int init(afb_api_t api)
627 {
628     AFB_DEBUG("binding init");
629
630     if(g_hs_instance != nullptr) {
631         AFB_WARNING( "g_hs_instance isn't null.");
632         delete g_hs_instance->client_manager;
633         delete g_hs_instance->app_info;
634         delete g_hs_instance;
635         g_hs_instance = nullptr;
636     }
637     g_hs_instance = new hs_instance();
638     if(g_hs_instance == nullptr) {
639         AFB_ERROR( "Fatal Error: new g_hs_instance failed.");
640         return -1;
641     }
642
643     return g_hs_instance->init(api);
644 }
645
646 /**
647  * homescreen binding event function
648  *
649  * #### Parameters
650  *  - api : the api serving the request
651  *  - event  : event name
652  *  - object : event json object
653  *
654  * #### Return
655  * None
656  *
657  */
658 static void onevent(afb_api_t api, const char *event, struct json_object *object)
659 {
660     AFB_INFO("on_event %s", event);
661     g_hs_instance->onEvent(api, event, object);
662 }
663
664 const afb_binding_t afbBindingExport = {
665     .api = "homescreen",
666     .specification = NULL,
667     .info = NULL,
668     .verbs = verbs,
669     .preinit = preinit,
670     .init = init,
671     .onevent = onevent
672 };