bluetooth: Expose service data from BlueZ
BlueZ exposed Bluetooth device's ServiceData as a{sv} property[1]
where the dict value variant is an array of byte.
This CL exposes that to upper layer by
- Add support to map<string, vector<uint8_t>> in dbus::Property
- Add new service_data property in BluetoothDeviceClient
- Implement GetServiceDataUUIDs() and GetServiceDataForUUID()
in BluetoothDeviceBlueZ
- Fix misc style issues in original code to make linter happy
[1] http://git.kernel.org/cgit/bluetooth/bluez.git/tree/src/device.c#n2551
BUG=618442,653310,b:28670943
TEST=Manually tested.
Review-Url: https://codereview.chromium.org/2369423003
Cr-Original-Commit-Position: refs/heads/master@{#423434}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: 0dd82b1c975662a10f34a53b3df56d98526b36d0
diff --git a/property.cc b/property.cc
index faca4a0..0ac65ef 100644
--- a/property.cc
+++ b/property.cc
@@ -6,6 +6,8 @@
#include <stddef.h>
+#include <memory>
+
#include "base/bind.h"
#include "base/logging.h"
@@ -659,6 +661,70 @@
writer->CloseContainer(&variant_writer);
}
+//
+// Property<std::map<std::string, std::vector<uint8_t>>>
+// specialization.
+//
+
+template <>
+bool Property<std::unordered_map<std::string, std::vector<uint8_t>>>::
+ PopValueFromReader(MessageReader* reader) {
+ MessageReader variant_reader(nullptr);
+ MessageReader dict_reader(nullptr);
+ if (!reader->PopVariant(&variant_reader) ||
+ !variant_reader.PopArray(&dict_reader))
+ return false;
+
+ value_.clear();
+ while (dict_reader.HasMoreData()) {
+ MessageReader entry_reader(nullptr);
+ if (!dict_reader.PopDictEntry(&entry_reader))
+ return false;
+
+ std::string key;
+ MessageReader value_varient_reader(nullptr);
+ if (!entry_reader.PopString(&key) ||
+ !entry_reader.PopVariant(&value_varient_reader))
+ return false;
+
+ const uint8_t* bytes = nullptr;
+ size_t length = 0;
+ if (!value_varient_reader.PopArrayOfBytes(&bytes, &length))
+ return false;
+
+ value_[key].assign(bytes, bytes + length);
+ }
+ return true;
+}
+
+template <>
+void Property<std::unordered_map<std::string, std::vector<uint8_t>>>::
+ AppendSetValueToWriter(MessageWriter* writer) {
+ MessageWriter variant_writer(nullptr);
+ MessageWriter dict_writer(nullptr);
+
+ writer->OpenVariant("a{sv}", &variant_writer);
+ variant_writer.OpenArray("{sv}", &dict_writer);
+
+ for (const auto& pair : set_value_) {
+ MessageWriter entry_writer(nullptr);
+ dict_writer.OpenDictEntry(&entry_writer);
+
+ entry_writer.AppendString(pair.first);
+
+ MessageWriter value_varient_writer(nullptr);
+ entry_writer.OpenVariant("ay", &value_varient_writer);
+ value_varient_writer.AppendArrayOfBytes(pair.second.data(),
+ pair.second.size());
+ entry_writer.CloseContainer(&value_varient_writer);
+
+ dict_writer.CloseContainer(&entry_writer);
+ }
+
+ variant_writer.CloseContainer(&dict_writer);
+ writer->CloseContainer(&variant_writer);
+}
+
template class Property<uint8_t>;
template class Property<bool>;
template class Property<int16_t>;
@@ -675,5 +741,6 @@
template class Property<std::vector<uint8_t>>;
template class Property<std::map<std::string, std::string>>;
template class Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>;
+template class Property<std::unordered_map<std::string, std::vector<uint8_t>>>;
} // namespace dbus
diff --git a/property.h b/property.h
index efbad22..616a595 100644
--- a/property.h
+++ b/property.h
@@ -9,6 +9,7 @@
#include <map>
#include <string>
+#include <unordered_map>
#include <utility>
#include <vector>
@@ -610,6 +611,17 @@
extern template class CHROME_DBUS_EXPORT
Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>;
+template <>
+CHROME_DBUS_EXPORT bool
+Property<std::unordered_map<std::string, std::vector<uint8_t>>>::
+ PopValueFromReader(MessageReader* reader);
+template <>
+CHROME_DBUS_EXPORT void
+Property<std::unordered_map<std::string, std::vector<uint8_t>>>::
+ AppendSetValueToWriter(MessageWriter* writer);
+extern template class CHROME_DBUS_EXPORT
+ Property<std::unordered_map<std::string, std::vector<uint8_t>>>;
+
#pragma GCC diagnostic pop
} // namespace dbus
diff --git a/property_unittest.cc b/property_unittest.cc
index 5922554..8208581 100644
--- a/property_unittest.cc
+++ b/property_unittest.cc
@@ -7,6 +7,7 @@
#include <stddef.h>
#include <stdint.h>
+#include <memory>
#include <string>
#include <vector>
@@ -431,4 +432,59 @@
EXPECT_EQ(test_list, ip_list.value());
}
+TEST(PropertyTestStatic, ReadWriteStringToByteVectorMap) {
+ std::unique_ptr<Response> message(Response::CreateEmpty());
+ MessageWriter writer(message.get());
+ MessageWriter variant_writer(nullptr);
+ MessageWriter dict_writer(nullptr);
+
+ writer.OpenVariant("a{sv}", &variant_writer);
+ variant_writer.OpenArray("{sv}", &dict_writer);
+
+ const char* keys[] = {"One", "Two", "Three", "Four"};
+ const std::vector<uint8_t> values[] = {{1}, {1, 2}, {1, 2, 3}, {1, 2, 3, 4}};
+ for (unsigned i = 0; i < arraysize(keys); ++i) {
+ MessageWriter entry_writer(nullptr);
+ dict_writer.OpenDictEntry(&entry_writer);
+
+ entry_writer.AppendString(keys[i]);
+
+ MessageWriter value_varient_writer(nullptr);
+ entry_writer.OpenVariant("ay", &value_varient_writer);
+ value_varient_writer.AppendArrayOfBytes(values[i].data(), values[i].size());
+ entry_writer.CloseContainer(&value_varient_writer);
+
+ dict_writer.CloseContainer(&entry_writer);
+ }
+
+ variant_writer.CloseContainer(&dict_writer);
+ writer.CloseContainer(&variant_writer);
+
+ MessageReader reader(message.get());
+ Property<std::unordered_map<std::string, std::vector<uint8_t>>> test_property;
+ EXPECT_TRUE(test_property.PopValueFromReader(&reader));
+
+ ASSERT_EQ(arraysize(keys), test_property.value().size());
+ for (unsigned i = 0; i < arraysize(keys); ++i)
+ EXPECT_EQ(values[i], test_property.value().at(keys[i]));
+}
+
+TEST(PropertyTestStatic, SerializeStringToByteVectorMap) {
+ std::unordered_map<std::string, std::vector<uint8_t>> test_map;
+ test_map["Hi"] = {1, 2, 3};
+ test_map["Map"] = {0xab, 0xcd};
+ test_map["Random"] = {0x0};
+
+ std::unique_ptr<Response> message(Response::CreateEmpty());
+ MessageWriter writer(message.get());
+
+ Property<std::unordered_map<std::string, std::vector<uint8_t>>> test_property;
+ test_property.ReplaceSetValueForTesting(test_map);
+ test_property.AppendSetValueToWriter(&writer);
+
+ MessageReader reader(message.get());
+ EXPECT_TRUE(test_property.PopValueFromReader(&reader));
+ EXPECT_EQ(test_map, test_property.value());
+}
+
} // namespace dbus