[Bluetooth] Fix onstatechanged callback 82/230182/8
authorDawid Juszczak <d.juszczak@samsung.com>
Wed, 8 Apr 2020 08:14:22 +0000 (10:14 +0200)
committerDawid Juszczak <d.juszczak@samsung.com>
Tue, 9 Jun 2020 10:25:26 +0000 (10:25 +0000)
https://code.sec.samsung.net/jira/browse/XWALK-2065

[Description]
+ removed unnecessary calls of onstatechanged of BluetoothAdapterChangeCallback
+ refactor setPowered function

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

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

index f718617f5f1e6f0c5f182860f7ed091eab1ad127..d56079cf2569147b531796bb9520db0230fee6be 100644 (file)
@@ -115,7 +115,7 @@ void BluetoothAdapter::StateChangedCB(int result, bt_adapter_state_e state, void
     adapter->is_visible_ = adapter->get_visible();
   }
 
-  if (previous_powered != powered && BT_ERROR_NONE == result) {
+  if (adapter->is_callback_set_ && previous_powered != powered && BT_ERROR_NONE == result) {
     picojson::value value = picojson::value(picojson::object());
     picojson::object* data_obj = &value.get<picojson::object>();
 
@@ -341,7 +341,8 @@ void BluetoothAdapter::DiscoveryStateChangedCB(int result,
 }
 
 BluetoothAdapter::BluetoothAdapter(BluetoothInstance& instance)
-    : is_callback_set_(false),
+    : is_response_sent_(false),
+      is_callback_set_(false),
       is_visible_(false),
       is_powered_(false),
       is_initialized_(false),
@@ -525,106 +526,126 @@ void BluetoothAdapter::SetPowered(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_POWERED]) {
+  if (this->user_request_list_[SET_POWERED]) {
     ret = LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Already requested");
+    instance_.AsyncResponse(callback_handle, ret);
+    return;
   }
 
   bool cur_powered = this->get_powered();
 
-  if (ret.IsSuccess() && new_powered != cur_powered) {
-#ifdef APP_CONTROL_SETTINGS_SUPPORT
-    app_control_h service;
-    int err = 0;
-
-    if ((err = app_control_create(&service)) != APP_CONTROL_ERROR_NONE) {
-      ret = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "app control create failed",
-                               ("app control create failed: %d", err));
-    }
+  if (new_powered == cur_powered) {
+    LoggerD("Requested already set value, calling success callback");
+    instance_.AsyncResponse(callback_handle, ret);
+    return;
+  }
 
-    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", err));
-      }
-    }
+  this->requested_powered_ = new_powered;
+  this->user_request_callback_[SET_POWERED] = callback_handle;
+#ifdef APP_CONTROL_SETTINGS_SUPPORT
+  app_control_h app_control_ptr{nullptr};
+  int err = app_control_create(&app_control_ptr);
+  if (err != APP_CONTROL_ERROR_NONE) {
+    ret = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown exception",
+                             ("app_control_create() failed: %d", err));
+    instance_.AsyncResponse(callback_handle, ret);
+    return;
+  }
 
-    if (ret.IsSuccess()) {
-      err = app_control_set_mime(service, "application/x-bluetooth-on-off");
-      if (err != APP_CONTROL_ERROR_NONE) {
-        ret = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "app control set mime failed",
-                                 ("app control set mime failed: %d", err));
-      }
-    }
+  std::unique_ptr<std::remove_pointer<app_control_h>::type, decltype(&app_control_destroy)> service(
+      app_control_ptr, &app_control_destroy);
 
-    if (ret.IsSuccess()) {
-      struct UserData {
-        BluetoothAdapter* adapter;
-        double callback_handle;
-      };
+  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", err));
+    instance_.AsyncResponse(callback_handle, ret);
+    return;
+  }
 
-      UserData* user_data = new UserData{this, callback_handle};
+  err = app_control_set_mime(service.get(), "application/x-bluetooth-on-off");
+  if (err != APP_CONTROL_ERROR_NONE) {
+    ret = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown exception",
+                             ("app_control_set_mime() failed: %d", err));
+    instance_.AsyncResponse(callback_handle, ret);
+    return;
+  }
 
