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