[Bluetooth] Add bluetooth power off listener for GATTServer 54/244454/2
authorRafal Walczyna <r.walczyna@samsung.com>
Fri, 18 Sep 2020 11:25:33 +0000 (13:25 +0200)
committerRafal Walczyna <r.walczyna@samsung.com>
Fri, 18 Sep 2020 11:38:39 +0000 (13:38 +0200)
GATTServer has to be stopped in case of bluetooth power off.

[ACR] https://code.sec.samsung.net/jira/browse/TWDAPI-263
[TASK] https://code.sec.samsung.net/jira/browse/XWALK-2161

[Verification] Tested in Chrome developer console

Change-Id: I92cca9dec5b7847b5073e88845846ce5e8446474
Signed-off-by: Rafal Walczyna <r.walczyna@samsung.com>
src/bluetooth/bluetooth_adapter.cc
src/bluetooth/bluetooth_adapter.h
src/bluetooth/bluetooth_api.js
src/bluetooth/bluetooth_gatt_server.cc
src/bluetooth/bluetooth_gatt_server.h
src/bluetooth/bluetooth_instance.cc
src/bluetooth/bluetooth_instance.h

index f4aaf96..17ad6c9 100644 (file)
@@ -111,6 +111,8 @@ void BluetoothAdapter::StateChangedCB(int result, bt_adapter_state_e state, void
   bool previous_powered = adapter->is_powered_;
   adapter->is_powered_ = powered;
 
+  adapter->power_state_listeners_.FireAll(powered);
+
   if (powered) {
     // update visible state if bluetooth device has been turned on
     adapter->is_visible_ = adapter->get_visible();
@@ -1803,5 +1805,13 @@ void BluetoothAdapter::SetChangeListenerCallback(bool val) {
   is_callback_set_ = val;
 }
 
+int BluetoothAdapter::AddPowerStateListener(const std::function<void(const int)>& listener) {
+  return power_state_listeners_.Add(listener);
+}
+
+void BluetoothAdapter::RemovePowerStateListener(int id) {
+  power_state_listeners_.Remove(id);
+}
+
 }  // namespace bluetooth
 }  // namespace extension
index caee94c..f19107e 100644 (file)
@@ -17,6 +17,7 @@
 #ifndef BLUETOOTH_BLUETOOTH_ADAPTER_H_
 #define BLUETOOTH_BLUETOOTH_ADAPTER_H_
 
+#include <functional>
 #include <list>
 #include <map>
 #include <memory>
