c02f62b1a53269569f989fc2fae17fb7beb00b4c
[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("FATAL ERROR: client_manager is nullptr.");
63         return -1;
64     }
65     client_manager->init();
66
67     if(app_info == nullptr) {
68         AFB_ERROR("FATAL 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     AFB_DEBUG("called.");
177     int ret = 0;
178     const char* value = afb_req_value(request, _application_id);
179     if (value) {
180         AFB_INFO("request appid = %s.", value);
181         ret = g_hs_instance->client_manager->handleRequest(request, __FUNCTION__, value);
182         if(ret == AFB_REQ_NOT_STARTED_APPLICATION) {
183             std::string id = g_hs_instance->app_info->getAppProperty(value, _keyId);
184             HS_AfmMainProxy afm_proxy;
185             afm_proxy.start(request, id);
186             ret = 0;
187         }
188     }
189     else {
190         ret = AFB_EVENT_BAD_REQUEST;
191     }
192
193     if (ret) {
194         afb_req_fail_f(request, "failed", "called %s, Unknown parameter", __FUNCTION__);
195     }
196     else {
197         struct json_object *res = json_object_new_object();
198         hs_add_object_to_json_object_func(res, __FUNCTION__, 2,
199           _error,  ret);
200         afb_req_success(request, res, "afb_event_push event [tap_shortcut]");
201     }
202 }
203
204 /**
205  * HomeScreen OnScreen message
206  *
207  * #### Parameters
208  * Request key
209  * - display_message   : message for display
210  *
211  * #### Return
212  * None
213  *
214  */
215 static void on_screen_message (afb_req_t request)
216 {
217     AFB_DEBUG("called.");
218     int ret = g_hs_instance->client_manager->handleRequest(request, __FUNCTION__);
219     if (ret) {
220         afb_req_fail_f(request, "failed", "called %s, Unknown parameter", __FUNCTION__);
221     }
222     else {
223         struct json_object *res = json_object_new_object();
224         hs_add_object_to_json_object_func(res, __FUNCTION__, 2,
225           _error,  ret);
226         afb_req_success(request, res, "afb_event_push event [on_screen_message]");
227     }
228 }
229
230 /**
231  * HomeScreen OnScreen Reply
232  *
233  * #### Parameters
234  * Request key
235  * - reply_message   : message for reply
236  *
237  * #### Return
238  * None
239  *
240  */
241 static void on_screen_reply (afb_req_t request)
242 {
243     AFB_DEBUG("called.");
244     int ret = g_hs_instance->client_manager->handleRequest(request, __FUNCTION__);
245     if (ret) {
246         afb_req_fail_f(request, "failed", "called %s, Unknown parameter", __FUNCTION__);
247     }
248     else {
249         struct json_object *res = json_object_new_object();
250         hs_add_object_to_json_object_func(res, __FUNCTION__, 2,
251           _error,  ret);
252         afb_req_success(request, res, "afb_event_push event [on_screen_reply]");
253     }
254 }
255
256 /**
257  * Subscribe event
258  *
259  * #### Parameters
260  *  - event  : Event name. Event list is written in libhomescreen.cpp
261  *
262  * #### Return
263  * None
264  *
265  */
266 static void subscribe(afb_req_t request)
267 {
268     AFB_DEBUG("called.");
269     int ret = 0;
270     std::string req_appid = std::move(get_application_id(request));
271     if(!req_appid.empty()) {
272         ret = g_hs_instance->client_manager->handleRequest(request, __FUNCTION__, req_appid.c_str());
273     }
274     else {
275         ret = AFB_EVENT_BAD_REQUEST;
276     }
277
278     if(ret) {
279         afb_req_fail_f(request, "afb_req_subscribe failed", "called %s.", __FUNCTION__);
280     }
281     else {
282         struct json_object *res = json_object_new_object();
283         hs_add_object_to_json_object_func(res, __FUNCTION__, 2,
284             _error, ret);
285         afb_req_success_f(request, res, "homescreen binder subscribe.");
286     }
287 }
288
289 /**
290  * Unsubscribe event
291  *
292  * #### Parameters
293  *  - event  : Event name. Event list is written in libhomescreen.cpp
294  *
295  * #### Return
296  * None
297  *
298  */
299 static void unsubscribe(afb_req_t request)
300 {
301     AFB_DEBUG("called.");
302     int ret = 0;
303     std::string req_appid = std::move(get_application_id(request));
304     if(!req_appid.empty()) {
305         ret = g_hs_instance->client_manager->handleRequest(request, __FUNCTION__, req_appid.c_str());
306     }
307     else {
308         ret = AFB_EVENT_BAD_REQUEST;
309     }
310
311     if(ret) {
312         afb_req_fail_f(request, "afb_req_unsubscribe failed", "called %s.", __FUNCTION__);
313     }
314     else {
315         struct json_object *res = json_object_new_object();
316         hs_add_object_to_json_object_func(res, __FUNCTION__, 2,
317             _error, ret);
318         afb_req_success_f(request, res, "homescreen binder unsubscribe success.");
319     }
320 }
321
322 /**
323  * showWindow event
324  *
325  * #### Parameters
326  *  - request : the request
327  *
328  * #### Return
329  * None
330  *
331  */
332 static void showWindow(afb_req_t request)
333 {
334     AFB_DEBUG("called.");
335     int ret = 0;
336     const char* value = afb_req_value(request, _application_id);
337     if (value) {
338         ret = g_hs_instance->client_manager->handleRequest(request, __FUNCTION__, value);
339         if(ret == AFB_REQ_NOT_STARTED_APPLICATION) {
340             std::string id = g_hs_instance->app_info->getAppProperty(value, _keyId);
341             HS_AfmMainProxy afm_proxy;
342             afm_proxy.start(request, id);
343             ret = 0;
344         }
345     }
346     else {
347         ret = AFB_EVENT_BAD_REQUEST;
348     }
349
350     if (ret) {
351         afb_req_fail_f(request, "failed", "called %s, Unknown parameter", __FUNCTION__);
352     }
353     else {
354         struct json_object *res = json_object_new_object();
355         hs_add_object_to_json_object_func(res, __FUNCTION__, 2,
356           _error,  ret);
357         afb_req_success(request, res, "afb_event_push event [showWindow]");
358     }
359 }
360
361 /**
362  * hideWindow event
363  *
364  * #### Parameters
365  *  - request : the request
366  *
367  * #### Return
368  * None
369  *
370  */
371 static void hideWindow(afb_req_t request)
372 {
373     AFB_DEBUG("called.");
374     int ret = 0;
375     const char* value = afb_req_value(request, _application_id);
376     if (value) {
377         ret = g_hs_instance->client_manager->handleRequest(request, __FUNCTION__, value);
378     }
379     else {
380         ret = AFB_EVENT_BAD_REQUEST;
381     }
382
383     if (ret) {
384         afb_req_fail_f(request, "failed", "called %s, Unknown parameter", __FUNCTION__);
385     }
386     else {
387         struct json_object *res = json_object_new_object();
388         hs_add_object_to_json_object_func(res, __FUNCTION__, 2,
389           _error,  ret);
390         afb_req_success(request, res, "afb_event_push event [hideWindow]");
391     }
392 }
393
394 /**
395  * replyShowWindow event
396  *
397  * #### Parameters
398  *  - request : the request
399  *
400  * #### Return
401  *  None
402  *
403  */
404 static void replyShowWindow(afb_req_t request)
405 {
406     AFB_DEBUG("called.");
407     int ret = 0;
408     const char* value = afb_req_value(request, _application_id);
409     if (value) {
410         ret = g_hs_instance->client_manager->handleRequest(request, __FUNCTION__, value);
411     }
412     else {
413         ret = AFB_EVENT_BAD_REQUEST;
414     }
415
416     if (ret) {
417         afb_req_fail_f(request, "failed", "called %s, Unknown parameter", __FUNCTION__);
418     }
419     else {
420         struct json_object *res = json_object_new_object();
421         hs_add_object_to_json_object_func(res, __FUNCTION__, 2,
422           _error,  ret);
423         afb_req_success(request, res, "afb_event_push event [replyShowWindow]");
424     }
425 }
426
427 /**
428  * showNotification event
429  *
430  * the contents to homescreen which display at top area.
431  *
432  * #### Parameters
433  *  - request : the request
434  *
435  * #### Return
436  * None
437  *
438  */
439 static void showNotification(afb_req_t request)
440 {
441     AFB_DEBUG("called.");
442     int ret = g_hs_instance->client_manager->handleRequest(request, __FUNCTION__, "homescreen");
443     if (ret) {
444         afb_req_fail_f(request, "failed", "called %s, Unknown parameter", __FUNCTION__);
445     }
446     else {
447         struct json_object *res = json_object_new_object();
448         hs_add_object_to_json_object_func(res, __FUNCTION__, 2,
449           _error,  ret);
450         afb_req_success(request, res, "afb_event_push event [showNotification]");
451     }
452 }
453
454 /**
455  * showInformation event
456  *
457  * the contents to homescreen which display at bottom area.
458  *
459  * #### Parameters
460  *  - request : the request
461  *
462  * #### Return
463  * None
464  *
465  */
466 static void showInformation(afb_req_t request)
467 {
468     AFB_DEBUG("called.");
469     int ret = g_hs_instance->client_manager->handleRequest(request,  __FUNCTION__, "homescreen");
470     if (ret) {
471         afb_req_fail_f(request, "failed", "called %s, Unknown parameter", __FUNCTION__);
472     }
473     else {
474         struct json_object *res = json_object_new_object();
475         hs_add_object_to_json_object_func(res, __FUNCTION__, 2,
476           _error,  ret);
477         afb_req_success(request, res, "afb_event_push event [showInformation]");
478     }
479 }
480
481 /**
482  * get runnables list
483  *
484  * #### Parameters
485  *  - request : the request
486  *
487  * #### Return
488  * None
489  *
490  */
491 static void getRunnables(afb_req_t request)
492 {
493     AFB_DEBUG("called.");
494     struct json_object* j_runnable = json_object_new_array();
495     g_hs_instance->app_info->getRunnables(&j_runnable);
496
497     /*create response json object*/
498     struct json_object *res = json_object_new_object();
499     hs_add_object_to_json_object_func(res, __FUNCTION__, 2, _error, 0);
500     json_object_object_add(res, _keyData, j_runnable);
501     afb_req_success_f(request, res, "homescreen binder unsubscribe success.");
502 }
503
504 /*
505  * array of the verbs exported to afb-daemon
506  */
507 static const afb_verb_t verbs[]= {
508     /* VERB'S NAME                 FUNCTION TO CALL                  */
509     { .verb="ping",              .callback=pingSample             },
510     { .verb="tap_shortcut",      .callback=tap_shortcut           },
511     { .verb="showWindow",        .callback=showWindow             },
512     { .verb="hideWindow",        .callback=hideWindow             },
513     { .verb="replyShowWindow",   .callback=replyShowWindow        },
514     { .verb="on_screen_message", .callback=on_screen_message      },
515     { .verb="on_screen_reply",   .callback=on_screen_reply        },
516     { .verb="subscribe",         .callback=subscribe              },
517     { .verb="unsubscribe",       .callback=unsubscribe            },
518     { .verb="showNotification",  .callback=showNotification       },
519     { .verb="showInformation",   .callback=showInformation        },
520     { .verb="getRunnables",      .callback=getRunnables           },
521     {NULL } /* marker for end of the array */
522 };
523
524 /**
525  * homescreen binding preinit function
526  *
527  * #### Parameters
528  *  - api : the api serving the request
529  *
530  * #### Return
531  * None
532  *
533  */
534 static int preinit(afb_api_t api)
535 {
536    AFB_DEBUG("binding preinit (was register)");
537    return 0;
538 }
539
540 /**
541  * homescreen binding init function
542  *
543  * #### Parameters
544  *  - api : the api serving the request
545  *
546  * #### Return
547  * None
548  *
549  */
550 static int init(afb_api_t api)
551 {
552     AFB_DEBUG("binding init");
553
554     if(g_hs_instance != nullptr) {
555         AFB_WARNING( "g_hs_instance isn't null.");
556         delete g_hs_instance->client_manager;
557         delete g_hs_instance->app_info;
558         delete g_hs_instance;
559         g_hs_instance = nullptr;
560     }
561     g_hs_instance = new hs_instance();
562     if(g_hs_instance == nullptr) {
563         AFB_ERROR( "Fatal Error: new g_hs_instance failed.");
564         return -1;
565     }
566
567     return g_hs_instance->init(api);
568 }
569
570 /**
571  * homescreen binding event function
572  *
573  * #### Parameters
574  *  - api : the api serving the request
575  *  - event  : event name
576  *  - object : event json object
577  *
578  * #### Return
579  * None
580  *
581  */
582 static void onevent(afb_api_t api, const char *event, struct json_object *object)
583 {
584     AFB_INFO("on_event %s", event);
585     g_hs_instance->onEvent(api, event, object);
586 }
587
588 const afb_binding_t afbBindingExport = {
589     .api = "homescreen",
590     .specification = NULL,
591     .info = NULL,
592     .verbs = verbs,
593     .preinit = preinit,
594     .init = init,
595     .onevent = onevent
596 };