[Bluetooth] Fix onvisibilitychanged callback 83/230183/6
authorDawid Juszczak <d.juszczak@samsung.com>
Mon, 8 Jun 2020 18:14:47 +0000 (20:14 +0200)
committerDawid Juszczak <d.juszczak@samsung.com>
Tue, 9 Jun 2020 10:25:51 +0000 (10:25 +0000)
https://code.sec.samsung.net/jira/browse/XWALK-2065

[Description]
+ removed unnecessary calls of onvisibilitychanged of BluetoothAdapterChangeCallback
+ refactor setVisible function

[Verification]
+ tested manually on chrome console
+ tct-bluetooth-tizen-tests (auto) - 100% PASS

Change-Id: I7edcb5a1028fec68d917a9b0e91a18c4d0d5294c
Signed-off-by: Dawid Juszczak <d.juszczak@samsung.com>
src/bluetooth/bluetooth_adapter.cc
src/bluetooth/bluetooth_adapter.h

index d56079c..8a4bed4 100644 (file)
@@ -192,7 +192,7 @@ void BluetoothAdapter::VisibilityChangedCB(int result, bt_adapter_visibility_mod
   bool previous_visible = adapter->is_visible_;
   adapter->is_visible_ = visible;
 
-  if (previous_visible != visible) {
+  if (adapter->is_callback_set_ && previous_visible != visible) {
     picojson::value value = picojson::value(picojson::object());
     picojson::object* data_obj = &value.get<picojson::object>();
 
@@ -342,6 +342,7 @@ void BluetoothAdapter::DiscoveryStateChangedCB(int result,
 
 BluetoothAdapter::BluetoothAdapter(BluetoothInstance& instance)
     : is_response_sent_(false),
+      is_visible_response_sent_(false),
       is_callback_set_(false),
       is_visible_(false),
       is_powered_(false),
@@ -670,139 +671,162 @@ void BluetoothAdapter::SetVisible(const picojson::value& data, picojson::object&
 
   if (!this->is_initialized()) {
     ret = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
+    instance_.AsyncResponse(callback_handle, ret);
+    return;
   }
 
-  if (ret.IsSuccess() && this->user_request_list_[SET_VISIBLE]) {
+  if (this->user_request_list_[SET_VISIBLE]) {
     ret = LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Already requested");
+    instance_.AsyncResponse(callback_handle, ret);
+    return;
   }
 
-  if (ret.IsSuccess() && this->get_powered()) {
-    bt_adapter_visibility_mode_e new_mode = BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE;
-    if (visible) {
-      if (0 == new_timeout) {
-        new_mode = BT_ADAPTER_VISIBILITY_MODE_GENERAL_DISCOVERABLE;
-      } else {
-        new_mode = BT_ADAPTER_VISIBILITY_MODE_LIMITED_DISCOVERABLE;
-      }
+  if (!this->get_powered()) {
+    ret =
+        LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is turned off");
+    instance_.AsyncResponse(callback_handle, ret);
+    return;
+  }
+
+  bt_adapter_visibility_mode_e new_mode = BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE;
+  if (visible) {
+    if (0 == new_timeout) {
+      new_mode = BT_ADAPTER_VISIBILITY_MODE_GENERAL_DISCOVERABLE;
+    } else {
+      new_mode = BT_ADAPTER_VISIBILITY_MODE_LIMITED_DISCOVERABLE;
     }
+  }
 
-    bt_adapter_visibility_mode_e cur_mode = BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE;
-    int cur_timeout = 0;
-    int ntv_ret = bt_adapter_get_visibility(&cur_mode, &cur_timeout);
-    if (BT_ERROR_NONE != ntv_ret) {
-      ret = LogAndCreateResult(
-          ErrorCode::UNKNOWN_ERR, "Unknown exception",
-          ("bt_adapter_get_visibility error: %d (%s)", ntv_ret, get_error_message(ntv_ret)));
+  bt_adapter_visibility_mode_e cur_mode = BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE;
+  int cur_timeout = 0;
+  int ntv_ret = bt_adapter_get_visibility(&cur_mode, &cur_timeout);
+  if (BT_ERROR_NONE != ntv_ret) {
+    ret = LogAndCreateResult(
+        ErrorCode::UNKNOWN_ERR, "Unknown exception",
+        ("bt_adapter_get_visibility error: %d (%s)", ntv_ret, get_error_message(ntv_ret)));
+    instance_.AsyncResponse(callback_handle, ret);
+    return;
+  }
+
+  if (new_mode == cur_mode && (BT_ADAPTER_VISIBILITY_MODE_LIMITED_DISCOVERABLE != new_mode ||
+                               (unsigned int)cur_timeout == new_timeout)) {
+    instance_.AsyncResponse(callback_handle, ret);
+    return;
+  }
+
+  this->requested_visibility_ = new_mode;
+  this->user_request_callback_[SET_VISIBLE] = callback_handle;
+#ifdef APP_CONTROL_SETTINGS_SUPPORT
+  app_control_h tmp_service{nullptr};
+  int err = app_control_create(&tmp_service);
+  if (err != APP_CONTROL_ERROR_NONE) {
+    ret = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown exception",
+                             ("app_control_create() failed: %d (%s)", err, get_error_message(err)));
+    instance_.AsyncResponse(callback_handle, ret);
+    return;
+  }
+
+  std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)> service(
+      tmp_service, &app_control_destroy);
+
+  err = app_control_set_operation(service.get(), "http://tizen.org/appcontrol/operation/edit");
+  if (err != APP_CONTROL_ERROR_NONE) {
+    ret = LogAndCreateResult(
+        ErrorCode::UNKNOWN_ERR, "Unknown exception",
+        ("app_control_set_operation() failed: %d (%s)", err, get_error_message(err)));
+    instance_.AsyncResponse(callback_handle, ret);
+    return;
+  }
+
+  err = app_control_set_mime(service.get(), "application/x-bluetooth-visibility");
+  if (err != APP_CONTROL_ERROR_NONE) {
+    ret =
+        LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown exception",
+                           ("app_control_set_mime() failed: %d (%s)", err, get_error_message(err)));
+    instance_.AsyncResponse(callback_handle, ret);
+    return;
+  }
+
+  this->is_response_sent_ = false;
+  app_control_reply_cb reply_cb = [](app_control_h request, app_control_h reply,
+                                     app_control_result_e app_res, void* user_data) {
+    LoggerD("Inside app_control_send_launch_request_async() reply callback");
+    BluetoothAdapter* adapter = static_cast<BluetoothAdapter*>(user_data);
+
+    if (adapter->is_visible_response_sent_) {
+      LoggerE("response already sent");
+      return;
     }
 
-    if (ret.IsSuccess() && new_mode == cur_mode) {
-      if (BT_ADAPTER_VISIBILITY_MODE_LIMITED_DISCOVERABLE != new_mode ||
-          (unsigned int)cur_timeout == new_timeout) {
-        instance_.AsyncResponse(callback_handle, ret);
-        return;
-      }
+    if (app_res < APP_CONTROL_RESULT_SUCCEEDED) {
+      LoggerE("app control setVisible failed");
+      adapter->is_visible_response_sent_ = true;
+      adapter->instance_.AsyncResponse(
+          adapter->user_request_callback_[SET_VISIBLE],
+          LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown exception"));
+    } else {
+      adapter->user_request_list_[SET_VISIBLE] = true;
     }
+  };
 
-    if (ret.IsSuccess()) {
-#ifdef APP_CONTROL_SETTINGS_SUPPORT
-      app_control_h service;
-      int err = 0;
+  app_control_result_cb result_cb = [](app_control_h request, app_control_error_e app_res,
+                                       void* user_data) {
+    LoggerD("Inside app_control_send_launch_request_async() result callback");
 
-      if ((err = app_control_create(&service)) != APP_CONTROL_ERROR_NONE) {
-        ret =
-            LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "app control create failed",
-                               ("app control create failed: %d (%s)", err, get_error_message(err)));
-      }
+    BluetoothAdapter* adapter = static_cast<BluetoothAdapter*>(user_data);
 
-      if (ret.IsSuccess()) {
-        err = app_control_set_operation(service, "http://tizen.org/appcontrol/operation/edit");
-        if (err != APP_CONTROL_ERROR_NONE) {
-          ret = LogAndCreateResult(
-              ErrorCode::UNKNOWN_ERR, "app control set operation failed",
-              ("app control set operation failed: %d (%s)", err, get_error_message(err)));
-        }
-      }
+    if (adapter->is_visible_response_sent_) {
+      LoggerE("response already sent");
+      return;
+    }
 
-      if (ret.IsSuccess()) {
-        err = app_control_set_mime(service, "application/x-bluetooth-visibility");
-        if (err != APP_CONTROL_ERROR_NONE) {
-          ret = LogAndCreateResult(
-              ErrorCode::UNKNOWN_ERR, "app control set mime failed",
-              ("app control set mime failed: %d (%s)", err, get_error_message(err)));
-        }
-      }
+    if (APP_CONTROL_ERROR_NONE != app_res) {
+      LoggerE("app control setVisible failed");
+      adapter->user_request_list_[SET_VISIBLE] = false;
+      adapter->is_visible_response_sent_ = true;
+      adapter->instance_.AsyncResponse(
+          adapter->user_request_callback_[SET_VISIBLE],
+          LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown exception"));
+    } else {
+      adapter->user_request_list_[SET_VISIBLE] = true;
+    }
+  };
 
-      if (ret.IsSuccess()) {
-        const void* t_param[] = {this, &ret, &new_mode, &callback_handle};
-
-        err = app_control_send_launch_request(
-            service,
-            [](app_control_h request, app_control_h reply, app_control_result_e r,
-               void* user_data) {
-              BluetoothAdapter* self = static_cast<BluetoothAdapter*>(((void**)user_data)[0]);
-              PlatformResult* p_ret = static_cast<PlatformResult*>(((void**)user_data)[1]);
-              bt_adapter_visibility_mode_e* p_new_mode =
-                  static_cast<bt_adapter_visibility_mode_e*>(((void**)user_data)[2]);
-              double* p_callback_handle = static_cast<double*>(((void**)user_data)[3]);
-
-              char* result = nullptr;
-              app_control_get_extra_data(reply, "result", &result);
-              LoggerD("bt visibility onoff: %s", result);
-
-              if (strcmp(result, "success") == 0) {
-                self->requested_visibility_ = *p_new_mode;
-                self->user_request_list_[SET_VISIBLE] = true;
-                self->user_request_callback_[SET_VISIBLE] = *p_callback_handle;
-              } else {
-                *p_ret =
-                    LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "app control setVisible failed");
-              }
-              free(result);
-            },
-            t_param);
-
-        if (err != APP_CONTROL_ERROR_NONE) {
-          ret = LogAndCreateResult(
-              ErrorCode::UNKNOWN_ERR, "app control set launch request failed",
-              ("app control set launch request failed: %d (%s)", err, get_error_message(err)));
-        }
-      }
+  err = app_control_send_launch_request_async(service.get(), result_cb, reply_cb, this);
+  if (err != APP_CONTROL_ERROR_NONE) {
+    ret = LogAndCreateResult(
+        ErrorCode::UNKNOWN_ERR, "Unknown exception",
+        ("app_control_send_launch_request_async() failed: %d (%s)", err, get_error_message(err)));
+    instance_.AsyncResponse(callback_handle, ret);
+    return;
+  }
 
-      err = app_control_destroy(service);
-      if (err != APP_CONTROL_ERROR_NONE) {
-        ret = LogAndCreateResult(
-            ErrorCode::UNKNOWN_ERR, "app control destroy failed",
-            ("app control destroy failed: %d (%s)", err, get_error_message(err)));
-      }
 #else
-      this->requested_visibility_ = new_mode;
-      this->user_request_list_[SET_VISIBLE] = true;
-      this->user_request_callback_[SET_VISIBLE] = callback_handle;
-      int ntv_ret = bt_adapter_set_visibility(new_mode, new_timeout);
-
-      switch (ntv_ret) {
-        case BT_ERROR_NONE:
-          // bt_adapter_visibility_mode_changed_cb() will be invoked
-          // if this function returns #BT_ERROR_NONE
-          break;
-        case BT_ERROR_INVALID_PARAMETER:
-          ret = LogAndCreateResult(
-              ErrorCode::INVALID_VALUES_ERR, "Invalid value",
-              ("bt_adapter_set_visibility error: %d (%s)", ntv_ret, get_error_message(ntv_ret)));
-          break;
-        default:
-          ret = LogAndCreateResult(
-              ErrorCode::UNKNOWN_ERR, "Unknown exception",
-              ("bt_adapter_set_visibility error: %d (%s)", ntv_ret, get_error_message(ntv_ret)));
-      }
-#endif
-    }
-  } else if (ret.IsSuccess()) {
-    ret =
-        LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is turned off");
+  this->user_request_list_[SET_VISIBLE] = true;
+  int ntv_ret = bt_adapter_set_visibility(new_mode, new_timeout);
+
+  switch (ntv_ret) {
+    case BT_ERROR_NONE:
+      // bt_adapter_visibility_mode_changed_cb() will be invoked
+      // if this function returns #BT_ERROR_NONE
+      break;
+    case BT_ERROR_INVALID_PARAMETER:
+      ret = LogAndCreateResult(
+          ErrorCode::INVALID_VALUES_ERR, "Invalid value",
+          ("bt_adapter_set_visibility error: %d (%s)", ntv_ret, get_error_message(ntv_ret)));
+      break;
+    default:
+      ret = LogAndCreateResult(
+          ErrorCode::UNKNOWN_ERR, "Unknown exception",
+          ("bt_adapter_set_visibility error: %d (%s)", ntv_ret, get_error_message(ntv_ret)));
   }
 
-  instance_.AsyncResponse(callback_handle, ret);
+  if (!ret) {
+    instance_.AsyncResponse(callback_handle, ret);
+    this->user_request_list_[SET_VISIBLE] = false;
+    return;
+  }
+#endif
 }
 
 void BluetoothAdapter::DiscoverDevices(const picojson::value& /* data */, picojson::object& out) {
index 5a759a2..caee94c 100644 (file)
@@ -332,6 +332,7 @@ class BluetoothAdapter {
   void InvokeSocketOnCloseEvent(int id);
 
   bool is_response_sent_;
+  bool is_visible_response_sent_;
   bool is_callback_set_;
   bool is_visible_;
   bool is_powered_;