@@ -35,6 +36,40 @@ enum AdapterAsyncEvent { SET_POWERED = 0, SET_NAME, SET_VISIBLE, DISCOVER_DEVICE
 
 class BluetoothInstance;
 
+class PowerStateListenersManager {
+ public:
+  PowerStateListenersManager() : count_(0) {
+    ScopeLogger();
+  }
+
+  ~PowerStateListenersManager() {
+    ScopeLogger();
+    power_state_listeners_map_.clear();
+  }
+
+  int Add(const std::function<void(const int)>& listener) {
+    ScopeLogger();
+    power_state_listeners_map_[count_] = listener;
+    return count_++;
+  }
+
+  void Remove(int id) {
+    ScopeLogger();
+    power_state_listeners_map_.erase(id);
+  }
+
+  void FireAll(bool state) {
+    ScopeLogger();
+    for (const auto& it : power_state_listeners_map_) {
+      it.second(state);
+    }
+  }
+
+ private:
+  std::map<int, std::function<void(const int)>> power_state_listeners_map_;
+  int count_;
+};
+
 class BluetoothAdapter {
  public:
   /**
@@ -305,11 +340,15 @@ class BluetoothAdapter {
   void UnregisterUUID(const std::string& uuid, int callback_handle);
 
   void SetChangeListenerCallback(bool val);
+  int AddPowerStateListener(const std::function<void(const int)>& listener);
+  void RemovePowerStateListener(int id);
 
  private:
   BluetoothAdapter(const BluetoothAdapter&) = delete;
   BluetoothAdapter& operator=(const BluetoothAdapter&) = delete;
 
+  PowerStateListenersManager power_state_listeners_;
+
   static void StateChangedCB(int result, bt_adapter_state_e state, void* user_data);
   static void NameChangedCB(char* name, void* user_data);
   static void VisibilityChangedCB(int result, bt_adapter_visibility_mode_e mode, void* user_data);
index 290a411..164784d 100755 (executable)
@@ -293,7 +293,7 @@ tizen.BluetoothLEAdvertiseData = function(dict) {
                 if (T.isNull(v)) {
                     servicesData_ = v;
                 } else if (T.isArray(v)) {
-                    var tmpArray = []
+                    var tmpArray = [];
                     for (var i = 0; i < v.length; ++i) {
                         if (v[i] instanceof tizen.BluetoothLEServiceData) {
                             tmpArray.push(v[i]);
@@ -2681,7 +2681,7 @@ var _setReadValueRequestCallbackCommon = function() {
                 }
             );
             _BluetoothGATTServerReadWriteValueRequestCallbacks[
-                "ReadValueCallback" + entityId
+                'ReadValueCallback' + entityId
             ] = readValueRequestCallback;
             native.callIfPossible(args.successCallback, native.getErrorObject(result));
         }
@@ -3773,6 +3773,12 @@ function _BluetoothGattServerIsRunningChangeListener(result) {
     _isBluetoothGATTServerRunning = result.state;
 }
 
+function _BluetoothGattServerBluetoothAdapterStateChangeListener(result) {
+    if (_isBluetoothGATTServerRunning && false === result.state) {
+        _BluetoothGATTServerServicesRegisteredInNativeLayer = {};
+    }
+}
+
 /*
  * This set is used in BluetoothGATTServer::start() to check which services
  * from BluetoothGATTServer::services have already been registered in native
@@ -3803,6 +3809,12 @@ var BluetoothGATTServer = function() {
         'BluetoothGattServerIsRunningChangeListener',
         _BluetoothGattServerIsRunningChangeListener
     );
+
+    // Register listener for managing BluetoothAdapter power off
+    native.addListener(
+        'BluetoothGattServerBluetoothAdapterStateChangeListener',
+        _BluetoothGattServerBluetoothAdapterStateChangeListener
+    );
 };
 
 var BluetoothGATTServer_valid_registerService_errors = [
index d1a4bd6..fe33139 100644 (file)
@@ -34,18 +34,27 @@ BluetoothGATTServer::BluetoothGATTServer(BluetoothInstance& instance,
       service_{service},
       initialized_{false},
       running_{false},
-      handle_{nullptr} {
+      handle_{nullptr},
+      power_state_change_callback_id_{-1} {
   ScopeLogger();
-  /*
-   * TODO: register a callback, that deinitializes a server, unregisters its
-   * services, destroys handle_ and sets running_ to false
-   * when Bluetooth is turned off.
-   */
+
+  power_state_change_callback_id_ =
+      instance_.GetBluetoothAdapter().AddPowerStateListener([this](const int state) {
+        ScopeLogger("BluetoothGATTServer PowerStateListenerCallback: %d", state);
+        if ((false == state) && (true == running_)) {
+          UnregisterAllServicesImpl();
+          DestroyAllGATTObjects();
+          Deinitialize();
+          PowerStateChangeCb(false);
+          SetRunningState(false);
+        }
+      });
 }
 
 BluetoothGATTServer::~BluetoothGATTServer() {
   ScopeLogger();
 
+  instance_.GetBluetoothAdapter().RemovePowerStateListener(power_state_change_callback_id_);
   UnregisterAllServicesImpl();
   DestroyAllGATTObjects();
   Deinitialize();
@@ -403,6 +412,18 @@ bool BluetoothGATTServer::DestroyDescriptor(int total, int index, bt_gatt_h hand
   return true;
 }
 
+void BluetoothGATTServer::PowerStateChangeCb(bool state) {
+  ScopeLogger();
+  picojson::value result{picojson::object{}};
+  auto& obj = result.get<picojson::object>();
+
+  obj.insert(
+      std::make_pair("listenerId", "BluetoothGattServerBluetoothAdapterStateChangeListener"));
+  obj.insert(std::make_pair("state", picojson::value(state)));
+
+  Instance::PostMessage(&instance_, result.serialize().c_str());
+}
+
 void BluetoothGATTServer::SetRunningState(bool state) {
   ScopeLogger();
   if (state != running_) {
index 9dc72be..e63ce5b 100644 (file)
@@ -56,7 +56,9 @@ class BluetoothGATTServer {
   // always use SetRunningState(bool) to change value of running_
   bool running_;
   bt_gatt_server_h handle_;
+  int power_state_change_callback_id_;
 
+  void PowerStateChangeCb(bool state);
   void SetRunningState(bool state);
 
   PlatformResult UnregisterAllServicesImpl();
index ad0e2b0..0a6bd70 100644 (file)
@@ -190,6 +190,10 @@ common::Worker& BluetoothInstance::GetWorker() {
   return worker;
 }
 
+BluetoothAdapter& BluetoothInstance::GetBluetoothAdapter() {
+  return bluetooth_adapter_;
+}
+
 void BluetoothInstance::BluetoothAdapterSetName(const picojson::value& args,
                                                 picojson::object& out) {
   ScopeLogger();
index a7043b2..04156d0 100644 (file)
@@ -51,6 +51,7 @@ class BluetoothInstance : public common::ParsedInstance {
   void FireEvent(const std::string& event, const std::shared_ptr<picojson::value>& value);
 
   common::Worker& GetWorker();
+  BluetoothAdapter& GetBluetoothAdapter();
 
  private:
   void BluetoothAdapterSetName(const picojson::value& args, picojson::object& out);