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