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