[Bluetooth] Added servicesData to BluetoothLEAdvertiseData 38/244338/2
authorPiotr Kosko/Native/Web API (PLT) /SRPOL/Engineer/Samsung Electronics <p.kosko@samsung.com>
Thu, 17 Sep 2020 09:01:43 +0000 (11:01 +0200)
committerPiotr Kosko/Native/Web API (PLT) /SRPOL/Engineer/Samsung Electronics <p.kosko@samsung.com>
Fri, 18 Sep 2020 07:35:19 +0000 (09:35 +0200)
servicesData has a higher priority of usage over serviceData.
To avoid problems with duplicated datas in both sets, deprecated member
serviceData is used only if servicesData is null or undefined.

[ACR] https://code.sec.samsung.net/jira/browse/TWDAPI-267

[Verification] Auto Bluetooth TCTs pass.

Change-Id: I4bb9e9a5e953a660f60d8e2b863291f848eae38f

src/bluetooth/bluetooth_api.js
src/bluetooth/bluetooth_le_adapter.cc

index 5608e2e..78df4ca 100755 (executable)
@@ -204,6 +204,7 @@ tizen.BluetoothLEAdvertiseData = function(dict) {
     var appearance_ = null;
     var includeTxPowerLevel_ = false;
     var serviceData_ = null;
+    var servicesData_ = null;
     var manufacturerData_ = null;
 
     Object.defineProperties(this, {
@@ -281,6 +282,25 @@ tizen.BluetoothLEAdvertiseData = function(dict) {
                 }
             }
         },
+        servicesData: {
+            enumerable: true,
+            get: function() {
+                return servicesData_;
+            },
+            set: function(v) {
+                if (T.isNull(v)) {
+                    servicesData_ = v;
+                } else if (T.isArray(v)) {
+                    var tmpArray = []
+                    for (var i = 0; i < v.length; ++i) {
+                        if (v[i] instanceof tizen.BluetoothLEServiceData) {
+                            tmpArray.push(v[i]);
+                        }
+                    }
+                    servicesData_ = tmpArray;
+                }
+            }
+        },
         manufacturerData: {
             enumerable: true,
             get: function() {
@@ -356,6 +376,12 @@ tizen.BluetoothLEAdvertiseData = function(dict) {
             return;
         }
 
+        // servicesData
+        if (T.isNull(dict.servicesData) || T.isArray(dict.servicesData)) {
+            // additional validation is done in setter of BluetoothLEAdvertiseData.servicesData
+            o.servicesData = dict.servicesData;
+        }
+
         // manufacturerData
         if (
             T.isNull(dict.manufacturerData) ||
index 27fd38f..cbd08ae 100644 (file)
@@ -35,6 +35,7 @@ const std::string kUuid = "uuid";
 const std::string kUuids = "uuids";
 const std::string kSolicitationUuids = "solicitationuuids";
 const std::string kServiceData = "serviceData";
+const std::string kServicesData = "servicesData";
 
 class ParsedDataHolder {
  public:
@@ -114,6 +115,7 @@ class BluetoothLEServiceData : public ParsedDataHolder {
       return {};
     }
 
+    LoggerD("BluetoohtLEServiceData: %s : %s", uuid_str.get<std::string>().c_str(), data.get<std::string>().c_str());
     return BluetoothLEServiceData{std::move(*uuid), data.get<std::string>()};
   }
 
@@ -323,26 +325,34 @@ class BluetoothLEAdvertiseData : public ParsedDataHolder {
     ScopeLogger();
 
     const auto& service_data_obj = obj.get(kServiceData);
-    if (service_data_obj.is<picojson::null>()) {
+    const auto& services_data_obj = obj.get(kServicesData);
+
+    if (service_data_obj.is<picojson::null>() && services_data_obj.is<picojson::null>()) {
+      LoggerD("Service data is null");
       return true;
-    } else if (!service_data_obj.is<picojson::object>()) {
-      return false;
     }
 
-    /*
-     * Currently, only advertising of a single service data object is supported
-     * by the Web API. In the future, support for advertising arrays of those
-     * may be added.
-     *
-     * TODO: if supported, parse here the whole array of service data instances.
-     */
-    auto service_data = BluetoothLEServiceData::Construct(service_data_obj);
-    if (!service_data) {
-      return false;
+    // check servicesData first and append services to a vector (higher priority)
+    if (!services_data_obj.is<picojson::null>() && services_data_obj.is<picojson::array>()) {
+      LoggerD("Parsing service data array");
+      for (auto single_service : services_data_obj.get<picojson::array>()) {
+        auto service_data = BluetoothLEServiceData::Construct(single_service);
+        if (!service_data) {
+          return false;
+        }
+        out->service_data_.emplace_back(std::move(*service_data));
+      }
+      return true;
+    } else if (!service_data_obj.is<picojson::null>() && service_data_obj.is<picojson::object>()) {
+      LoggerD("Parsing single service data");
+      auto service_data = BluetoothLEServiceData::Construct(service_data_obj);
+      if (!service_data) {
+        return false;
+      }
+      out->service_data_.emplace_back(std::move(*service_data));
+      return true;
     }
-
-    out->service_data_.emplace_back(std::move(*service_data));
-    return true;
+    return false;
   }
 
   static bool ParseManufacturerData(const picojson::value& obj, BluetoothLEAdvertiseData* out) {
@@ -648,6 +658,11 @@ void BluetoothLEAdapter::StartAdvertise(const picojson::value& data, picojson::o
           error_message =
               "Failed to start advertising: only 16 bit values of BluetoothLEServiceData::uuid are "
               "supported";
+        } else if (BT_ERROR_ALREADY_DONE == ret) {  // in case of duplicated advertiser data report it with correct message
+          LogAndReportError(util::GetBluetoothError(BT_ERROR_INVALID_PARAMETER, "Duplicated advertiser data"), &out,
+                          ("bt_adapter_le_set_advertising_device_name() failed with: %d (%s)", ret,
+                          get_error_message(ret)));
+          return;
         }
 
         LogAndReportError(util::GetBluetoothError(ret, error_message), &out,