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