service: Add AdvertiseData and AdvertiseSettings
Added native definitions for AdvertiseData and AdvertiseSettings
framework objects. Also introduced parcel_helpers, which currently
provides functions to convert AdvertiseData and AdvertiseSettings
to/from Parcel.
As part of this, the bt_service_binder_unittests executable has been
added. This is built for the target device rather than host, as it
requires libbinder and libbinder currently can't be built for host.
Bug: 23793954
Change-Id: Ic55d7f48579e519006decaada5b6f2ef7aefe595
diff --git a/system/service/Android.mk b/system/service/Android.mk
index 635b319..1362ca3 100644
--- a/system/service/Android.mk
+++ b/system/service/Android.mk
@@ -21,6 +21,8 @@
btserviceCommonSrc := \
adapter.cpp \
adapter_state.cpp \
+ advertise_data.cpp \
+ advertise_settings.cpp \
daemon.cpp \
gatt_server.cpp \
hal/bluetooth_gatt_interface.cpp \
@@ -42,7 +44,8 @@
ipc/binder/IBluetoothCallback.cpp \
ipc/binder/IBluetoothLowEnergy.cpp \
ipc/binder/IBluetoothLowEnergyCallback.cpp \
- ipc/binder/ipc_handler_binder.cpp
+ ipc/binder/ipc_handler_binder.cpp \
+ ipc/binder/parcel_helpers.cpp
btserviceCommonIncludes := $(LOCAL_PATH)/../
@@ -78,6 +81,7 @@
hal/fake_bluetooth_gatt_interface.cpp \
hal/fake_bluetooth_interface.cpp \
test/adapter_unittest.cpp \
+ test/advertise_data_unittest.cpp \
test/fake_hal_util.cpp \
test/ipc_unix_unittest.cpp \
test/low_energy_client_unittest.cpp \
@@ -94,7 +98,26 @@
include $(BUILD_HOST_NATIVE_TEST)
endif
+# Native system service unittests for Binder code, for target
+# ========================================================
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := \
+ $(btserviceBinderSrc) \
+ $(btserviceCommonSrc) \
+ test/parcel_helpers_unittest.cpp
+LOCAL_C_INCLUDES += $(btserviceCommonIncludes)
+LOCAL_CFLAGS += -std=c++11
+LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE := bt_service_binder_unittests
+LOCAL_SHARED_LIBRARIES += \
+ libbinder \
+ libchrome \
+ libutils
+LOCAL_STATIC_LIBRARIES += liblog
+include $(BUILD_NATIVE_TEST)
+
# Native system service CLI for target
+# ========================================================
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
$(btserviceBinderSrc) \
diff --git a/system/service/advertise_data.cpp b/system/service/advertise_data.cpp
new file mode 100644
index 0000000..79227db
--- /dev/null
+++ b/system/service/advertise_data.cpp
@@ -0,0 +1,104 @@
+//
+// Copyright (C) 2015 Google, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "service/advertise_data.h"
+
+#include <base/logging.h>
+
+#include "stack/include/bt_types.h"
+#include "stack/include/hcidefs.h"
+
+namespace bluetooth {
+
+AdvertiseData::AdvertiseData(const std::vector<uint8_t>& data)
+ : data_(data),
+ include_device_name_(false),
+ include_tx_power_level_(false) {
+}
+
+AdvertiseData::AdvertiseData()
+ : include_device_name_(false),
+ include_tx_power_level_(false) {
+}
+
+AdvertiseData::AdvertiseData(const AdvertiseData& other)
+ : data_(other.data_),
+ include_device_name_(other.include_device_name_),
+ include_tx_power_level_(other.include_tx_power_level_) {
+}
+
+bool AdvertiseData::IsValid() const {
+ size_t len = data_.size();
+
+ // Consider empty data as valid.
+ if (!len)
+ return true;
+
+ for (size_t i = 0, field_len = 0; i < len; i += (field_len + 1)) {
+ field_len = data_[i];
+
+ // If the length of the current field would exceed the total data length,
+ // then the data is badly formatted.
+ if (i + field_len >= len) {
+ VLOG(1) << "Advertising data badly formatted";
+ return false;
+ }
+
+ uint8_t type = data_[i + 1];
+
+ // Clients are not allowed to set the following EIR fields as these are
+ // managed by stack.
+ switch (type) {
+ case HCI_EIR_FLAGS_TYPE:
+ case HCI_EIR_TX_POWER_LEVEL_TYPE:
+ case HCI_EIR_SHORTENED_LOCAL_NAME_TYPE:
+ case HCI_EIR_COMPLETE_LOCAL_NAME_TYPE:
+ case HCI_EIR_OOB_BD_ADDR_TYPE:
+ case HCI_EIR_OOB_COD_TYPE:
+ case HCI_EIR_OOB_SSP_HASH_C_TYPE:
+ case HCI_EIR_OOB_SSP_RAND_R_TYPE:
+ VLOG(1) << "Cannot set EIR field type: " << type;
+ return false;
+ default:
+ break;
+ }
+ }
+
+ return true;
+}
+
+bool AdvertiseData::operator==(const AdvertiseData& rhs) const {
+ if (include_tx_power_level_ != rhs.include_tx_power_level_)
+ return false;
+
+ if (include_device_name_ != rhs.include_device_name_)
+ return false;
+
+ return data_ == rhs.data_;
+}
+
+AdvertiseData& AdvertiseData::operator=(const AdvertiseData& other) {
+ if (this == &other)
+ return *this;
+
+ data_ = other.data_;
+ include_device_name_ = other.include_device_name_;
+ include_tx_power_level_ = other.include_tx_power_level_;
+
+ return *this;
+}
+
+} // namespace bluetooth
diff --git a/system/service/advertise_data.h b/system/service/advertise_data.h
new file mode 100644
index 0000000..5e6226a
--- /dev/null
+++ b/system/service/advertise_data.h
@@ -0,0 +1,79 @@
+//
+// Copyright (C) 2015 Google, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#pragma once
+
+#include <stdint.h>
+
+#include <vector>
+
+#include <base/macros.h>
+
+namespace bluetooth {
+
+// Represents a data packet for Bluetooth Low Energy advertisements. This is the
+// native equivalent of the Android framework class defined in
+// frameworks/base/core/j/android/bluetooth/le/AdvertiseData.java
+class AdvertiseData final {
+ public:
+ // Constructs an AdvertiseData with the given parameters. |data| can only
+ // contain the "Service UUIDs", "Service Data", and "Manufacturer Data" fields
+ // as specified in the Core Specification Supplement. |data| must be properly
+ // formatted according to the supplement and contains the data as it will be
+ // sent over the wire.
+ //
+ // The values for include_device_name() and include_tx_power_level() are
+ // initialized to false by default. These can be modified using the setters
+ // declared below.
+ explicit AdvertiseData(const std::vector<uint8_t>& data);
+
+ // Default constructor initializes all fields to be empty/false.
+ AdvertiseData();
+ AdvertiseData(const AdvertiseData& other);
+ ~AdvertiseData() = default;
+
+ // Returns true if the advertising data is formatted correctly according to
+ // the TLV format.
+ bool IsValid() const;
+
+ // data() returns the current advertising data contained by this instance. The
+ // data is in the TLV format as specified in the Bluetooth Core Specification.
+ const std::vector<uint8_t>& data() const { return data_; }
+
+ // Whether the device name should be included in the advertisement packet.
+ bool include_device_name() const { return include_device_name_; }
+ void set_include_device_name(bool value) { include_device_name_ = value; }
+
+ // Whether the transmission power level should be included in the
+ // advertisement packet.
+ bool include_tx_power_level() const { return include_tx_power_level_; }
+ void set_include_tx_power_level(bool value) {
+ include_tx_power_level_ = value;
+ }
+
+ // Comparison operator.
+ bool operator==(const AdvertiseData& rhs) const;
+
+ // Assignment operator
+ AdvertiseData& operator=(const AdvertiseData& other);
+
+ private:
+ std::vector<uint8_t> data_;
+ bool include_device_name_;
+ bool include_tx_power_level_;
+};
+
+} // namespace bluetooth
diff --git a/system/service/advertise_settings.cpp b/system/service/advertise_settings.cpp
new file mode 100644
index 0000000..bd561b2
--- /dev/null
+++ b/system/service/advertise_settings.cpp
@@ -0,0 +1,55 @@
+//
+// Copyright (C) 2015 Google, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "service/advertise_settings.h"
+
+namespace bluetooth {
+
+AdvertiseSettings::AdvertiseSettings(
+ Mode mode,
+ base::TimeDelta timeout,
+ TxPowerLevel tx_power_level,
+ bool connectable)
+ : mode_(mode),
+ timeout_(timeout),
+ tx_power_level_(tx_power_level),
+ connectable_(connectable) {
+}
+
+// Default values are taken from the AdvertiseSettings.java
+AdvertiseSettings::AdvertiseSettings()
+ : mode_(MODE_LOW_POWER),
+ tx_power_level_(TX_POWER_LEVEL_MEDIUM),
+ connectable_(true) {
+}
+
+bool AdvertiseSettings::operator==(const AdvertiseSettings& rhs) const {
+ if (mode_ != rhs.mode_)
+ return false;
+
+ if (timeout_ != rhs.timeout_)
+ return false;
+
+ if (tx_power_level_ != rhs.tx_power_level_)
+ return false;
+
+ if (connectable_ != rhs.connectable_)
+ return false;
+
+ return true;
+}
+
+} // namespace bluetooth
diff --git a/system/service/advertise_settings.h b/system/service/advertise_settings.h
new file mode 100644
index 0000000..5d928f4
--- /dev/null
+++ b/system/service/advertise_settings.h
@@ -0,0 +1,98 @@
+//
+// Copyright (C) 2015 Google, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#pragma once
+
+#include <base/macros.h>
+#include <base/time/time.h>
+
+namespace bluetooth {
+
+// AdvertiseSettings provides a way to adjust advertising preferences for each
+// Bluetooth LE advertisement instance. This is the native equivalent of the
+// Android framework class defined in
+// frameworks/base/core/java/android/bluetooth/le/AdvertiseSettings.java
+class AdvertiseSettings {
+ public:
+ // Advertising mode describes power consumption mode used for advertising.
+ enum Mode {
+ // Perform Bluetooth LE advertising in low power mode. This is the default
+ // and preferred advertising mode as it consumes the least power.
+ MODE_LOW_POWER = 0x00,
+
+ // Perform Bluetooth LE advertising in balanced power mode. This is balanced
+ // between advertising frequency and power consumption.
+ MODE_BALANCED = 0x01,
+
+ // Perform Bluetooth LE advertising in low latency, high power mode. This
+ // has the highest power consumption and should not be used for continuous
+ // background advertising.
+ MODE_LOW_LATENCY = 0x02,
+ };
+
+ // Levels that can be set for advertising transmission power.
+ enum TxPowerLevel {
+ // Advertise using the lowest transmission (TX) power level. Low
+ // transmission power can be used to restrict the visibility range of
+ // advertising packets.
+ TX_POWER_LEVEL_ULTRA_LOW = 0x00,
+
+ // Advertise using low TX power level.
+ TX_POWER_LEVEL_LOW = 0x01,
+
+ // Advertise using medium TX power level.
+ TX_POWER_LEVEL_MEDIUM = 0x02,
+
+ // Advertise using high TX power level. This corresponds to largest
+ // visibility range of the advertising packet.
+ TX_POWER_LEVEL_HIGH = 0x03,
+ };
+
+ AdvertiseSettings(Mode mode,
+ base::TimeDelta timeout,
+ TxPowerLevel tx_power_level,
+ bool connectable);
+
+ // The default constructor sets all fields to defaults:
+ // mode: MODE_LOW_POWER
+ // TX power level: TX_POWER_LEVEL_MEDIUM
+ // connectable: true
+ AdvertiseSettings();
+ ~AdvertiseSettings() = default;
+
+ // Returns the advertise mode.
+ Mode mode() const { return mode_; }
+
+ // Returns the advertising time limit in milliseconds.
+ const base::TimeDelta& timeout() const { return timeout_; }
+
+ // Returns the TX power level for advertising.
+ TxPowerLevel tx_power_level() const { return tx_power_level_; }
+
+ // Returns whether the advertisement will indicate connectable.
+ bool connectable() const { return connectable_; }
+
+ // Comparison operator.
+ bool operator==(const AdvertiseSettings& rhs) const;
+
+ private:
+ Mode mode_;
+ base::TimeDelta timeout_;
+ TxPowerLevel tx_power_level_;
+ bool connectable_;
+};
+
+} // namespace bluetooth
diff --git a/system/service/ipc/binder/parcel_helpers.cpp b/system/service/ipc/binder/parcel_helpers.cpp
new file mode 100644
index 0000000..3582606
--- /dev/null
+++ b/system/service/ipc/binder/parcel_helpers.cpp
@@ -0,0 +1,89 @@
+//
+// Copyright (C) 2015 Google, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "service/ipc/binder/parcel_helpers.h"
+
+using android::Parcel;
+
+using bluetooth::AdvertiseData;
+using bluetooth::AdvertiseSettings;
+
+namespace ipc {
+namespace binder {
+
+// TODO(armansito): The helpers below currently don't match the Java
+// definitions. We need to change the AIDL and framework code to comply with the
+// new definition and Parcel format provided here.
+
+void WriteAdvertiseDataToParcel(const AdvertiseData& data, Parcel* parcel) {
+ CHECK(parcel);
+ parcel->writeByteArray(data.data().size(), data.data().data()); // lol
+ parcel->writeInt32(data.include_device_name());
+ parcel->writeInt32(data.include_tx_power_level());
+}
+
+std::unique_ptr<AdvertiseData> CreateAdvertiseDataFromParcel(
+ const Parcel& parcel) {
+ std::vector<uint8_t> data;
+
+ // For len=0 Parcel::writeByteArray writes "-1" for the length value. So, any
+ // other value means that there is data to read.
+ // TODO(pavlin): We shouldn't need to worry about his here. Instead, Parcel
+ // should have an API for deserializing an array of bytes (e.g.
+ // Parcel::readByteArray()).
+ int data_len = parcel.readInt32();
+ if (data_len != -1) {
+ uint8_t bytes[data_len];
+ parcel.read(bytes, data_len);
+
+ data = std::vector<uint8_t>(bytes, bytes + data_len);
+ }
+
+ bool include_device_name = parcel.readInt32();
+ bool include_tx_power = parcel.readInt32();
+
+ std::unique_ptr<AdvertiseData> adv(new AdvertiseData(data));
+ adv->set_include_device_name(include_device_name);
+ adv->set_include_tx_power_level(include_tx_power);
+
+ return std::move(adv);
+}
+
+void WriteAdvertiseSettingsToParcel(const AdvertiseSettings& settings,
+ Parcel* parcel) {
+ CHECK(parcel);
+ parcel->writeInt32(settings.mode());
+ parcel->writeInt32(settings.tx_power_level());
+ parcel->writeInt32(settings.connectable());
+ parcel->writeInt64(settings.timeout().InMilliseconds());
+}
+
+std::unique_ptr<AdvertiseSettings> CreateAdvertiseSettingsFromParcel(
+ const Parcel& parcel) {
+ AdvertiseSettings::Mode mode =
+ static_cast<AdvertiseSettings::Mode>(parcel.readInt32());
+ AdvertiseSettings::TxPowerLevel tx_power =
+ static_cast<AdvertiseSettings::TxPowerLevel>(parcel.readInt32());
+ bool connectable = parcel.readInt32();
+ base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(
+ parcel.readInt64());
+
+ return std::unique_ptr<AdvertiseSettings>(
+ new AdvertiseSettings(mode, timeout, tx_power, connectable));
+}
+
+} // namespace binder
+} // namespace ipc
diff --git a/system/service/ipc/binder/parcel_helpers.h b/system/service/ipc/binder/parcel_helpers.h
new file mode 100644
index 0000000..7d7823b
--- /dev/null
+++ b/system/service/ipc/binder/parcel_helpers.h
@@ -0,0 +1,48 @@
+//
+// Copyright (C) 2015 Google, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#pragma once
+
+#include <memory>
+
+#include <binder/Parcel.h>
+
+#include "service/advertise_data.h"
+#include "service/advertise_settings.h"
+
+namespace ipc {
+namespace binder {
+
+// Helpers for converting bluetooth::AdvertiseData to/from Parcel
+
+void WriteAdvertiseDataToParcel(
+ const bluetooth::AdvertiseData& data,
+ android::Parcel* parcel);
+
+std::unique_ptr<bluetooth::AdvertiseData> CreateAdvertiseDataFromParcel(
+ const android::Parcel& parcel);
+
+// Helpers for converting bluetooth::AdvertiseSettings to/from Parcel
+
+void WriteAdvertiseSettingsToParcel(
+ const bluetooth::AdvertiseSettings& settings,
+ android::Parcel* parcel);
+
+std::unique_ptr<bluetooth::AdvertiseSettings> CreateAdvertiseSettingsFromParcel(
+ const android::Parcel& parcel);
+
+} // namespace binder
+} // namespace ipc
diff --git a/system/service/test/advertise_data_unittest.cpp b/system/service/test/advertise_data_unittest.cpp
new file mode 100644
index 0000000..a3524bf
--- /dev/null
+++ b/system/service/test/advertise_data_unittest.cpp
@@ -0,0 +1,152 @@
+//
+// Copyright (C) 2015 Google, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <gtest/gtest.h>
+
+#include "service/advertise_data.h"
+#include "stack/include/bt_types.h"
+#include "stack/include/hcidefs.h"
+
+namespace bluetooth {
+
+TEST(AdvertiseDataTest, EmptyData) {
+ const std::vector<uint8_t> data0;
+ AdvertiseData adv0(data0);
+ EXPECT_TRUE(adv0.IsValid());
+
+ const std::vector<uint8_t> data1{ 0x00 };
+ AdvertiseData adv1(data1);
+ EXPECT_TRUE(adv1.IsValid());
+}
+
+TEST(AdvertiseDataTest, BadTLV) {
+ // Single field, field empty.
+ const std::vector<uint8_t> data0{ 0x01 };
+ AdvertiseData adv0(data0);
+ EXPECT_FALSE(adv0.IsValid());
+
+ // Single field, first field length too long.
+ const std::vector<uint8_t> data1{ 0x05, 0x02, 0x00, 0x00, 0x00 };
+ AdvertiseData adv1(data1);
+ EXPECT_FALSE(adv1.IsValid());
+
+ // Two fields, second field length too long.
+ const std::vector<uint8_t> data2{ 0x02, 0x02, 0x00, 0x02, 0x00 };
+ AdvertiseData adv2(data2);
+ EXPECT_FALSE(adv2.IsValid());
+
+ // Two fields, second field empty.
+ const std::vector<uint8_t> data3{ 0x02, 0x02, 0x00, 0x01 };
+ AdvertiseData adv3(data3);
+ EXPECT_FALSE(adv3.IsValid());
+}
+
+TEST(AdvertiseDataTest, GoodTLV) {
+ // Singe field.
+ const std::vector<uint8_t> data0{ 0x03, 0x02, 0x01, 0x02 };
+ AdvertiseData adv0(data0);
+ EXPECT_TRUE(adv0.IsValid());
+
+ // Twi fields.
+ const std::vector<uint8_t> data1{ 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x01 };
+ AdvertiseData adv1(data1);
+ EXPECT_TRUE(adv0.IsValid());
+}
+
+TEST(AdvertiseDataTest, DisallowedFields) {
+ // Singe field.
+ const std::vector<uint8_t> data0{ 0x02, HCI_EIR_FLAGS_TYPE, 0x00 };
+ AdvertiseData adv0(data0);
+ EXPECT_FALSE(adv0.IsValid());
+
+ // Two fields, first invalid.
+ const std::vector<uint8_t> data1{
+ 0x02, HCI_EIR_FLAGS_TYPE, 0x00,
+ 0x03, 0x02, 0x01, 0x02
+ };
+ AdvertiseData adv1(data1);
+ EXPECT_FALSE(adv1.IsValid());
+
+ // Two fields, second invalid.
+ const std::vector<uint8_t> data2{
+ 0x03, 0x02, 0x01, 0x02,
+ 0x02, HCI_EIR_FLAGS_TYPE, 0x00
+ };
+ AdvertiseData adv2(data2);
+ EXPECT_FALSE(adv2.IsValid());
+
+ // Check all blacklisted fields
+ uint8_t blacklist[] = {
+ HCI_EIR_FLAGS_TYPE,
+ HCI_EIR_TX_POWER_LEVEL_TYPE,
+ HCI_EIR_SHORTENED_LOCAL_NAME_TYPE,
+ HCI_EIR_COMPLETE_LOCAL_NAME_TYPE,
+ HCI_EIR_OOB_BD_ADDR_TYPE,
+ HCI_EIR_OOB_COD_TYPE,
+ HCI_EIR_OOB_SSP_HASH_C_TYPE,
+ HCI_EIR_OOB_SSP_RAND_R_TYPE
+ };
+ for (size_t i = 0; i < sizeof(blacklist); i++) {
+ const std::vector<uint8_t> data{ 0x02, blacklist[i], 0x00 };
+ AdvertiseData adv(data);
+ EXPECT_FALSE(adv.IsValid());
+ }
+}
+
+TEST(AdvertiseDataTest, EqualsData) {
+ const std::vector<uint8_t> data0{ 0x02, 0x02, 0x00 };
+ const std::vector<uint8_t> data1{ 0x02, 0x03, 0x00 };
+
+ AdvertiseData adv0(data0);
+ AdvertiseData adv1(data1);
+
+ EXPECT_FALSE(adv0 == adv1);
+
+ AdvertiseData adv2(data1);
+ EXPECT_TRUE(adv1 == adv2);
+}
+
+TEST(AdvertiseDataTest, EqualsIncludes) {
+ const std::vector<uint8_t> data;
+
+ AdvertiseData adv0;
+ AdvertiseData adv1;
+ AdvertiseData adv2;
+ AdvertiseData adv3;
+ AdvertiseData adv4;
+
+ adv0.set_include_device_name(true);
+ adv0.set_include_tx_power_level(false);
+
+ adv1.set_include_device_name(false);
+ adv1.set_include_tx_power_level(false);
+
+ adv2.set_include_device_name(false);
+ adv2.set_include_tx_power_level(true);
+
+ adv3.set_include_device_name(true);
+ adv3.set_include_tx_power_level(true);
+
+ adv4.set_include_device_name(true);
+ adv4.set_include_tx_power_level(false);
+
+ EXPECT_FALSE(adv0 == adv1);
+ EXPECT_FALSE(adv0 == adv2);
+ EXPECT_FALSE(adv3 == adv1);
+ EXPECT_TRUE(adv4 == adv0);
+}
+
+} // namespace bluetooth
diff --git a/system/service/test/parcel_helpers_unittest.cpp b/system/service/test/parcel_helpers_unittest.cpp
new file mode 100644
index 0000000..0de761f
--- /dev/null
+++ b/system/service/test/parcel_helpers_unittest.cpp
@@ -0,0 +1,93 @@
+//
+// Copyright (C) 2015 Google, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <gtest/gtest.h>
+
+#include "service/advertise_data.h"
+#include "service/advertise_settings.h"
+#include "service/ipc/binder/parcel_helpers.h"
+
+using android::Parcel;
+
+using bluetooth::AdvertiseData;
+using bluetooth::AdvertiseSettings;
+
+namespace ipc {
+namespace binder {
+namespace {
+
+bool TestAdvertiseData(const AdvertiseData &adv_in) {
+ Parcel parcel;
+
+ WriteAdvertiseDataToParcel(adv_in, &parcel);
+ parcel.setDataPosition(0);
+ std::unique_ptr<AdvertiseData> adv_out =
+ CreateAdvertiseDataFromParcel(parcel);
+
+ return adv_in == *adv_out;
+}
+
+bool TestAdvertiseSettings(const AdvertiseSettings &settings_in) {
+ Parcel parcel;
+
+ WriteAdvertiseSettingsToParcel(settings_in, &parcel);
+ parcel.setDataPosition(0);
+ std::unique_ptr<AdvertiseSettings> settings_out =
+ CreateAdvertiseSettingsFromParcel(parcel);
+
+ return settings_in == *settings_out;
+}
+
+TEST(ParcelHelpersTest, EmptyAdvertiseData) {
+ std::vector<uint8_t> data;
+ AdvertiseData adv(data);
+
+ EXPECT_TRUE(TestAdvertiseData(adv));
+}
+
+TEST(ParcelHelpersTest, NonEmptyAdvertiseData) {
+ std::vector<uint8_t> data{ 0x02, 0x02, 0x00 };
+ AdvertiseData adv0(data);
+ adv0.set_include_tx_power_level(true);
+ EXPECT_TRUE(TestAdvertiseData(adv0));
+
+ AdvertiseData adv1(data);
+ adv1.set_include_device_name(true);
+ EXPECT_TRUE(TestAdvertiseData(adv1));
+
+ AdvertiseData adv2(data);
+ adv2.set_include_tx_power_level(true);
+ adv2.set_include_device_name(true);
+ EXPECT_TRUE(TestAdvertiseData(adv2));
+}
+
+TEST(ParcelHelpersTest, DefaultAdvertiseSettings) {
+ AdvertiseSettings settings;
+ EXPECT_TRUE(TestAdvertiseSettings(settings));
+}
+
+TEST(ParcelHelpersTest, NonEmptyAdvertiseSettings) {
+ AdvertiseSettings settings(
+ AdvertiseSettings::MODE_BALANCED,
+ base::TimeDelta::FromMilliseconds(150),
+ AdvertiseSettings::TX_POWER_LEVEL_HIGH,
+ false /* connectable */);
+ EXPECT_TRUE(TestAdvertiseSettings(settings));
+}
+
+} // namespace
+} // namespace binder
+} // namespace ipc