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