2 * Copyright 2018 Samsung Electronics Co., Ltd
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "setting-accessibility-universal-switch-dbus.h"
19 #include "AccessibilitySettingLog.hpp"
20 #include "setting-accessibility.h"
22 #define BUS "org.tizen.UniversalSwitch"
23 #define PATH "/org/tizen/UniversalSwitch"
24 #define IFACE "org.tizen.UniversalSwitch"
25 #define ELDBUS_TIMEOUT 400.0
27 static void __bus_name_acquired(void *data, const char *bus, const char *old_id, const char *new_id);
29 static Eina_Bool __eldbus_init(UniversalSwitchDbusConfig *config)
31 UniversalSwitchEldbus *eldbus = &config->eldbus;
34 eldbus->capture_switch_request = NULL;
36 eldbus->is_init = eldbus_init();
37 if (!eldbus->is_init) {
38 ERROR("DBus initialization failed");
42 if (!(eldbus->conn = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SESSION))) {
43 ERROR("Connection to session bus failed");
47 eldbus_name_owner_changed_callback_add(eldbus->conn, BUS, __bus_name_acquired, config, EINA_TRUE);
52 static void __eldbus_shutdown(UniversalSwitchDbusConfig *config)
54 UniversalSwitchEldbus *eldbus = &config->eldbus;
60 eldbus_name_owner_changed_callback_del(eldbus->conn, BUS, __bus_name_acquired, config);
62 if (eldbus->capture_switch_request)
63 eldbus_pending_cancel(eldbus->capture_switch_request);
64 eldbus->capture_switch_request = NULL;
67 eldbus_proxy_unref(eldbus->proxy);
71 eldbus_object_unref(eldbus->dobj);
75 eldbus_connection_unref(eldbus->conn);
81 static void __eldbus_getInfoArray(std::vector<UniversalSwitchInfoType *> &infoTypes, Eldbus_Message *reply)
83 Eldbus_Message_Iter *array;
84 Eldbus_Message_Iter *struct_sss;
85 if (!eldbus_message_arguments_get(reply, "a(sss)", &array)) {
86 ERROR("Error on eldbus_message_arguments_get()");
89 while (eldbus_message_iter_get_and_next(array, 'r', &struct_sss)) {
92 char *description = NULL;
93 if (!eldbus_message_iter_arguments_get(struct_sss, "sss", &id, &name, &description)) {
94 ERROR("Error on eldbus_message_arguments_get()");
97 auto info = new UniversalSwitchInfoType;
101 info->description = description;
102 infoTypes.push_back(info);
106 static std::vector<UniversalSwitchInfoType *> __eldbus_getAllSwitchesByProviderId(
107 UniversalSwitchEldbus *eldbus,
108 const std::string &provider_id)
110 Eldbus_Message *req = NULL;
111 Eldbus_Message *reply = NULL;
112 Eldbus_Message_Iter *iter = NULL;
113 const char *errname = NULL;
114 const char *errmsg = NULL;
116 if (!(req = eldbus_proxy_method_call_new(eldbus->proxy, "getAllSwitchesByProviderId"))) {
117 ERROR("Failed to create method call on " IFACE ".getAllSwitchesByProviderId");
120 iter = eldbus_message_iter_get(req);
121 eldbus_message_iter_arguments_append(iter, "s", provider_id.c_str());
123 std::vector<UniversalSwitchInfoType *> switches;
124 reply = eldbus_proxy_send_and_block(eldbus->proxy, req, ELDBUS_TIMEOUT);
125 if (!reply || eldbus_message_error_get(reply, &errname, &errmsg))
126 ERROR("Unable to call method " IFACE ".getAllSwitchesByProviderId: %s %s", errname, errmsg);
128 __eldbus_getInfoArray(switches, reply);
131 eldbus_message_unref(reply);
136 static std::vector<UniversalSwitchSwitchProvider *> __eldbus_getAllSwitchProviders(UniversalSwitchEldbus *eldbus)
138 Eldbus_Message *req = NULL;
139 Eldbus_Message *reply = NULL;
140 const char *errname = NULL;
141 const char *errmsg = NULL;
143 if (!(req = eldbus_proxy_method_call_new(eldbus->proxy, "getAllSwitchProviders"))) {
144 ERROR("Failed to create method call on " IFACE ".getAllSwitchProviders");
148 std::vector<UniversalSwitchSwitchProvider *> switch_providers;
149 reply = eldbus_proxy_send_and_block(eldbus->proxy, req, ELDBUS_TIMEOUT);
150 if (!reply || eldbus_message_error_get(reply, &errname, &errmsg)) {
151 ERROR("Unable to call method " IFACE ".getAllSwitchProviders: %s %s", errname, errmsg);
154 std::vector<UniversalSwitchInfoType *> switch_providers_info;
156 __eldbus_getInfoArray(switch_providers_info, reply);
158 for (auto &it : switch_providers_info) {
159 auto switch_provider = new UniversalSwitchSwitchProvider;
160 switch_provider->info = it;
161 switch_provider->switches = __eldbus_getAllSwitchesByProviderId(eldbus, it->id);
162 switch_providers.push_back(switch_provider);
165 ERROR("Switch Providers could not be initialized!");
169 eldbus_message_unref(reply);
171 return switch_providers;
174 static std::vector<UniversalSwitchInfoType *> __eldbus_getBindableActivityTypes(UniversalSwitchEldbus *eldbus)
176 Eldbus_Message *req = NULL;
177 Eldbus_Message *reply = NULL;
178 const char *errname = NULL;
179 const char *errmsg = NULL;
181 if (!(req = eldbus_proxy_method_call_new(eldbus->proxy, "getBindableActivityTypes"))) {
182 ERROR("Failed to create method call on " IFACE ".getBindableActivityTypes");
186 std::vector<UniversalSwitchInfoType *> activity_types;
187 reply = eldbus_proxy_send_and_block(eldbus->proxy, req, ELDBUS_TIMEOUT);
188 if (!reply || eldbus_message_error_get(reply, &errname, &errmsg)) {
189 ERROR("Unable to call method " IFACE ".getBindableActivityTypes: %s %s", errname, errmsg);
191 __eldbus_getInfoArray(activity_types, reply);
195 eldbus_message_unref(reply);
197 return activity_types;
200 static void __eldbus_getAllSwitchConfigurationItemsArray(
201 std::vector<UniversalSwitchConfigurationItem *> &infoTypes,
202 Eldbus_Message *reply)
205 Eldbus_Message_Iter *array;
206 Eldbus_Message_Iter *struct_sssi;
208 if (!eldbus_message_arguments_get(reply, "a(sssi)", &array)) {
209 ERROR("Error on eldbus_message_arguments_get()");
212 while (eldbus_message_iter_get_and_next(array, 'r', &struct_sssi)) {
218 if (!eldbus_message_iter_arguments_get(struct_sssi, "sssi", &switchId, &userName, &activityType, &changeType)) {
219 ERROR("Error on eldbus_message_arguments_get()\n");
222 char *pointer_to_end_of_switch_provider_str = strstr(switchId, "_");
223 if (!pointer_to_end_of_switch_provider_str) {
224 ERROR("Wrong switch ID format");
227 size_t provider_id_size = pointer_to_end_of_switch_provider_str - switchId;
228 auto item = new UniversalSwitchConfigurationItem;
229 item->provider_id = std::string{switchId, provider_id_size};
230 item->switch_id = switchId;
231 item->user_name = userName;
232 item->activity_type = activityType;
233 infoTypes.push_back(item);
237 static std::vector<UniversalSwitchConfigurationItem *> __eldbus_getAllSwitchConfigurationItems(UniversalSwitchEldbus *eldbus)
239 Eldbus_Message *req = NULL;
240 Eldbus_Message *reply = NULL;
241 const char *errname = NULL;
242 const char *errmsg = NULL;
244 if (!(req = eldbus_proxy_method_call_new(eldbus->proxy, "getAllSwitchConfigurationItems"))) {
245 ERROR("Failed to create method call on " IFACE ".getAllSwitchConfigurationItems");
249 std::vector<UniversalSwitchConfigurationItem *> configurationItems;
250 reply = eldbus_proxy_send_and_block(eldbus->proxy, req, ELDBUS_TIMEOUT);
251 if (!reply || eldbus_message_error_get(reply, &errname, &errmsg)) {
252 ERROR("Unable to call method " IFACE ".getAllSwitchConfigurationItems: %s %s", errname, errmsg);
254 __eldbus_getAllSwitchConfigurationItemsArray(configurationItems, reply);
258 eldbus_message_unref(reply);
260 return configurationItems;
263 static void __relese_configuration_items(UniversalSwitchDbusConfig *config)
265 for (auto &it : config->configuration_items) {
269 config->configuration_items = {};
272 static void __relese_info_type(UniversalSwitchInfoType *info)
280 static void __relese_info_type_array(std::vector<UniversalSwitchInfoType *> &infoArray)
282 for (auto &it : infoArray)
288 static void __relese_activity_types(UniversalSwitchDbusConfig *config)
290 if (config->activity_types.empty())
293 __relese_info_type_array(config->activity_types);
294 config->activity_types = {};
297 static void __relese_switch_providers(UniversalSwitchDbusConfig *config)
299 if (config->switch_providers.empty())
302 for (auto &it : config->switch_providers) {
303 __relese_info_type(it->info);
304 __relese_info_type_array(it->switches);
308 config->switch_providers = {};
311 static void __update_configuration_items(UniversalSwitchDbusConfig *config)
313 __relese_configuration_items(config);
314 config->configuration_items = __eldbus_getAllSwitchConfigurationItems(&config->eldbus);
317 static void __bus_name_acquired(void *data, const char *bus, const char *old_id, const char *new_id)
319 DEBUG("dbus name acquired, bus=%s, old_id=%s, new_id=%s", bus, old_id, new_id);
321 if (!new_id || strlen(new_id) == 0)
324 auto config = static_cast<UniversalSwitchDbusConfig *>(data);
325 UniversalSwitchEldbus *eldbus = &config->eldbus;
327 if (!eldbus->dobj && !(eldbus->dobj = eldbus_object_get(eldbus->conn, BUS, PATH))) {
328 ERROR("Failed to create eldbus object for " PATH);
332 if (!eldbus->proxy && !(eldbus->proxy = eldbus_proxy_get(eldbus->dobj, IFACE))) {
333 ERROR("Failed to create proxy object for " IFACE);
337 config->activity_types = __eldbus_getBindableActivityTypes(&config->eldbus);
338 config->switch_providers = __eldbus_getAllSwitchProviders(&config->eldbus);
339 __update_configuration_items(config);
341 if (eldbus->init_done_callback) {
342 eldbus->init_done_callback(eldbus->init_done_callback_data);
343 eldbus->init_done_callback = NULL;
344 eldbus->init_done_callback_data = NULL;
348 Eina_Bool setting_accessibility_universal_switch_dbus_config_init(
349 UniversalSwitchDbusConfig *config,
350 init_done_cb callback,
354 config->eldbus.init_done_callback = callback;
355 config->eldbus.init_done_callback_data = callback_data;
356 Eina_Bool v = __eldbus_init(config);
361 int setting_accessibility_universal_switch_dbus_config_get_switch_count(UniversalSwitchDbusConfig *config)
363 return config->configuration_items.size();
366 void setting_accessibility_universal_switch_dbus_config_addSwitchConfigurationItem(
367 UniversalSwitchDbusConfig *config,
368 const std::string &switch_id,
369 const std::string &user_name,
370 const std::string &activity_type)
372 DEBUG("Running " IFACE ".addSwitchConfigurationItem(%s, %s ,%s)", switch_id.c_str(), user_name.c_str(), activity_type.c_str());
374 config->eldbus.proxy, "addSwitchConfigurationItem", NULL, NULL, ELDBUS_TIMEOUT, "sss", switch_id.c_str(), user_name.c_str(), activity_type.c_str());
375 __update_configuration_items(config);
377 void setting_accessibility_universal_switch_dbus_config_updateSwitchConfigurationItem(
378 UniversalSwitchDbusConfig *config,
379 const std::string &switch_id,
380 const std::string &user_name,
381 const std::string &activity_type)
383 DEBUG("Running " IFACE ".updateSwitchConfigurationItem(%s, %s ,%s)", switch_id.c_str(), user_name.c_str(), activity_type.c_str());
385 config->eldbus.proxy, "updateSwitchConfigurationItem", NULL, NULL, ELDBUS_TIMEOUT, "sss", switch_id.c_str(), user_name.c_str(), activity_type.c_str());
386 __update_configuration_items(config);
389 void setting_accessibility_universal_switch_dbus_config_removeSwitchConfigurationItem(
390 UniversalSwitchDbusConfig *config,
391 const std::string &switch_id)
393 DEBUG("Running " IFACE ".removeSwitchConfigurationItem(%s)", switch_id.c_str());
394 eldbus_proxy_call(config->eldbus.proxy, "removeSwitchConfigurationItem", NULL, NULL, ELDBUS_TIMEOUT, "s", switch_id.c_str());
395 __update_configuration_items(config);
398 void setting_accessibility_universal_switch_dbus_config_shutdown(UniversalSwitchDbusConfig *config)
400 __relese_configuration_items(config);
401 __relese_activity_types(config);
402 __relese_switch_providers(config);
403 __eldbus_shutdown(config);
406 std::string setting_accessibility_universal_switch_dbus_config_get_activity_name(
407 UniversalSwitchDbusConfig *config,
408 const std::string &activity_id)
410 for (auto &it : config->activity_types)
411 if (it->id == activity_id)
416 std::vector<UniversalSwitchInfoType *> setting_accessibility_universal_switch_dbus_config_get_switches(
417 UniversalSwitchDbusConfig *config,
418 const std::string &provider_id)
420 for (auto &it : config->switch_providers)
421 if (it->info->id == provider_id)
426 static void __eldbus_on_capture_switch(void *data EINA_UNUSED, const Eldbus_Message *msg, Eldbus_Pending *pending EINA_UNUSED)
428 auto eldbus = static_cast<UniversalSwitchEldbus *>(data);
429 const char *errname, *errmsg;
430 const char *switch_id = NULL;
432 if (eldbus_message_error_get(msg, &errname, &errmsg)) {
433 DEBUG("Error: %s %s", errname, errmsg);
435 if (!eldbus_message_arguments_get(msg, "s", &switch_id))
436 ERROR("Could not get switch_id");
439 DEBUG("DBus got captureSwitch %s", switch_id);
441 if (eldbus->capture_switch_callback) {
442 eldbus->capture_switch_callback(eldbus->capture_switch_data, switch_id);
443 eldbus->capture_switch_callback = NULL;
445 eldbus->capture_switch_request = NULL;
448 void setting_accessibility_universal_switch_dbus_config_captureSwitch(
449 UniversalSwitchDbusConfig *config,
450 const std::string &provider_id,
452 capture_switch_cb callback,
455 UniversalSwitchEldbus *eldbus = &config->eldbus;
456 DEBUG("DBus call captureSwitch for %s", provider_id.c_str());
457 eldbus->capture_switch_request = eldbus_proxy_call(
458 eldbus->proxy, "captureSwitch", __eldbus_on_capture_switch, eldbus, timeout, "s", provider_id.c_str());
459 if (eldbus->capture_switch_request) {
460 eldbus->capture_switch_callback = callback;
461 eldbus->capture_switch_data = callback_data;
463 ERROR("Dbus call to captureSwitch failed");
467 void setting_accessibility_universal_switch_dbus_config_cancelCaptureSwitch(UniversalSwitchDbusConfig *config)
469 UniversalSwitchEldbus *eldbus = &config->eldbus;
471 DEBUG("Running " IFACE ".cancelCaptureSwitch");
472 eldbus_proxy_call(config->eldbus.proxy, "cancelCaptureSwitch", NULL, NULL, ELDBUS_TIMEOUT, "");
474 DEBUG("DBus call captureSwitch canceled");
475 eldbus->capture_switch_callback = NULL;
476 if (eldbus->capture_switch_request) {
477 eldbus_pending_cancel(eldbus->capture_switch_request);
478 eldbus->capture_switch_request = NULL;