-      err = app_control_send_launch_request(
-          service,
-          [](app_control_h request, app_control_h reply, app_control_result_e r, void* user_data) {
-            LoggerD("app_control_send_launch_request() callback");
+  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() reply callback");
 
-            UserData* data = static_cast<UserData*>(user_data);
+    BluetoothAdapter* adapter = static_cast<BluetoothAdapter*>(user_data);
 
-            char* result = nullptr;
-            app_control_get_extra_data(reply, "result", &result);
+    if (adapter->is_response_sent_) {
+      LoggerE("response already sent");
+      return;
+    }
 
-            if (result && strcmp(result, "success") == 0) {
-              LoggerD("bt onoff: %s", result);
-              free(result);
-            } else {
-              LoggerE("app control setPowered failed");
-              data->adapter->instance_.AsyncResponse(
-                  data->callback_handle,
-                  LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "app control setPowered failed"));
-            }
+    if (app_res < APP_CONTROL_RESULT_SUCCEEDED) {
+      LoggerE("app control setPowered failed");
+      adapter->is_response_sent_ = true;
+      adapter->instance_.AsyncResponse(
+          adapter->user_request_callback_[SET_POWERED],
+          LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown exception"));
+    } else {
+      adapter->user_request_list_[SET_POWERED] = true;
+    }
+  };
+  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() result callback");
 
-            delete data;
-          },
-          user_data);
+    BluetoothAdapter* adapter = static_cast<BluetoothAdapter*>(user_data);
 
-      if (err != APP_CONTROL_ERROR_NONE) {
-        ret = LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "app control set launch request failed",
-                                 ("app control set launch request failed: %d", err));
-        delete user_data;
-      } else {
-        this->requested_powered_ = new_powered;
-        this->user_request_list_[SET_POWERED] = true;
-        this->user_request_callback_[SET_POWERED] = callback_handle;
-      }
+    if (adapter->is_response_sent_) {
+      LoggerE("response already sent");
+      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", err));
+    if (APP_CONTROL_ERROR_NONE != app_res) {
+      LoggerE("app control setPowered failed");
+      adapter->user_request_list_[SET_POWERED] = false;
+      adapter->is_response_sent_ = true;
+      adapter->instance_.AsyncResponse(
+          adapter->user_request_callback_[SET_POWERED],
+          LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown exception"));
+    } else {
+      adapter->user_request_list_[SET_POWERED] = true;
     }
+  };
 
-    if (!ret) {
-      instance_.AsyncResponse(callback_handle, ret);
-    }
+  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() failed: %d", err));
+    instance_.AsyncResponse(callback_handle, ret);
+    return;
+  }
 #else
-    this->requested_powered_ = new_powered;
-    this->user_request_list_[SET_POWERED] = true;
-    this->user_request_callback_[SET_POWERED] = callback_handle;
+  this->user_request_list_[SET_POWERED] = true;
+  int ntv_ret = 0;
 
-    if (new_powered) {
-      bt_adapter_enable();
-    } else {
-      bt_adapter_disable();
-    }
-#endif
+  if (new_powered) {
+    ntv_ret = bt_adapter_enable();
   } else {
+    ntv_ret = bt_adapter_disable();
+  }
+
+  if (!ntv_ret) {
+    ret = LogAndCreateResult(
+        ErrorCode::UNKNOWN_ERR, "Unknown exception",
+        ("enable/disable bt adapter failed, error: %d (%s)", ntv_ret, get_error_message(ntv_ret)));
     instance_.AsyncResponse(callback_handle, ret);
+    return;
   }
+#endif
 }
 
 void BluetoothAdapter::SetVisible(const picojson::value& data, picojson::object& out) {
index 85f4f267be4e7a17ad6efbd3c40fcbd5483ec96a..5a759a23eca90f8315716a5a651925fcc2ec3eed 100644 (file)
@@ -331,6 +331,7 @@ class BluetoothAdapter {
   void InvokeSocketOnMessageEvent(int id);
   void InvokeSocketOnCloseEvent(int id);
 
+  bool is_response_sent_;
   bool is_callback_set_;
   bool is_visible_;
   bool is_powered_;