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