82c111808106ad7c0de5f56560f6fc9308775a10
[platform/core/api/webapi-plugins.git] / src / bluetooth / bluetooth_adapter.cc
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
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 "bluetooth_adapter.h"
18
19 #include <algorithm>
20 #include <memory>
21 #include <regex>
22
23 #ifdef APP_CONTROL_SETTINGS_SUPPORT
24 #include <appfw/app_control.h>
25 #endif
26
27 #include <bluetooth.h>
28 #include <system_info.h>
29 #include "bluetooth_internal.h"
30
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"
37
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"
44
45 namespace extension {
46 namespace bluetooth {
47
48 using namespace common;
49 using namespace common::tools;
50
51 namespace {
52 const std::string kAction = "action";
53 const std::string kData = "data";
54 const std::string kName = "name";
55 // adapter
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";
73 // device
74 const std::string kDeviceAddress = "address";
75 const unsigned short kTimeout = 180;
76 }  // namespace
77
78 static bool IsValidAddress(const std::string& address) {
79   ScopeLogger();
80   const std::regex macAdressRegex{"([[:xdigit:]]{2}[:]){5}([[:xdigit:]]{2})"};
81
82   if (std::regex_match(address, macAdressRegex)) {
83     return true;
84   }
85   LoggerE("Invalid MAC address: %s", address.c_str());
86   return false;
87 }
88
89 static bool IsValidUUID(const std::string& uuid) {
90   ScopeLogger();
91   const std::regex uuidRegex{
92       "[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}"};
93
94   if (std::regex_match(uuid, uuidRegex)) {
95     return true;
96   }
97   LoggerE("Invalid UUID: %s", uuid.c_str());
98   return false;
99 }
100
101 void BluetoothAdapter::StateChangedCB(int result, bt_adapter_state_e state, void* user_data) {
102   ScopeLogger();
103
104   BluetoothAdapter* adapter = static_cast<BluetoothAdapter*>(user_data);
105   if (!adapter) {
106     LoggerD("User data is NULL");
107     return;
108   }
109
110   const bool powered = BT_ADAPTER_ENABLED == state;
111   bool previous_powered = adapter->is_powered_;
112   adapter->is_powered_ = powered;
113
114   adapter->power_state_listeners_.FireAll(powered);
115
116   if (powered) {
117     // update visible state if bluetooth device has been turned on
118     adapter->is_visible_ = adapter->get_visible();
119   }
120
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>();
124
125     data_obj->insert(std::make_pair(kAction, picojson::value(kOnStateChanged)));
126     data_obj->insert(std::make_pair(kAdapterPowered, picojson::value(powered)));
127
128     adapter->instance_.FireEvent(kAdapterChangeCallbackEvent, value);
129   }
130
131   if (adapter->user_request_list_[SET_POWERED]) {
132     if (adapter->requested_powered_ != powered) {
133       return;
134     }
135
136     PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
137     switch (result) {
138       case BT_ERROR_NONE:
139       case BT_ERROR_ALREADY_DONE:
140       case BT_ERROR_NOT_ENABLED:
141         // do nothing
142         break;
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)));
147         break;
148       default:
149         ret = LogAndCreateResult(
150             ErrorCode::UNKNOWN_ERR, "Unknown exception",
151             ("StateChangedCB result: %d (%s)", result, get_error_message(result)));
152     }
153
154     adapter->instance_.AsyncResponse(adapter->user_request_callback_[SET_POWERED], ret);
155     adapter->user_request_list_[SET_POWERED] = false;
156   }
157 }
158
159 void BluetoothAdapter::NameChangedCB(char* name, void* user_data) {
160   ScopeLogger();
161
162   BluetoothAdapter* adapter = static_cast<BluetoothAdapter*>(user_data);
163   if (!adapter) {
164     LoggerD("User data is NULL");
165     return;
166   }
167
168   if (adapter->is_callback_set_) {
169     picojson::value value = picojson::value(picojson::object());
170     picojson::object* data_obj = &value.get<picojson::object>();
171
172     data_obj->insert(std::make_pair(kAction, picojson::value(kOnNameChanged)));
173     data_obj->insert(std::make_pair(kName, picojson::value(name)));
174
175     adapter->instance_.FireEvent(kAdapterChangeCallbackEvent, value);
176   }
177
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;
183   }
184 }
185
186 void BluetoothAdapter::VisibilityChangedCB(int result, bt_adapter_visibility_mode_e mode,
187                                            void* user_data) {
188   ScopeLogger();
189
190   BluetoothAdapter* adapter = static_cast<BluetoothAdapter*>(user_data);
191   if (!adapter) {
192     LoggerD("User data is NULL");
193     return;
194   }
195
196   bool visible = BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE != mode;
197   bool previous_visible = adapter->is_visible_;
198   adapter->is_visible_ = visible;
199
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>();
203
204     data_obj->insert(std::make_pair(kAction, picojson::value(kOnVisibilityChanged)));
205     data_obj->insert(std::make_pair(kAdapterVisible, picojson::value(visible)));
206
207     adapter->instance_.FireEvent(kAdapterChangeCallbackEvent, value);
208   }
209
210   if (adapter->user_request_list_[SET_VISIBLE] && adapter->requested_visibility_ == mode) {
211     PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
212
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)));
217     }
218
219     adapter->instance_.AsyncResponse(adapter->user_request_callback_[SET_VISIBLE], ret);
220     adapter->user_request_list_[SET_VISIBLE] = false;
221   }
222 }
223
224 static bool ForeachBondedDevicesCB(bt_device_info_s* device_info, void* user_data) {
225   ScopeLogger();
226   if (nullptr == user_data) {
227     LoggerD("user data is NULL.");
228     return false;
229   }
230
231   if (nullptr == device_info) {
232     LoggerD("Device info is not valid.");
233     return false;
234   }
235
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>()
241                                                  .c_str())) {
242       BluetoothDevice::ToJson(device_info, &iter->get<picojson::object>());
243       return true;
244     }
245   }
246
247   array->push_back(picojson::value(picojson::object()));
248
249   BluetoothDevice::ToJson(device_info, &array->back().get<picojson::object>());
250   return true;
251 }
252
253 void BluetoothAdapter::DiscoveryStateChangedCB(int result,
254                                                bt_adapter_device_discovery_state_e discovery_state,
255                                                bt_adapter_device_discovery_info_s* discovery_info,
256                                                void* user_data) {
257   ScopeLogger();
258
259   BluetoothAdapter* adapter = static_cast<BluetoothAdapter*>(user_data);
260   if (!adapter) {
261     LoggerD("User data is NULL");
262     return;
263   }
264
265   picojson::value value = picojson::value(picojson::object());
266   picojson::object* data_obj = &value.get<picojson::object>();
267
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();
276
277           data_obj->insert(std::make_pair(kAction, picojson::value(kOnDiscoverStarted)));
278           adapter->instance_.FireEvent(kAdapterDiscoverSuccessEvent, value);
279         } else {
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;
284         }
285       }
286       break;
287     }
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)));
292
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>();
296
297             disapeared_obj->insert(
298                 std::make_pair(kAction, picojson::value(kOnDiscoverDisappeared)));
299             disapeared_obj->insert(std::make_pair(kData, picojson::value(it)));
300
301             adapter->instance_.FireEvent(kAdapterDiscoverSuccessEvent, disapeared_val);
302           }
303
304           data_obj->insert(std::make_pair(kData, picojson::value(adapter->discovered_devices_)));
305
306           adapter->user_request_list_[DISCOVER_DEVICES] = false;
307           adapter->instance_.FireEvent(kAdapterDiscoverSuccessEvent, value);
308         }
309
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()));
313
314           ReportSuccess(response->get<picojson::object>());
315           adapter->instance_.AsyncResponse(adapter->user_request_callback_[STOP_DISCOVERY],
316                                            response);
317
318           adapter->user_request_list_[STOP_DISCOVERY] = false;
319         }
320       }
321       break;
322     }
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);
328
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())))
332                   .first->second;
333
334           BluetoothDevice::ToJson(discovery_info, &data.get<picojson::object>());
335           adapter->discovered_devices_.push_back(data);
336
337           adapter->instance_.FireEvent(kAdapterDiscoverSuccessEvent, value);
338         }
339       }
340       break;
341     }
342     default:
343       LoggerD("Unknown state");
344       break;
345   }
346 }
347
348 BluetoothAdapter::BluetoothAdapter(BluetoothInstance& instance)
349     : is_response_sent_(false),
350       is_visible_response_sent_(false),
351       is_callback_set_(false),
352       is_visible_(false),
353       is_powered_(false),
354       is_initialized_(false),
355       user_request_list_(),
356       user_request_callback_(),
357       requested_powered_(),
358       requested_visibility_(),
359       instance_(instance) {
360   ScopeLogger();
361   if (BT_ERROR_NONE == bt_initialize()) {
362     LoggerD("Bluetooth service is initialized.");
363     is_initialized_ = true;
364
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);
370
371     if (BT_ERROR_NONE != ret) {
372       LoggerE("Setting listeners function failed.");
373     }
374   } else {
375     LoggerE("Bluetooth service initialization failed.");
376   }
377
378   bt_adapter_state_e state;
379   if (BT_ERROR_NONE == bt_adapter_get_state(&state)) {
380     is_powered_ = BT_ADAPTER_ENABLED == state;
381   }
382
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;
386   }
387 }
388
389 BluetoothAdapter::~BluetoothAdapter() {
390   ScopeLogger();
391   bt_socket_unset_data_received_cb();
392   bt_socket_unset_connection_state_changed_cb();
393
394   for (auto it : connected_sockets_) {
395     bt_socket_disconnect_rfcomm(it);
396   }
397
398   for (auto it : registered_uuids_) {
399     bt_socket_destroy_rfcomm(it.second.first);
400   }
401
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();
406
407   if (is_initialized_) {
408     if (BT_ERROR_NONE == bt_deinitialize()) {
409       LoggerD("Bluetooth service is deinitialized.");
410     } else {
411       LoggerE("Bluetooth service deinitialization failed.");
412     }
413   }
414 }
415
416 std::string BluetoothAdapter::get_name() const {
417   ScopeLogger();
418   char* name = nullptr;
419   std::string str_name = "";
420   if (BT_ERROR_NONE == bt_adapter_get_name(&name)) {
421     if (name) {
422       str_name = name;
423       free(name);
424     }
425   }
426
427   return str_name;
428 }
429
430 bool BluetoothAdapter::get_visible() const {
431   ScopeLogger();
432   bt_adapter_visibility_mode_e mode;
433
434   if (BT_ERROR_NONE == bt_adapter_get_visibility(&mode, NULL)) {
435     return mode != BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE;
436   }
437
438   return false;
439 }
440
441 void BluetoothAdapter::set_visible(bool visible) {
442   is_visible_ = visible;
443 }
444
445 bool BluetoothAdapter::get_powered() {
446   return is_powered_;
447 }
448
449 void BluetoothAdapter::set_powered(bool powered) {
450   is_powered_ = powered;
451 }
452
453 bool BluetoothAdapter::is_initialized() const {
454   return is_initialized_;
455 }
456
457 void BluetoothAdapter::SetName(const picojson::value& data, picojson::object& out) {
458   ScopeLogger();
459
460   CHECK_BACKWARD_COMPABILITY_PRIVILEGE_ACCESS(Privilege::kBluetooth, Privilege::kBluetoothAdmin,
461                                               &out);
462
463   const auto callback_handle = util::GetAsyncCallbackHandle(data);
464   const auto& args = util::GetArguments(data);
465   const auto name = FromJson<std::string>(args, "name");
466
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);
471     return;
472   }
473
474   if (!this->get_powered()) {
475     result =
476         LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is turned off");
477     instance_.AsyncResponse(callback_handle, result);
478     return;
479   }
480
481   if (get_name() == name) {
482     LoggerD("Requested the same name, calling success callback");
483     instance_.AsyncResponse(callback_handle, result);
484     return;
485   }
486
487   if (this->user_request_list_[SET_NAME]) {
488     result = LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Already requested");
489     instance_.AsyncResponse(callback_handle, result);
490     return;
491   }
492
493   this->user_request_list_[SET_NAME] = true;
494   this->user_request_callback_[SET_NAME] = callback_handle;
495
496   int ret = bt_adapter_set_name(name.c_str());
497   switch (ret) {
498     case BT_ERROR_NONE:
499       // bt_adapter_name_changed_cb() will be invoked
500       // if this function returns #BT_ERROR_NONE
501       this->requested_name_ = name;
502       break;
503     case BT_ERROR_INVALID_PARAMETER:
504       result =
505           LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Invalid value",
506                              ("bt_adapter_set_name error: %d (%s)", ret, get_error_message(ret)));
507       break;
508     default:
509       result =
510           LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown exception",
511                              ("bt_adapter_set_name error: %d (%s)", ret, get_error_message(ret)));
512   }
513
514   if (result.IsError()) {
515     this->user_request_list_[SET_NAME] = false;
516     instance_.AsyncResponse(callback_handle, result);
517     return;
518   }
519 }
520
521 void BluetoothAdapter::SetPowered(const picojson::value& data, picojson::object& out) {
522   ScopeLogger();
523   LoggerW(
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.");
526
527   CHECK_BACKWARD_COMPABILITY_PRIVILEGE_ACCESS(Privilege::kBluetooth, Privilege::kBluetoothAdmin,
528                                               &out);
529
530   const auto callback_handle = util::GetAsyncCallbackHandle(data);
531   const auto& args = util::GetArguments(data);
532   const auto new_powered = FromJson<bool>(args, "powered");
533
534   PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
535
536   if (!this->is_initialized()) {
537     ret = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
538     instance_.AsyncResponse(callback_handle, ret);
539     return;
540   }
541
542   if (this->user_request_list_[SET_POWERED]) {
543     ret = LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Already requested");
544     instance_.AsyncResponse(callback_handle, ret);
545     return;
546   }
547
548   bool cur_powered = this->get_powered();
549
550   if (new_powered == cur_powered) {
551     LoggerD("Requested already set value, calling success callback");
552     instance_.AsyncResponse(callback_handle, ret);
553     return;
554   }
555
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);
565     return;
566   }
567
568   std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)> service(
569       app_control_ptr, &app_control_destroy);
570
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);
576     return;
577   }
578
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);
584     return;
585   }
586
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");
591
592     BluetoothAdapter* adapter = static_cast<BluetoothAdapter*>(user_data);
593
594     if (adapter->is_response_sent_) {
595       LoggerE("response already sent");
596       return;
597     }
598
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"));
605     } else {
606       adapter->user_request_list_[SET_POWERED] = true;
607     }
608   };
609   app_control_result_cb result_cb = [](app_control_h request, app_control_error_e app_res,
610                                        void* user_data) {
611     LoggerD("Inside app_control_send_launch_request() result callback");
612
613     BluetoothAdapter* adapter = static_cast<BluetoothAdapter*>(user_data);
614
615     if (adapter->is_response_sent_) {
616       LoggerE("response already sent");
617       return;
618     }
619
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"));
627     } else {
628       adapter->user_request_list_[SET_POWERED] = true;
629     }
630   };
631
632   err = app_control_send_launch_request_async(service.get(), result_cb, reply_cb, this);
633
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);
638     return;
639   }
640 #else
641   this->user_request_list_[SET_POWERED] = true;
642   int ntv_ret = 0;
643
644   if (new_powered) {
645     ntv_ret = bt_adapter_enable();
646   } else {
647     ntv_ret = bt_adapter_disable();
648   }
649
650   if (!ntv_ret) {
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);
655     return;
656   }
657 #endif
658 }
659
660 void BluetoothAdapter::SetVisible(const picojson::value& data, picojson::object& out) {
661   ScopeLogger();
662   LoggerW(
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.");
665
666   CHECK_BACKWARD_COMPABILITY_PRIVILEGE_ACCESS(Privilege::kBluetooth, Privilege::kBluetoothManager,
667                                               &out);
668
669   const auto callback_handle = util::GetAsyncCallbackHandle(data);
670   const auto& args = util::GetArguments(data);
671   const auto visible = FromJson<bool>(args, "visible");
672
673   unsigned short new_timeout = kTimeout;
674   if (visible) {
675     new_timeout = static_cast<unsigned short>(FromJson<double>(args, "timeout"));
676   }
677
678   PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
679
680   if (!this->is_initialized()) {
681     ret = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
682     instance_.AsyncResponse(callback_handle, ret);
683     return;
684   }
685
686   if (this->user_request_list_[SET_VISIBLE]) {
687     ret = LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Already requested");
688     instance_.AsyncResponse(callback_handle, ret);
689     return;
690   }
691
692   if (!this->get_powered()) {
693     ret =
694         LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is turned off");
695     instance_.AsyncResponse(callback_handle, ret);
696     return;
697   }
698
699   bt_adapter_visibility_mode_e new_mode = BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE;
700   if (visible) {
701     if (0 == new_timeout) {
702       new_mode = BT_ADAPTER_VISIBILITY_MODE_GENERAL_DISCOVERABLE;
703     } else {
704       new_mode = BT_ADAPTER_VISIBILITY_MODE_LIMITED_DISCOVERABLE;
705     }
706   }
707
708   bt_adapter_visibility_mode_e cur_mode = BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE;
709   int cur_timeout = 0;
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);
716     return;
717   }
718
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);
722     return;
723   }
724
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);
734     return;
735   }
736
737   std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)> service(
738       tmp_service, &app_control_destroy);
739
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);
746     return;
747   }
748
749   err = app_control_set_mime(service.get(), "application/x-bluetooth-visibility");
750   if (err != APP_CONTROL_ERROR_NONE) {
751     ret =
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);
755     return;
756   }
757
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);
763
764     if (adapter->is_visible_response_sent_) {
765       LoggerE("response already sent");
766       return;
767     }
768
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"));
775     } else {
776       adapter->user_request_list_[SET_VISIBLE] = true;
777     }
778   };
779
780   app_control_result_cb result_cb = [](app_control_h request, app_control_error_e app_res,
781                                        void* user_data) {
782     LoggerD("Inside app_control_send_launch_request_async() result callback");
783
784     BluetoothAdapter* adapter = static_cast<BluetoothAdapter*>(user_data);
785
786     if (adapter->is_visible_response_sent_) {
787       LoggerE("response already sent");
788       return;
789     }
790
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"));
798     } else {
799       adapter->user_request_list_[SET_VISIBLE] = true;
800     }
801   };
802
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);
809     return;
810   }
811
812 #else
813   this->user_request_list_[SET_VISIBLE] = true;
814   ntv_ret = bt_adapter_set_visibility(new_mode, new_timeout);
815
816   switch (ntv_ret) {
817     case BT_ERROR_NONE:
818       // bt_adapter_visibility_mode_changed_cb() will be invoked
819       // if this function returns #BT_ERROR_NONE
820       break;
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)));
825       break;
826     default:
827       ret = LogAndCreateResult(
828           ErrorCode::UNKNOWN_ERR, "Unknown exception",
829           ("bt_adapter_set_visibility error: %d (%s)", ntv_ret, get_error_message(ntv_ret)));
830   }
831
832   if (!ret) {
833     instance_.AsyncResponse(callback_handle, ret);
834     this->user_request_list_[SET_VISIBLE] = false;
835     return;
836   }
837 #endif
838 }
839
840 void BluetoothAdapter::DiscoverDevices(const picojson::value& /* data */, picojson::object& out) {
841   ScopeLogger();
842
843   CHECK_BACKWARD_COMPABILITY_PRIVILEGE_ACCESS(Privilege::kBluetooth, Privilege::kBluetoothGap,
844                                               &out);
845
846   PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
847
848   if (!is_initialized_) {
849     result = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
850   }
851
852   if (result.IsSuccess() && this->user_request_list_[DISCOVER_DEVICES]) {
853     result = LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Already requested");
854   }
855
856   if (result.IsSuccess() && !get_powered()) {
857     result =
858         LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is turned off");
859   }
860
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");
865     }
866   }
867
868   if (result.IsSuccess()) {
869     this->user_request_list_[DISCOVER_DEVICES] = true;
870   } else {
871     std::shared_ptr<picojson::value> response =
872         std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
873
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);
878         },
879         response);
880   }
881 }
882
883 void BluetoothAdapter::StopDiscovery(const picojson::value& data, picojson::object& out) {
884   ScopeLogger();
885
886   CHECK_BACKWARD_COMPABILITY_PRIVILEGE_ACCESS(Privilege::kBluetooth, Privilege::kBluetoothGap,
887                                               &out);
888
889   const auto callback_handle = util::GetAsyncCallbackHandle(data);
890
891   PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
892
893   if (!this->is_initialized()) {
894     result = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
895   }
896
897   if (result.IsSuccess() && this->user_request_list_[STOP_DISCOVERY]) {
898     result = LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Already requested");
899   }
900
901   if (result.IsSuccess() && this->get_powered()) {
902     bool is_discovering = false;
903     bt_adapter_is_discovering(&is_discovering);
904
905     if (!is_discovering) {
906       instance_.AsyncResponse(callback_handle, result);
907       return;
908     }
909
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();
913     switch (ret) {
914       case BT_ERROR_NONE: {
915         // This function invokes bt_adapter_device_discovery_state_changed_cb().
916         break;
917       }
918       default: {
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)));
923       }
924     }
925   } else if (result.IsSuccess()) {
926     result =
927         LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is turned off");
928   }
929
930   if (result.IsError()) {
931     instance_.AsyncResponse(callback_handle, result);
932   }
933 }
934
935 void BluetoothAdapter::GetKnownDevices(const picojson::value& data, picojson::object& out) {
936   ScopeLogger();
937
938   CHECK_BACKWARD_COMPABILITY_PRIVILEGE_ACCESS(Privilege::kBluetooth, Privilege::kBluetoothGap,
939                                               &out);
940
941   const auto callback_handle = util::GetAsyncCallbackHandle(data);
942
943   auto get_known_devices = [this](const std::shared_ptr<picojson::value>& response) -> void {
944     PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
945
946     if (!this->is_initialized()) {
947       ret = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
948     }
949
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>();
957
958       array = discovered_devices_;
959
960       int ntv_ret = bt_adapter_foreach_bonded_device(ForeachBondedDevicesCB, &array);
961       if (BT_ERROR_NONE == ntv_ret) {
962         ReportSuccess(result, response_obj);
963       } else {
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)));
967       }
968     } else if (ret.IsSuccess()) {
969       ret = LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR,
970                                "Bluetooth device is turned off");
971     }
972
973     if (ret.IsError()) {
974       LogAndReportError(ret, &response->get<picojson::object>());
975     }
976   };
977   auto get_known_devices_response =
978       [this, callback_handle](const std::shared_ptr<picojson::value>& response) -> void {
979     instance_.SyncResponse(callback_handle, response);
980   };
981
982   auto queue_data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
983
984   TaskQueue::GetInstance().Queue<picojson::value>(get_known_devices, get_known_devices_response,
985                                                   queue_data);
986
987   ReportSuccess(out);
988 }
989
990 void BluetoothAdapter::GetDevice(const picojson::value& data, picojson::object& out) {
991   ScopeLogger();
992
993   CHECK_BACKWARD_COMPABILITY_PRIVILEGE_ACCESS(Privilege::kBluetooth, Privilege::kBluetoothGap,
994                                               &out);
995
996   const auto callback_handle = util::GetAsyncCallbackHandle(data);
997   const auto& args = util::GetArguments(data);
998
999   const auto& address = FromJson<std::string>(args, "address");
1000
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");
1006     }
1007
1008     if (ret.IsSuccess() && !this->is_initialized()) {
1009       ret = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
1010     }
1011     if (ret.IsSuccess() && this->get_powered()) {
1012       picojson::object& response_obj = response->get<picojson::object>();
1013       bt_device_info_s* info = nullptr;
1014
1015       if (bt_adapter_get_bonded_device_info(address.c_str(), &info) == BT_ERROR_NONE &&
1016           info != nullptr) {
1017         picojson::value result = picojson::value(picojson::object());
1018         picojson::object& result_obj = result.get<picojson::object>();
1019
1020         BluetoothDevice::ToJson(info, &result_obj);
1021         ReportSuccess(result, response_obj);
1022         bt_adapter_free_device_info(info);
1023         return;
1024       }
1025
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>()
1032                                            .c_str())) {
1033             ReportSuccess(*iter, response_obj);
1034             return;
1035           }
1036         }
1037       } else {
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()));
1041       }
1042     } else if (ret.IsSuccess()) {
1043       ret = LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR,
1044                                "Bluetooth device is turned off");
1045     }
1046
1047     if (ret.IsError()) {
1048       LogAndReportError(ret, &response->get<picojson::object>());
1049     }
1050   };
1051
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);
1056   };
1057
1058   auto queue_data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
1059
1060   TaskQueue::GetInstance().Queue<picojson::value>(get_device, get_device_response, queue_data);
1061
1062   ReportSuccess(out);
1063 }
1064
1065 class BondingHandler {
1066  public:
1067   BondingHandler(BluetoothInstance& instance, double callback_handle, const std::string& address)
1068       : instance_(instance), callback_handle_(callback_handle), address_(address) {
1069     ScopeLogger();
1070   }
1071
1072   void set_address(const std::string& address) {
1073     address_ = address;
1074   }
1075
1076   const std::string& address() const {
1077     return address_;
1078   }
1079
1080   void Invoke(const PlatformResult& result, const std::shared_ptr<picojson::value>& response) {
1081     ScopeLogger();
1082
1083     if (result.IsError()) {
1084       LogAndReportError(result, &response->get<picojson::object>());
1085     } else {
1086       ReportSuccess(response->get<picojson::object>());
1087     }
1088
1089     instance_.AsyncResponse(callback_handle_, response);
1090   }
1091
1092  private:
1093   BluetoothInstance& instance_;
1094   double callback_handle_;
1095   std::string address_;
1096 };
1097
1098 void BluetoothAdapter::CreateBonding(const picojson::value& data, picojson::object& out) {
1099   ScopeLogger();
1100
1101   CHECK_BACKWARD_COMPABILITY_PRIVILEGE_ACCESS(Privilege::kBluetooth, Privilege::kBluetoothGap,
1102                                               &out);
1103
1104   const auto callback_handle = util::GetAsyncCallbackHandle(data);
1105   const auto& args = util::GetArguments(data);
1106
1107   const auto& address = FromJson<std::string>(args, "address");
1108
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()));
1115     }
1116
1117     if (result.IsSuccess() && !this->is_initialized()) {
1118       result = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
1119     }
1120
1121     if (result.IsSuccess() && this->get_powered()) {
1122       auto bond_create_callback = [](int callback_result, bt_device_info_s* device_info,
1123                                      void* user_data) {
1124         ScopeLogger("Entered into asynchronous function, bond_create_callback");
1125
1126         BondingHandler* handler = static_cast<BondingHandler*>(user_data);
1127         if (!handler) {
1128           LoggerW("user_data is nullptr");
1129           return;
1130         }
1131         if (!device_info) {
1132           LoggerW("device_info is nullptr");
1133           return;
1134         }
1135
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()));
1139
1140         std::string address(handler->address());
1141         for (size_t i = 0; i < handler->address().length(); i++) {
1142           address[i] = toupper(handler->address()[i]);
1143         }
1144
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]);
1148         }
1149
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>();
1155
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)));
1163           } else {
1164             ret = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown exception",
1165                                      ("bond_create_callback result: %d (%s)", callback_result,
1166                                       get_error_message(callback_result)));
1167           }
1168
1169           handler->Invoke(ret, response);
1170           delete handler;
1171           bt_device_unset_bond_created_cb();
1172         } else {  // unexpected event
1173           LoggerD("An unexpected bonding detected");
1174         }
1175       };
1176
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) {
1180         delete handler;
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)));
1185       } else {
1186         LoggerD("bt_device_set_bond_created_cb() succeeded");
1187
1188         ret = bt_device_create_bond(address.c_str());
1189
1190         switch (ret) {
1191           case BT_ERROR_NONE: {
1192             LoggerD("bt_device_create_bond() succeeded");
1193             break;
1194           }
1195           case BT_ERROR_INVALID_PARAMETER: {
1196             bt_device_unset_bond_created_cb();
1197             delete handler;
1198             result = LogAndCreateResult(
1199                 ErrorCode::INVALID_VALUES_ERR, "Invalid value",
1200                 ("bt_device_create_bond error: %d (%s)", ret, get_error_message(ret)));
1201             break;
1202           }
1203           default: {
1204             bt_device_unset_bond_created_cb();
1205             delete handler;
1206             result = LogAndCreateResult(
1207                 ErrorCode::UNKNOWN_ERR, "Unknown error",
1208                 ("bt_device_create_bond error: %d (%s)", ret, get_error_message(ret)));
1209           }
1210         }
1211       }
1212     } else if (result.IsSuccess()) {
1213       result = LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR,
1214                                   "Bluetooth device is turned off");
1215     }
1216
1217     if (result.IsError()) {
1218       instance_.AsyncResponse(callback_handle, result);
1219     }
1220   };
1221   TaskQueue::GetInstance().Queue(create_bonding);
1222   ReportSuccess(out);
1223 }
1224
1225 void BluetoothAdapter::DestroyBonding(const picojson::value& data, picojson::object& out) {
1226   ScopeLogger();
1227
1228   CHECK_BACKWARD_COMPABILITY_PRIVILEGE_ACCESS(Privilege::kBluetooth, Privilege::kBluetoothGap,
1229                                               &out);
1230
1231   const auto callback_handle = util::GetAsyncCallbackHandle(data);
1232   const auto& args = util::GetArguments(data);
1233
1234   const auto& address = FromJson<std::string>(args, "address");
1235
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()));
1242     }
1243     if (result.IsSuccess() && !this->is_initialized()) {
1244       result = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
1245     }
1246
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);
1250
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)));
1254       } else {
1255         bt_adapter_free_device_info(device_info);
1256
1257         auto bond_destroy_callback = [](int callback_result, char* remote_address,
1258                                         void* user_data) {
1259           LoggerD("bond_destroy_callback");
1260
1261           BondingHandler* handler = static_cast<BondingHandler*>(user_data);
1262           if (!handler) {
1263             LoggerW("user_data is nullptr");
1264             return;
1265           }
1266
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()));
1270
1271           std::string address(handler->address());
1272           for (auto& c : address) {
1273             c = toupper(c);
1274           }
1275
1276           std::string r_address(remote_address);
1277           for (auto& c : r_address) {
1278             c = toupper(c);
1279           }
1280
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)));
1286             }
1287
1288             handler->Invoke(ret, response);
1289             delete handler;
1290             bt_device_unset_bond_destroyed_cb();
1291           } else {  // unexpected event
1292             LoggerD("An unexpected bonding detected");
1293           }
1294         };
1295
1296         BondingHandler* handler = new BondingHandler(instance_, callback_handle, address);
1297         bt_device_set_bond_destroyed_cb(bond_destroy_callback, handler);
1298
1299         int ret = bt_device_destroy_bond(address.c_str());
1300
1301         switch (ret) {
1302           case BT_ERROR_NONE: {
1303             LoggerD("bt_device_destroy_bond() succeeded");
1304             break;
1305           }
1306           case BT_ERROR_INVALID_PARAMETER: {
1307             bt_device_unset_bond_destroyed_cb();
1308             delete handler;
1309             result = LogAndCreateResult(
1310                 ErrorCode::INVALID_VALUES_ERR, "Invalid value",
1311                 ("bt_device_destroy_bond error: %d (%s)", ret, get_error_message(ret)));
1312             break;
1313           }
1314           default: {
1315             bt_device_unset_bond_destroyed_cb();
1316             delete handler;
1317             result = LogAndCreateResult(
1318                 ErrorCode::UNKNOWN_ERR, "Unknown exception",
1319                 ("bt_device_destroy_bond error: %d (%s)", ret, get_error_message(ret)));
1320           }
1321         }
1322       }
1323     } else if (result.IsSuccess()) {
1324       result = LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR,
1325                                   "Bluetooth device is turned off");
1326     }
1327
1328     if (result.IsError()) {
1329       instance_.AsyncResponse(callback_handle, result);
1330     }
1331   };
1332   TaskQueue::GetInstance().Queue(destroy_bonding);
1333   ReportSuccess(out);
1334 }
1335
1336 void BluetoothAdapter::RegisterRFCOMMServiceByUUID(const picojson::value& data,
1337                                                    picojson::object& out) {
1338   ScopeLogger();
1339
1340   CHECK_BACKWARD_COMPABILITY_PRIVILEGE_ACCESS(Privilege::kBluetooth, Privilege::kBluetoothSpp,
1341                                               &out);
1342
1343   const auto callback_handle = util::GetAsyncCallbackHandle(data);
1344   const auto& args = util::GetArguments(data);
1345
1346   const auto& uuid = FromJson<std::string>(args, "uuid");
1347   const auto& name = FromJson<std::string>(args, "name");
1348
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.");
1354     }
1355
1356     if (result.IsSuccess() && !IsValidUUID(uuid)) {
1357       result = LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Wrong UUID",
1358                                   ("Wrong UUID: %s", uuid.c_str()));
1359     }
1360
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);
1364
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)));
1369       } else {
1370         int socket = -1;
1371         ret = bt_socket_create_rfcomm(uuid.c_str(), &socket);
1372
1373         switch (ret) {
1374           case BT_ERROR_NONE: {
1375             int ret_in = bt_socket_listen_and_accept_rfcomm(socket, 0);
1376             switch (ret_in) {
1377               case BT_ERROR_NONE: {
1378                 LoggerD("bt_socket_listen() succeeded");
1379                 bt_socket_set_connection_state_changed_cb(OnSocketConnected, this);
1380
1381                 registered_uuids_.insert(std::make_pair(uuid, std::make_pair(socket, false)));
1382
1383                 ReportSuccess(response->get<picojson::object>());
1384                 break;
1385               }
1386
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)));
1391                 break;
1392               }
1393
1394               default: {
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)));
1398                 break;
1399               }
1400             }
1401             break;
1402           }
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)));
1407             break;
1408           default:
1409             result = LogAndCreateResult(
1410                 ErrorCode::UNKNOWN_ERR, "Unknown error",
1411                 ("bt_socket_create_rfcomm error: %d (%s)", ret, get_error_message(ret)));
1412             break;
1413         }
1414       }
1415     } else if (result.IsSuccess()) {
1416       result = LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR,
1417                                   "Bluetooth device is turned off");
1418     }
1419
1420     if (result.IsError()) {
1421       LogAndReportError(result, &response->get<picojson::object>());
1422     }
1423   };
1424
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);
1429   };
1430
1431   auto queue_data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
1432
1433   TaskQueue::GetInstance().Queue<picojson::value>(rfcomm, rfcomm_response, queue_data);
1434
1435   ReportSuccess(out);
1436 }
1437
1438 void BluetoothAdapter::UnregisterUUID(const std::string& uuid, int callback_handle) {
1439   ScopeLogger();
1440
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()));
1445   }
1446
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);
1453       } else {
1454         result = LogAndCreateResult(
1455             ErrorCode::UNKNOWN_ERR, "Unknown exception",
1456             ("bt_socket_destroy_rfcomm error: %d (%s)", ntv_ret, get_error_message(ntv_ret)));
1457       }
1458     }
1459
1460     if (registered_uuids_.empty() && connection_requests_.empty() && connected_sockets_.empty()) {
1461       bt_socket_unset_connection_state_changed_cb();
1462     }
1463   } else if (result.IsSuccess()) {
1464     result =
1465         LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is turned off");
1466   }
1467
1468   instance_.AsyncResponse(callback_handle, result);
1469 }
1470
1471 void BluetoothAdapter::GetBluetoothProfileHandler(const picojson::value& data,
1472                                                   picojson::object& out) {
1473   ScopeLogger();
1474
1475   const auto& args = util::GetArguments(data);
1476   auto profile = FromJson<std::string>(args, "profileType");
1477
1478   PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
1479
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");
1485     }
1486
1487     if (!supported) {
1488       result = LogAndCreateResult(ErrorCode::NOT_SUPPORTED_ERR,
1489                                   "Bluetooth health profile is not supported");
1490     } else {
1491       LoggerD("BT health profile is supported");
1492     }
1493   } else {
1494     result = LogAndCreateResult(ErrorCode::TYPE_MISMATCH_ERR, "Wrong profile type.");
1495   }
1496
1497   if (result.IsSuccess()) {
1498     ReportSuccess(out);
1499   } else {
1500     LogAndReportError(result, &out);
1501   }
1502 }
1503
1504 void BluetoothAdapter::GetName(const picojson::value& /* data */, picojson::object& out) {
1505   ScopeLogger();
1506
1507   ReportSuccess(picojson::value(get_name()), out);
1508 }
1509
1510 void BluetoothAdapter::GetAddress(const picojson::value& /* data */, picojson::object& out) {
1511   ScopeLogger();
1512
1513   if (!is_initialized_) {
1514     LogAndReportError(
1515         PlatformResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized."), &out);
1516     return;
1517   }
1518
1519   std::string str_address = "";
1520   char* address = nullptr;
1521   if (BT_ERROR_NONE == bt_adapter_get_address(&address)) {
1522     if (address) {
1523       str_address = address;
1524       free(address);
1525     }
1526   }
1527
1528   ReportSuccess(picojson::value(str_address), out);
1529 }
1530
1531 void BluetoothAdapter::GetPowered(const picojson::value& /* data */, picojson::object& out) {
1532   ScopeLogger();
1533
1534   ReportSuccess(picojson::value(is_powered_), out);
1535 }
1536
1537 void BluetoothAdapter::GetVisible(const picojson::value& /* data */, picojson::object& out) {
1538   ScopeLogger();
1539
1540   ReportSuccess(picojson::value(get_visible()), out);
1541 }
1542
1543 void BluetoothAdapter::OnSocketConnected(int result, bt_socket_connection_state_e state,
1544                                          bt_socket_connection_s* connection, void* user_data) {
1545   ScopeLogger();
1546
1547   BluetoothAdapter* object = static_cast<BluetoothAdapter*>(user_data);
1548
1549   if (!object) {
1550     LoggerW("user_data is NULL");
1551     return;
1552   }
1553
1554   if (!connection) {
1555     LoggerW("connection is NULL");
1556     return;
1557   }
1558
1559   if (BT_SOCKET_SERVER == connection->local_role) {
1560     LoggerD("Server");
1561
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");
1565       return;
1566     }
1567
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;
1572
1573         // Call BluetoothServiceHandler.onconnect
1574         object->instance_.FireEvent("BLUETOOTH_SERVICE_ONCONNECT",
1575                                     BluetoothSocket::ToJson(connection));
1576
1577         // Update connected_sockets_
1578         object->connected_sockets_.push_back(connection->socket_fd);
1579         bt_socket_set_data_received_cb(OnSocketReceivedData, user_data);
1580       } else {
1581         LoggerW("Establishing a connection failed");
1582       }
1583       return;
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);
1589       } else {
1590         LoggerW("Disconnecting a connection failed");
1591       }
1592     }
1593   } else if (BT_SOCKET_CLIENT == connection->local_role) {
1594     LoggerD("Client");
1595
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();
1599       auto request = end;
1600
1601       for (auto it = range.first; it != range.second; ++it) {
1602         if (strcmp(it->second->uuid_.c_str(), connection->service_uuid) == 0) {
1603           request = it;
1604           break;
1605         }
1606       }
1607
1608       if (end == request) {
1609         LoggerW("Connection state has changed unexpectedly");
1610         return;
1611       }
1612
1613       std::shared_ptr<picojson::value> response =
1614           std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
1615
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);
1619
1620         ReportSuccess(BluetoothSocket::ToJson(connection), response->get<picojson::object>());
1621       } else {
1622         LogAndReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Not found"),
1623                           &response->get<picojson::object>());
1624       }
1625
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);
1629
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);
1634       } else {
1635         LoggerW("Disconnecting a connection failed");
1636       }
1637     }
1638   } else {
1639     LoggerW("Unknown role");
1640     return;
1641   }
1642
1643   if (object->connected_sockets_.empty()) {
1644     bt_socket_unset_data_received_cb();
1645   }
1646
1647   if (object->registered_uuids_.empty() && object->connection_requests_.empty() &&
1648       object->connected_sockets_.empty()) {
1649     bt_socket_unset_connection_state_changed_cb();
1650   }
1651 }
1652
1653 void BluetoothAdapter::OnSocketReceivedData(bt_socket_received_data_s* data, void* user_data) {
1654   ScopeLogger();
1655
1656   BluetoothAdapter* object = static_cast<BluetoothAdapter*>(user_data);
1657
1658   if (!object) {
1659     LoggerW("user_data is NULL");
1660     return;
1661   }
1662
1663   if (!data) {
1664     LoggerW("data is NULL");
1665     return;
1666   }
1667
1668   const auto it = std::find(object->connected_sockets_.begin(), object->connected_sockets_.end(),
1669                             data->socket_fd);
1670
1671   if (it == object->connected_sockets_.end()) {
1672     LoggerW("Unknown connected socket: %d", data->socket_fd);
1673     return;
1674   }
1675
1676   // Store received data
1677   object->StoreSocketData(data);
1678
1679   object->InvokeSocketOnMessageEvent(*it);
1680 }
1681
1682 void BluetoothAdapter::ConnectToServiceByUUID(const std::string& address, const std::string& uuid,
1683                                               double callback_handle) {
1684   ScopeLogger();
1685
1686   PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
1687
1688   if (!IsValidUUID(uuid)) {
1689     result = LogAndCreateResult(ErrorCode::INVALID_VALUES_ERR, "Wrong UUID",
1690                                 ("Wrong UUID: %s", uuid.c_str()));
1691   }
1692
1693   if (result.IsSuccess() && is_powered_) {
1694     int ret = bt_socket_connect_rfcomm(address.c_str(), uuid.c_str());
1695
1696     switch (ret) {
1697       case BT_ERROR_NONE: {
1698         LoggerD("bt_socket_connect_rfcomm() succeeded");
1699
1700         ConnectionRequestPtr request{new ConnectionRequest()};
1701         request->uuid_ = uuid;
1702         request->callback_handle_ = callback_handle;
1703
1704         std::string r_address(address);
1705         for (size_t i = 0; i < address.length(); i++) {
1706           r_address[i] = toupper(address[i]);
1707         }
1708         connection_requests_.insert(std::make_pair(r_address, request));
1709
1710         bt_socket_set_connection_state_changed_cb(OnSocketConnected, this);
1711         break;
1712       }
1713
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)));
1719         break;
1720       default:
1721         result = LogAndCreateResult(
1722             ErrorCode::UNKNOWN_ERR, "Unknown error",
1723             ("bt_socket_connect_rfcomm error: %d (%s)", ret, get_error_message(ret)));
1724         break;
1725     }
1726   } else if (result.IsSuccess()) {
1727     result =
1728         LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is turned off");
1729   }
1730
1731   if (result.IsError()) {
1732     instance_.AsyncResponse(callback_handle, result);
1733   }
1734 }
1735
1736 void BluetoothAdapter::InvokeSocketEvent(int id, const char* event) {
1737   ScopeLogger();
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);
1743 }
1744
1745 void BluetoothAdapter::InvokeSocketOnMessageEvent(int id) {
1746   ScopeLogger();
1747   InvokeSocketEvent(id, "onmessage");
1748 }
1749
1750 void BluetoothAdapter::InvokeSocketOnCloseEvent(int id) {
1751   ScopeLogger();
1752   InvokeSocketEvent(id, "onclose");
1753 }
1754
1755 void BluetoothAdapter::RemoveSocket(int socket) {
1756   ScopeLogger();
1757   const auto data_it = socket_data_.find(socket);
1758
1759   if (data_it != socket_data_.end()) {
1760     socket_data_.erase(data_it);
1761   } else {
1762     LoggerD("No stored data for socket: %d", socket);
1763   }
1764
1765   const auto it = std::find(connected_sockets_.begin(), connected_sockets_.end(), socket);
1766
1767   if (it == connected_sockets_.end()) {
1768     LoggerW("Unknown connected socket: %d", socket);
1769     return;
1770   }
1771   int id = *it;
1772   connected_sockets_.erase(it);
1773
1774   InvokeSocketOnCloseEvent(id);
1775 }
1776
1777 void BluetoothAdapter::StoreSocketData(bt_socket_received_data_s* data) {
1778   ScopeLogger();
1779
1780   auto& data_store = socket_data_[data->socket_fd];
1781
1782   for (int i = 0; i < data->data_size; ++i) {
1783     data_store.push_back(data->data[i]);
1784   }
1785 }
1786
1787 const std::list<char>& BluetoothAdapter::ReadSocketData(int socket) {
1788   ScopeLogger();
1789
1790   return socket_data_[socket];
1791 }
1792
1793 void BluetoothAdapter::ClearSocketData(int socket) {
1794   ScopeLogger();
1795
1796   const auto data_it = socket_data_.find(socket);
1797
1798   if (data_it != socket_data_.end()) {
1799     data_it->second.clear();
1800   }
1801 }
1802
1803 void BluetoothAdapter::IsServiceConnected(const picojson::value& data, picojson::object& out) {
1804   ScopeLogger();
1805
1806   const auto& args = util::GetArguments(data);
1807   const auto& uuid = FromJson<std::string>(args, "uuid");
1808
1809   auto iter = registered_uuids_.find(uuid);
1810   if (iter == registered_uuids_.end()) {
1811     LogAndReportError(
1812         PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter was passed."), &out,
1813         ("Invalid uuid was passed: %s", uuid.c_str()));
1814     return;
1815   }
1816
1817   ReportSuccess(picojson::value(iter->second.second), out);
1818 }
1819
1820 void BluetoothAdapter::SetChangeListenerCallback(bool val) {
1821   ScopeLogger();
1822   is_callback_set_ = val;
1823 }
1824
1825 int BluetoothAdapter::AddPowerStateListener(const std::function<void(const int)>& listener) {
1826   return power_state_listeners_.Add(listener);
1827 }
1828
1829 void BluetoothAdapter::RemovePowerStateListener(int id) {
1830   power_state_listeners_.Remove(id);
1831 }
1832
1833 }  // namespace bluetooth
1834 }  // namespace extension