Store the dbus connection while launching the service
[platform/core/context/context-service.git] / src / agent / legacy / trigger / ActionManager.cpp
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
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 #include <Types.h>
18 #include <CtxJson1.h>
19 #include <app_control.h>
20 #include <app_control_internal.h>
21 #include <bundle.h>
22 #include <device/display.h>
23 #include <notification.h>
24 #include <notification_internal.h>
25 #include <vconf.h>
26 #include <TriggerRuleTypes.h>
27 #include "../DBusServer.h"
28 #include "ActionManager.h"
29
30 using namespace ctx;
31
32 static void __triggerActionAppControl(CtxJson1& action);
33 static void __triggerActionNotification(CtxJson1& action, std::string pkgId);
34 static void __triggerActionDbusCall(CtxJson1& action);
35
36 void trigger::action_manager::triggerAction(CtxJson1& action, std::string pkgId)
37 {
38         std::list<std::string> types;
39         action.getKeys(&types);
40         IF_FAIL_VOID_TAG(types.size() == 1, _E, "Invalid action");
41
42         std::string& type = *(types.begin());
43
44         if (type.compare(TRIG_RULE_KEY_APP_LAUNCH) == 0) {
45                 __triggerActionAppControl(action);
46         } else if (type.compare(TRIG_RULE_KEY_NOTIFICATION) == 0) {
47                 __triggerActionNotification(action, pkgId);
48         } else if (type.compare(TRIG_RULE_KEY_DBUS_CALL) == 0) {
49                 __triggerActionDbusCall(action);
50         }
51 }
52
53 void __triggerActionAppControl(CtxJson1& action)
54 {
55         int error;
56         std::string appctlStr;
57         action.get(TRIG_RULE_KEY_APP_LAUNCH, TRIG_RULE_KEY_APP_LAUNCH_APP_CONTROL, &appctlStr);
58
59         char* str = static_cast<char*>(malloc(appctlStr.length()));
60         if (str == NULL) {
61                 _E("Memory allocation failed");
62                 return;
63         }
64         appctlStr.copy(str, appctlStr.length(), 0);
65         bundle_raw* encoded = reinterpret_cast<unsigned char*>(str);
66         bundle* appctlBundle = bundle_decode(encoded, appctlStr.length());
67
68         app_control_h app = NULL;
69         app_control_create(&app);
70         app_control_import_from_bundle(app, appctlBundle);
71
72         error = app_control_send_launch_request(app, NULL, NULL);
73         if (error != APP_CONTROL_ERROR_NONE) {
74                 _E("Launch request failed(%d)", error);
75         } else {
76                 _D("Launch request succeeded");
77         }
78         bundle_free(appctlBundle);
79         free(str);
80         app_control_destroy(app);
81
82         error = device_display_change_state(DISPLAY_STATE_NORMAL);
83         if (error != DEVICE_ERROR_NONE) {
84                 _E("Change display state failed(%d)", error);
85         }
86 }
87
88 void __triggerActionNotification(CtxJson1& action, std::string pkgId)
89 {
90         int error;
91         notification_h notification = notification_create(NOTIFICATION_TYPE_NOTI);
92         std::string title;
93         if (action.get(TRIG_RULE_KEY_NOTIFICATION, TRIG_RULE_KEY_NOTI_TITLE, &title)) {
94                 error = notification_set_text(notification, NOTIFICATION_TEXT_TYPE_TITLE, title.c_str(), NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
95                 if (error != NOTIFICATION_ERROR_NONE) {
96                         _E("Set notification title failed(%d)", error);
97                 }
98         }
99
100         std::string content;
101         if (action.get(TRIG_RULE_KEY_NOTIFICATION, TRIG_RULE_KEY_NOTI_CONTENT, &content)) {
102                 error = notification_set_text(notification, NOTIFICATION_TEXT_TYPE_CONTENT, content.c_str(), NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
103                 if (error != NOTIFICATION_ERROR_NONE) {
104                         _E("Set notification contents failed(%d)", error);
105                 }
106         }
107
108         std::string imagePath;
109         if (action.get(TRIG_RULE_KEY_NOTIFICATION, TRIG_RULE_KEY_NOTI_ICON_PATH, &imagePath)) {
110                 error = notification_set_image(notification, NOTIFICATION_IMAGE_TYPE_ICON, imagePath.c_str());
111                 if (error != NOTIFICATION_ERROR_NONE) {
112                         _E("Set notification icon image failed(%d)", error);
113                 }
114         }
115
116         std::string appctlStr;
117         char* str = NULL;
118         bundle_raw* encoded = NULL;
119         bundle* appctlBundle = NULL;
120         app_control_h app = NULL;
121         if (action.get(TRIG_RULE_KEY_NOTIFICATION, TRIG_RULE_KEY_NOTI_APP_CONTROL, &appctlStr)) {
122                 str = static_cast<char*>(malloc(appctlStr.length()));
123                 if (str == NULL) {
124                         _E("Memory allocation failed");
125                         notification_free(notification);
126                         return;
127                 }
128                 appctlStr.copy(str, appctlStr.length(), 0);
129                 encoded = reinterpret_cast<unsigned char*>(str);
130                 appctlBundle = bundle_decode(encoded, appctlStr.length());
131
132                 app_control_create(&app);
133                 app_control_import_from_bundle(app, appctlBundle);
134
135                 error = notification_set_launch_option(notification, NOTIFICATION_LAUNCH_OPTION_APP_CONTROL, app);
136                 if (error != NOTIFICATION_ERROR_NONE) {
137                         _E("Set launch option failed(%d)", error);
138                 }
139         }
140
141         if (!pkgId.empty()) {
142                 error = notification_set_pkgname(notification, pkgId.c_str());
143                 if (error != NOTIFICATION_ERROR_NONE) {
144                         _E("Set package id(%s) failed(%#x)", pkgId.c_str(), error);
145                 }
146         }
147
148         int soundOn = 0;
149         error = vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &soundOn);
150         if (error < 0) {
151                 _E("vconf error (%d)", error);
152         } else if (soundOn) {
153                 error = notification_set_sound(notification, NOTIFICATION_SOUND_TYPE_DEFAULT, NULL);
154                 if (error != NOTIFICATION_ERROR_NONE) {
155                         _E("Set notification sound failed(%d)", error);
156                 }
157         }
158
159         int vibrationOn = 0;
160         error = vconf_get_bool(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL, &vibrationOn);
161         if (error < 0) {
162                 _E("vconf error (%d)", error);
163         } else if (vibrationOn) {
164                 error = notification_set_vibration(notification, NOTIFICATION_VIBRATION_TYPE_DEFAULT, NULL);
165                 if (error != NOTIFICATION_ERROR_NONE) {
166                         _E("Set notification vibration failed(%d)", error);
167                 }
168         }
169
170         error = notification_post(notification);
171         if (error != NOTIFICATION_ERROR_NONE) {
172                 _E("Post notification failed(%d)", error);
173         } else {
174                 _D("Post notification succeeded");
175         }
176
177         bundle_free(appctlBundle);
178         free(str);
179         notification_free(notification);
180         if (app) {
181                 app_control_destroy(app);
182         }
183
184         error = device_display_change_state(DISPLAY_STATE_NORMAL);
185         if (error != DEVICE_ERROR_NONE) {
186                 _E("Change display state failed(%d)", error);
187         }
188 }
189
190 void __triggerActionDbusCall(CtxJson1& action)
191 {
192         std::string busName, object, iface, method;
193         GVariant *param = NULL;
194
195         action.get(TRIG_RULE_KEY_DBUS_CALL, TRIG_RULE_KEY_DBUS_NAME, &busName);
196         IF_FAIL_VOID_TAG(!busName.empty(), _E, "No target bus name");
197
198         action.get(TRIG_RULE_KEY_DBUS_CALL, TRIG_RULE_KEY_DBUS_OBJECT, &object);
199         IF_FAIL_VOID_TAG(!object.empty(), _E, "No object path");
200
201         action.get(TRIG_RULE_KEY_DBUS_CALL, TRIG_RULE_KEY_DBUS_INTERFACE, &iface);
202         IF_FAIL_VOID_TAG(!iface.empty(), _E, "No interface name");
203
204         action.get(TRIG_RULE_KEY_DBUS_CALL, TRIG_RULE_KEY_DBUS_METHOD, &method);
205         IF_FAIL_VOID_TAG(!method.empty(), _E, "No method name");
206
207         action.get(TRIG_RULE_KEY_DBUS_CALL, TRIG_RULE_KEY_DBUS_PARAMETER, &param);
208
209         DBusServer::call(busName, object, iface, method, param);
210 }