2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
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 "bluetooth_adapter.h"
23 #ifdef APP_CONTROL_SETTINGS_SUPPORT
24 #include <appfw/app_control.h>
27 #include <bluetooth.h>
28 #include <system_info.h>
29 #include "bluetooth_internal.h"
31 #include "common/converter.h"
32 #include "common/extension.h"
33 #include "common/logger.h"
34 #include "common/platform_result.h"
35 #include "common/task-queue.h"
36 #include "common/tools.h"
38 #include "bluetooth/bluetooth_class.h"
39 #include "bluetooth/bluetooth_device.h"
40 #include "bluetooth/bluetooth_instance.h"
41 #include "bluetooth/bluetooth_privilege.h"
42 #include "bluetooth/bluetooth_socket.h"
43 #include "bluetooth/bluetooth_util.h"
48 using namespace common;
49 using namespace common::tools;
52 const std::string kAction = "action";
53 const std::string kData = "data";
54 const std::string kName = "name";
56 const std::string kAdapterPowered = "powered";
57 const std::string kAdapterVisible = "visible";
58 // AdapterChangeCallback
59 const std::string kOnStateChanged = "onstatechanged";
60 const std::string kOnNameChanged = "onnamechanged";
61 const std::string kOnVisibilityChanged = "onvisibilitychanged";
62 const std::string kAdapterChangeCallbackEvent = "BluetoothAdapterChangeCallback";
63 // BluetoothProfileHandler
64 const std::string kBluetoothProfileHealth = "HEALTH";
65 const std::string kFeatureBluetoothHealth = "tizen.org/feature/network.bluetooth.health";
66 // DiscoverDevicesCallback
67 const std::string kOnDiscoverStarted = "onstarted";
68 const std::string kOnDiscoverFound = "ondevicefound";
69 const std::string kOnDiscoverDisappeared = "ondevicedisappeared";
70 const std::string kOnDiscoverFinished = "onfinished";
71 const std::string kAdapterDiscoverSuccessEvent = "BluetoothDiscoverDevicesSuccessCallback";
72 const std::string kAdapterDiscoverErrorEvent = "BluetoothDiscoverDevicesErrorCallback";
74 const std::string kDeviceAddress = "address";
75 const unsigned short kTimeout = 180;
78 static bool IsValidAddress(const std::string& address) {
80 const std::regex macAdressRegex{"([[:xdigit:]]{2}[:]){5}([[:xdigit:]]{2})"};
82 if (std::regex_match(address, macAdressRegex)) {
85 LoggerE("Invalid MAC address: %s", address.c_str());
89 static bool IsValidUUID(const std::string& uuid) {
91 const std::regex uuidRegex{
92 "[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}"};
94 if (std::regex_match(uuid, uuidRegex)) {
97 LoggerE("Invalid UUID: %s", uuid.c_str());
101 void BluetoothAdapter::StateChangedCB(int result, bt_adapter_state_e state, void* user_data) {
104 BluetoothAdapter* adapter = static_cast<BluetoothAdapter*>(user_data);
106 LoggerD("User data is NULL");
110 const bool powered = BT_ADAPTER_ENABLED == state;
111 bool previous_powered = adapter->is_powered_;
112 adapter->is_powered_ = powered;
114 adapter->power_state_listeners_.FireAll(powered);
117 // update visible state if bluetooth device has been turned on
118 adapter->is_visible_ = adapter->get_visible();
121 if (adapter->is_callback_set_ && previous_powered != powered && BT_ERROR_NONE == result) {
122 picojson::value value = picojson::value(picojson::object());
123 picojson::object* data_obj = &value.get<picojson::object>();
125 data_obj->insert(std::make_pair(kAction, picojson::value(kOnStateChanged)));
126 data_obj->insert(std::make_pair(kAdapterPowered, picojson::value(powered)));
128 adapter->instance_.FireEvent(kAdapterChangeCallbackEvent, value);
131 if (adapter->user_request_list_[SET_POWERED]) {
132 if (adapter->requested_powered_ != powered) {
136 PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
139 case BT_ERROR_ALREADY_DONE:
140 case BT_ERROR_NOT_ENABLED:
143 case BT_ERROR_NOW_IN_PROGRESS:
144 ret = LogAndCreateResult(
145 ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is busy",
146 ("StateChangedCB result: %d (%s)", result, get_error_message(result)));
149 ret = LogAndCreateResult(
150 ErrorCode::UNKNOWN_ERR, "Unknown exception",
151 ("StateChangedCB result: %d (%s)", result, get_error_message(result)));
154 adapter->instance_.AsyncResponse(adapter->user_request_callback_[SET_POWERED], ret);
155 adapter->user_request_list_[SET_POWERED] = false;
159 void BluetoothAdapter::NameChangedCB(char* name, void* user_data) {
162 BluetoothAdapter* adapter = static_cast<BluetoothAdapter*>(user_data);
164 LoggerD("User data is NULL");
168 if (adapter->is_callback_set_) {
169 picojson::value value = picojson::value(picojson::object());
170 picojson::object* data_obj = &value.get<picojson::object>();
172 data_obj->insert(std::make_pair(kAction, picojson::value(kOnNameChanged)));
173 data_obj->insert(std::make_pair(kName, picojson::value(name)));
175 adapter->instance_.FireEvent(kAdapterChangeCallbackEvent, value);
178 if (adapter->user_request_list_[SET_NAME] && name == adapter->requested_name_) {
179 std::shared_ptr<picojson::value> response =
180 std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
181 adapter->instance_.AsyncResponse(adapter->user_request_callback_[SET_NAME], response);
182 adapter->user_request_list_[SET_NAME] = false;
186 void BluetoothAdapter::VisibilityChangedCB(int result, bt_adapter_visibility_mode_e mode,
190 BluetoothAdapter* adapter = static_cast<BluetoothAdapter*>(user_data);
192 LoggerD("User data is NULL");
196 bool visible = BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE != mode;
197 bool previous_visible = adapter->is_visible_;
198 adapter->is_visible_ = visible;
200 if (adapter->is_callback_set_ && previous_visible != visible) {
201 picojson::value value = picojson::value(picojson::object());
202 picojson::object* data_obj = &value.get<picojson::object>();
204 data_obj->insert(std::make_pair(kAction, picojson::value(kOnVisibilityChanged)));
205 data_obj->insert(std::make_pair(kAdapterVisible, picojson::value(visible)));
207 adapter->instance_.FireEvent(kAdapterChangeCallbackEvent, value);
210 if (adapter->user_request_list_[SET_VISIBLE] && adapter->requested_visibility_ == mode) {
211 PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
213 if (BT_ERROR_NONE != result) {
214 ret = LogAndCreateResult(
215 ErrorCode::UNKNOWN_ERR, "Unknown exception",
216 ("VisibilityChangedCB error: %d (%s)", result, get_error_message(result)));
219 adapter->instance_.AsyncResponse(adapter->user_request_callback_[SET_VISIBLE], ret);
220 adapter->user_request_list_[SET_VISIBLE] = false;
224 static bool ForeachBondedDevicesCB(bt_device_info_s* device_info, void* user_data) {
226 if (nullptr == user_data) {
227 LoggerD("user data is NULL.");
231 if (nullptr == device_info) {
232 LoggerD("Device info is not valid.");
236 picojson::array* array = static_cast<picojson::array*>(user_data);
237 for (auto iter = array->begin(); iter != array->end(); iter++) {
238 if (!strcmp(device_info->remote_address, ((*iter).get<picojson::object>())
239 .find(kDeviceAddress)
240 ->second.get<std::string>()
242 BluetoothDevice::ToJson(device_info, &iter->get<picojson::object>());
247 array->push_back(picojson::value(picojson::object()));
249 BluetoothDevice::ToJson(device_info, &array->back().get<picojson::object>());
253 void BluetoothAdapter::DiscoveryStateChangedCB(int result,
254 bt_adapter_device_discovery_state_e discovery_state,
255 bt_adapter_device_discovery_info_s* discovery_info,
259 BluetoothAdapter* adapter = static_cast<BluetoothAdapter*>(user_data);
261 LoggerD("User data is NULL");
265 picojson::value value = picojson::value(picojson::object());
266 picojson::object* data_obj = &value.get<picojson::object>();
268 switch (discovery_state) {
269 case BT_ADAPTER_DEVICE_DISCOVERY_STARTED: {
270 if (adapter->user_request_list_[DISCOVER_DEVICES]) {
271 if (BT_ERROR_NONE == result) {
272 // store addresses of previously found devices into disappeared_addresses
273 adapter->disappeared_addresses_ = adapter->discovered_addresses_;
274 adapter->discovered_addresses_.clear();
275 adapter->discovered_devices_.clear();
277 data_obj->insert(std::make_pair(kAction, picojson::value(kOnDiscoverStarted)));
278 adapter->instance_.FireEvent(kAdapterDiscoverSuccessEvent, value);
280 LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error"), data_obj,
281 ("Wrong discovery state: %d", discovery_state));
282 adapter->instance_.FireEvent(kAdapterDiscoverErrorEvent, value);
283 adapter->user_request_list_[DISCOVER_DEVICES] = false;
288 case BT_ADAPTER_DEVICE_DISCOVERY_FINISHED: {
289 if (BT_ERROR_NONE == result || BT_ERROR_CANCELLED == result) {
290 if (adapter->user_request_list_[DISCOVER_DEVICES]) {
291 data_obj->insert(std::make_pair(kAction, picojson::value(kOnDiscoverFinished)));
293 for (auto it : adapter->disappeared_addresses_) {
294 picojson::value disapeared_val = picojson::value(picojson::object());
295 picojson::object* disapeared_obj = &disapeared_val.get<picojson::object>();
297 disapeared_obj->insert(
298 std::make_pair(kAction, picojson::value(kOnDiscoverDisappeared)));
299 disapeared_obj->insert(std::make_pair(kData, picojson::value(it)));
301 adapter->instance_.FireEvent(kAdapterDiscoverSuccessEvent, disapeared_val);
304 data_obj->insert(std::make_pair(kData, picojson::value(adapter->discovered_devices_)));
306 adapter->user_request_list_[DISCOVER_DEVICES] = false;
307 adapter->instance_.FireEvent(kAdapterDiscoverSuccessEvent, value);
310 if (adapter->user_request_list_[STOP_DISCOVERY]) {
311 std::shared_ptr<picojson::value> response =
312 std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
314 ReportSuccess(response->get<picojson::object>());
315 adapter->instance_.AsyncResponse(adapter->user_request_callback_[STOP_DISCOVERY],
318 adapter->user_request_list_[STOP_DISCOVERY] = false;
323 case BT_ADAPTER_DEVICE_DISCOVERY_FOUND: {
324 if (adapter->user_request_list_[DISCOVER_DEVICES]) {
325 if (BT_ERROR_NONE == result &&
326 adapter->discovered_addresses_.insert(discovery_info->remote_address).second) {
327 adapter->disappeared_addresses_.erase(discovery_info->remote_address);
329 data_obj->insert(std::make_pair(kAction, picojson::value(kOnDiscoverFound)));
330 picojson::value& data =
331 data_obj->insert(std::make_pair(kData, picojson::value(picojson::object())))
334 BluetoothDevice::ToJson(discovery_info, &data.get<picojson::object>());
335 adapter->discovered_devices_.push_back(data);
337 adapter->instance_.FireEvent(kAdapterDiscoverSuccessEvent, value);
343 LoggerD("Unknown state");
348 BluetoothAdapter::BluetoothAdapter(BluetoothInstance& instance)
349 : is_response_sent_(false),
350 is_visible_response_sent_(false),
351 is_callback_set_(false),
354 is_initialized_(false),
355 user_request_list_(),
356 user_request_callback_(),
357 requested_powered_(),
358 requested_visibility_(),
359 instance_(instance) {
361 if (BT_ERROR_NONE == bt_initialize()) {
362 LoggerD("Bluetooth service is initialized.");
363 is_initialized_ = true;
365 int ret = BT_ERROR_NONE;
366 ret |= bt_adapter_set_device_discovery_state_changed_cb(DiscoveryStateChangedCB, this);
367 ret |= bt_adapter_set_state_changed_cb(StateChangedCB, this);
368 ret |= bt_adapter_set_name_changed_cb(NameChangedCB, this);
369 ret |= bt_adapter_set_visibility_mode_changed_cb(VisibilityChangedCB, this);
371 if (BT_ERROR_NONE != ret) {
372 LoggerE("Setting listeners function failed.");
375 LoggerE("Bluetooth service initialization failed.");
378 bt_adapter_state_e state;
379 if (BT_ERROR_NONE == bt_adapter_get_state(&state)) {
380 is_powered_ = BT_ADAPTER_ENABLED == state;
383 bt_adapter_visibility_mode_e mode;
384 if (BT_ERROR_NONE == bt_adapter_get_visibility(&mode, nullptr)) {
385 is_visible_ = BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE != mode;
389 BluetoothAdapter::~BluetoothAdapter() {
391 bt_socket_unset_data_received_cb();
392 bt_socket_unset_connection_state_changed_cb();
394 for (auto it : connected_sockets_) {
395 bt_socket_disconnect_rfcomm(it);
398 for (auto it : registered_uuids_) {
399 bt_socket_destroy_rfcomm(it.second.first);
402 bt_adapter_unset_state_changed_cb();
403 bt_adapter_unset_name_changed_cb();
404 bt_adapter_unset_visibility_mode_changed_cb();
405 bt_adapter_unset_device_discovery_state_changed_cb();
407 if (is_initialized_) {
408 if (BT_ERROR_NONE == bt_deinitialize()) {
409 LoggerD("Bluetooth service is deinitialized.");
411 LoggerE("Bluetooth service deinitialization failed.");
416 std::string BluetoothAdapter::get_name() const {
418 char* name = nullptr;
419 std::string str_name = "";
420 if (BT_ERROR_NONE == bt_adapter_get_name(&name)) {
430 bool BluetoothAdapter::get_visible() const {
432 bt_adapter_visibility_mode_e mode;
434 if (BT_ERROR_NONE == bt_adapter_get_visibility(&mode, NULL)) {
435 return mode != BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE;
441 void BluetoothAdapter::set_visible(bool visible) {
442 is_visible_ = visible;
445 bool BluetoothAdapter::get_powered() {
449 void BluetoothAdapter::set_powered(bool powered) {
450 is_powered_ = powered;
453 bool BluetoothAdapter::is_initialized() const {
454 return is_initialized_;
457 void BluetoothAdapter::SetName(const picojson::value& data, picojson::object& out) {
460 CHECK_BACKWARD_COMPABILITY_PRIVILEGE_ACCESS(Privilege::kBluetooth, Privilege::kBluetoothAdmin,
463 const auto callback_handle = util::GetAsyncCallbackHandle(data);
464 const auto& args = util::GetArguments(data);
465 const auto name = FromJson<std::string>(args, "name");
467 PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
468 if (!this->is_initialized()) {
469 result = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
470 instance_.AsyncResponse(callback_handle, result);
474 if (!this->get_powered()) {
476 LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is turned off");
477 instance_.AsyncResponse(callback_handle, result);
481 if (get_name() == name) {
482 LoggerD("Requested the same name, calling success callback");
483 instance_.AsyncResponse(callback_handle, result);
487 if (this->user_request_list_[SET_NAME]) {
488 result = LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Already requested");
489 instance_.AsyncResponse(callback_handle, result);
493 this->user_request_list_[SET_NAME] = true;
494 this->user_request_callback_[SET_NAME] = callback_handle;
496 int ret = bt_adapter_set_name(name.c_str());
499 // bt_adapter_name_changed_cb() will be invoked
500 // if this function returns #BT_ERROR_NONE
501 this->requested_name_ = name;
503 case BT_ERROR_INVALID_PARAMETER:
505 LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid value",
506 ("bt_adapter_set_name error: %d (%s)", ret, get_error_message(ret)));
510 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown exception",
511 ("bt_adapter_set_name error: %d (%s)", ret, get_error_message(ret)));
514 if (result.IsError()) {
515 this->user_request_list_[SET_NAME] = false;
516 instance_.AsyncResponse(callback_handle, result);
521 void BluetoothAdapter::SetPowered(const picojson::value& data, picojson::object& out) {
524 "DEPRECATION WARNING: setPowered() is deprecated and will be removed from next release. "
525 "Let the user turn on/off Bluetooth through the Settings application instead.");
527 CHECK_BACKWARD_COMPABILITY_PRIVILEGE_ACCESS(Privilege::kBluetooth, Privilege::kBluetoothAdmin,
530 const auto callback_handle = util::GetAsyncCallbackHandle(data);
531 const auto& args = util::GetArguments(data);
532 const auto new_powered = FromJson<bool>(args, "powered");
534 PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
536 if (!this->is_initialized()) {
537 ret = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
538 instance_.AsyncResponse(callback_handle, ret);
542 if (this->user_request_list_[SET_POWERED]) {
543 ret = LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Already requested");
544 instance_.AsyncResponse(callback_handle, ret);
548 bool cur_powered = this->get_powered();
550 if (new_powered == cur_powered) {
551 LoggerD("Requested already set value, calling success callback");
552 instance_.AsyncResponse(callback_handle, ret);
556 this->requested_powered_ = new_powered;
557 this->user_request_callback_[SET_POWERED] = callback_handle;
558 #ifdef APP_CONTROL_SETTINGS_SUPPORT
559 app_control_h app_control_ptr{nullptr};
560 int err = app_control_create(&app_control_ptr);
561 if (err != APP_CONTROL_ERROR_NONE) {
562 ret = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown exception",
563 ("app_control_create() failed: %d", err));
564 instance_.AsyncResponse(callback_handle, ret);
568 std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)> service(
569 app_control_ptr, &app_control_destroy);
571 err = app_control_set_operation(service.get(), "http://tizen.org/appcontrol/operation/edit");
572 if (err != APP_CONTROL_ERROR_NONE) {
573 ret = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown exception",
574 ("app_control_set_operation() failed: %d", err));
575 instance_.AsyncResponse(callback_handle, ret);
579 err = app_control_set_mime(service.get(), "application/x-bluetooth-on-off");
580 if (err != APP_CONTROL_ERROR_NONE) {
581 ret = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown exception",
582 ("app_control_set_mime() failed: %d", err));
583 instance_.AsyncResponse(callback_handle, ret);
587 this->is_response_sent_ = false;
588 app_control_reply_cb reply_cb = [](app_control_h request, app_control_h reply,
589 app_control_result_e app_res, void* user_data) {
590 LoggerD("Inside app_control_send_launch_request() reply callback");
592 BluetoothAdapter* adapter = static_cast<BluetoothAdapter*>(user_data);
594 if (adapter->is_response_sent_) {
595 LoggerE("response already sent");
599 if (app_res < APP_CONTROL_RESULT_SUCCEEDED) {
600 LoggerE("app control setPowered failed");
601 adapter->is_response_sent_ = true;
602 adapter->instance_.AsyncResponse(
603 adapter->user_request_callback_[SET_POWERED],
604 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown exception"));
606 adapter->user_request_list_[SET_POWERED] = true;
609 app_control_result_cb result_cb = [](app_control_h request, app_control_error_e app_res,
611 LoggerD("Inside app_control_send_launch_request() result callback");
613 BluetoothAdapter* adapter = static_cast<BluetoothAdapter*>(user_data);
615 if (adapter->is_response_sent_) {
616 LoggerE("response already sent");
620 if (APP_CONTROL_ERROR_NONE != app_res) {
621 LoggerE("app control setPowered failed");
622 adapter->user_request_list_[SET_POWERED] = false;
623 adapter->is_response_sent_ = true;
624 adapter->instance_.AsyncResponse(
625 adapter->user_request_callback_[SET_POWERED],
626 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown exception"));
628 adapter->user_request_list_[SET_POWERED] = true;
632 err = app_control_send_launch_request_async(service.get(), result_cb, reply_cb, this);
634 if (err != APP_CONTROL_ERROR_NONE) {
635 ret = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown exception",
636 ("app_control_send_launch_request() failed: %d", err));
637 instance_.AsyncResponse(callback_handle, ret);
641 this->user_request_list_[SET_POWERED] = true;
645 ntv_ret = bt_adapter_enable();
647 ntv_ret = bt_adapter_disable();
651 ret = LogAndCreateResult(
652 ErrorCode::UNKNOWN_ERR, "Unknown exception",
653 ("enable/disable bt adapter failed, error: %d (%s)", ntv_ret, get_error_message(ntv_ret)));
654 instance_.AsyncResponse(callback_handle, ret);
660 void BluetoothAdapter::SetVisible(const picojson::value& data, picojson::object& out) {
663 "DEPRECATION WARNING: setVisible() is deprecated and will be removed from next release. "
664 "Let the user change the Bluetooth visibility through the Settings application instead.");
666 CHECK_BACKWARD_COMPABILITY_PRIVILEGE_ACCESS(Privilege::kBluetooth, Privilege::kBluetoothManager,
669 const auto callback_handle = util::GetAsyncCallbackHandle(data);
670 const auto& args = util::GetArguments(data);
671 const auto visible = FromJson<bool>(args, "visible");
673 unsigned short new_timeout = kTimeout;
675 new_timeout = static_cast<unsigned short>(FromJson<double>(args, "timeout"));
678 PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
680 if (!this->is_initialized()) {
681 ret = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
682 instance_.AsyncResponse(callback_handle, ret);
686 if (this->user_request_list_[SET_VISIBLE]) {
687 ret = LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Already requested");
688 instance_.AsyncResponse(callback_handle, ret);
692 if (!this->get_powered()) {
694 LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is turned off");
695 instance_.AsyncResponse(callback_handle, ret);
699 bt_adapter_visibility_mode_e new_mode = BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE;
701 if (0 == new_timeout) {
702 new_mode = BT_ADAPTER_VISIBILITY_MODE_GENERAL_DISCOVERABLE;
704 new_mode = BT_ADAPTER_VISIBILITY_MODE_LIMITED_DISCOVERABLE;
708 bt_adapter_visibility_mode_e cur_mode = BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE;
710 int ntv_ret = bt_adapter_get_visibility(&cur_mode, &cur_timeout);
711 if (BT_ERROR_NONE != ntv_ret) {
712 ret = LogAndCreateResult(
713 ErrorCode::UNKNOWN_ERR, "Unknown exception",
714 ("bt_adapter_get_visibility error: %d (%s)", ntv_ret, get_error_message(ntv_ret)));
715 instance_.AsyncResponse(callback_handle, ret);
719 if (new_mode == cur_mode && (BT_ADAPTER_VISIBILITY_MODE_LIMITED_DISCOVERABLE != new_mode ||
720 (unsigned int)cur_timeout == new_timeout)) {
721 instance_.AsyncResponse(callback_handle, ret);
725 this->requested_visibility_ = new_mode;
726 this->user_request_callback_[SET_VISIBLE] = callback_handle;
727 #ifdef APP_CONTROL_SETTINGS_SUPPORT
728 app_control_h tmp_service{nullptr};
729 int err = app_control_create(&tmp_service);
730 if (err != APP_CONTROL_ERROR_NONE) {
731 ret = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown exception",
732 ("app_control_create() failed: %d (%s)", err, get_error_message(err)));
733 instance_.AsyncResponse(callback_handle, ret);
737 std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)> service(
738 tmp_service, &app_control_destroy);
740 err = app_control_set_operation(service.get(), "http://tizen.org/appcontrol/operation/edit");
741 if (err != APP_CONTROL_ERROR_NONE) {
742 ret = LogAndCreateResult(
743 ErrorCode::UNKNOWN_ERR, "Unknown exception",
744 ("app_control_set_operation() failed: %d (%s)", err, get_error_message(err)));
745 instance_.AsyncResponse(callback_handle, ret);
749 err = app_control_set_mime(service.get(), "application/x-bluetooth-visibility");
750 if (err != APP_CONTROL_ERROR_NONE) {
752 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown exception",
753 ("app_control_set_mime() failed: %d (%s)", err, get_error_message(err)));
754 instance_.AsyncResponse(callback_handle, ret);
758 this->is_response_sent_ = false;
759 app_control_reply_cb reply_cb = [](app_control_h request, app_control_h reply,
760 app_control_result_e app_res, void* user_data) {
761 LoggerD("Inside app_control_send_launch_request_async() reply callback");
762 BluetoothAdapter* adapter = static_cast<BluetoothAdapter*>(user_data);
764 if (adapter->is_visible_response_sent_) {
765 LoggerE("response already sent");
769 if (app_res < APP_CONTROL_RESULT_SUCCEEDED) {
770 LoggerE("app control setVisible failed");
771 adapter->is_visible_response_sent_ = true;
772 adapter->instance_.AsyncResponse(
773 adapter->user_request_callback_[SET_VISIBLE],
774 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown exception"));
776 adapter->user_request_list_[SET_VISIBLE] = true;
780 app_control_result_cb result_cb = [](app_control_h request, app_control_error_e app_res,
782 LoggerD("Inside app_control_send_launch_request_async() result callback");
784 BluetoothAdapter* adapter = static_cast<BluetoothAdapter*>(user_data);
786 if (adapter->is_visible_response_sent_) {
787 LoggerE("response already sent");
791 if (APP_CONTROL_ERROR_NONE != app_res) {
792 LoggerE("app control setVisible failed");
793 adapter->user_request_list_[SET_VISIBLE] = false;
794 adapter->is_visible_response_sent_ = true;
795 adapter->instance_.AsyncResponse(
796 adapter->user_request_callback_[SET_VISIBLE],
797 LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown exception"));
799 adapter->user_request_list_[SET_VISIBLE] = true;
803 err = app_control_send_launch_request_async(service.get(), result_cb, reply_cb, this);
804 if (err != APP_CONTROL_ERROR_NONE) {
805 ret = LogAndCreateResult(
806 ErrorCode::UNKNOWN_ERR, "Unknown exception",
807 ("app_control_send_launch_request_async() failed: %d (%s)", err, get_error_message(err)));
808 instance_.AsyncResponse(callback_handle, ret);
813 this->user_request_list_[SET_VISIBLE] = true;
814 ntv_ret = bt_adapter_set_visibility(new_mode, new_timeout);
818 // bt_adapter_visibility_mode_changed_cb() will be invoked
819 // if this function returns #BT_ERROR_NONE
821 case BT_ERROR_INVALID_PARAMETER:
822 ret = LogAndCreateResult(
823 ErrorCode::INVALID_VALUES_ERR, "Invalid value",
824 ("bt_adapter_set_visibility error: %d (%s)", ntv_ret, get_error_message(ntv_ret)));
827 ret = LogAndCreateResult(
828 ErrorCode::UNKNOWN_ERR, "Unknown exception",
829 ("bt_adapter_set_visibility error: %d (%s)", ntv_ret, get_error_message(ntv_ret)));
833 instance_.AsyncResponse(callback_handle, ret);
834 this->user_request_list_[SET_VISIBLE] = false;
840 void BluetoothAdapter::DiscoverDevices(const picojson::value& /* data */, picojson::object& out) {
843 CHECK_BACKWARD_COMPABILITY_PRIVILEGE_ACCESS(Privilege::kBluetooth, Privilege::kBluetoothGap,
846 PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
848 if (!is_initialized_) {
849 result = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
852 if (result.IsSuccess() && this->user_request_list_[DISCOVER_DEVICES]) {
853 result = LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Already requested");
856 if (result.IsSuccess() && !get_powered()) {
858 LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is turned off");
861 if (result.IsSuccess()) {
862 auto ret = bt_adapter_start_device_discovery();
863 if (BT_ERROR_NONE != ret) {
864 result = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "An unknown error occurred");
868 if (result.IsSuccess()) {
869 this->user_request_list_[DISCOVER_DEVICES] = true;
871 std::shared_ptr<picojson::value> response =
872 std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
874 LogAndReportError(result, &response->get<picojson::object>());
875 TaskQueue::GetInstance().Async<picojson::value>(
876 [this](const std::shared_ptr<picojson::value>& result) {
877 instance_.FireEvent(kAdapterDiscoverErrorEvent, result);
883 void BluetoothAdapter::StopDiscovery(const picojson::value& data, picojson::object& out) {
886 CHECK_BACKWARD_COMPABILITY_PRIVILEGE_ACCESS(Privilege::kBluetooth, Privilege::kBluetoothGap,
889 const auto callback_handle = util::GetAsyncCallbackHandle(data);
891 PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
893 if (!this->is_initialized()) {
894 result = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
897 if (result.IsSuccess() && this->user_request_list_[STOP_DISCOVERY]) {
898 result = LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Already requested");
901 if (result.IsSuccess() && this->get_powered()) {
902 bool is_discovering = false;
903 bt_adapter_is_discovering(&is_discovering);
905 if (!is_discovering) {
906 instance_.AsyncResponse(callback_handle, result);
910 this->user_request_list_[STOP_DISCOVERY] = true;
911 this->user_request_callback_[STOP_DISCOVERY] = callback_handle;
912 int ret = bt_adapter_stop_device_discovery();
914 case BT_ERROR_NONE: {
915 // This function invokes bt_adapter_device_discovery_state_changed_cb().
919 this->user_request_list_[STOP_DISCOVERY] = false;
920 result = LogAndCreateResult(
921 ErrorCode::UNKNOWN_ERR, "Unknown exception",
922 ("bt_adapter_stop_device_discovery error: %d (%s)", ret, get_error_message(ret)));
925 } else if (result.IsSuccess()) {
927 LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is turned off");
930 if (result.IsError()) {
931 instance_.AsyncResponse(callback_handle, result);
935 void BluetoothAdapter::GetKnownDevices(const picojson::value& data, picojson::object& out) {
938 CHECK_BACKWARD_COMPABILITY_PRIVILEGE_ACCESS(Privilege::kBluetooth, Privilege::kBluetoothGap,
941 const auto callback_handle = util::GetAsyncCallbackHandle(data);
943 auto get_known_devices = [this](const std::shared_ptr<picojson::value>& response) -> void {
944 PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
946 if (!this->is_initialized()) {
947 ret = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
950 if (ret.IsSuccess() && this->get_powered()) {
951 picojson::object& response_obj = response->get<picojson::object>();
952 picojson::value result = picojson::value(picojson::object());
953 picojson::object& result_obj = result.get<picojson::object>();
954 picojson::array& array =
955 result_obj.insert(std::make_pair("devices", picojson::value(picojson::array())))
956 .first->second.get<picojson::array>();
958 array = discovered_devices_;
960 int ntv_ret = bt_adapter_foreach_bonded_device(ForeachBondedDevicesCB, &array);
961 if (BT_ERROR_NONE == ntv_ret) {
962 ReportSuccess(result, response_obj);
964 ret = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown exception",
965 ("bt_adapter_foreach_bonded_device error %d (%s)", ntv_ret,
966 get_error_message(ntv_ret)));
968 } else if (ret.IsSuccess()) {
969 ret = LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR,
970 "Bluetooth device is turned off");
974 LogAndReportError(ret, &response->get<picojson::object>());
977 auto get_known_devices_response =
978 [this, callback_handle](const std::shared_ptr<picojson::value>& response) -> void {
979 instance_.SyncResponse(callback_handle, response);
982 auto queue_data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
984 TaskQueue::GetInstance().Queue<picojson::value>(get_known_devices, get_known_devices_response,
990 void BluetoothAdapter::GetDevice(const picojson::value& data, picojson::object& out) {
993 CHECK_BACKWARD_COMPABILITY_PRIVILEGE_ACCESS(Privilege::kBluetooth, Privilege::kBluetoothGap,
996 const auto callback_handle = util::GetAsyncCallbackHandle(data);
997 const auto& args = util::GetArguments(data);
999 const auto& address = FromJson<std::string>(args, "address");
1001 auto get_device = [this, address](const std::shared_ptr<picojson::value>& response) -> void {
1002 ScopeLogger("Entered into asynchronous function");
1003 PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
1004 if (!IsValidAddress(address)) {
1005 ret = LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Wrong address");
1008 if (ret.IsSuccess() && !this->is_initialized()) {
1009 ret = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
1011 if (ret.IsSuccess() && this->get_powered()) {
1012 picojson::object& response_obj = response->get<picojson::object>();
1013 bt_device_info_s* info = nullptr;
1015 if (bt_adapter_get_bonded_device_info(address.c_str(), &info) == BT_ERROR_NONE &&
1017 picojson::value result = picojson::value(picojson::object());
1018 picojson::object& result_obj = result.get<picojson::object>();
1020 BluetoothDevice::ToJson(info, &result_obj);
1021 ReportSuccess(result, response_obj);
1022 bt_adapter_free_device_info(info);
1026 auto is_address = discovered_addresses_.find(address);
1027 if (is_address != discovered_addresses_.end()) {
1028 for (auto iter = discovered_devices_.begin(); iter != discovered_devices_.end(); iter++) {
1029 if (!strcmp(address.c_str(), ((*iter).get<picojson::object>())
1030 .find(kDeviceAddress)
1031 ->second.get<std::string>()
1033 ReportSuccess(*iter, response_obj);
1038 ret = LogAndCreateResult(
1039 ErrorCode::NOT_FOUND_ERR, "There is no device with the given address",
1040 ("There is no device with the given address: %s", address.c_str()));
1042 } else if (ret.IsSuccess()) {
1043 ret = LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR,
1044 "Bluetooth device is turned off");
1047 if (ret.IsError()) {
1048 LogAndReportError(ret, &response->get<picojson::object>());
1052 auto get_device_response =
1053 [this, callback_handle](const std::shared_ptr<picojson::value>& response) -> void {
1054 ScopeLogger("Entered into asynchronous function");
1055 instance_.SyncResponse(callback_handle, response);
1058 auto queue_data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
1060 TaskQueue::GetInstance().Queue<picojson::value>(get_device, get_device_response, queue_data);
1065 class BondingHandler {
1067 BondingHandler(BluetoothInstance& instance, double callback_handle, const std::string& address)
1068 : instance_(instance), callback_handle_(callback_handle), address_(address) {
1072 void set_address(const std::string& address) {
1076 const std::string& address() const {
1080 void Invoke(const PlatformResult& result, const std::shared_ptr<picojson::value>& response) {
1083 if (result.IsError()) {
1084 LogAndReportError(result, &response->get<picojson::object>());
1086 ReportSuccess(response->get<picojson::object>());
1089 instance_.AsyncResponse(callback_handle_, response);
1093 BluetoothInstance& instance_;
1094 double callback_handle_;
1095 std::string address_;
1098 void BluetoothAdapter::CreateBonding(const picojson::value& data, picojson::object& out) {
1101 CHECK_BACKWARD_COMPABILITY_PRIVILEGE_ACCESS(Privilege::kBluetooth, Privilege::kBluetoothGap,
1104 const auto callback_handle = util::GetAsyncCallbackHandle(data);
1105 const auto& args = util::GetArguments(data);
1107 const auto& address = FromJson<std::string>(args, "address");
1109 auto create_bonding = [address, callback_handle, this]() -> void {
1110 ScopeLogger("Entered into asynchronous function, create_bonding");
1111 PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
1112 if (!IsValidAddress(address)) {
1113 result = LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Wrong address",
1114 ("Wrong address: %s", address.c_str()));
1117 if (result.IsSuccess() && !this->is_initialized()) {
1118 result = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
1121 if (result.IsSuccess() && this->get_powered()) {
1122 auto bond_create_callback = [](int callback_result, bt_device_info_s* device_info,
1124 ScopeLogger("Entered into asynchronous function, bond_create_callback");
1126 BondingHandler* handler = static_cast<BondingHandler*>(user_data);
1128 LoggerW("user_data is nullptr");
1132 LoggerW("device_info is nullptr");
1136 PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
1137 std::shared_ptr<picojson::value> response =
1138 std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
1140 std::string address(handler->address());
1141 for (size_t i = 0; i < handler->address().length(); i++) {
1142 address[i] = toupper(handler->address()[i]);
1145 std::string remote_address(device_info->remote_address);
1146 for (size_t i = 0; i < sizeof(device_info->remote_address); i++) {
1147 remote_address[i] = toupper(device_info->remote_address[i]);
1150 if (!strcmp(address.c_str(), remote_address.c_str())) { // requested event
1151 if (BT_ERROR_NONE == callback_result && nullptr != device_info) {
1152 picojson::object& response_obj = response->get<picojson::object>();
1153 picojson::value result = picojson::value(picojson::object());
1154 picojson::object& result_obj = result.get<picojson::object>();
1156 BluetoothDevice::ToJson(device_info, &result_obj);
1157 result_obj["address"] = picojson::value(handler->address());
1158 ReportSuccess(result, response_obj);
1159 } else if (BT_ERROR_REMOTE_DEVICE_NOT_FOUND == callback_result) {
1160 ret = LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Not found",
1161 ("bond_create_callback result: %d (%s)", callback_result,
1162 get_error_message(callback_result)));
1164 ret = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown exception",
1165 ("bond_create_callback result: %d (%s)", callback_result,
1166 get_error_message(callback_result)));
1169 handler->Invoke(ret, response);
1171 bt_device_unset_bond_created_cb();
1172 } else { // unexpected event
1173 LoggerD("An unexpected bonding detected");
1177 BondingHandler* handler = new BondingHandler(instance_, callback_handle, address);
1178 int ret = bt_device_set_bond_created_cb(bond_create_callback, handler);
1179 if (BT_ERROR_NONE != ret) {
1181 // We ignore other error types that can be in ret, because they are highly improbable
1182 result = LogAndCreateResult(
1183 ErrorCode::UNKNOWN_ERR, "Unknown error",
1184 ("bt_device_set_bond_created_cb error: %d (%s)", ret, get_error_message(ret)));
1186 LoggerD("bt_device_set_bond_created_cb() succeeded");
1188 ret = bt_device_create_bond(address.c_str());
1191 case BT_ERROR_NONE: {
1192 LoggerD("bt_device_create_bond() succeeded");
1195 case BT_ERROR_INVALID_PARAMETER: {
1196 bt_device_unset_bond_created_cb();
1198 result = LogAndCreateResult(
1199 ErrorCode::INVALID_VALUES_ERR, "Invalid value",
1200 ("bt_device_create_bond error: %d (%s)", ret, get_error_message(ret)));
1204 bt_device_unset_bond_created_cb();
1206 result = LogAndCreateResult(
1207 ErrorCode::UNKNOWN_ERR, "Unknown error",
1208 ("bt_device_create_bond error: %d (%s)", ret, get_error_message(ret)));
1212 } else if (result.IsSuccess()) {
1213 result = LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR,
1214 "Bluetooth device is turned off");
1217 if (result.IsError()) {
1218 instance_.AsyncResponse(callback_handle, result);
1221 TaskQueue::GetInstance().Queue(create_bonding);
1225 void BluetoothAdapter::DestroyBonding(const picojson::value& data, picojson::object& out) {
1228 CHECK_BACKWARD_COMPABILITY_PRIVILEGE_ACCESS(Privilege::kBluetooth, Privilege::kBluetoothGap,
1231 const auto callback_handle = util::GetAsyncCallbackHandle(data);
1232 const auto& args = util::GetArguments(data);
1234 const auto& address = FromJson<std::string>(args, "address");
1236 auto destroy_bonding = [address, callback_handle, this]() -> void {
1237 ScopeLogger("Entered into asynchronous function, destroy_bonding");
1238 PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
1239 if (!IsValidAddress(address)) {
1240 result = LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Wrong address",
1241 ("Wrong address: %s", address.c_str()));
1243 if (result.IsSuccess() && !this->is_initialized()) {
1244 result = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
1247 if (result.IsSuccess() && this->get_powered()) {
1248 bt_device_info_s* device_info = nullptr;
1249 int ret = bt_adapter_get_bonded_device_info(address.c_str(), &device_info);
1251 if (BT_ERROR_NONE != ret || nullptr == device_info) {
1252 result = LogAndCreateResult(ErrorCode::NOT_FOUND_ERR, "Not found",
1253 ("There is no bonding %d (%s)", ret, get_error_message(ret)));
1255 bt_adapter_free_device_info(device_info);
1257 auto bond_destroy_callback = [](int callback_result, char* remote_address,
1259 LoggerD("bond_destroy_callback");
1261 BondingHandler* handler = static_cast<BondingHandler*>(user_data);
1263 LoggerW("user_data is nullptr");
1267 PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
1268 std::shared_ptr<picojson::value> response =
1269 std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
1271 std::string address(handler->address());
1272 for (auto& c : address) {
1276 std::string r_address(remote_address);
1277 for (auto& c : r_address) {
1281 if (!strcmp(address.c_str(), r_address.c_str())) { // requested event
1282 if (BT_ERROR_NONE != callback_result) {
1283 ret = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown exception",
1284 ("bond_destroy_callback result error: %d (%s)",
1285 callback_result, get_error_message(callback_result)));
1288 handler->Invoke(ret, response);
1290 bt_device_unset_bond_destroyed_cb();
1291 } else { // unexpected event
1292 LoggerD("An unexpected bonding detected");
1296 BondingHandler* handler = new BondingHandler(instance_, callback_handle, address);
1297 bt_device_set_bond_destroyed_cb(bond_destroy_callback, handler);
1299 int ret = bt_device_destroy_bond(address.c_str());
1302 case BT_ERROR_NONE: {
1303 LoggerD("bt_device_destroy_bond() succeeded");
1306 case BT_ERROR_INVALID_PARAMETER: {
1307 bt_device_unset_bond_destroyed_cb();
1309 result = LogAndCreateResult(
1310 ErrorCode::INVALID_VALUES_ERR, "Invalid value",
1311 ("bt_device_destroy_bond error: %d (%s)", ret, get_error_message(ret)));
1315 bt_device_unset_bond_destroyed_cb();
1317 result = LogAndCreateResult(
1318 ErrorCode::UNKNOWN_ERR, "Unknown exception",
1319 ("bt_device_destroy_bond error: %d (%s)", ret, get_error_message(ret)));
1323 } else if (result.IsSuccess()) {
1324 result = LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR,
1325 "Bluetooth device is turned off");
1328 if (result.IsError()) {
1329 instance_.AsyncResponse(callback_handle, result);
1332 TaskQueue::GetInstance().Queue(destroy_bonding);
1336 void BluetoothAdapter::RegisterRFCOMMServiceByUUID(const picojson::value& data,
1337 picojson::object& out) {
1340 CHECK_BACKWARD_COMPABILITY_PRIVILEGE_ACCESS(Privilege::kBluetooth, Privilege::kBluetoothSpp,
1343 const auto callback_handle = util::GetAsyncCallbackHandle(data);
1344 const auto& args = util::GetArguments(data);
1346 const auto& uuid = FromJson<std::string>(args, "uuid");
1347 const auto& name = FromJson<std::string>(args, "name");
1349 auto rfcomm = [this, uuid, name](const std::shared_ptr<picojson::value>& response) -> void {
1350 ScopeLogger("Entered into asynchronous function, rfcomm");
1351 PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
1352 if (!this->is_initialized()) {
1353 result = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
1356 if (result.IsSuccess() && !IsValidUUID(uuid)) {
1357 result = LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Wrong UUID",
1358 ("Wrong UUID: %s", uuid.c_str()));
1361 if (result.IsSuccess() && this->get_powered()) {
1362 bool is_registered = false;
1363 int ret = bt_adapter_is_service_used(uuid.c_str(), &is_registered);
1365 if (BT_ERROR_NONE == ret && is_registered) {
1366 result = LogAndCreateResult(
1367 ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Already requested",
1368 ("bt_adapter_is_service_used error: %d (%s)", ret, get_error_message(ret)));
1371 ret = bt_socket_create_rfcomm(uuid.c_str(), &socket);
1374 case BT_ERROR_NONE: {
1375 int ret_in = bt_socket_listen_and_accept_rfcomm(socket, 0);
1377 case BT_ERROR_NONE: {
1378 LoggerD("bt_socket_listen() succeeded");
1379 bt_socket_set_connection_state_changed_cb(OnSocketConnected, this);
1381 registered_uuids_.insert(std::make_pair(uuid, std::make_pair(socket, false)));
1383 ReportSuccess(response->get<picojson::object>());
1387 case BT_ERROR_INVALID_PARAMETER: {
1388 result = LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid value",
1389 ("bt_socket_listen_and_accept_rfcomm error: %d (%s)",
1390 ret_in, get_error_message(ret_in)));
1395 result = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown error",
1396 ("bt_socket_listen_and_accept_rfcomm error: %d (%s)",
1397 ret_in, get_error_message(ret_in)));
1403 case BT_ERROR_INVALID_PARAMETER:
1404 result = LogAndCreateResult(
1405 ErrorCode::INVALID_VALUES_ERR, "Invalid value",
1406 ("bt_socket_create_rfcomm error: %d (%s)", ret, get_error_message(ret)));
1409 result = LogAndCreateResult(
1410 ErrorCode::UNKNOWN_ERR, "Unknown error",
1411 ("bt_socket_create_rfcomm error: %d (%s)", ret, get_error_message(ret)));
1415 } else if (result.IsSuccess()) {
1416 result = LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR,
1417 "Bluetooth device is turned off");
1420 if (result.IsError()) {
1421 LogAndReportError(result, &response->get<picojson::object>());
1425 auto rfcomm_response =
1426 [this, callback_handle](const std::shared_ptr<picojson::value>& response) -> void {
1427 ScopeLogger("Entered into asynchronous function, rfcomm_response");
1428 instance_.SyncResponse(callback_handle, response);
1431 auto queue_data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
1433 TaskQueue::GetInstance().Queue<picojson::value>(rfcomm, rfcomm_response, queue_data);
1438 void BluetoothAdapter::UnregisterUUID(const std::string& uuid, int callback_handle) {
1441 PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
1442 if (!IsValidUUID(uuid)) {
1443 result = LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Wrong UUID",
1444 ("Wrong UUID: %s", uuid.c_str()));
1447 if (result.IsSuccess() && is_powered_) {
1448 auto iter = registered_uuids_.find(uuid);
1449 if (iter != registered_uuids_.end()) {
1450 int ntv_ret = bt_socket_destroy_rfcomm(iter->second.first);
1451 if (BT_ERROR_NONE == ntv_ret) {
1452 registered_uuids_.erase(iter);
1454 result = LogAndCreateResult(
1455 ErrorCode::UNKNOWN_ERR, "Unknown exception",
1456 ("bt_socket_destroy_rfcomm error: %d (%s)", ntv_ret, get_error_message(ntv_ret)));
1460 if (registered_uuids_.empty() && connection_requests_.empty() && connected_sockets_.empty()) {
1461 bt_socket_unset_connection_state_changed_cb();
1463 } else if (result.IsSuccess()) {
1465 LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is turned off");
1468 instance_.AsyncResponse(callback_handle, result);
1471 void BluetoothAdapter::GetBluetoothProfileHandler(const picojson::value& data,
1472 picojson::object& out) {
1475 const auto& args = util::GetArguments(data);
1476 auto profile = FromJson<std::string>(args, "profileType");
1478 PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
1480 if (kBluetoothProfileHealth == profile) {
1481 bool supported = false;
1482 if (SYSTEM_INFO_ERROR_NONE !=
1483 system_info_get_platform_bool(kFeatureBluetoothHealth.c_str(), &supported)) {
1484 LoggerW("Can't check if BT health profile is supported or not");
1488 result = LogAndCreateResult(ErrorCode::NOT_SUPPORTED_ERR,
1489 "Bluetooth health profile is not supported");
1491 LoggerD("BT health profile is supported");
1494 result = LogAndCreateResult(ErrorCode::TYPE_MISMATCH_ERR, "Wrong profile type.");
1497 if (result.IsSuccess()) {
1500 LogAndReportError(result, &out);
1504 void BluetoothAdapter::GetName(const picojson::value& /* data */, picojson::object& out) {
1507 ReportSuccess(picojson::value(get_name()), out);
1510 void BluetoothAdapter::GetAddress(const picojson::value& /* data */, picojson::object& out) {
1513 if (!is_initialized_) {
1515 PlatformResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized."), &out);
1519 std::string str_address = "";
1520 char* address = nullptr;
1521 if (BT_ERROR_NONE == bt_adapter_get_address(&address)) {
1523 str_address = address;
1528 ReportSuccess(picojson::value(str_address), out);
1531 void BluetoothAdapter::GetPowered(const picojson::value& /* data */, picojson::object& out) {
1534 ReportSuccess(picojson::value(is_powered_), out);
1537 void BluetoothAdapter::GetVisible(const picojson::value& /* data */, picojson::object& out) {
1540 ReportSuccess(picojson::value(get_visible()), out);
1543 void BluetoothAdapter::OnSocketConnected(int result, bt_socket_connection_state_e state,
1544 bt_socket_connection_s* connection, void* user_data) {
1547 BluetoothAdapter* object = static_cast<BluetoothAdapter*>(user_data);
1550 LoggerW("user_data is NULL");
1555 LoggerW("connection is NULL");
1559 if (BT_SOCKET_SERVER == connection->local_role) {
1562 const auto iter = object->registered_uuids_.find(connection->service_uuid);
1563 if (iter == object->registered_uuids_.end()) {
1564 LoggerW("Connection state has changed unexpectedly");
1568 if (BT_SOCKET_CONNECTED == state) { // connected when Server
1569 if (BT_ERROR_NONE == result) {
1570 // Update registered_uuids_ state
1571 iter->second.second = true;
1573 // Call BluetoothServiceHandler.onconnect
1574 object->instance_.FireEvent("BLUETOOTH_SERVICE_ONCONNECT",
1575 BluetoothSocket::ToJson(connection));
1577 // Update connected_sockets_
1578 object->connected_sockets_.push_back(connection->socket_fd);
1579 bt_socket_set_data_received_cb(OnSocketReceivedData, user_data);
1581 LoggerW("Establishing a connection failed");
1584 } else { // disconnected when Server
1585 if (BT_ERROR_NONE == result) {
1586 // Update registered_uuids_ state
1587 iter->second.second = false;
1588 object->RemoveSocket(connection->socket_fd);
1590 LoggerW("Disconnecting a connection failed");
1593 } else if (BT_SOCKET_CLIENT == connection->local_role) {
1596 if (BT_SOCKET_CONNECTED == state) { // connected when Client
1597 const auto range = object->connection_requests_.equal_range(connection->remote_address);
1598 const auto end = object->connection_requests_.end();
1601 for (auto it = range.first; it != range.second; ++it) {
1602 if (strcmp(it->second->uuid_.c_str(), connection->service_uuid) == 0) {
1608 if (end == request) {
1609 LoggerW("Connection state has changed unexpectedly");
1613 std::shared_ptr<picojson::value> response =
1614 std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
1616 if (BT_ERROR_NONE == result) {
1617 object->connected_sockets_.push_back(connection->socket_fd);
1618 bt_socket_set_data_received_cb(OnSocketReceivedData, user_data);
1620 ReportSuccess(BluetoothSocket::ToJson(connection), response->get<picojson::object>());
1622 LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Not found"),
1623 &response->get<picojson::object>());
1626 const auto request_callback_handle = request->second->callback_handle_;
1627 // request will be handled, can be safely removed
1628 object->connection_requests_.erase(request);
1630 object->instance_.SyncResponse(request_callback_handle, response);
1631 } else { // disconnected when Client
1632 if (result == BT_ERROR_NONE) {
1633 object->RemoveSocket(connection->socket_fd);
1635 LoggerW("Disconnecting a connection failed");
1639 LoggerW("Unknown role");
1643 if (object->connected_sockets_.empty()) {
1644 bt_socket_unset_data_received_cb();
1647 if (object->registered_uuids_.empty() && object->connection_requests_.empty() &&
1648 object->connected_sockets_.empty()) {
1649 bt_socket_unset_connection_state_changed_cb();
1653 void BluetoothAdapter::OnSocketReceivedData(bt_socket_received_data_s* data, void* user_data) {
1656 BluetoothAdapter* object = static_cast<BluetoothAdapter*>(user_data);
1659 LoggerW("user_data is NULL");
1664 LoggerW("data is NULL");
1668 const auto it = std::find(object->connected_sockets_.begin(), object->connected_sockets_.end(),
1671 if (it == object->connected_sockets_.end()) {
1672 LoggerW("Unknown connected socket: %d", data->socket_fd);
1676 // Store received data
1677 object->StoreSocketData(data);
1679 object->InvokeSocketOnMessageEvent(*it);
1682 void BluetoothAdapter::ConnectToServiceByUUID(const std::string& address, const std::string& uuid,
1683 double callback_handle) {
1686 PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
1688 if (!IsValidUUID(uuid)) {
1689 result = LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Wrong UUID",
1690 ("Wrong UUID: %s", uuid.c_str()));
1693 if (result.IsSuccess() && is_powered_) {
1694 int ret = bt_socket_connect_rfcomm(address.c_str(), uuid.c_str());
1697 case BT_ERROR_NONE: {
1698 LoggerD("bt_socket_connect_rfcomm() succeeded");
1700 ConnectionRequestPtr request{new ConnectionRequest()};
1701 request->uuid_ = uuid;
1702 request->callback_handle_ = callback_handle;
1704 std::string r_address(address);
1705 for (size_t i = 0; i < address.length(); i++) {
1706 r_address[i] = toupper(address[i]);
1708 connection_requests_.insert(std::make_pair(r_address, request));
1710 bt_socket_set_connection_state_changed_cb(OnSocketConnected, this);
1714 case BT_ERROR_INVALID_PARAMETER:
1715 case BT_ERROR_REMOTE_DEVICE_NOT_BONDED:
1716 result = LogAndCreateResult(
1717 ErrorCode::INVALID_VALUES_ERR, "Invalid value",
1718 ("bt_socket_connect_rfcomm error: %d (%s)", ret, get_error_message(ret)));
1721 result = LogAndCreateResult(
1722 ErrorCode::UNKNOWN_ERR, "Unknown error",
1723 ("bt_socket_connect_rfcomm error: %d (%s)", ret, get_error_message(ret)));
1726 } else if (result.IsSuccess()) {
1728 LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is turned off");
1731 if (result.IsError()) {
1732 instance_.AsyncResponse(callback_handle, result);
1736 void BluetoothAdapter::InvokeSocketEvent(int id, const char* event) {
1738 picojson::value value = picojson::value(picojson::object());
1739 picojson::object& value_obj = value.get<picojson::object>();
1740 value_obj.insert(std::make_pair("id", picojson::value(std::to_string(id))));
1741 value_obj.insert(std::make_pair("event", picojson::value(event)));
1742 instance_.FireEvent("BLUETOOTH_SOCKET_STATE_CHANGED", value);
1745 void BluetoothAdapter::InvokeSocketOnMessageEvent(int id) {
1747 InvokeSocketEvent(id, "onmessage");
1750 void BluetoothAdapter::InvokeSocketOnCloseEvent(int id) {
1752 InvokeSocketEvent(id, "onclose");
1755 void BluetoothAdapter::RemoveSocket(int socket) {
1757 const auto data_it = socket_data_.find(socket);
1759 if (data_it != socket_data_.end()) {
1760 socket_data_.erase(data_it);
1762 LoggerD("No stored data for socket: %d", socket);
1765 const auto it = std::find(connected_sockets_.begin(), connected_sockets_.end(), socket);
1767 if (it == connected_sockets_.end()) {
1768 LoggerW("Unknown connected socket: %d", socket);
1772 connected_sockets_.erase(it);
1774 InvokeSocketOnCloseEvent(id);
1777 void BluetoothAdapter::StoreSocketData(bt_socket_received_data_s* data) {
1780 auto& data_store = socket_data_[data->socket_fd];
1782 for (int i = 0; i < data->data_size; ++i) {
1783 data_store.push_back(data->data[i]);
1787 const std::list<char>& BluetoothAdapter::ReadSocketData(int socket) {
1790 return socket_data_[socket];
1793 void BluetoothAdapter::ClearSocketData(int socket) {
1796 const auto data_it = socket_data_.find(socket);
1798 if (data_it != socket_data_.end()) {
1799 data_it->second.clear();
1803 void BluetoothAdapter::IsServiceConnected(const picojson::value& data, picojson::object& out) {
1806 const auto& args = util::GetArguments(data);
1807 const auto& uuid = FromJson<std::string>(args, "uuid");
1809 auto iter = registered_uuids_.find(uuid);
1810 if (iter == registered_uuids_.end()) {
1812 PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter was passed."), &out,
1813 ("Invalid uuid was passed: %s", uuid.c_str()));
1817 ReportSuccess(picojson::value(iter->second.second), out);
1820 void BluetoothAdapter::SetChangeListenerCallback(bool val) {
1822 is_callback_set_ = val;
1825 int BluetoothAdapter::AddPowerStateListener(const std::function<void(const int)>& listener) {
1826 return power_state_listeners_.Add(listener);
1829 void BluetoothAdapter::RemovePowerStateListener(int id) {
1830 power_state_listeners_.Remove(id);
1833 } // namespace bluetooth
1834 } // namespace extension