Make RawAddress into a class (1/3)

* Add libbluetooth-types - library containing types implementation, that
is common between stystem/bt and packages/apps/Bluetooth. It must be
included in every project using btif interface.
* Put Raw Address implementation into libbluetooth-types
* Unify all "to/from string" helper methods into ToString and FromString
* bd_addr_empty -> RawAddress::kEmpty
* bd_addr_any -> RawAddress::kAny

Also fix leaks in jni str2addr by adding ReleaseStringUTFChars

Test: types_unittest
Change-Id: Ie0694843ad5fbd2a80b310c5f532e5e5a9548043
diff --git a/Android.bp b/Android.bp
index dae6460..462b8be 100644
--- a/Android.bp
+++ b/Android.bp
@@ -14,6 +14,7 @@
     "bta",
     "vendor_libs",
     "test",
+    "types",
     "udrv",
     "tools",
 ]
diff --git a/system/bta/Android.bp b/system/bta/Android.bp
index ffe01ad..79f7726 100644
--- a/system/bta/Android.bp
+++ b/system/bta/Android.bp
@@ -126,6 +126,7 @@
     static_libs: [
         "libbtcore",
         "libbt-bta",
+        "libbluetooth-types",
         "libosi",
         "libbt-protos",
     ],
diff --git a/system/bta/ag/bta_ag_act.cc b/system/bta/ag/bta_ag_act.cc
index ff4cb87..ad40c5d 100644
--- a/system/bta/ag/bta_ag_act.cc
+++ b/system/bta/ag/bta_ag_act.cc
@@ -305,7 +305,7 @@
   /* reinitialize stuff */
 
   /* clear the remote BD address */
-  p_scb->peer_addr = bd_addr_empty;
+  p_scb->peer_addr = RawAddress::kEmpty;
 
   /* call open cback w. failure */
   bta_ag_cback_open(p_scb, NULL, BTA_AG_FAIL_SDP);
@@ -347,7 +347,7 @@
   p_scb->svc_conn = false;
   p_scb->hsp_version = HSP_VERSION_1_2;
   /*Clear the BD address*/
-  p_scb->peer_addr = bd_addr_empty;
+  p_scb->peer_addr = RawAddress::kEmpty;
 
   /* reopen registered servers */
   bta_ag_start_servers(p_scb, p_scb->reg_services);
@@ -408,7 +408,7 @@
   /* if not deregistering (deallocating) reopen registered servers */
   if (p_scb->dealloc == false) {
     /* Clear peer bd_addr so instance can be reused */
-    p_scb->peer_addr = bd_addr_empty;
+    p_scb->peer_addr = RawAddress::kEmpty;
 
     /* start only unopened server */
     services = p_scb->reg_services;
diff --git a/system/bta/ag/bta_ag_rfc.cc b/system/bta/ag/bta_ag_rfc.cc
index 80fe95b..02729d5 100644
--- a/system/bta/ag/bta_ag_rfc.cc
+++ b/system/bta/ag/bta_ag_rfc.cc
@@ -274,7 +274,7 @@
 
       bta_ag_port_status = RFCOMM_CreateConnection(
           bta_ag_uuid[i], bta_ag_cb.profile[i].scn, true, BTA_AG_MTU,
-          bd_addr_any, &(p_scb->serv_handle[i]),
+          RawAddress::kAny, &(p_scb->serv_handle[i]),
           bta_ag_mgmt_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1]);
 
       if (bta_ag_port_status == PORT_SUCCESS) {
diff --git a/system/bta/av/bta_av_act.cc b/system/bta/av/bta_av_act.cc
index 2bdedbc..5e363d8 100644
--- a/system/bta/av/bta_av_act.cc
+++ b/system/bta/av/bta_av_act.cc
@@ -306,7 +306,7 @@
 uint8_t bta_av_rc_create(tBTA_AV_CB* p_cb, uint8_t role, uint8_t shdl,
                          uint8_t lidx) {
   tAVRC_CONN_CB ccb;
-  RawAddress bda = bd_addr_any;
+  RawAddress bda = RawAddress::kAny;
   uint8_t status = BTA_AV_RC_ROLE_ACP;
   tBTA_AV_SCB* p_scb = p_cb->p_scb[shdl - 1];
   int i;
@@ -1247,7 +1247,7 @@
       /* the stream is closed.
        * clear the peer address, so it would not mess up the AVRCP for the next
        * round of operation */
-      p_scb->peer_addr = bd_addr_empty;
+      p_scb->peer_addr = RawAddress::kEmpty;
       if (p_scb->chnl == BTA_AV_CHNL_AUDIO) {
         if (p_lcb) {
           p_lcb->conn_msk &= ~conn_msk;
diff --git a/system/bta/dm/bta_dm_act.cc b/system/bta/dm/bta_dm_act.cc
index 3388df6..cc2bf57 100644
--- a/system/bta/dm/bta_dm_act.cc
+++ b/system/bta/dm/bta_dm_act.cc
@@ -486,8 +486,8 @@
 void bta_dm_disable(UNUSED_ATTR tBTA_DM_MSG* p_data) {
   /* Set l2cap idle timeout to 0 (so BTE immediately disconnects ACL link after
    * last channel is closed) */
-  L2CA_SetIdleTimeoutByBdAddr(bd_addr_any, 0, BT_TRANSPORT_BR_EDR);
-  L2CA_SetIdleTimeoutByBdAddr(bd_addr_any, 0, BT_TRANSPORT_LE);
+  L2CA_SetIdleTimeoutByBdAddr(RawAddress::kAny, 0, BT_TRANSPORT_BR_EDR);
+  L2CA_SetIdleTimeoutByBdAddr(RawAddress::kAny, 0, BT_TRANSPORT_LE);
 
   /* disable all active subsystems */
   bta_sys_disable(BTA_SYS_HW_BLUETOOTH);
@@ -755,7 +755,7 @@
   if (continue_delete_dev) bta_dm_process_remove_device(p_dev->bd_addr);
 
   /* Delete the other paired device too */
-  if (continue_delete_other_dev && other_address != bd_addr_empty)
+  if (continue_delete_other_dev && !other_address.IsEmpty())
     bta_dm_process_remove_device(other_address);
 }
 
@@ -4588,7 +4588,7 @@
   if (bta_dm_search_cb.conn_id != BTA_GATT_INVALID_CONN_ID)
     BTA_GATTC_Close(bta_dm_search_cb.conn_id);
 
-  bta_dm_search_cb.pending_close_bda = bd_addr_empty;
+  bta_dm_search_cb.pending_close_bda = RawAddress::kEmpty;
   bta_dm_search_cb.conn_id = BTA_GATT_INVALID_CONN_ID;
 }
 /*******************************************************************************
@@ -4607,7 +4607,7 @@
   /* connection is already open */
   if (bta_dm_search_cb.pending_close_bda == bd_addr &&
       bta_dm_search_cb.conn_id != BTA_GATT_INVALID_CONN_ID) {
-    bta_dm_search_cb.pending_close_bda = bd_addr_empty;
+    bta_dm_search_cb.pending_close_bda = RawAddress::kEmpty;
     alarm_cancel(bta_dm_search_cb.gatt_close_timer);
     btm_dm_start_disc_gatt_services(bta_dm_search_cb.conn_id);
   } else {
diff --git a/system/bta/gatt/bta_gattc_utils.cc b/system/bta/gatt/bta_gattc_utils.cc
index d4ef668..f14f469 100644
--- a/system/bta/gatt/bta_gattc_utils.cc
+++ b/system/bta/gatt/bta_gattc_utils.cc
@@ -32,7 +32,6 @@
 #include "bt_common.h"
 #include "bta_gattc_int.h"
 #include "bta_sys.h"
-#include "btcore/include/bdaddr.h"
 #include "l2c_api.h"
 #include "utl.h"
 
@@ -488,7 +487,7 @@
 
   for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i++, p_bg_tck++) {
     if (p_bg_tck->in_use && ((p_bg_tck->remote_bda == remote_bda_ptr) ||
-                             (p_bg_tck->remote_bda == bd_addr_empty))) {
+                             (p_bg_tck->remote_bda.IsEmpty()))) {
       p_cif_mask = &p_bg_tck->cif_mask;
 
       if (add) /* mask on the cif bit */
@@ -546,7 +545,7 @@
 
   for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX && !is_bg_conn; i++, p_bg_tck++) {
     if (p_bg_tck->in_use && (p_bg_tck->remote_bda == remote_bda ||
-                             p_bg_tck->remote_bda == bd_addr_empty)) {
+                             p_bg_tck->remote_bda.IsEmpty())) {
       if (((p_bg_tck->cif_mask & (1 << (client_if - 1))) != 0) &&
           role == HCI_ROLE_MASTER)
         is_bg_conn = true;
@@ -665,7 +664,7 @@
 
   if (p_conn != NULL) {
     p_conn->in_use = false;
-    p_conn->remote_bda = bd_addr_empty;
+    p_conn->remote_bda = RawAddress::kEmpty;
     return true;
   }
   return false;
diff --git a/system/bta/hd/bta_hd_act.cc b/system/bta/hd/bta_hd_act.cc
index 1c2da81..0886422 100644
--- a/system/bta/hd/bta_hd_act.cc
+++ b/system/bta/hd/bta_hd_act.cc
@@ -480,7 +480,7 @@
   }
 
   cback_data.conn.bda = p_cback->addr;
-  bta_hd_cb.bd_addr = bd_addr_empty;
+  bta_hd_cb.bd_addr = RawAddress::kEmpty;
 
   bta_hd_cb.p_cback(cback_event, &cback_data);
 }
diff --git a/system/bta/hf_client/bta_hf_client_main.cc b/system/bta/hf_client/bta_hf_client_main.cc
index 4c23755..5fa26e2 100644
--- a/system/bta/hf_client/bta_hf_client_main.cc
+++ b/system/bta/hf_client/bta_hf_client_main.cc
@@ -27,7 +27,6 @@
 #include "bta_hf_client_api.h"
 #include "bta_hf_client_int.h"
 #include "bta_sys.h"
-#include "btcore/include/bdaddr.h"
 #include "osi/include/osi.h"
 #include "osi/include/properties.h"
 #include "utl.h"
diff --git a/system/bta/hf_client/bta_hf_client_rfc.cc b/system/bta/hf_client/bta_hf_client_rfc.cc
index 3f92068..3e2aa59 100644
--- a/system/bta/hf_client/bta_hf_client_rfc.cc
+++ b/system/bta/hf_client/bta_hf_client_rfc.cc
@@ -179,7 +179,7 @@
 
   port_status = RFCOMM_CreateConnection(
       UUID_SERVCLASS_HF_HANDSFREE, bta_hf_client_cb_arr.scn, true,
-      BTA_HF_CLIENT_MTU, bd_addr_any, &(bta_hf_client_cb_arr.serv_handle),
+      BTA_HF_CLIENT_MTU, RawAddress::kAny, &(bta_hf_client_cb_arr.serv_handle),
       bta_hf_client_mgmt_cback);
 
   APPL_TRACE_DEBUG("%s: started rfcomm server with handle %d", __func__,
diff --git a/system/bta/hh/bta_hh_utils.cc b/system/bta/hh/bta_hh_utils.cc
index 756a166..c687a2a 100644
--- a/system/bta/hh/bta_hh_utils.cc
+++ b/system/bta/hh/bta_hh_utils.cc
@@ -60,7 +60,7 @@
   /* See how many active devices there are. */
   for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++) {
     /* check if any active/known devices is a match */
-    if ((bda == bta_hh_cb.kdev[xx].addr && bda != bd_addr_empty)) {
+    if ((bda == bta_hh_cb.kdev[xx].addr && !bda.IsEmpty())) {
 #if (BTA_HH_DEBUG == TRUE)
       APPL_TRACE_DEBUG("found kdev_cb[%d] hid_handle = %d ", xx,
                        bta_hh_cb.kdev[xx].hid_handle)
diff --git a/system/bta/jv/bta_jv_act.cc b/system/bta/jv/bta_jv_act.cc
index 911534c..deba611 100644
--- a/system/bta/jv/bta_jv_act.cc
+++ b/system/bta/jv/bta_jv_act.cc
@@ -401,7 +401,7 @@
   p_pm_cb->state = BTA_JV_PM_FREE_ST;
   p_pm_cb->app_id = BTA_JV_PM_ALL;
   p_pm_cb->handle = BTA_JV_PM_HANDLE_CLEAR;
-  p_pm_cb->peer_bd_addr = bd_addr_empty;
+  p_pm_cb->peer_bd_addr = RawAddress::kEmpty;
 }
 
 /*******************************************************************************
@@ -1785,7 +1785,7 @@
     if (used < p_cb->max_sess && listen == 1 && si) {
       si--;
       if (RFCOMM_CreateConnection(p_cb->sec_id, p_cb->scn, true,
-                                  BTA_JV_DEF_RFC_MTU, bd_addr_any,
+                                  BTA_JV_DEF_RFC_MTU, RawAddress::kAny,
                                   &(p_cb->rfc_hdl[si]),
                                   bta_jv_port_mgmt_sr_cback) == PORT_SUCCESS) {
         p_cb->curr_sess++;
@@ -1858,7 +1858,7 @@
     }
 
     if (RFCOMM_CreateConnection(sec_id, rs->local_scn, true, BTA_JV_DEF_RFC_MTU,
-                                bd_addr_any, &handle,
+                                RawAddress::kAny, &handle,
                                 bta_jv_port_mgmt_sr_cback) != PORT_SUCCESS) {
       APPL_TRACE_ERROR(
           "bta_jv_rfcomm_start_server, RFCOMM_CreateConnection failed");
diff --git a/system/bta/test/bta_hf_client_test.cc b/system/bta/test/bta_hf_client_test.cc
index 50c24af..18f3d39 100644
--- a/system/bta/test/bta_hf_client_test.cc
+++ b/system/bta/test/bta_hf_client_test.cc
@@ -22,8 +22,8 @@
 #include "bta/include/bta_hf_client_api.h"
 
 namespace {
-const RawAddress bdaddr1 = {.address = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}};
-const RawAddress bdaddr2 = {.address = {0x66, 0x55, 0x44, 0x33, 0x22, 0x11}};
+const RawAddress bdaddr1({0x11, 0x22, 0x33, 0x44, 0x55, 0x66});
+const RawAddress bdaddr2({0x66, 0x55, 0x44, 0x33, 0x22, 0x11});
 }  // namespace
 
 // TODO(jpawlowski): there is some weird dependency issue in tests, and the
diff --git a/system/btcore/Android.bp b/system/btcore/Android.bp
index 603eea3..56458bd 100644
--- a/system/btcore/Android.bp
+++ b/system/btcore/Android.bp
@@ -6,7 +6,6 @@
     local_include_dirs: ["include"],
     include_dirs: ["packages/modules/Bluetooth/system"],
     srcs: [
-        "src/bdaddr.cc",
         "src/device_class.cc",
         "src/hal_util.cc",
         "src/module.cc",
@@ -39,7 +38,6 @@
     local_include_dirs: ["include"],
     include_dirs: ["packages/modules/Bluetooth/system"],
     srcs: [
-        "test/bdaddr_test.cc",
         "test/device_class_test.cc",
         "test/property_test.cc",
         "test/uuid_test.cc",
diff --git a/system/btcore/include/bdaddr.h b/system/btcore/include/bdaddr.h
deleted file mode 100644
index 7e2baf0..0000000
--- a/system/btcore/include/bdaddr.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/******************************************************************************
- *
- *  Copyright (C) 2014 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 <hardware/bluetooth.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include "stack/include/bt_types.h"
-
-// Note: the string representation of a bdaddr is expected to have the format
-// xx:xx:xx:xx:xx:xx
-// where each 'x' is a hex digit. The API presented in this header will accept
-// both uppercase and lowercase digits but will only ever produce lowercase
-// digits.
-
-typedef char bdstr_t[sizeof("xx:xx:xx:xx:xx:xx")];
-
-// Returns true if |addr| is the empty address (00:00:00:00:00:00).
-// |addr| may not be NULL.
-bool bdaddr_is_empty(const RawAddress* addr);
-
-// Makes a string representation of |addr| and places it into |string|. |size|
-// refers to the size of |string|'s buffer and must be >= 18. On success, this
-// function returns |string|, otherwise it returns NULL. Neither |addr| nor
-// |string| may be NULL.
-const char* bdaddr_to_string(const RawAddress* addr, char* string, size_t size);
-
-// Returns true if |string| represents a Bluetooth address. |string| may not be
-// NULL.
-bool string_is_bdaddr(const char* string);
-
-// Converts |string| to RawAddress and places it in |addr|. If |string| does
-// not represent a Bluetooth address, |addr| is not modified and this function
-// returns false. Otherwise, it returns true. Neither |string| nor |addr| may be
-// NULL.
-bool string_to_bdaddr(const char* string, RawAddress* addr);
diff --git a/system/btcore/src/bdaddr.cc b/system/btcore/src/bdaddr.cc
deleted file mode 100644
index c25b9d7..0000000
--- a/system/btcore/src/bdaddr.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-/******************************************************************************
- *
- *  Copyright (C) 2014 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 <base/logging.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "btcore/include/bdaddr.h"
-
-bool bdaddr_is_empty(const RawAddress* addr) {
-  CHECK(addr != NULL);
-
-  uint8_t zero[sizeof(RawAddress)] = {0};
-  return memcmp(addr, &zero, sizeof(RawAddress)) == 0;
-}
-
-const char* bdaddr_to_string(const RawAddress* addr, char* string,
-                             size_t size) {
-  CHECK(addr != NULL);
-  CHECK(string != NULL);
-
-  if (size < 18) return NULL;
-
-  const uint8_t* ptr = addr->address;
-  snprintf(string, size, "%02x:%02x:%02x:%02x:%02x:%02x", ptr[0], ptr[1],
-           ptr[2], ptr[3], ptr[4], ptr[5]);
-  return string;
-}
-
-bool string_is_bdaddr(const char* string) {
-  CHECK(string != NULL);
-
-  size_t len = strlen(string);
-  if (len != 17) return false;
-
-  for (size_t i = 0; i < len; ++i) {
-    // Every 3rd char must be ':'.
-    if (((i + 1) % 3) == 0 && string[i] != ':') return false;
-
-    // All other chars must be a hex digit.
-    if (((i + 1) % 3) != 0 && !isxdigit(string[i])) return false;
-  }
-  return true;
-}
-
-bool string_to_bdaddr(const char* string, RawAddress* addr) {
-  CHECK(string != NULL);
-  CHECK(addr != NULL);
-
-  RawAddress new_addr;
-  uint8_t* ptr = new_addr.address;
-  bool ret = sscanf(string, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
-                    &ptr[0], &ptr[1], &ptr[2], &ptr[3], &ptr[4], &ptr[5]) == 6;
-
-  if (ret) memcpy(addr, &new_addr, sizeof(RawAddress));
-
-  return ret;
-}
diff --git a/system/btcore/src/property.cc b/system/btcore/src/property.cc
index 790e9b2..1e314f0 100644
--- a/system/btcore/src/property.cc
+++ b/system/btcore/src/property.cc
@@ -19,7 +19,6 @@
 #include "btcore/include/property.h"
 #include <base/logging.h>
 #include <string.h>
-#include "btcore/include/bdaddr.h"
 #include "btcore/include/device_class.h"
 #include "btcore/include/uuid.h"
 #include "osi/include/allocator.h"
diff --git a/system/btcore/test/bdaddr_test.cc b/system/btcore/test/bdaddr_test.cc
deleted file mode 100644
index 11d5a9a..0000000
--- a/system/btcore/test/bdaddr_test.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-/******************************************************************************
- *
- *  Copyright (C) 2014 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 "btcore/include/bdaddr.h"
-
-static const char* test_addr = "12:34:56:78:9a:bc";
-static const char* test_addr2 = "cb:a9:87:65:43:21";
-
-TEST(BdaddrTest, test_empty) {
-  RawAddress empty;
-  string_to_bdaddr("00:00:00:00:00:00", &empty);
-  ASSERT_TRUE(bdaddr_is_empty(&empty));
-
-  RawAddress not_empty;
-  string_to_bdaddr("00:00:00:00:00:01", &not_empty);
-  ASSERT_FALSE(bdaddr_is_empty(&not_empty));
-}
-
-TEST(BdaddrTest, test_to_from_str) {
-  char ret[19];
-  RawAddress bdaddr;
-  string_to_bdaddr(test_addr, &bdaddr);
-
-  ASSERT_EQ(0x12, bdaddr.address[0]);
-  ASSERT_EQ(0x34, bdaddr.address[1]);
-  ASSERT_EQ(0x56, bdaddr.address[2]);
-  ASSERT_EQ(0x78, bdaddr.address[3]);
-  ASSERT_EQ(0x9A, bdaddr.address[4]);
-  ASSERT_EQ(0xBC, bdaddr.address[5]);
-
-  bdaddr_to_string(&bdaddr, ret, sizeof(ret));
-
-  ASSERT_STREQ(test_addr, ret);
-}
-
-TEST(BdaddrTest, test_equals) {
-  RawAddress bdaddr1;
-  RawAddress bdaddr2;
-  RawAddress bdaddr3;
-  string_to_bdaddr(test_addr, &bdaddr1);
-  string_to_bdaddr(test_addr, &bdaddr2);
-  EXPECT_TRUE(bdaddr1 == bdaddr2);
-
-  string_to_bdaddr(test_addr2, &bdaddr3);
-  EXPECT_FALSE(bdaddr2 == bdaddr3);
-}
-
-TEST(BdaddrTest, test_copy) {
-  RawAddress bdaddr1;
-  RawAddress bdaddr2;
-  string_to_bdaddr(test_addr, &bdaddr1);
-  bdaddr2 = bdaddr1;
-
-  EXPECT_TRUE(bdaddr1 == bdaddr2);
-}
diff --git a/system/btif/Android.bp b/system/btif/Android.bp
index 20acccf..a8faea0 100644
--- a/system/btif/Android.bp
+++ b/system/btif/Android.bp
@@ -115,6 +115,7 @@
         "libbtcore",
         "libbtif",
         "libbt-stack",
+        "libbluetooth-types",
         "libosi",
     ],
     cflags: ["-DBUILDCFG"],
diff --git a/system/btif/co/bta_hh_co.cc b/system/btif/co/bta_hh_co.cc
index 3f7bfb4..f6bc7cf 100644
--- a/system/btif/co/bta_hh_co.cc
+++ b/system/btif/co/bta_hh_co.cc
@@ -31,7 +31,6 @@
 #include "bta_api.h"
 #include "bta_hh_api.h"
 #include "bta_hh_co.h"
-#include "btcore/include/bdaddr.h"
 #include "btif_hh.h"
 #include "btif_util.h"
 #include "osi/include/osi.h"
@@ -525,8 +524,8 @@
                            UNUSED_ATTR uint8_t app_id) {
   unsigned idx = 0;
 
-  bdstr_t bdstr;
-  bdaddr_to_string(&remote_bda, bdstr, sizeof(bdstr));
+  std::string addrstr = remote_bda.ToString();
+  const char* bdstr = addrstr.c_str();
 
   size_t len = btif_config_get_bin_length(bdstr, "HidReport");
   if (len >= sizeof(tBTA_HH_RPT_CACHE_ENTRY) && len <= sizeof(sReportCache)) {
@@ -562,8 +561,8 @@
 tBTA_HH_RPT_CACHE_ENTRY* bta_hh_le_co_cache_load(const RawAddress& remote_bda,
                                                  uint8_t* p_num_rpt,
                                                  UNUSED_ATTR uint8_t app_id) {
-  bdstr_t bdstr;
-  bdaddr_to_string(&remote_bda, bdstr, sizeof(bdstr));
+  std::string addrstr = remote_bda.ToString();
+  const char* bdstr = addrstr.c_str();
 
   size_t len = btif_config_get_bin_length(bdstr, "HidReport");
   if (!p_num_rpt && len < sizeof(tBTA_HH_RPT_CACHE_ENTRY)) return NULL;
@@ -591,8 +590,8 @@
  ******************************************************************************/
 void bta_hh_le_co_reset_rpt_cache(const RawAddress& remote_bda,
                                   UNUSED_ATTR uint8_t app_id) {
-  bdstr_t bdstr;
-  bdaddr_to_string(&remote_bda, bdstr, sizeof(bdstr));
+  std::string addrstr = remote_bda.ToString();
+  const char* bdstr = addrstr.c_str();
 
   btif_config_remove(bdstr, "HidReport");
 
diff --git a/system/btif/co/bta_pan_co.cc b/system/btif/co/bta_pan_co.cc
index b740c61..1868c78 100644
--- a/system/btif/co/bta_pan_co.cc
+++ b/system/btif/co/bta_pan_co.cc
@@ -33,7 +33,6 @@
 #include "bta_api.h"
 #include "bta_pan_api.h"
 #include "bta_pan_ci.h"
-#include "btcore/include/bdaddr.h"
 #include "btif_pan_internal.h"
 #include "btif_sock_thread.h"
 #include "btif_util.h"
diff --git a/system/btif/include/btif_pan_internal.h b/system/btif/include/btif_pan_internal.h
index 59802f5..a902946 100644
--- a/system/btif/include/btif_pan_internal.h
+++ b/system/btif/include/btif_pan_internal.h
@@ -103,7 +103,7 @@
                    bool forward);
 
 static inline int is_empty_eth_addr(const RawAddress& addr) {
-  return addr == bd_addr_empty;
+  return addr == RawAddress::kEmpty;
 }
 
 static inline int is_valid_bt_eth_addr(const RawAddress& addr) {
diff --git a/system/btif/src/btif_a2dp_source.cc b/system/btif/src/btif_a2dp_source.cc
index d49dfeb..6667687 100644
--- a/system/btif/src/btif_a2dp_source.cc
+++ b/system/btif/src/btif_a2dp_source.cc
@@ -29,7 +29,6 @@
 #include "audio_a2dp_hw/include/audio_a2dp_hw.h"
 #include "bt_common.h"
 #include "bta_av_ci.h"
-#include "btcore/include/bdaddr.h"
 #include "btif_a2dp.h"
 #include "btif_a2dp_control.h"
 #include "btif_a2dp_source.h"
@@ -1089,8 +1088,6 @@
     return;
   }
 
-  char temp_buffer[20] = {0};
   LOG_WARN(LOG_TAG, "%s device: %s, rssi: %d", __func__,
-           bdaddr_to_string(&result->rem_bda, temp_buffer, sizeof(temp_buffer)),
-           result->rssi);
+           result->rem_bda.ToString().c_str(), result->rssi);
 }
diff --git a/system/btif/src/btif_ble_scanner.cc b/system/btif/src/btif_ble_scanner.cc
index 5dbf97d..baad278 100644
--- a/system/btif/src/btif_ble_scanner.cc
+++ b/system/btif/src/btif_ble_scanner.cc
@@ -28,7 +28,6 @@
 #include <unordered_set>
 #include "device/include/controller.h"
 
-#include "btcore/include/bdaddr.h"
 #include "btif_common.h"
 #include "btif_util.h"
 
diff --git a/system/btif/src/btif_config.cc b/system/btif/src/btif_config.cc
index 5919c39..c6e860d 100644
--- a/system/btif/src/btif_config.cc
+++ b/system/btif/src/btif_config.cc
@@ -31,7 +31,6 @@
 #include <mutex>
 
 #include "bt_types.h"
-#include "btcore/include/bdaddr.h"
 #include "btcore/include/module.h"
 #include "btif_api.h"
 #include "btif_common.h"
@@ -92,8 +91,8 @@
 bool btif_get_device_type(const RawAddress& bda, int* p_device_type) {
   if (p_device_type == NULL) return false;
 
-  bdstr_t bd_addr_str;
-  bdaddr_to_string(&bda, bd_addr_str, sizeof(bd_addr_str));
+  std::string addrstr = bda.ToString();
+  const char* bd_addr_str = addrstr.c_str();
 
   if (!btif_config_get_int(bd_addr_str, "DevType", p_device_type)) return false;
 
@@ -105,8 +104,8 @@
 bool btif_get_address_type(const RawAddress& bda, int* p_addr_type) {
   if (p_addr_type == NULL) return false;
 
-  bdstr_t bd_addr_str;
-  bdaddr_to_string(&bda, bd_addr_str, sizeof(bd_addr_str));
+  std::string addrstr = bda.ToString();
+  const char* bd_addr_str = addrstr.c_str();
 
   if (!btif_config_get_int(bd_addr_str, "AddrType", p_addr_type)) return false;
 
@@ -469,7 +468,7 @@
   const config_section_node_t* snode = config_section_begin(conf);
   while (snode != config_section_end(conf)) {
     const char* section = config_section_name(snode);
-    if (string_is_bdaddr(section)) {
+    if (RawAddress::IsValidAddress(section)) {
       if (!config_has_key(conf, section, "LinkKey") &&
           !config_has_key(conf, section, "LE_KEY_PENC") &&
           !config_has_key(conf, section, "LE_KEY_PID") &&
@@ -527,7 +526,7 @@
   const config_section_node_t* snode = config_section_begin(config);
   while (snode != config_section_end(config)) {
     const char* section = config_section_name(snode);
-    if (string_is_bdaddr(section) &&
+    if (RawAddress::IsValidAddress(section) &&
         config_has_key(config, section, "Restricted")) {
       BTIF_TRACE_DEBUG("%s: Removing restricted device %s", __func__, section);
       config_remove_section(config, section);
diff --git a/system/btif/src/btif_core.cc b/system/btif/src/btif_core.cc
index 4887ee5..43da993 100644
--- a/system/btif/src/btif_core.cc
+++ b/system/btif/src/btif_core.cc
@@ -42,7 +42,6 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include "bdaddr.h"
 #include "bt_common.h"
 #include "bt_utils.h"
 #include "bta_api.h"
@@ -84,8 +83,9 @@
  ******************************************************************************/
 
 /* These type definitions are used when passing data from the HAL to BTIF
-* context
-*  in the downstream path for the adapter and remote_device property APIs */
+ * context in the downstream path for the adapter and remote_device property
+ * APIs
+ */
 
 typedef struct {
   RawAddress bd_addr;
@@ -116,11 +116,11 @@
 static tBTA_SERVICE_MASK btif_enabled_services = 0;
 
 /*
-* This variable should be set to 1, if the Bluedroid+BTIF libraries are to
-* function in DUT mode.
-*
-* To set this, the btif_init_bluetooth needs to be called with argument as 1
-*/
+ * This variable should be set to 1, if the Bluedroid+BTIF libraries are to
+ * function in DUT mode.
+ *
+ * To set this, the btif_init_bluetooth needs to be called with argument as 1
+ */
 static uint8_t btif_dut_mode = 0;
 
 static thread_t* bt_jni_workqueue_thread;
@@ -383,16 +383,15 @@
   /* Fetch the local BD ADDR */
   RawAddress local_bd_addr = *controller_get_interface()->get_address();
 
-  bdstr_t bdstr;
-  bdaddr_to_string(&local_bd_addr, bdstr, sizeof(bdstr));
+  std::string bdstr = local_bd_addr.ToString();
 
   char val[PROPERTY_VALUE_MAX] = "";
   int val_size = 0;
   if ((btif_config_get_str("Adapter", "Address", val, &val_size) == 0) ||
-      strcmp(bdstr, val) == 0) {
+      strcmp(bdstr.c_str(), val) == 0) {
     // This address is not present in the config file, save it there.
     BTIF_TRACE_WARNING("%s: Saving the Adapter Address", __func__);
-    btif_config_set_str("Adapter", "Address", bdstr);
+    btif_config_set_str("Adapter", "Address", bdstr.c_str());
     btif_config_save();
 
     // fire HAL callback for property change
diff --git a/system/btif/src/btif_debug_conn.cc b/system/btif/src/btif_debug_conn.cc
index 69ca87c..869782f 100644
--- a/system/btif/src/btif_debug_conn.cc
+++ b/system/btif/src/btif_debug_conn.cc
@@ -20,7 +20,6 @@
 #include <string.h>
 #include <time.h>
 
-#include "btcore/include/bdaddr.h"
 #include "btif/include/btif_debug_conn.h"
 #include "osi/include/time.h"
 
@@ -81,7 +80,6 @@
       current_event;  // Cache to avoid threading issues
   uint8_t dump_event = current_event_local;
   char ts_buffer[TEMP_BUFFER_SIZE] = {0};
-  char name_buffer[TEMP_BUFFER_SIZE] = {0};
 
   dprintf(fd, "\nConnection Events:\n");
   if (connection_events[dump_event].ts == 0) dprintf(fd, "  None\n");
@@ -89,8 +87,7 @@
   while (connection_events[dump_event].ts) {
     conn_event_t* evt = &connection_events[dump_event];
     dprintf(fd, "  %s %s %s", format_ts(evt->ts, ts_buffer, sizeof(ts_buffer)),
-            format_state(evt->state),
-            bdaddr_to_string(&evt->bda, name_buffer, sizeof(name_buffer)));
+            format_state(evt->state), evt->bda.ToString().c_str());
     if (evt->state == BTIF_DEBUG_DISCONNECTED)
       dprintf(fd, " reason=%d", evt->disconnect_reason);
     dprintf(fd, "\n");
diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc
index 04b26b9..0f12ca4 100644
--- a/system/btif/src/btif_dm.cc
+++ b/system/btif/src/btif_dm.cc
@@ -44,7 +44,6 @@
 #include <hardware/bluetooth.h>
 
 #include "advertise_data_parser.h"
-#include "bdaddr.h"
 #include "bt_common.h"
 #include "bta_closure_api.h"
 #include "bta_gatt_api.h"
@@ -438,9 +437,8 @@
   if (btif_storage_get_remote_device_property(
           (RawAddress*)remote_bdaddr, &prop_name) == BT_STATUS_SUCCESS) {
     if (remote_dev_type == BT_DEVICE_DEVTYPE_BLE) {
-      bdstr_t bdstr;
-      bdaddr_to_string(remote_bdaddr, bdstr, sizeof(bdstr));
-      if (btif_config_exist(bdstr, "HidAppId")) return true;
+      if (btif_config_exist(remote_bdaddr->ToString().c_str(), "HidAppId"))
+        return true;
     }
   }
   return false;
@@ -473,8 +471,8 @@
   BTIF_STORAGE_FILL_PROPERTY(&prop_name, BT_PROPERTY_REMOTE_VERSION_INFO,
                              sizeof(bt_remote_version_t), &info);
 
-  if (btif_storage_get_remote_device_property(
-          (RawAddress*)remote_bdaddr, &prop_name) != BT_STATUS_SUCCESS) {
+  if (btif_storage_get_remote_device_property(remote_bdaddr, &prop_name) !=
+      BT_STATUS_SUCCESS) {
     return false;
   }
   manufacturer = info.manufacturer;
@@ -493,7 +491,7 @@
   // duplicates
   if ((pairing_cb.state == state) && (state == BT_BOND_STATE_BONDING)) {
     // Cross key pairing so send callback for static address
-    if (!bdaddr_is_empty(&pairing_cb.static_bdaddr)) {
+    if (!pairing_cb.static_bdaddr.IsEmpty()) {
       auto tmp = bd_addr;
       HAL_CBACK(bt_hal_cbacks, bond_state_changed_cb, status, &tmp, state);
     }
@@ -529,13 +527,11 @@
   tBTM_STATUS btm_status;
   bt_remote_version_t info;
   bt_status_t status;
-  bdstr_t bdstr;
 
   btm_status = BTM_ReadRemoteVersion(*p_bd, &lmp_ver, &mfct_set, &lmp_subver);
 
   LOG_DEBUG(LOG_TAG, "remote version info [%s]: %x, %x, %x",
-            bdaddr_to_string(p_bd, bdstr, sizeof(bdstr)), lmp_ver, mfct_set,
-            lmp_subver);
+            p_bd->ToString().c_str(), lmp_ver, mfct_set, lmp_subver);
 
   if (btm_status == BTM_SUCCESS) {
     // Always update cache to ensure we have availability whenever BTM API is
@@ -663,10 +659,10 @@
 
   int device_type;
   int addr_type;
-  bdstr_t bdstr;
-  bdaddr_to_string(&bd_addr, bdstr, sizeof(bdstr));
+  std::string addrstr = bd_addr.ToString();
+  const char* bdstr = addrstr.c_str();
   if (transport == BT_TRANSPORT_LE) {
-    if (!btif_config_get_int((char const*)&bdstr, "DevType", &device_type)) {
+    if (!btif_config_get_int(bdstr, "DevType", &device_type)) {
       btif_config_set_int(bdstr, "DevType", BT_DEVICE_TYPE_BLE);
     }
     if (btif_storage_get_remote_addr_type(&bd_addr, &addr_type) !=
@@ -681,7 +677,7 @@
       btif_storage_set_remote_addr_type(&bd_addr, addr_type);
     }
   }
-  if ((btif_config_get_int((char const*)&bdstr, "DevType", &device_type) &&
+  if ((btif_config_get_int(bdstr, "DevType", &device_type) &&
        (btif_storage_get_remote_addr_type(&bd_addr, &addr_type) ==
         BT_STATUS_SUCCESS) &&
        (device_type & BT_DEVICE_TYPE_BLE) == BT_DEVICE_TYPE_BLE) ||
@@ -1233,13 +1229,12 @@
       bt_bdname_t bdname;
       uint8_t remote_name_len;
       tBTA_SERVICE_MASK services = 0;
-      bdstr_t bdstr;
 
       p_search_data = (tBTA_DM_SEARCH*)p_param;
       RawAddress& bdaddr = p_search_data->inq_res.bd_addr;
 
       BTIF_TRACE_DEBUG("%s() %s device_type = 0x%x\n", __func__,
-                       bdaddr_to_string(&bdaddr, bdstr, sizeof(bdstr)),
+                       bdaddr.ToString().c_str(),
                        p_search_data->inq_res.device_type);
       bdname.name[0] = 0;
 
@@ -2214,9 +2209,8 @@
   create_bond_cb.transport = transport;
   create_bond_cb.bdaddr = *bd_addr;
 
-  bdstr_t bdstr;
   BTIF_TRACE_EVENT("%s: bd_addr=%s, transport=%d", __func__,
-                   bdaddr_to_string(bd_addr, bdstr, sizeof(bdstr)), transport);
+                   bd_addr->ToString().c_str(), transport);
   if (pairing_cb.state != BT_BOND_STATE_NONE) return BT_STATUS_BUSY;
 
   btif_stats_add_bond_event(*bd_addr, BTIF_DM_FUNC_CREATE_BOND,
@@ -2258,9 +2252,8 @@
     }
   }
 
-  bdstr_t bdstr;
   BTIF_TRACE_EVENT("%s: bd_addr=%s, transport=%d", __func__,
-                   bdaddr_to_string(bd_addr, bdstr, sizeof(bdstr)), transport);
+                   bd_addr->ToString().c_str(), transport);
   return btif_dm_create_bond(bd_addr, transport);
 }
 
@@ -2275,10 +2268,7 @@
  ******************************************************************************/
 
 bt_status_t btif_dm_cancel_bond(const RawAddress* bd_addr) {
-  bdstr_t bdstr;
-
-  BTIF_TRACE_EVENT("%s: bd_addr=%s", __func__,
-                   bdaddr_to_string(bd_addr, bdstr, sizeof(bdstr)));
+  BTIF_TRACE_EVENT("%s: bd_addr=%s", __func__, bd_addr->ToString().c_str());
 
   btif_stats_add_bond_event(*bd_addr, BTIF_DM_FUNC_CANCEL_BOND,
                             pairing_cb.state);
@@ -2339,10 +2329,7 @@
  ******************************************************************************/
 
 bt_status_t btif_dm_remove_bond(const RawAddress* bd_addr) {
-  bdstr_t bdstr;
-
-  BTIF_TRACE_EVENT("%s: bd_addr=%s", __func__,
-                   bdaddr_to_string(bd_addr, bdstr, sizeof(bdstr)));
+  BTIF_TRACE_EVENT("%s: bd_addr=%s", __func__, bd_addr->ToString().c_str());
 
   btif_stats_add_bond_event(*bd_addr, BTIF_DM_FUNC_REMOVE_BOND,
                             pairing_cb.state);
@@ -2472,10 +2459,7 @@
  *
  ******************************************************************************/
 bt_status_t btif_dm_get_remote_services(const RawAddress& remote_addr) {
-  bdstr_t bdstr;
-
-  BTIF_TRACE_EVENT("%s: remote_addr=%s", __func__,
-                   bdaddr_to_string(&remote_addr, bdstr, sizeof(bdstr)));
+  BTIF_TRACE_EVENT("%s: bd_addr=%s", __func__, remote_addr.ToString().c_str());
 
   BTA_DmDiscover(remote_addr, BTA_ALL_SERVICE_MASK, bte_dm_search_services_evt,
                  true);
@@ -2519,12 +2503,9 @@
  ******************************************************************************/
 bt_status_t btif_dm_get_remote_service_record(RawAddress* remote_addr,
                                               bt_uuid_t* uuid) {
+  BTIF_TRACE_EVENT("%s: bd_addr=%s", __func__, remote_addr->ToString().c_str());
+
   tSDP_UUID sdp_uuid;
-  bdstr_t bdstr;
-
-  BTIF_TRACE_EVENT("%s: remote_addr=%s", __func__,
-                   bdaddr_to_string(remote_addr, bdstr, sizeof(bdstr)));
-
   sdp_uuid.len = MAX_UUID_SIZE;
   memcpy(sdp_uuid.uu.uuid128, uuid->uu, MAX_UUID_SIZE);
 
@@ -3286,9 +3267,6 @@
     snprintf(eventtime, sizeof(eventtime), "%s.%03ld", temptime,
              event->timestamp.tv_nsec / 1000000);
 
-    char bdaddr[18];
-    bdaddr_to_string(&event->bd_addr, bdaddr, sizeof(bdaddr));
-
     const char* func_name;
     switch (event->function) {
       case BTIF_DM_FUNC_CREATE_BOND:
@@ -3320,6 +3298,8 @@
         bond_state = "Invalid bond state";
         break;
     }
-    dprintf(fd, "  %s  %s  %s  %s\n", eventtime, bdaddr, func_name, bond_state);
+
+    dprintf(fd, "  %s  %s  %s  %s\n", eventtime,
+            event->bd_addr.ToString().c_str(), func_name, bond_state);
   }
 }
diff --git a/system/btif/src/btif_gatt_client.cc b/system/btif/src/btif_gatt_client.cc
index c850c5a..59b8bab 100644
--- a/system/btif/src/btif_gatt_client.cc
+++ b/system/btif/src/btif_gatt_client.cc
@@ -35,7 +35,6 @@
 #include <string.h>
 #include "device/include/controller.h"
 
-#include "btcore/include/bdaddr.h"
 #include "btif_common.h"
 #include "btif_util.h"
 
@@ -583,10 +582,8 @@
 
 int btif_gattc_get_device_type(const RawAddress& bd_addr) {
   int device_type = 0;
-  char bd_addr_str[18] = {0};
 
-  bdaddr_to_string(&bd_addr, bd_addr_str, sizeof(bd_addr_str));
-  if (btif_config_get_int(bd_addr_str, "DevType", &device_type))
+  if (btif_config_get_int(bd_addr.ToString().c_str(), "DevType", &device_type))
     return device_type;
   return 0;
 }
diff --git a/system/btif/src/btif_gatt_util.cc b/system/btif/src/btif_gatt_util.cc
index 61c7663..9745917 100644
--- a/system/btif/src/btif_gatt_util.cc
+++ b/system/btif/src/btif_gatt_util.cc
@@ -28,7 +28,6 @@
 #include <hardware/bluetooth.h>
 #include <hardware/bt_gatt.h>
 
-#include "bdaddr.h"
 #include "bt_common.h"
 #include "bta_api.h"
 #include "bta_gatt_api.h"
diff --git a/system/btif/src/btif_hf.cc b/system/btif/src/btif_hf.cc
index 4e701f1..15c23dc 100644
--- a/system/btif/src/btif_hf.cc
+++ b/system/btif/src/btif_hf.cc
@@ -36,7 +36,6 @@
 
 #include "bta/include/utl.h"
 #include "bta_ag_api.h"
-#include "btcore/include/bdaddr.h"
 #include "btif_common.h"
 #include "btif_hf.h"
 #include "btif_profile_queue.h"
@@ -336,7 +335,6 @@
  ******************************************************************************/
 static void btif_hf_upstreams_evt(uint16_t event, char* p_param) {
   tBTA_AG* p_data = (tBTA_AG*)p_param;
-  bdstr_t bdstr;
   int idx = p_data->hdr.handle - 1;
 
   BTIF_TRACE_DEBUG("%s: event=%s", __func__, dump_hf_event(event));
@@ -372,8 +370,7 @@
             "%s: AG open failed, but another device connected. status=%d "
             "state=%d connected device=%s",
             __func__, p_data->open.status, btif_hf_cb[idx].state,
-            bdaddr_to_string(&btif_hf_cb[idx].connected_bda, bdstr,
-                             sizeof(bdstr)));
+            btif_hf_cb[idx].connected_bda.ToString().c_str());
         break;
       }
 
@@ -381,7 +378,7 @@
                 &btif_hf_cb[idx].connected_bda);
 
       if (btif_hf_cb[idx].state == BTHF_CONNECTION_STATE_DISCONNECTED)
-        btif_hf_cb[idx].connected_bda = bd_addr_any;
+        btif_hf_cb[idx].connected_bda = RawAddress::kAny;
 
       if (p_data->open.status != BTA_AG_SUCCESS) btif_queue_advance();
       break;
@@ -395,7 +392,7 @@
           __func__, idx, btif_hf_cb[idx].handle);
       HAL_CBACK(bt_hf_callbacks, connection_state_cb, btif_hf_cb[idx].state,
                 &btif_hf_cb[idx].connected_bda);
-      btif_hf_cb[idx].connected_bda = bd_addr_any;
+      btif_hf_cb[idx].connected_bda = RawAddress::kAny;
       btif_hf_cb[idx].peer_feat = 0;
       clear_phone_state_multihf(idx);
       hf_idx = btif_hf_latest_connected_idx();
diff --git a/system/btif/src/btif_hf_client.cc b/system/btif/src/btif_hf_client.cc
index 7833c0e..80a8d29 100644
--- a/system/btif/src/btif_hf_client.cc
+++ b/system/btif/src/btif_hf_client.cc
@@ -52,7 +52,6 @@
 
 #include "bt_utils.h"
 #include "bta_hf_client_api.h"
-#include "btcore/include/bdaddr.h"
 #include "btif_common.h"
 #include "btif_profile_queue.h"
 #include "btif_util.h"
@@ -814,7 +813,6 @@
  ******************************************************************************/
 static void btif_hf_client_upstreams_evt(uint16_t event, char* p_param) {
   tBTA_HF_CLIENT* p_data = (tBTA_HF_CLIENT*)p_param;
-  bdstr_t bdstr;
 
   btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(p_data->bd_addr);
   if (cb == NULL && event == BTA_HF_CLIENT_OPEN_EVT) {
@@ -845,7 +843,7 @@
             "%s: HF CLient open failed, but another device connected. "
             "status=%d state=%d connected device=%s",
             __func__, p_data->open.status, cb->state,
-            bdaddr_to_string(&cb->peer_bda, bdstr, sizeof(bdstr)));
+            cb->peer_bda.ToString().c_str());
         break;
       }
 
@@ -854,7 +852,7 @@
                 0 /* AT+CHLD feat */);
 
       if (cb->state == BTHF_CLIENT_CONNECTION_STATE_DISCONNECTED)
-        cb->peer_bda = bd_addr_any;
+        cb->peer_bda = RawAddress::kAny;
 
       if (p_data->open.status != BTA_HF_CLIENT_SUCCESS) btif_queue_advance();
       break;
@@ -880,7 +878,7 @@
       cb->state = BTHF_CLIENT_CONNECTION_STATE_DISCONNECTED;
       HAL_CBACK(bt_hf_client_callbacks, connection_state_cb, &cb->peer_bda,
                 cb->state, 0, 0);
-      cb->peer_bda = bd_addr_any;
+      cb->peer_bda = RawAddress::kAny;
       cb->peer_feat = 0;
       cb->chld_feat = 0;
       btif_queue_advance();
diff --git a/system/btif/src/btif_hh.cc b/system/btif/src/btif_hh.cc
index 2f87554..5ce9bb2 100644
--- a/system/btif/src/btif_hh.cc
+++ b/system/btif/src/btif_hh.cc
@@ -38,7 +38,6 @@
 
 #include "bt_common.h"
 #include "bta_api.h"
-#include "btcore/include/bdaddr.h"
 #include "btif_common.h"
 #include "btif_storage.h"
 #include "btif_util.h"
@@ -434,7 +433,7 @@
     }
   }
   for (i = 0; i < BTIF_HH_MAX_ADDED_DEV; i++) {
-    if (btif_hh_cb.added_devices[i].bd_addr == bd_addr_empty) {
+    if (btif_hh_cb.added_devices[i].bd_addr.IsEmpty()) {
       LOG(WARNING) << " Added device " << bda;
       btif_hh_cb.added_devices[i].bd_addr = bda;
       btif_hh_cb.added_devices[i].dev_handle = BTA_HH_INVALID_HANDLE;
@@ -591,7 +590,7 @@
       // No space for more HID device now.
       LOG(ERROR) << __func__ << ": Error, device " << *bd_addr
                  << " added but addition failed";
-      added_dev->bd_addr = bd_addr_empty;
+      added_dev->bd_addr = RawAddress::kEmpty;
       added_dev->dev_handle = BTA_HH_INVALID_HANDLE;
       return BT_STATUS_FAIL;
     }
@@ -1020,7 +1019,7 @@
           if (p_data->dev_info.status == BTA_HH_OK) {
             btif_hh_cb.added_devices[i].dev_handle = p_data->dev_info.handle;
           } else {
-            btif_hh_cb.added_devices[i].bd_addr = bd_addr_empty;
+            btif_hh_cb.added_devices[i].bd_addr = RawAddress::kEmpty;
             btif_hh_cb.added_devices[i].dev_handle = BTA_HH_INVALID_HANDLE;
           }
           break;
@@ -1296,9 +1295,7 @@
 static bt_status_t get_idle_time(RawAddress* bd_addr) {
   CHECK_BTHH_INIT();
 
-  char bdstr[20] = {0};
-  BTIF_TRACE_DEBUG("%s: addr = %s", __func__,
-                   bdaddr_to_string(bd_addr, bdstr, sizeof(bdstr)));
+  BTIF_TRACE_DEBUG("%s: addr = %s", __func__, bd_addr->ToString().c_str());
 
   if (btif_hh_cb.status == BTIF_HH_DISABLED) {
     BTIF_TRACE_ERROR("%s: Error, HH status = %d", __func__, btif_hh_cb.status);
@@ -1324,9 +1321,8 @@
 static bt_status_t set_idle_time(RawAddress* bd_addr, uint8_t idle_time) {
   CHECK_BTHH_INIT();
 
-  char bdstr[20] = {0};
   BTIF_TRACE_DEBUG("%s: addr = %s, idle time = %d", __func__,
-                   bdaddr_to_string(bd_addr, bdstr, sizeof(bdstr)), idle_time);
+                   bd_addr->ToString().c_str(), idle_time);
 
   if (btif_hh_cb.status == BTIF_HH_DISABLED) {
     BTIF_TRACE_ERROR("%s: Error, HH status = %d", __func__, btif_hh_cb.status);
@@ -1336,7 +1332,7 @@
   btif_hh_device_t* p_dev = p_dev = btif_hh_find_connected_dev_by_bda(*bd_addr);
   if (p_dev == NULL) {
     BTIF_TRACE_WARNING("%s: addr = %s not opened", __func__,
-                       bdaddr_to_string(bd_addr, bdstr, sizeof(bdstr)));
+                       bd_addr->ToString().c_str());
     return BT_STATUS_FAIL;
   }
 
diff --git a/system/btif/src/btif_mce.cc b/system/btif/src/btif_mce.cc
index 0074272..53102e8 100644
--- a/system/btif/src/btif_mce.cc
+++ b/system/btif/src/btif_mce.cc
@@ -37,7 +37,6 @@
 #include "bt_types.h"
 #include "bta_api.h"
 #include "bta_mce_api.h"
-#include "btcore/include/bdaddr.h"
 #include "btif_common.h"
 #include "btif_profile_queue.h"
 #include "btif_util.h"
diff --git a/system/btif/src/btif_pan.cc b/system/btif/src/btif_pan.cc
index a872236..7b2c861 100644
--- a/system/btif/src/btif_pan.cc
+++ b/system/btif/src/btif_pan.cc
@@ -54,7 +54,6 @@
 #include "bt_common.h"
 #include "bta_api.h"
 #include "bta_pan_api.h"
-#include "btcore/include/bdaddr.h"
 #include "btif_common.h"
 #include "btif_pan_internal.h"
 #include "btif_sock_thread.h"
@@ -592,10 +591,9 @@
     }
     case BTA_PAN_OPENING_EVT: {
       btpan_conn_t* conn;
-      bdstr_t bds;
-      bdaddr_to_string(&p_data->opening.bd_addr, bds, sizeof(bds));
       BTIF_TRACE_DEBUG("BTA_PAN_OPENING_EVT handle %d, addr: %s",
-                       p_data->opening.handle, bds);
+                       p_data->opening.handle,
+                       p_data->opening.bd_addr.ToString().c_str());
       conn = btpan_find_conn_addr(p_data->opening.bd_addr);
 
       asrt(conn != NULL);
diff --git a/system/btif/src/btif_rc.cc b/system/btif/src/btif_rc.cc
index 9e51917..43e5613 100644
--- a/system/btif/src/btif_rc.cc
+++ b/system/btif/src/btif_rc.cc
@@ -37,7 +37,6 @@
 #include <hardware/bt_rc.h>
 
 #include "avrc_defs.h"
-#include "bdaddr.h"
 #include "bt_common.h"
 #include "bta_api.h"
 #include "bta_av_api.h"
@@ -489,7 +488,6 @@
 
 void handle_rc_features(btif_rc_device_cb_t* p_dev) {
   RawAddress rc_addr = p_dev->rc_addr;
-  bdstr_t addr1, addr2;
 
   CHECK(bt_rc_callbacks);
 
@@ -497,8 +495,7 @@
   RawAddress avdtp_addr = btif_av_get_addr();
 
   BTIF_TRACE_DEBUG("%s: AVDTP Address: %s AVCTP address: %s", __func__,
-                   bdaddr_to_string(&avdtp_addr, addr1, sizeof(addr1)),
-                   bdaddr_to_string(&rc_addr, addr2, sizeof(addr2)));
+                   avdtp_addr.ToString().c_str(), rc_addr.ToString().c_str());
 
   if (interop_match_addr(INTEROP_DISABLE_ABSOLUTE_VOLUME, &rc_addr) ||
       absolute_volume_disabled() || avdtp_addr != rc_addr) {
@@ -690,14 +687,14 @@
     p_dev->rc_vol_label = MAX_LABEL;
     p_dev->rc_volume = MAX_VOLUME;
 
-    p_dev->rc_addr = bd_addr_empty;
+    p_dev->rc_addr = RawAddress::kEmpty;
   }
   if (get_num_connected_devices() == 0) {
     BTIF_TRACE_DEBUG("%s: Closing all handles", __func__);
     init_all_transactions();
   }
 
-  p_dev->rc_addr = bd_addr_empty;
+  p_dev->rc_addr = RawAddress::kEmpty;
   /* report connection state if device is AVRCP target */
   if (bt_rc_ctrl_callbacks != NULL) {
     HAL_CBACK(bt_rc_ctrl_callbacks, connection_state_cb, false, false,
diff --git a/system/btif/src/btif_storage.cc b/system/btif/src/btif_storage.cc
index 40c188e..394d69e 100644
--- a/system/btif/src/btif_storage.cc
+++ b/system/btif/src/btif_storage.cc
@@ -42,7 +42,6 @@
 #include "bt_common.h"
 #include "bta_hd_api.h"
 #include "bta_hh_api.h"
-#include "btcore/include/bdaddr.h"
 #include "btif_api.h"
 #include "btif_config.h"
 #include "btif_hd.h"
@@ -179,8 +178,13 @@
  ******************************************************************************/
 
 static int prop2cfg(const RawAddress* remote_bd_addr, bt_property_t* prop) {
-  bdstr_t bdstr = {0};
-  if (remote_bd_addr) bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
+  std::string addrstr;
+  const char* bdstr = addrstr.c_str();
+  if (remote_bd_addr) {
+    addrstr = remote_bd_addr->ToString();
+    bdstr = addrstr.c_str();
+  }
+
   BTIF_TRACE_DEBUG("in, bd addr:%s, prop type:%d, len:%d", bdstr, prop->type,
                    prop->len);
   char value[1024];
@@ -265,8 +269,12 @@
 }
 
 static int cfg2prop(const RawAddress* remote_bd_addr, bt_property_t* prop) {
-  bdstr_t bdstr = {0};
-  if (remote_bd_addr) bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
+  std::string addrstr;
+  const char* bdstr = addrstr.c_str();
+  if (remote_bd_addr) {
+    addrstr = remote_bd_addr->ToString();
+    bdstr = addrstr.c_str();
+  }
   BTIF_TRACE_DEBUG("in, bd addr:%s, prop type:%d, len:%d", bdstr, prop->type,
                    prop->len);
   if (prop->len <= 0) {
@@ -422,7 +430,7 @@
        iter != btif_config_section_end();
        iter = btif_config_section_next(iter)) {
     const char* name = btif_config_section_name(iter);
-    if (!string_is_bdaddr(name)) continue;
+    if (!RawAddress::IsValidAddress(name)) continue;
 
     BTIF_TRACE_DEBUG("Remote device:%s", name);
     LINK_KEY link_key;
@@ -431,7 +439,7 @@
       int linkkey_type;
       if (btif_config_get_int(name, "LinkKeyType", &linkkey_type)) {
         RawAddress bd_addr;
-        string_to_bdaddr(name, &bd_addr);
+        RawAddress::FromString(name, bd_addr);
         if (add) {
           DEV_CLASS dev_class = {0, 0, 0};
           int cod;
@@ -480,9 +488,8 @@
         *device_added = true;
       }
 
-      char bd_str[20] = {0};
       BTIF_TRACE_DEBUG("%s() Adding key type %d for %s", __func__, key_type,
-                       bdaddr_to_string(&bd_addr, bd_str, sizeof(bd_str)));
+                       bd_addr.ToString().c_str());
       BTA_DmAddBleKey(bd_addr, (tBTA_LE_KEY_VALUE*)buffer, key_type);
     }
 
@@ -726,8 +733,8 @@
 bt_status_t btif_storage_add_bonded_device(RawAddress* remote_bd_addr,
                                            LINK_KEY link_key, uint8_t key_type,
                                            uint8_t pin_length) {
-  bdstr_t bdstr;
-  bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
+  std::string addrstr = remote_bd_addr->ToString();
+  const char* bdstr = addrstr.c_str();
   int ret = btif_config_set_int(bdstr, "LinkKeyType", (int)key_type);
   ret &= btif_config_set_int(bdstr, "PinLength", (int)pin_length);
   ret &= btif_config_set_bin(bdstr, "LinkKey", link_key, sizeof(LINK_KEY));
@@ -755,8 +762,8 @@
  ******************************************************************************/
 bt_status_t btif_storage_remove_bonded_device(
     const RawAddress* remote_bd_addr) {
-  bdstr_t bdstr;
-  bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
+  std::string addrstr = remote_bd_addr->ToString();
+  const char* bdstr = addrstr.c_str();
   BTIF_TRACE_DEBUG("in bd addr:%s", bdstr);
 
   btif_storage_remove_ble_bonding_keys(remote_bd_addr);
@@ -922,8 +929,6 @@
 bt_status_t btif_storage_add_ble_bonding_key(RawAddress* remote_bd_addr,
                                              char* key, uint8_t key_type,
                                              uint8_t key_length) {
-  bdstr_t bdstr;
-  bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
   const char* name;
   switch (key_type) {
     case BTIF_DM_LE_KEY_PENC:
@@ -947,7 +952,8 @@
     default:
       return BT_STATUS_FAIL;
   }
-  int ret = btif_config_set_bin(bdstr, name, (const uint8_t*)key, key_length);
+  int ret = btif_config_set_bin(remote_bd_addr->ToString().c_str(), name,
+                                (const uint8_t*)key, key_length);
   btif_config_save();
   return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
 }
@@ -965,8 +971,6 @@
 bt_status_t btif_storage_get_ble_bonding_key(RawAddress* remote_bd_addr,
                                              uint8_t key_type, char* key_value,
                                              int key_length) {
-  bdstr_t bdstr;
-  bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
   const char* name;
   switch (key_type) {
     case BTIF_DM_LE_KEY_PENC:
@@ -990,7 +994,8 @@
       return BT_STATUS_FAIL;
   }
   size_t length = key_length;
-  int ret = btif_config_get_bin(bdstr, name, (uint8_t*)key_value, &length);
+  int ret = btif_config_get_bin(remote_bd_addr->ToString().c_str(), name,
+                                (uint8_t*)key_value, &length);
   return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
 }
 
@@ -1006,8 +1011,8 @@
  ******************************************************************************/
 bt_status_t btif_storage_remove_ble_bonding_keys(
     const RawAddress* remote_bd_addr) {
-  bdstr_t bdstr;
-  bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
+  std::string addrstr = remote_bd_addr->ToString();
+  const char* bdstr = addrstr.c_str();
   BTIF_TRACE_DEBUG(" %s in bd addr:%s", __func__, bdstr);
   int ret = 1;
   if (btif_config_exist(bdstr, "LE_KEY_PENC"))
@@ -1122,7 +1127,6 @@
     btif_bonded_devices_t* p_bonded_devices) {
   int device_type;
   int addr_type;
-  RawAddress bd_addr;
   bool device_added = false;
   bool key_found = false;
 
@@ -1133,7 +1137,8 @@
       btif_has_ble_keys(remote_bd_addr)) {
     BTIF_TRACE_DEBUG("%s Found a LE device: %s", __func__, remote_bd_addr);
 
-    string_to_bdaddr(remote_bd_addr, &bd_addr);
+    RawAddress bd_addr;
+    RawAddress::FromString(remote_bd_addr, bd_addr);
 
     if (btif_storage_get_remote_addr_type(&bd_addr, &addr_type) !=
         BT_STATUS_SUCCESS) {
@@ -1173,9 +1178,8 @@
 
 bt_status_t btif_storage_set_remote_addr_type(const RawAddress* remote_bd_addr,
                                               uint8_t addr_type) {
-  bdstr_t bdstr;
-  bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
-  int ret = btif_config_set_int(bdstr, "AddrType", (int)addr_type);
+  int ret = btif_config_set_int(remote_bd_addr->ToString().c_str(), "AddrType",
+                                (int)addr_type);
   return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
 }
 
@@ -1195,9 +1199,8 @@
  ******************************************************************************/
 bt_status_t btif_storage_get_remote_addr_type(const RawAddress* remote_bd_addr,
                                               int* addr_type) {
-  bdstr_t bdstr;
-  bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
-  int ret = btif_config_get_int(bdstr, "AddrType", addr_type);
+  int ret = btif_config_get_int(remote_bd_addr->ToString().c_str(), "AddrType",
+                                addr_type);
   return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
 }
 /*******************************************************************************
@@ -1217,9 +1220,9 @@
     uint8_t app_id, uint16_t vendor_id, uint16_t product_id, uint16_t version,
     uint8_t ctry_code, uint16_t ssr_max_latency, uint16_t ssr_min_tout,
     uint16_t dl_len, uint8_t* dsc_list) {
-  bdstr_t bdstr;
   BTIF_TRACE_DEBUG("btif_storage_add_hid_device_info:");
-  bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
+  std::string addrstr = remote_bd_addr->ToString();
+  const char* bdstr = addrstr.c_str();
   btif_config_set_int(bdstr, "HidAttrMask", attr_mask);
   btif_config_set_int(bdstr, "HidSubClass", sub_class);
   btif_config_set_int(bdstr, "HidAppId", app_id);
@@ -1256,7 +1259,7 @@
        iter != btif_config_section_end();
        iter = btif_config_section_next(iter)) {
     const char* name = btif_config_section_name(iter);
-    if (!string_is_bdaddr(name)) continue;
+    if (!RawAddress::IsValidAddress(name)) continue;
 
     BTIF_TRACE_DEBUG("Remote device:%s", name);
     int value;
@@ -1297,7 +1300,7 @@
           btif_config_get_bin(name, "HidDescriptor",
                               (uint8_t*)dscp_info.descriptor.dsc_list, &len);
         }
-        string_to_bdaddr(name, &bd_addr);
+        RawAddress::FromString(name, bd_addr);
         // add extracted information to BTA HH
         if (btif_hh_add_added_dev(bd_addr, attr_mask)) {
           BTA_HhAddDev(bd_addr, attr_mask, sub_class, app_id, dscp_info);
@@ -1306,7 +1309,7 @@
     } else {
       if (btif_config_get_int(name, "HidAttrMask", &value)) {
         btif_storage_remove_hid_info(&bd_addr);
-        string_to_bdaddr(name, &bd_addr);
+        RawAddress::FromString(name, bd_addr);
       }
     }
   }
@@ -1326,8 +1329,8 @@
  *
  ******************************************************************************/
 bt_status_t btif_storage_remove_hid_info(RawAddress* remote_bd_addr) {
-  bdstr_t bdstr;
-  bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
+  std::string addrstr = remote_bd_addr->ToString();
+  const char* bdstr = addrstr.c_str();
 
   btif_config_remove(bdstr, "HidAttrMask");
   btif_config_remove(bdstr, "HidSubClass");
@@ -1355,10 +1358,7 @@
  *
  ******************************************************************************/
 bool btif_storage_is_restricted_device(const RawAddress* remote_bd_addr) {
-  bdstr_t bdstr;
-  bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
-
-  return btif_config_exist(bdstr, "Restricted");
+  return btif_config_exist(remote_bd_addr->ToString().c_str(), "Restricted");
 }
 
 /*******************************************************************************
@@ -1370,19 +1370,19 @@
  *
  ******************************************************************************/
 bt_status_t btif_storage_load_hidd(void) {
-  RawAddress bd_addr;
 
   for (const btif_config_section_iter_t* iter = btif_config_section_begin();
        iter != btif_config_section_end();
        iter = btif_config_section_next(iter)) {
     const char* name = btif_config_section_name(iter);
-    if (!string_is_bdaddr(name)) continue;
+    if (!RawAddress::IsValidAddress(name)) continue;
 
     BTIF_TRACE_DEBUG("Remote device:%s", name);
     int value;
     if (btif_in_fetch_bonded_device(name) == BT_STATUS_SUCCESS) {
       if (btif_config_get_int(name, "HidDeviceCabled", &value)) {
-        string_to_bdaddr(name, &bd_addr);
+        RawAddress bd_addr;
+        RawAddress::FromString(name, bd_addr);
         BTA_HdAddDevice(bd_addr);
         break;
       }
@@ -1402,9 +1402,7 @@
  *
  ******************************************************************************/
 bt_status_t btif_storage_set_hidd(RawAddress* remote_bd_addr) {
-  bdstr_t bdstr = {0};
-  bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
-  btif_config_set_int(bdstr, "HidDeviceCabled", 1);
+  btif_config_set_int(remote_bd_addr->ToString().c_str(), "HidDeviceCabled", 1);
   btif_config_save();
   return BT_STATUS_SUCCESS;
 }
@@ -1419,10 +1417,7 @@
  *
  ******************************************************************************/
 bt_status_t btif_storage_remove_hidd(RawAddress* remote_bd_addr) {
-  bdstr_t bdstr;
-  bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
-
-  btif_config_remove(bdstr, "HidDeviceCabled");
+  btif_config_remove(remote_bd_addr->ToString().c_str(), "HidDeviceCabled");
   btif_config_save();
 
   return BT_STATUS_SUCCESS;
diff --git a/system/build/Android.bp b/system/build/Android.bp
index 2422430..fc6eae8 100644
--- a/system/build/Android.bp
+++ b/system/build/Android.bp
@@ -15,7 +15,7 @@
 }
 
 fluoride_defaults {
-    name: "fluoride_defaults",
+    name: "fluoride_types_defaults",
     cflags: [
         "-DEXPORT_SYMBOL=__attribute__((visibility(\"default\")))",
         "-fvisibility=hidden",
@@ -45,3 +45,11 @@
     shared_libs: [ "libchrome" ]
     // Setup Bluetooth local make variables for handling configuration
 }
+
+fluoride_defaults {
+    name: "fluoride_defaults",
+    defaults: ["fluoride_types_defaults"],
+    static_libs: [
+        "libbluetooth-types",
+    ],
+}
diff --git a/system/device/Android.bp b/system/device/Android.bp
index 1513d85..a1c90be 100644
--- a/system/device/Android.bp
+++ b/system/device/Android.bp
@@ -43,5 +43,6 @@
         "libosi",
         "libosi-AllocationTestHarness",
         "libcutils",
+        "libbluetooth-types",
     ],
 }
diff --git a/system/device/include/controller.h b/system/device/include/controller.h
index 4e7e34a..135cdcd 100644
--- a/system/device/include/controller.h
+++ b/system/device/include/controller.h
@@ -21,7 +21,6 @@
 #include <stdbool.h>
 #include <stdint.h>
 
-#include "bdaddr.h"
 #include "device_features.h"
 #include "hci_layer.h"
 #include "hci_packet_factory.h"
diff --git a/system/device/include/interop.h b/system/device/include/interop.h
index f723e3a..cb7faed 100644
--- a/system/device/include/interop.h
+++ b/system/device/include/interop.h
@@ -20,7 +20,7 @@
 
 #include <stdbool.h>
 
-#include "btcore/include/bdaddr.h"
+#include "raw_address.h"
 
 static const char INTEROP_MODULE[] = "interop_module";
 
diff --git a/system/device/include/interop_database.h b/system/device/include/interop_database.h
index 8a39e01..7cc5c79 100644
--- a/system/device/include/interop_database.h
+++ b/system/device/include/interop_database.h
@@ -19,6 +19,7 @@
 #pragma once
 
 #include "device/include/interop.h"
+#include "raw_address.h"
 
 typedef struct {
   RawAddress addr;
diff --git a/system/device/src/interop.cc b/system/device/src/interop.cc
index caf5b43..78eb997 100644
--- a/system/device/src/interop.cc
+++ b/system/device/src/interop.cc
@@ -50,9 +50,8 @@
 
   if (interop_match_fixed_(feature, addr) ||
       interop_match_dynamic_(feature, addr)) {
-    char bdstr[20] = {0};
     LOG_WARN(LOG_TAG, "%s() Device %s is a match for interop workaround %s.",
-             __func__, bdaddr_to_string(addr, bdstr, sizeof(bdstr)),
+             __func__, addr->ToString().c_str(),
              interop_feature_string_(feature));
     return true;
   }
diff --git a/system/device/test/interop_test.cc b/system/device/test/interop_test.cc
index 1f40958..e82a3b5 100644
--- a/system/device/test/interop_test.cc
+++ b/system/device/test/interop_test.cc
@@ -22,31 +22,31 @@
 
 TEST(InteropTest, test_lookup_hit) {
   RawAddress test_address;
-  string_to_bdaddr("38:2c:4a:e6:67:89", &test_address);
+  RawAddress::FromString("38:2c:4a:e6:67:89", test_address);
   EXPECT_TRUE(
       interop_match_addr(INTEROP_DISABLE_LE_SECURE_CONNECTIONS, &test_address));
-  string_to_bdaddr("9c:df:03:12:34:56", &test_address);
+  RawAddress::FromString("9c:df:03:12:34:56", test_address);
   EXPECT_TRUE(interop_match_addr(INTEROP_AUTO_RETRY_PAIRING, &test_address));
 }
 
 TEST(InteropTest, test_lookup_miss) {
   RawAddress test_address;
-  string_to_bdaddr("00:00:00:00:00:00", &test_address);
+  RawAddress::FromString("00:00:00:00:00:00", test_address);
   EXPECT_FALSE(
       interop_match_addr(INTEROP_DISABLE_LE_SECURE_CONNECTIONS, &test_address));
-  string_to_bdaddr("ff:ff:ff:ff:ff:ff", &test_address);
+  RawAddress::FromString("ff:ff:ff:ff:ff:ff", test_address);
   EXPECT_FALSE(interop_match_addr(INTEROP_AUTO_RETRY_PAIRING, &test_address));
-  string_to_bdaddr("42:08:15:ae:ae:ae", &test_address);
+  RawAddress::FromString("42:08:15:ae:ae:ae", test_address);
   EXPECT_FALSE(
       interop_match_addr(INTEROP_DISABLE_LE_SECURE_CONNECTIONS, &test_address));
-  string_to_bdaddr("38:2c:4a:59:67:89", &test_address);
+  RawAddress::FromString("38:2c:4a:59:67:89", test_address);
   EXPECT_FALSE(interop_match_addr(INTEROP_AUTO_RETRY_PAIRING, &test_address));
 }
 
 TEST(InteropTest, test_dynamic) {
   RawAddress test_address;
 
-  string_to_bdaddr("11:22:33:44:55:66", &test_address);
+  RawAddress::FromString("11:22:33:44:55:66", test_address);
   EXPECT_FALSE(
       interop_match_addr(INTEROP_DISABLE_LE_SECURE_CONNECTIONS, &test_address));
 
@@ -55,7 +55,7 @@
       interop_match_addr(INTEROP_DISABLE_LE_SECURE_CONNECTIONS, &test_address));
   EXPECT_FALSE(interop_match_addr(INTEROP_AUTO_RETRY_PAIRING, &test_address));
 
-  string_to_bdaddr("66:55:44:33:22:11", &test_address);
+  RawAddress::FromString("66:55:44:33:22:11", test_address);
   EXPECT_FALSE(interop_match_addr(INTEROP_AUTO_RETRY_PAIRING, &test_address));
 
   interop_database_add(INTEROP_AUTO_RETRY_PAIRING, &test_address, 3);
diff --git a/system/hci/include/hci_packet_parser.h b/system/hci/include/hci_packet_parser.h
index ab88bb7..0e74c29 100644
--- a/system/hci/include/hci_packet_parser.h
+++ b/system/hci/include/hci_packet_parser.h
@@ -20,7 +20,6 @@
 
 #include <stdint.h>
 
-#include "bdaddr.h"
 #include "bt_types.h"
 #include "device_features.h"
 #include "features.h"
diff --git a/system/service/Android.bp b/system/service/Android.bp
index 11af0ed..3b47492 100644
--- a/system/service/Android.bp
+++ b/system/service/Android.bp
@@ -59,7 +59,6 @@
     "test/low_energy_client_unittest.cc",
     "test/low_energy_scanner_unittest.cc",
     "test/settings_unittest.cc",
-    "test/util_unittest.cc",
     "test/uuid_unittest.cc",
 ]
 
diff --git a/system/service/BUILD.gn b/system/service/BUILD.gn
index ba49728..ae8153a 100644
--- a/system/service/BUILD.gn
+++ b/system/service/BUILD.gn
@@ -26,7 +26,6 @@
     "common/bluetooth/scan_result.cc",
     "common/bluetooth/scan_settings.cc",
     "common/bluetooth/service.cc",
-    "common/bluetooth/util/address_helper.cc",
     "common/bluetooth/util/atomic_string.cc",
     "common/bluetooth/uuid.cc",
     "daemon.cc",
diff --git a/system/service/common/Android.bp b/system/service/common/Android.bp
index 86ca84f..b028703 100644
--- a/system/service/common/Android.bp
+++ b/system/service/common/Android.bp
@@ -17,7 +17,6 @@
         "bluetooth/scan_result.cc",
         "bluetooth/scan_settings.cc",
         "bluetooth/service.cc",
-        "bluetooth/util/address_helper.cc",
         "bluetooth/util/atomic_string.cc",
         "bluetooth/uuid.cc",
     ],
diff --git a/system/service/common/bluetooth/scan_filter.cc b/system/service/common/bluetooth/scan_filter.cc
index 1baa0b4..3226c50 100644
--- a/system/service/common/bluetooth/scan_filter.cc
+++ b/system/service/common/bluetooth/scan_filter.cc
@@ -16,8 +16,6 @@
 
 #include "bluetooth/scan_filter.h"
 
-#include "bluetooth/util/address_helper.h"
-
 namespace bluetooth {
 
 ScanFilter::ScanFilter(const ScanFilter& other) {
@@ -48,7 +46,7 @@
 }
 
 bool ScanFilter::SetDeviceAddress(const std::string& device_address) {
-  if (!util::IsAddressValid(device_address)) return false;
+  if (!RawAddress::IsValidAddress(device_address)) return false;
 
   device_address_ = device_address;
   return true;
diff --git a/system/service/common/bluetooth/scan_result.cc b/system/service/common/bluetooth/scan_result.cc
index 168dae7..007019e 100644
--- a/system/service/common/bluetooth/scan_result.cc
+++ b/system/service/common/bluetooth/scan_result.cc
@@ -15,18 +15,17 @@
 //
 
 #include "bluetooth/scan_result.h"
+#include "raw_address.h"
 
 #include <base/logging.h>
 
-#include "bluetooth/util/address_helper.h"
-
 namespace bluetooth {
 
 ScanResult::ScanResult(const std::string& device_address,
                        const std::vector<uint8_t>& scan_record, int rssi)
     : device_address_(device_address), scan_record_(scan_record), rssi_(rssi) {
-  CHECK(util::IsAddressValid(device_address)) << "Invalid BD_ADDR given: "
-                                              << device_address;
+  CHECK(RawAddress::IsValidAddress(device_address)) << "Invalid BD_ADDR given: "
+                                                    << device_address;
 }
 
 bool ScanResult::operator==(const ScanResult& rhs) const {
diff --git a/system/service/common/bluetooth/util/address_helper.cc b/system/service/common/bluetooth/util/address_helper.cc
deleted file mode 100644
index 0a7cf02..0000000
--- a/system/service/common/bluetooth/util/address_helper.cc
+++ /dev/null
@@ -1,54 +0,0 @@
-//
-//  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/common/bluetooth/util/address_helper.h"
-
-#include <cstdlib>
-
-#include <base/logging.h>
-#include <base/strings/string_split.h>
-
-namespace util {
-
-bool IsAddressValid(const std::string& address) {
-  RawAddress addr;
-  return BdAddrFromString(address, &addr);
-}
-
-bool BdAddrFromString(const std::string& address, RawAddress* out_addr) {
-  CHECK(out_addr);
-
-  if (address.length() != 17) return false;
-
-  std::vector<std::string> byte_tokens = base::SplitString(
-      address, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
-
-  if (byte_tokens.size() != 6) return false;
-
-  for (int i = 0; i < 6; i++) {
-    const auto& token = byte_tokens[i];
-
-    if (token.length() != 2) return false;
-
-    char* temp = nullptr;
-    out_addr->address[i] = strtol(token.c_str(), &temp, 16);
-    if (*temp != '\0') return false;
-  }
-
-  return true;
-}
-
-}  // namespace util
diff --git a/system/service/common/bluetooth/util/address_helper.h b/system/service/common/bluetooth/util/address_helper.h
deleted file mode 100644
index 13079f5..0000000
--- a/system/service/common/bluetooth/util/address_helper.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-//  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 <hardware/bluetooth.h>
-#include <string>
-
-namespace util {
-
-// Checks if the given string representing a Bluetooth device address (BD_ADDR)
-// is correctly formatted. The correct formatting is of the form
-//
-//   XX:XX:XX:XX:XX:XX
-//
-// where X is an alpha-numeric character.
-bool IsAddressValid(const std::string& address);
-
-// Populates a RawAddress from a given string. Returns false if the data is
-// invalid.
-bool BdAddrFromString(const std::string& address, RawAddress* out_addr);
-
-}  // namespace util
diff --git a/system/service/gatt_server.cc b/system/service/gatt_server.cc
index e23bb0f..63bacbb 100644
--- a/system/service/gatt_server.cc
+++ b/system/service/gatt_server.cc
@@ -16,7 +16,6 @@
 
 #include "service/gatt_server.h"
 
-#include "service/common/bluetooth/util/address_helper.h"
 #include "service/logging_helpers.h"
 #include "stack/include/bt_types.h"
 
@@ -110,7 +109,7 @@
   lock_guard<mutex> lock(mutex_);
 
   RawAddress addr;
-  if (!util::BdAddrFromString(device_address, &addr)) {
+  if (!RawAddress::FromString(device_address, addr)) {
     LOG(ERROR) << "Invalid device address given: " << device_address;
     return false;
   }
@@ -179,7 +178,7 @@
   lock_guard<mutex> lock(mutex_);
 
   RawAddress addr;
-  if (!util::BdAddrFromString(device_address, &addr)) {
+  if (!RawAddress::FromString(device_address, addr)) {
     LOG(ERROR) << "Invalid device address given: " << device_address;
     return false;
   }
diff --git a/system/service/ipc/dbus/bluetooth_adapter.cc b/system/service/ipc/dbus/bluetooth_adapter.cc
index 171fef0..8619a35 100644
--- a/system/service/ipc/dbus/bluetooth_adapter.cc
+++ b/system/service/ipc/dbus/bluetooth_adapter.cc
@@ -17,7 +17,6 @@
 #include "service/ipc/dbus/bluetooth_adapter.h"
 #include <base/files/file_util.h>
 #include <base/logging.h>
-#include "service/common/bluetooth/util/address_helper.h"
 #include "service/hal/bluetooth_interface.h"
 
 using ::dbus::Bus;
diff --git a/system/service/low_energy_advertiser.cc b/system/service/low_energy_advertiser.cc
index f25d4f9..3df55db 100644
--- a/system/service/low_energy_advertiser.cc
+++ b/system/service/low_energy_advertiser.cc
@@ -20,7 +20,6 @@
 #include <base/logging.h>
 
 #include "service/adapter.h"
-#include "service/common/bluetooth/util/address_helper.h"
 #include "service/logging_helpers.h"
 #include "stack/include/bt_types.h"
 #include "stack/include/hcidefs.h"
diff --git a/system/service/low_energy_client.cc b/system/service/low_energy_client.cc
index 2e79249..5894676 100644
--- a/system/service/low_energy_client.cc
+++ b/system/service/low_energy_client.cc
@@ -19,7 +19,6 @@
 #include <base/logging.h>
 
 #include "service/adapter.h"
-#include "service/common/bluetooth/util/address_helper.h"
 #include "service/logging_helpers.h"
 #include "stack/include/bt_types.h"
 #include "stack/include/hcidefs.h"
@@ -55,7 +54,7 @@
   VLOG(2) << __func__ << "Address: " << address << " is_direct: " << is_direct;
 
   RawAddress bda;
-  util::BdAddrFromString(address, &bda);
+  RawAddress::FromString(address, bda);
 
   bt_status_t status =
       hal::BluetoothGattInterface::Get()->GetClientHALInterface()->connect(
@@ -72,7 +71,7 @@
   VLOG(2) << __func__ << "Address: " << address;
 
   RawAddress bda;
-  util::BdAddrFromString(address, &bda);
+  RawAddress::FromString(address, bda);
 
   std::map<const RawAddress, int>::iterator conn_id;
   {
@@ -99,7 +98,7 @@
   VLOG(2) << __func__ << "Address: " << address << " MTU: " << mtu;
 
   RawAddress bda;
-  util::BdAddrFromString(address, &bda);
+  RawAddress::FromString(address, bda);
 
   std::map<const RawAddress, int>::iterator conn_id;
   {
diff --git a/system/service/low_energy_scanner.cc b/system/service/low_energy_scanner.cc
index 7dd0ade..093a554 100644
--- a/system/service/low_energy_scanner.cc
+++ b/system/service/low_energy_scanner.cc
@@ -20,7 +20,6 @@
 #include <base/logging.h>
 
 #include "service/adapter.h"
-#include "service/common/bluetooth/util/address_helper.h"
 #include "service/logging_helpers.h"
 #include "stack/include/bt_types.h"
 #include "stack/include/hcidefs.h"
diff --git a/system/service/test/adapter_unittest.cc b/system/service/test/adapter_unittest.cc
index b7a5df4..c3827dc 100644
--- a/system/service/test/adapter_unittest.cc
+++ b/system/service/test/adapter_unittest.cc
@@ -18,7 +18,6 @@
 #include <gtest/gtest.h>
 
 #include "service/adapter.h"
-#include "service/common/bluetooth/util/address_helper.h"
 #include "service/hal/fake_bluetooth_gatt_interface.h"
 #include "service/hal/fake_bluetooth_interface.h"
 
@@ -256,7 +255,7 @@
   EXPECT_FALSE(adapter_->IsDeviceConnected(kDeviceAddr));
 
   RawAddress hal_addr;
-  ASSERT_TRUE(util::BdAddrFromString(kDeviceAddr, &hal_addr));
+  ASSERT_TRUE(RawAddress::FromString(kDeviceAddr, hal_addr));
 
   // status != BT_STATUS_SUCCESS should be ignored
   fake_hal_iface_->NotifyAclStateChangedCallback(BT_STATUS_FAIL, hal_addr,
diff --git a/system/service/test/gatt_server_unittest.cc b/system/service/test/gatt_server_unittest.cc
index ee4ce3d..0e70ac9 100644
--- a/system/service/test/gatt_server_unittest.cc
+++ b/system/service/test/gatt_server_unittest.cc
@@ -17,7 +17,6 @@
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
-#include "service/common/bluetooth/util/address_helper.h"
 #include "service/gatt_server.h"
 #include "service/hal/fake_bluetooth_gatt_interface.h"
 
@@ -401,8 +400,8 @@
                                           GATT_ERROR_NONE, 0, kTestValue));
 
   RawAddress hal_addr0, hal_addr1;
-  ASSERT_TRUE(util::BdAddrFromString(kTestAddress0, &hal_addr0));
-  ASSERT_TRUE(util::BdAddrFromString(kTestAddress1, &hal_addr1));
+  ASSERT_TRUE(RawAddress::FromString(kTestAddress0, hal_addr0));
+  ASSERT_TRUE(RawAddress::FromString(kTestAddress1, hal_addr1));
 
   // Send a connection callback. The GattServer should store the connection
   // information and be able to process the incoming read requests for this
@@ -511,8 +510,8 @@
                                           GATT_ERROR_NONE, 0, kTestValue));
 
   RawAddress hal_addr0, hal_addr1;
-  ASSERT_TRUE(util::BdAddrFromString(kTestAddress0, &hal_addr0));
-  ASSERT_TRUE(util::BdAddrFromString(kTestAddress1, &hal_addr1));
+  ASSERT_TRUE(RawAddress::FromString(kTestAddress0, hal_addr0));
+  ASSERT_TRUE(RawAddress::FromString(kTestAddress1, hal_addr1));
 
   // Send a connection callback. The GattServer should store the connection
   // information and be able to process the incoming read requests for this
@@ -621,7 +620,7 @@
   const int kConnId1 = 1;
   std::vector<uint8_t> value;
   RawAddress hal_addr0;
-  ASSERT_TRUE(util::BdAddrFromString(kTestAddress0, &hal_addr0));
+  ASSERT_TRUE(RawAddress::FromString(kTestAddress0, hal_addr0));
 
   // Set up two connections with the same address.
   fake_hal_gatt_iface_->NotifyServerConnectionCallback(
diff --git a/system/service/test/util_unittest.cc b/system/service/test/util_unittest.cc
deleted file mode 100644
index 7cea354..0000000
--- a/system/service/test/util_unittest.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-//
-//  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/common/bluetooth/util/address_helper.h"
-
-namespace util {
-
-TEST(UtilTest, IsAddressValid) {
-  EXPECT_FALSE(IsAddressValid(""));
-  EXPECT_FALSE(IsAddressValid("000000000000"));
-  EXPECT_FALSE(IsAddressValid("00:00:00:00:0000"));
-  EXPECT_FALSE(IsAddressValid("00:00:00:00:00:0"));
-  EXPECT_FALSE(IsAddressValid("00:00:00:00:00:0;"));
-  EXPECT_TRUE(IsAddressValid("00:00:00:00:00:00"));
-  EXPECT_FALSE(IsAddressValid("aB:cD:eF:Gh:iJ:Kl"));
-}
-
-TEST(UtilTest, BdAddrFromString) {
-  RawAddress addr;
-  memset(&addr, 0, sizeof(addr));
-
-  EXPECT_TRUE(BdAddrFromString("00:00:00:00:00:00", &addr));
-  const RawAddress result0 = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
-  EXPECT_EQ(0, memcmp(&addr, &result0, sizeof(addr)));
-
-  EXPECT_TRUE(BdAddrFromString("ab:01:4C:d5:21:9f", &addr));
-  const RawAddress result1 = {{0xab, 0x01, 0x4c, 0xd5, 0x21, 0x9f}};
-  EXPECT_EQ(0, memcmp(&addr, &result1, sizeof(addr)));
-}
-
-}  // namespace util
diff --git a/system/stack/Android.bp b/system/stack/Android.bp
index 1b23aaa..e7a294f 100644
--- a/system/stack/Android.bp
+++ b/system/stack/Android.bp
@@ -267,6 +267,7 @@
         "libcutils",
     ],
     static_libs: [
+        "libbluetooth-types",
         "liblog",
         "libgmock",
     ],
@@ -284,6 +285,7 @@
         "test/ad_parser_unittest.cc",
     ],
     static_libs: [
+        "libbluetooth-types",
         "liblog",
         "libgmock",
     ],
@@ -314,6 +316,7 @@
         "libprotobuf-cpp-lite",
     ],
     static_libs: [
+        "libbluetooth-types",
         "libgmock",
         "libosi",
         "libbt-protos",
diff --git a/system/stack/btm/btm_acl.cc b/system/stack/btm/btm_acl.cc
index 7f295e4..4644ad8 100644
--- a/system/stack/btm/btm_acl.cc
+++ b/system/stack/btm/btm_acl.cc
@@ -1406,7 +1406,7 @@
       BTM_TRACE_WARNING(
           "%s: Device %s blacklisted for role switching - "
           "multiple role switch failed attempts: %u",
-          __func__, to_string(bd_addr).c_str(), p->switch_role_failed_attempts);
+          __func__, bd_addr.ToString().c_str(), p->switch_role_failed_attempts);
       interop_database_add(INTEROP_DYNAMIC_ROLE_SWITCH, &bd_addr, 3);
     }
   }
diff --git a/system/stack/btm/btm_ble.cc b/system/stack/btm/btm_ble.cc
index 332e1ca..cd52216 100644
--- a/system/stack/btm/btm_ble.cc
+++ b/system/stack/btm/btm_ble.cc
@@ -667,7 +667,7 @@
     } else if (p_dev_rec->device_type & BT_DEVICE_TYPE_BREDR) {
       *remote_bda = p_dev_rec->bd_addr;
     } else
-      *remote_bda = bd_addr_empty;
+      *remote_bda = RawAddress::kEmpty;
     return false;
   }
 
@@ -2102,7 +2102,7 @@
           /* Reset btm state only if the callback address matches pairing
            * address*/
           if (bd_addr == btm_cb.pairing_bda) {
-            btm_cb.pairing_bda = bd_addr_any;
+            btm_cb.pairing_bda = RawAddress::kAny;
             btm_cb.pairing_state = BTM_PAIR_STATE_IDLE;
             btm_cb.pairing_flags = 0;
           }
diff --git a/system/stack/btm/btm_ble_addr.cc b/system/stack/btm/btm_ble_addr.cc
index d664440..b5010db 100644
--- a/system/stack/btm/btm_ble_addr.cc
+++ b/system/stack/btm/btm_ble_addr.cc
@@ -212,7 +212,7 @@
  ******************************************************************************/
 bool btm_ble_init_pseudo_addr(tBTM_SEC_DEV_REC* p_dev_rec,
                               const RawAddress& new_pseudo_addr) {
-  if (p_dev_rec->ble.pseudo_addr == bd_addr_empty) {
+  if (p_dev_rec->ble.pseudo_addr.IsEmpty()) {
     p_dev_rec->ble.pseudo_addr = new_pseudo_addr;
     return true;
   }
@@ -433,7 +433,7 @@
                                                   uint8_t rra_type) {
 #if (BLE_PRIVACY_SPT == TRUE)
   uint8_t rra_dummy = false;
-  if (rpa == bd_addr_empty) rra_dummy = true;
+  if (rpa.IsEmpty()) rra_dummy = true;
 
   /* update security record here, in adv event or connection complete process */
   tBTM_SEC_DEV_REC* p_sec_rec = btm_find_dev(pseudo_bda);
@@ -497,7 +497,7 @@
   if (p != NULL) {
     if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE) {
       p->conn_addr_type = BLE_ADDR_RANDOM;
-      if (local_rpa != bd_addr_empty)
+      if (!local_rpa.IsEmpty())
         p->conn_addr = local_rpa;
       else
         p->conn_addr = btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr;
diff --git a/system/stack/btm/btm_ble_adv_filter.cc b/system/stack/btm/btm_ble_adv_filter.cc
index 27fd397..eb3fc4d 100644
--- a/system/stack/btm/btm_ble_adv_filter.cc
+++ b/system/stack/btm/btm_ble_adv_filter.cc
@@ -212,7 +212,7 @@
   BTM_TRACE_DEBUG("%s: Recd: %d, %d, %d, %d, %d", __func__, op_subcode,
                   expected_ocf, action, status, num_avail);
   if (HCI_SUCCESS == status) {
-    if (btm_ble_adv_filt_cb.cur_filter_target.bda == bd_addr_empty)
+    if (btm_ble_adv_filt_cb.cur_filter_target.bda.IsEmpty())
       btm_ble_cs_update_pf_counter(action, cond_type, NULL, num_avail);
     else
       btm_ble_cs_update_pf_counter(
@@ -267,7 +267,7 @@
       &btm_ble_adv_filt_cb.p_addr_filter_count[1];
 
   for (i = 0; i < cmn_ble_vsc_cb.max_filter; i++, p_addr_filter++) {
-    if (p_addr_filter->bd_addr == bd_addr_empty) {
+    if (p_addr_filter->bd_addr.IsEmpty()) {
       p_addr_filter->bd_addr = bd_addr;
       p_addr_filter->in_use = true;
       return p_addr_filter;
diff --git a/system/stack/btm/btm_ble_bgconn.cc b/system/stack/btm/btm_ble_bgconn.cc
index 3c866e9..f11a50e 100644
--- a/system/stack/btm/btm_ble_bgconn.cc
+++ b/system/stack/btm/btm_ble_bgconn.cc
@@ -185,7 +185,7 @@
         started = true;
         p_dev_rec->ble.in_controller_list |= BTM_WHITE_LIST_BIT;
       } else if (p_dev_rec->ble.static_addr != bd_addr &&
-                 p_dev_rec->ble.static_addr != bd_addr_empty) {
+                 !p_dev_rec->ble.static_addr.IsEmpty()) {
         background_connection_add(p_dev_rec->ble.static_addr_type,
                                   p_dev_rec->ble.static_addr);
         started = true;
@@ -198,7 +198,7 @@
         started = true;
       }
 
-      if (p_dev_rec->ble.static_addr != bd_addr_empty &&
+      if (!p_dev_rec->ble.static_addr.IsEmpty() &&
           p_dev_rec->ble.static_addr != bd_addr) {
         background_connection_remove(p_dev_rec->ble.static_addr);
         started = true;
@@ -439,7 +439,7 @@
           scan_win,                       /* uint16_t scan_win      */
           0x01,                           /* uint8_t white_list     */
           peer_addr_type,                 /* uint8_t addr_type_peer */
-          bd_addr_empty,                  /* BD_ADDR bda_peer     */
+          RawAddress::kEmpty,             /* BD_ADDR bda_peer     */
           own_addr_type,                  /* uint8_t addr_type_own */
           BTM_BLE_CONN_INT_MIN_DEF,       /* uint16_t conn_int_min  */
           BTM_BLE_CONN_INT_MAX_DEF,       /* uint16_t conn_int_max  */
diff --git a/system/stack/btm/btm_ble_gap.cc b/system/stack/btm/btm_ble_gap.cc
index a8f03f7..9630a84 100644
--- a/system/stack/btm/btm_ble_gap.cc
+++ b/system/stack/btm/btm_ble_gap.cc
@@ -360,7 +360,7 @@
 void BTM_BleUpdateAdvFilterPolicy(tBTM_BLE_AFP adv_policy) {
   tBTM_BLE_INQ_CB* p_cb = &btm_cb.ble_ctr_cb.inq_var;
   tBLE_ADDR_TYPE init_addr_type = BLE_ADDR_PUBLIC;
-  RawAddress p_addr_ptr = bd_addr_empty;
+  RawAddress adv_address = RawAddress::kEmpty;
   uint8_t adv_mode = p_cb->adv_mode;
 
   BTM_TRACE_EVENT("BTM_BleUpdateAdvFilterPolicy");
@@ -375,14 +375,14 @@
 
     if (p_cb->connectable_mode & BTM_BLE_CONNECTABLE)
       p_cb->evt_type = btm_set_conn_mode_adv_init_addr(
-          p_cb, p_addr_ptr, &init_addr_type, &p_cb->adv_addr_type);
+          p_cb, adv_address, &init_addr_type, &p_cb->adv_addr_type);
 
     btsnd_hcic_ble_write_adv_params(
         (uint16_t)(p_cb->adv_interval_min ? p_cb->adv_interval_min
                                           : BTM_BLE_GAP_ADV_SLOW_INT),
         (uint16_t)(p_cb->adv_interval_max ? p_cb->adv_interval_max
                                           : BTM_BLE_GAP_ADV_SLOW_INT),
-        p_cb->evt_type, p_cb->adv_addr_type, init_addr_type, p_addr_ptr,
+        p_cb->evt_type, p_cb->adv_addr_type, init_addr_type, adv_address,
         p_cb->adv_chnl_map, p_cb->afp);
 
     if (adv_mode == BTM_BLE_ADV_ENABLE) btm_ble_start_adv();
@@ -896,7 +896,7 @@
   tBTM_LE_RANDOM_CB* p_addr_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
   tBTM_BLE_INQ_CB* p_cb = &btm_cb.ble_ctr_cb.inq_var;
   tBTM_STATUS status = BTM_SUCCESS;
-  RawAddress p_addr_ptr = bd_addr_empty;
+  RawAddress address = RawAddress::kEmpty;
   tBLE_ADDR_TYPE init_addr_type = BLE_ADDR_PUBLIC;
   tBLE_ADDR_TYPE own_addr_type = p_addr_cb->own_addr_type;
   uint8_t adv_mode = p_cb->adv_mode;
@@ -922,12 +922,12 @@
   btm_ble_stop_adv();
 
   p_cb->evt_type = btm_set_conn_mode_adv_init_addr(
-      p_cb, p_addr_ptr, &init_addr_type, &own_addr_type);
+      p_cb, address, &init_addr_type, &own_addr_type);
 
   /* update adv params */
   btsnd_hcic_ble_write_adv_params(
       p_cb->adv_interval_min, p_cb->adv_interval_max, p_cb->evt_type,
-      own_addr_type, init_addr_type, p_addr_ptr, p_cb->adv_chnl_map, p_cb->afp);
+      own_addr_type, init_addr_type, address, p_cb->adv_chnl_map, p_cb->afp);
 
   if (adv_mode == BTM_BLE_ADV_ENABLE) btm_ble_start_adv();
 
@@ -1171,7 +1171,7 @@
   uint8_t new_mode = BTM_BLE_ADV_ENABLE;
   uint8_t evt_type;
   tBTM_STATUS status = BTM_SUCCESS;
-  RawAddress p_addr_ptr = bd_addr_empty;
+  RawAddress address = RawAddress::kEmpty;
   tBLE_ADDR_TYPE init_addr_type = BLE_ADDR_PUBLIC,
                  own_addr_type = p_addr_cb->own_addr_type;
   uint16_t adv_int_min, adv_int_max;
@@ -1184,7 +1184,7 @@
 
   p_cb->discoverable_mode = mode;
 
-  evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type,
+  evt_type = btm_set_conn_mode_adv_init_addr(p_cb, address, &init_addr_type,
                                              &own_addr_type);
 
   if (p_cb->connectable_mode == BTM_BLE_NON_CONNECTABLE &&
@@ -1208,7 +1208,7 @@
 
       /* update adv params */
       btsnd_hcic_ble_write_adv_params(adv_int_min, adv_int_max, evt_type,
-                                      own_addr_type, init_addr_type, p_addr_ptr,
+                                      own_addr_type, init_addr_type, address,
                                       p_cb->adv_chnl_map, p_cb->afp);
       p_cb->evt_type = evt_type;
       p_cb->adv_addr_type = own_addr_type;
@@ -1264,7 +1264,7 @@
   uint8_t new_mode = BTM_BLE_ADV_ENABLE;
   uint8_t evt_type;
   tBTM_STATUS status = BTM_SUCCESS;
-  RawAddress p_addr_ptr = bd_addr_empty;
+  RawAddress address = RawAddress::kEmpty;
   tBLE_ADDR_TYPE peer_addr_type = BLE_ADDR_PUBLIC,
                  own_addr_type = p_addr_cb->own_addr_type;
   uint16_t adv_int_min, adv_int_max;
@@ -1277,7 +1277,7 @@
 
   p_cb->connectable_mode = mode;
 
-  evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &peer_addr_type,
+  evt_type = btm_set_conn_mode_adv_init_addr(p_cb, address, &peer_addr_type,
                                              &own_addr_type);
 
   if (mode == BTM_BLE_NON_CONNECTABLE &&
@@ -1295,7 +1295,7 @@
       btm_ble_stop_adv();
 
       btsnd_hcic_ble_write_adv_params(adv_int_min, adv_int_max, evt_type,
-                                      own_addr_type, peer_addr_type, p_addr_ptr,
+                                      own_addr_type, peer_addr_type, address,
                                       p_cb->adv_chnl_map, p_cb->afp);
       p_cb->evt_type = evt_type;
       p_cb->adv_addr_type = own_addr_type;
@@ -1516,7 +1516,7 @@
   status = GAP_BleCancelReadPeerDevName(remote_bda);
 
   p_inq->remname_active = false;
-  p_inq->remname_bda = bd_addr_empty;
+  p_inq->remname_bda = RawAddress::kEmpty;
   alarm_cancel(p_inq->remote_name_timer);
 
   return status;
@@ -2379,20 +2379,19 @@
 
   if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE) {
     tBTM_LE_RANDOM_CB* p_addr_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
-    RawAddress p_addr_ptr = bd_addr_empty;
+    RawAddress address = RawAddress::kEmpty;
     tBLE_ADDR_TYPE init_addr_type = BLE_ADDR_PUBLIC;
     tBLE_ADDR_TYPE own_addr_type = p_addr_cb->own_addr_type;
 
     btm_ble_stop_adv();
 
     p_cb->evt_type = btm_set_conn_mode_adv_init_addr(
-        p_cb, p_addr_ptr, &init_addr_type, &own_addr_type);
+        p_cb, address, &init_addr_type, &own_addr_type);
 
     /* slow adv mode never goes into directed adv */
-    btsnd_hcic_ble_write_adv_params(BTM_BLE_GAP_ADV_SLOW_INT,
-                                    BTM_BLE_GAP_ADV_SLOW_INT, p_cb->evt_type,
-                                    own_addr_type, init_addr_type, p_addr_ptr,
-                                    p_cb->adv_chnl_map, p_cb->afp);
+    btsnd_hcic_ble_write_adv_params(
+        BTM_BLE_GAP_ADV_SLOW_INT, BTM_BLE_GAP_ADV_SLOW_INT, p_cb->evt_type,
+        own_addr_type, init_addr_type, address, p_cb->adv_chnl_map, p_cb->afp);
 
     btm_ble_start_adv();
   }
diff --git a/system/stack/btm/btm_ble_multi_adv.cc b/system/stack/btm/btm_ble_multi_adv.cc
index 913ee26..1e83020 100644
--- a/system/stack/btm/btm_ble_multi_adv.cc
+++ b/system/stack/btm/btm_ble_multi_adv.cc
@@ -87,7 +87,7 @@
         duration(0),
         timeout_timer(nullptr),
         own_address_type(0),
-        own_address(bd_addr_empty),
+        own_address(RawAddress::kEmpty),
         address_update_required(false),
         periodic_enabled(false),
         enable_status(false) {
@@ -621,7 +621,7 @@
     p_inst->advertising_event_properties =
         p_params->advertising_event_properties;
     p_inst->tx_power = p_params->tx_power;
-    const RawAddress& peer_address = bd_addr_empty;
+    const RawAddress& peer_address = RawAddress::kEmpty;
 
     GetHciInterface()->SetParameters(
         p_inst->inst_id, p_params->advertising_event_properties,
diff --git a/system/stack/btm/btm_ble_privacy.cc b/system/stack/btm/btm_ble_privacy.cc
index 6242279..50738fa 100644
--- a/system/stack/btm/btm_ble_privacy.cc
+++ b/system/stack/btm/btm_ble_privacy.cc
@@ -116,7 +116,7 @@
 
   if (p_q->q_next != p_q->q_pending) {
     pseudo_addr = p_q->resolve_q_random_pseudo[p_q->q_pending];
-    p_q->resolve_q_random_pseudo[p_q->q_pending] = bd_addr_empty;
+    p_q->resolve_q_random_pseudo[p_q->q_pending] = RawAddress::kEmpty;
     p_q->q_pending++;
     p_q->q_pending %=
         controller_get_interface()->get_ble_resolving_list_max_size();
@@ -696,7 +696,7 @@
           uint8_t* peer_irk = p_dev_rec->ble.keys.irk;
           uint8_t* local_irk = btm_cb.devcb.id_keys.irk;
 
-          if (p_dev_rec->ble.static_addr == bd_addr_empty) {
+          if (p_dev_rec->ble.static_addr.IsEmpty()) {
             p_dev_rec->ble.static_addr = p_dev_rec->bd_addr;
             p_dev_rec->ble.static_addr_type = p_dev_rec->ble.ble_addr_type;
           }
diff --git a/system/stack/btm/btm_devctl.cc b/system/stack/btm/btm_devctl.cc
index d782320..e3eb872 100644
--- a/system/stack/btm/btm_devctl.cc
+++ b/system/stack/btm/btm_devctl.cc
@@ -782,7 +782,7 @@
   if (!bd_addr) {
     /* This is to delete all link keys */
     /* We don't care the BD address. Just pass a non zero pointer */
-    RawAddress local_bd_addr = bd_addr_empty;
+    RawAddress local_bd_addr = RawAddress::kEmpty;
     btsnd_hcic_delete_stored_key(local_bd_addr, delete_all_flag);
   } else {
     btsnd_hcic_delete_stored_key(*bd_addr, delete_all_flag);
diff --git a/system/stack/btm/btm_inq.cc b/system/stack/btm/btm_inq.cc
index 0ba9fab..b048719 100644
--- a/system/stack/btm/btm_inq.cc
+++ b/system/stack/btm/btm_inq.cc
@@ -1175,7 +1175,7 @@
   if (p_inq->remname_active) {
     alarm_cancel(p_inq->remote_name_timer);
     p_inq->remname_active = false;
-    p_inq->remname_bda = bd_addr_empty;
+    p_inq->remname_bda = RawAddress::kEmpty;
 
     if (p_inq->p_remname_cmpl_cb) {
       rem_name.status = BTM_DEV_RESET;
@@ -2167,7 +2167,7 @@
       rem_name.remote_bd_name[0] = 0;
     }
     /* Reset the remote BAD to zero and call callback if possible */
-    p_inq->remname_bda = bd_addr_empty;
+    p_inq->remname_bda = RawAddress::kEmpty;
 
     p_inq->p_remname_cmpl_cb = NULL;
     if (p_cb) (p_cb)((tBTM_REMOTE_DEV_NAME*)&rem_name);
diff --git a/system/stack/btm/btm_sec.cc b/system/stack/btm/btm_sec.cc
index 188224f..76ef533 100644
--- a/system/stack/btm/btm_sec.cc
+++ b/system/stack/btm/btm_sec.cc
@@ -2835,7 +2835,7 @@
  ******************************************************************************/
 void btm_sec_init(uint8_t sec_mode) {
   btm_cb.security_mode = sec_mode;
-  btm_cb.pairing_bda = bd_addr_any;
+  btm_cb.pairing_bda = RawAddress::kAny;
   btm_cb.max_collision_delay = BTM_SEC_MAX_COLLISION_DELAY;
 }
 
@@ -5633,7 +5633,7 @@
     btm_sec_check_pending_reqs();
     btm_inq_clear_ssp();
 
-    btm_cb.pairing_bda = bd_addr_any;
+    btm_cb.pairing_bda = RawAddress::kAny;
   } else {
     /* If transitioning out of idle, mark the lcb as bonding */
     if (old_state == BTM_PAIR_STATE_IDLE)
diff --git a/system/stack/gap/gap_conn.cc b/system/stack/gap/gap_conn.cc
index 5ff63f0..190eeb5 100644
--- a/system/stack/gap/gap_conn.cc
+++ b/system/stack/gap/gap_conn.cc
@@ -178,8 +178,8 @@
 
   /* If caller specified a BD address, save it */
   if (p_rem_bda) {
-    /* the bd addr is not bd_addr_any, then a bd address was specified */
-    if (*p_rem_bda != bd_addr_any) p_ccb->rem_addr_specified = true;
+    /* the bd addr is not RawAddress::kAny, then a bd address was specified */
+    if (*p_rem_bda != RawAddress::kAny) p_ccb->rem_addr_specified = true;
 
     p_ccb->rem_dev_address = *p_rem_bda;
   } else if (!is_server) {
diff --git a/system/stack/include/bt_types.h b/system/stack/include/bt_types.h
index 423db45..380e8cd 100644
--- a/system/stack/include/bt_types.h
+++ b/system/stack/include/bt_types.h
@@ -527,30 +527,8 @@
 #define BD_ADDR_LEN 6 /* Device address length */
 
 #ifdef __cplusplus
-#include <base/strings/stringprintf.h>
 #include <hardware/bluetooth.h>
 
-inline bool operator==(const RawAddress& lhs, const RawAddress& rhs) {
-  return memcmp(&lhs, &rhs, sizeof(lhs)) == 0;
-}
-
-inline bool operator!=(const RawAddress& lhs, const RawAddress& rhs) {
-  return !(lhs == rhs);
-}
-
-inline std::ostream& operator<<(std::ostream& os, const RawAddress& a) {
-  os << base::StringPrintf("%02x:%02x:%02x:%02x:%02x:%02x", a.address[0],
-                           a.address[1], a.address[2], a.address[3],
-                           a.address[4], a.address[5]);
-  return os;
-}
-
-inline std::string to_string(const RawAddress& a) {
-  return base::StringPrintf("%02x:%02x:%02x:%02x:%02x:%02x", a.address[0],
-                            a.address[1], a.address[2], a.address[3],
-                            a.address[4], a.address[5]);
-}
-
 inline void BDADDR_TO_STREAM(uint8_t*& p, const RawAddress& a) {
   for (int ijk = 0; ijk < BD_ADDR_LEN; ijk++)
     *(p)++ = (uint8_t)(a.address)[BD_ADDR_LEN - 1 - ijk];
@@ -951,23 +929,4 @@
 /* Define a function for logging */
 typedef void(BT_LOG_FUNC)(int trace_type, const char* fmt_str, ...);
 
-// From bd.c
-
-/*****************************************************************************
- *  Constants
- ****************************************************************************/
-
-/* global constant for "any" bd addr */
-#ifdef __cplusplus
-static const RawAddress bd_addr_any = {
-    .address = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
-
-static const RawAddress bd_addr_empty = {
-    .address = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
-
-#endif
-/*****************************************************************************
- *  Functions
- ****************************************************************************/
-
 #endif
diff --git a/system/stack/include/l2c_api.h b/system/stack/include/l2c_api.h
index b420f8b..9d4feed 100644
--- a/system/stack/include/l2c_api.h
+++ b/system/stack/include/l2c_api.h
@@ -1,20 +1,20 @@
 /******************************************************************************
- *
- *  Copyright (C) 1999-2012 Broadcom Corporation
- *
- *  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.
- *
- ******************************************************************************/
+*
+*  Copyright (C) 1999-2012 Broadcom Corporation
+*
+*  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.
+*
+******************************************************************************/
 
 /******************************************************************************
  *
@@ -635,8 +635,8 @@
  *                  down immediately when the last channel is removed.
  *                  A timeout of 0xFFFF means no timeout. Values are in seconds.
  *                  A bd_addr is the remote BD address. If bd_addr =
- *                  bd_addr_any, then the idle timeouts for all active l2cap
- *                  links will be changed.
+ *                  RawAddress::kAny, then the idle timeouts for all active
+ *                  l2cap links will be changed.
  *
  * Returns          true if command succeeded, false if failed
  *
@@ -1131,8 +1131,8 @@
  *                  down immediately when the last channel is removed.
  *                  A timeout of 0xFFFF means no timeout. Values are in seconds.
  *                  A bd_addr is the remote BD address. If bd_addr =
- *                  bd_addr_any, then the idle timeouts for all active l2cap
- *                  links will be changed.
+ *                  RawAddress::kAny, then the idle timeouts for all active
+ *                  l2cap links will be changed.
  *
  * Returns          true if command succeeded, false if failed
  *
diff --git a/system/stack/l2cap/l2c_api.cc b/system/stack/l2cap/l2c_api.cc
index 6e70a4e..b921f51 100644
--- a/system/stack/l2cap/l2c_api.cc
+++ b/system/stack/l2cap/l2c_api.cc
@@ -962,7 +962,7 @@
   /* Fail if we have not established communications with the controller */
   if (!BTM_IsDeviceUp()) return (false);
 
-  if (bd_addr_any == p_bd_addr && (p_data == NULL)) {
+  if (RawAddress::kAny == p_bd_addr && (p_data == NULL)) {
     /* Only register callback without sending message. */
     l2cb.p_echo_data_cb = p_callback;
     return true;
@@ -1058,8 +1058,8 @@
  *                  down immediately when the last channel is removed.
  *                  A timeout of 0xFFFF means no timeout. Values are in seconds.
  *                  A bd_addr is the remote BD address. If bd_addr =
- *                  bd_addr_any, then the idle timeouts for all active l2cap
- *                  links will be changed.
+ *                  RawAddress::kAny, then the idle timeouts for all active
+ *                  l2cap links will be changed.
  *
  * Returns          true if command succeeded, false if failed
  *
@@ -1070,7 +1070,7 @@
                                  tBT_TRANSPORT transport) {
   tL2C_LCB* p_lcb;
 
-  if (bd_addr_any == bd_addr) {
+  if (RawAddress::kAny == bd_addr) {
     p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, transport);
     if ((p_lcb) && (p_lcb->in_use) && (p_lcb->link_state == LST_CONNECTED)) {
       p_lcb->idle_timeout = timeout;
@@ -1422,7 +1422,7 @@
     }
   }
 
-  if (bd_addr_any == bd_addr) {
+  if (RawAddress::kAny == bd_addr) {
     p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_BR_EDR);
 
     if ((p_lcb) && (p_lcb->in_use) && (p_lcb->link_state == LST_CONNECTED)) {
diff --git a/system/stack/l2cap/l2c_ble.cc b/system/stack/l2cap/l2c_ble.cc
index 02c3e49..573fde8 100644
--- a/system/stack/l2cap/l2c_ble.cc
+++ b/system/stack/l2cap/l2c_ble.cc
@@ -865,7 +865,7 @@
     btm_ble_disable_resolving_list(BTM_BLE_RL_INIT, true);
 
     // If we have a current RPA, use that instead.
-    if (!bdaddr_is_empty(&p_dev_rec->ble.cur_rand_addr)) {
+    if (!p_dev_rec->ble.cur_rand_addr.IsEmpty()) {
       peer_addr = p_dev_rec->ble.cur_rand_addr;
     }
   }
diff --git a/system/stack/l2cap/l2c_link.cc b/system/stack/l2cap/l2c_link.cc
index 0846673..c51967c 100644
--- a/system/stack/l2cap/l2c_link.cc
+++ b/system/stack/l2cap/l2c_link.cc
@@ -32,7 +32,6 @@
 #include "bt_common.h"
 #include "bt_types.h"
 #include "bt_utils.h"
-#include "btcore/include/bdaddr.h"
 #include "btm_api.h"
 #include "btm_int.h"
 #include "btu.h"
@@ -425,16 +424,13 @@
                 xx + L2CAP_FIRST_FIXED_CHNL, p_lcb->remote_bd_addr, false,
                 p_lcb->disc_reason, p_lcb->transport);
             if (p_lcb->p_fixed_ccbs[xx] == NULL) {
-              bdstr_t bd_addr_str = {0};
               L2CAP_TRACE_ERROR(
                   "%s: unexpected p_fixed_ccbs[%d] is NULL remote_bd_addr = %s "
                   "p_lcb = %p in_use = %d link_state = %d handle = %d "
                   "link_role = %d is_bonding = %d disc_reason = %d transport = "
                   "%d",
-                  __func__, xx,
-                  bdaddr_to_string((RawAddress*)&p_lcb->remote_bd_addr,
-                                   bd_addr_str, sizeof(bd_addr_str)),
-                  p_lcb, p_lcb->in_use, p_lcb->link_state, p_lcb->handle,
+                  __func__, xx, p_lcb->remote_bd_addr.ToString().c_str(), p_lcb,
+                  p_lcb->in_use, p_lcb->link_state, p_lcb->handle,
                   p_lcb->link_role, p_lcb->is_bonding, p_lcb->disc_reason,
                   p_lcb->transport);
             }
diff --git a/system/stack/l2cap/l2cap_client.cc b/system/stack/l2cap/l2cap_client.cc
index f20d3d9..aa43598 100644
--- a/system/stack/l2cap/l2cap_client.cc
+++ b/system/stack/l2cap/l2cap_client.cc
@@ -23,7 +23,6 @@
 #include <base/logging.h>
 #include <string.h>
 
-#include "btcore/include/bdaddr.h"
 #include "osi/include/allocator.h"
 #include "osi/include/buffer.h"
 #include "osi/include/list.h"
@@ -130,7 +129,7 @@
                           const RawAddress& remote_bdaddr, uint16_t psm) {
   CHECK(client != NULL);
   CHECK(psm != 0);
-  CHECK(!bdaddr_is_empty(&remote_bdaddr));
+  CHECK(!remote_bdaddr.IsEmpty());
   CHECK(client->local_channel_id == 0);
   CHECK(!client->configured_self);
   CHECK(!client->configured_peer);
diff --git a/system/stack/rfcomm/port_utils.cc b/system/stack/rfcomm/port_utils.cc
index 4057c9b..1390e60 100644
--- a/system/stack/rfcomm/port_utils.cc
+++ b/system/stack/rfcomm/port_utils.cc
@@ -258,7 +258,7 @@
       if (p_port->is_server) p_port->dlci &= 0xfe;
 
       p_port->local_ctrl.modem_signal = p_port->default_signal_state;
-      p_port->bd_addr = bd_addr_any;
+      p_port->bd_addr = RawAddress::kAny;
     } else {
       RFCOMM_TRACE_DEBUG("%s Clean-up handle: %d", __func__, p_port->inx);
       alarm_free(p_port->rfc.port_timer);
diff --git a/system/stack/smp/smp_act.cc b/system/stack/smp/smp_act.cc
index 808c885..2eba4d8 100644
--- a/system/stack/smp/smp_act.cc
+++ b/system/stack/smp/smp_act.cc
@@ -1868,7 +1868,7 @@
   } else {
     tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(bda);
     if (p_dev_rec != NULL && p_dev_rec->ble.pseudo_addr == smp_cb.pairing_bda &&
-        p_dev_rec->ble.pseudo_addr != bd_addr_empty) {
+        p_dev_rec->ble.pseudo_addr != RawAddress::kEmpty) {
       match = true;
     }
   }
diff --git a/system/stack/smp/smp_l2c.cc b/system/stack/smp/smp_l2c.cc
index 2700792..f596e0d 100644
--- a/system/stack/smp/smp_l2c.cc
+++ b/system/stack/smp/smp_l2c.cc
@@ -98,7 +98,7 @@
 
   SMP_TRACE_EVENT("SMDBG l2c %s", __func__);
 
-  if (transport == BT_TRANSPORT_BR_EDR || bd_addr == bd_addr_empty) return;
+  if (transport == BT_TRANSPORT_BR_EDR || bd_addr.IsEmpty()) return;
 
   if (bd_addr == p_cb->pairing_bda) {
     VLOG(2) << __func__ << " for pairing BDA: " << bd_addr
diff --git a/system/stack/test/stack_smp_test.cc b/system/stack/test/stack_smp_test.cc
index 1e53474..2391012 100644
--- a/system/stack/test/stack_smp_test.cc
+++ b/system/stack/test/stack_smp_test.cc
@@ -58,7 +58,7 @@
 bool BTM_ReadRemoteConnectionAddr(const RawAddress& pseudo_addr,
                                   RawAddress& conn_addr,
                                   tBLE_ADDR_TYPE* p_addr_type) {
-  conn_addr = {.address = {0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6}};
+  conn_addr = RawAddress({0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6});
   *p_addr_type = 0x00;
   return true;
 }
@@ -67,7 +67,7 @@
 void BTM_ReadConnectionAddr(const RawAddress& remote_bda,
                             RawAddress& local_conn_addr,
                             tBLE_ADDR_TYPE* p_addr_type) {
-  local_conn_addr = {.address = {0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6}};
+  local_conn_addr = RawAddress({0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6});
   *p_addr_type = 0x01;
 }
 
diff --git a/system/test/rootcanal/Android.bp b/system/test/rootcanal/Android.bp
index 265f712..74a7fde 100644
--- a/system/test/rootcanal/Android.bp
+++ b/system/test/rootcanal/Android.bp
@@ -45,6 +45,7 @@
         "android.hardware.bluetooth-async",
         "android.hardware.bluetooth-hci",
         "libbt-rootcanal",
+        "libbluetooth-types",
     ],
     include_dirs: [
         "packages/modules/Bluetooth/system",
diff --git a/system/test/run_unit_tests.sh b/system/test/run_unit_tests.sh
index ea895e3..9198cbb 100755
--- a/system/test/run_unit_tests.sh
+++ b/system/test/run_unit_tests.sh
@@ -13,6 +13,7 @@
   net_test_stack_multi_adv
   net_test_stack_ad_parser
   net_test_stack_smp
+  net_test_types
   net_test_btu_message_loop
   net_test_osi
   performance_test
diff --git a/system/test/suite/adapter/bluetooth_test.cc b/system/test/suite/adapter/bluetooth_test.cc
index 3b8ebda..dcb95d1 100644
--- a/system/test/suite/adapter/bluetooth_test.cc
+++ b/system/test/suite/adapter/bluetooth_test.cc
@@ -18,7 +18,6 @@
 
 #include "adapter/bluetooth_test.h"
 #include <mutex>
-#include "btcore/include/bdaddr.h"
 #include "btcore/include/property.h"
 
 namespace {
diff --git a/system/test/suite/gatt/gatt_test.cc b/system/test/suite/gatt/gatt_test.cc
index de1d68b..8f3ff61 100644
--- a/system/test/suite/gatt/gatt_test.cc
+++ b/system/test/suite/gatt/gatt_test.cc
@@ -18,7 +18,6 @@
 
 #include "gatt/gatt_test.h"
 #include "adapter/bluetooth_test.h"
-#include "btcore/include/bdaddr.h"
 
 namespace bttest {
 
diff --git a/system/test/suite/rfcomm/rfcomm_test.cc b/system/test/suite/rfcomm/rfcomm_test.cc
index 751a427..194320d 100644
--- a/system/test/suite/rfcomm/rfcomm_test.cc
+++ b/system/test/suite/rfcomm/rfcomm_test.cc
@@ -19,7 +19,6 @@
 #include "rfcomm/rfcomm_test.h"
 #include "adapter/bluetooth_test.h"
 
-#include "btcore/include/bdaddr.h"
 #include "btcore/include/uuid.h"
 
 namespace bttest {
@@ -40,7 +39,7 @@
   ASSERT_NE(socket_interface_, nullptr);
 
   // Find a bonded device that supports HFP
-  string_to_bdaddr("00:00:00:00:00:00", &bt_remote_bdaddr_);
+  bt_remote_bdaddr_ = RawAddress::kEmpty;
   char value[1280];
 
   bt_property_t* bonded_devices_prop =
@@ -48,8 +47,7 @@
   RawAddress* devices = (RawAddress*)bonded_devices_prop->val;
   int num_bonded_devices = bonded_devices_prop->len / sizeof(RawAddress);
 
-  for (int i = 0; i < num_bonded_devices && bdaddr_is_empty(&bt_remote_bdaddr_);
-       i++) {
+  for (int i = 0; i < num_bonded_devices && bt_remote_bdaddr_.IsEmpty(); i++) {
     ClearSemaphore(remote_device_properties_callback_sem_);
     bt_interface()->get_remote_device_property(&devices[i], BT_PROPERTY_UUIDS);
     semaphore_wait(remote_device_properties_callback_sem_);
@@ -69,7 +67,7 @@
     }
   }
 
-  ASSERT_FALSE(bdaddr_is_empty(&bt_remote_bdaddr_))
+  ASSERT_FALSE(bt_remote_bdaddr_.IsEmpty())
       << "Could not find paired device that supports HFP";
 }
 
diff --git a/system/test/suite/rfcomm/rfcomm_unittest.cc b/system/test/suite/rfcomm/rfcomm_unittest.cc
index 6fa633a..cb9cfe7 100644
--- a/system/test/suite/rfcomm/rfcomm_unittest.cc
+++ b/system/test/suite/rfcomm/rfcomm_unittest.cc
@@ -19,8 +19,6 @@
 #include "adapter/bluetooth_test.h"
 #include "rfcomm/rfcomm_test.h"
 
-#include "btcore/include/bdaddr.h"
-
 #include <sys/socket.h>
 #include <unistd.h>
 
diff --git a/system/tools/bdtool/adapter.c b/system/tools/bdtool/adapter.c
index a556aa5..c7067fc 100644
--- a/system/tools/bdtool/adapter.c
+++ b/system/tools/bdtool/adapter.c
@@ -18,7 +18,6 @@
 
 #include "support/adapter.h"
 #include "base.h"
-#include "btcore/include/bdaddr.h"
 #include "btcore/include/property.h"
 #include "support/callbacks.h"
 
diff --git a/system/tools/bdtool/bdtool.c b/system/tools/bdtool/bdtool.c
index 7e8f802..d37d3d3 100644
--- a/system/tools/bdtool/bdtool.c
+++ b/system/tools/bdtool/bdtool.c
@@ -21,7 +21,6 @@
 #include <stdlib.h>
 #include <unistd.h>
 
-#include "btcore/include/bdaddr.h"
 #include "btcore/include/property.h"
 #include "osi/include/osi.h"
 #include "test/suite/support/callbacks.h"
diff --git a/system/tools/mcap_tool/mcap_test_app.cc b/system/tools/mcap_tool/mcap_test_app.cc
index b247c96..f0c1b4f 100644
--- a/system/tools/mcap_tool/mcap_test_app.cc
+++ b/system/tools/mcap_tool/mcap_test_app.cc
@@ -52,19 +52,14 @@
 }
 
 static void print_mcap_event(const tMCA_DISCONNECT_IND* mcap_disconnect_ind) {
-  bdstr_t bd_addr_str;
   printf("%s: peer_bd_addr=%s,l2cap_disconnect_reason=0x%04x\n", __func__,
-         bdaddr_to_string(&mcap_disconnect_ind->bd_addr, bd_addr_str,
-                          sizeof(bd_addr_str)),
+         mcap_disconnect_ind->bd_addr.ToString().c_str(),
          mcap_disconnect_ind->reason);
 }
 
 static void print_mcap_event(const tMCA_CONNECT_IND* mcap_connect_ind) {
-  bdstr_t bd_addr_str;
   printf("%s: peer_bd_addr=%s, peer_mtu=%d \n", __func__,
-         bdaddr_to_string(&mcap_connect_ind->bd_addr, bd_addr_str,
-                          sizeof(bd_addr_str)),
-         mcap_connect_ind->mtu);
+         mcap_connect_ind->bd_addr.ToString().c_str(), mcap_connect_ind->mtu);
 }
 
 static void print_mcap_event(const tMCA_RSP_EVT* mcap_rsp) {
@@ -453,17 +448,11 @@
       RawAddress bd_addr = p_data->disconnect_ind.bd_addr;
       mcap_mcl = FindMclByPeerAddress(bd_addr);
       if (!mcap_mcl) {
-        bdstr_t bd_addr_str;
-        LOG(ERROR) << "No MCL for BD addr "
-                   << bdaddr_to_string(&bd_addr, bd_addr_str,
-                                       sizeof(bd_addr_str));
+        LOG(ERROR) << "No MCL for BD addr " << bd_addr;
         break;
       }
       if (!mcap_mcl->IsConnected()) {
-        bdstr_t bd_addr_str;
-        LOG(WARNING) << "MCL for " << bdaddr_to_string(&bd_addr, bd_addr_str,
-                                                       sizeof(bd_addr_str))
-                     << " is already disconnected";
+        LOG(WARNING) << "MCL for " << bd_addr << " is already disconnected";
       }
       mcap_mcl->SetHandle(0);
       mcap_mcl->SetMtu(0);
diff --git a/system/tools/mcap_tool/mcap_test_app.h b/system/tools/mcap_tool/mcap_test_app.h
index 96762bb..691b1f6 100644
--- a/system/tools/mcap_tool/mcap_test_app.h
+++ b/system/tools/mcap_tool/mcap_test_app.h
@@ -24,7 +24,6 @@
 
 #include <base/logging.h>
 
-#include "bdaddr.h"
 #include "mca_api.h"
 
 #include "mcap_test_mcl.h"
diff --git a/system/tools/mcap_tool/mcap_test_mcl.cc b/system/tools/mcap_tool/mcap_test_mcl.cc
index a017551..629350a 100644
--- a/system/tools/mcap_tool/mcap_test_mcl.cc
+++ b/system/tools/mcap_tool/mcap_test_mcl.cc
@@ -17,7 +17,6 @@
 
 #include <base/logging.h>
 
-#include "bdaddr.h"
 #include "mca_api.h"
 #include "mca_defs.h"
 #include "mcap_test_mcl.h"
diff --git a/system/tools/mcap_tool/mcap_test_mcl.h b/system/tools/mcap_tool/mcap_test_mcl.h
index 21b2e03..01a8aa6 100644
--- a/system/tools/mcap_tool/mcap_test_mcl.h
+++ b/system/tools/mcap_tool/mcap_test_mcl.h
@@ -17,7 +17,6 @@
 
 #include <vector>
 
-#include "bdaddr.h"
 #include "mca_api.h"
 #include "mcap_test_mdl.h"
 
diff --git a/system/tools/mcap_tool/mcap_tool.cc b/system/tools/mcap_tool/mcap_tool.cc
index 473a117..fad3378 100644
--- a/system/tools/mcap_tool/mcap_tool.cc
+++ b/system/tools/mcap_tool/mcap_tool.cc
@@ -48,7 +48,6 @@
 #endif
 #include <base/logging.h>
 
-#include "bdaddr.h"
 #include "bt_types.h"
 #include "l2c_api.h"
 #include "mca_api.h"
@@ -425,7 +424,6 @@
 static void adapter_properties_changed(bt_status_t status, int num_properties,
                                        bt_property_t* properties) {
   RawAddress bd_addr;
-  bdstr_t bd_addr_str;
   if (!properties) {
     printf("properties is null\n");
     return;
@@ -434,8 +432,7 @@
     case BT_PROPERTY_BDADDR:
       memcpy(bd_addr.address, properties->val,
              MIN((size_t)properties->len, sizeof(bd_addr)));
-      bdaddr_to_string(&bd_addr, bd_addr_str, sizeof(bd_addr_str));
-      LOG(INFO) << "Local Bd Addr = " << bd_addr_str;
+      LOG(INFO) << "Local Bd Addr = " << bd_addr;
       break;
     default:
       break;
@@ -480,11 +477,10 @@
 
 static void acl_state_changed(bt_status_t status, RawAddress* remote_bd_addr,
                               bt_acl_state_t state) {
-  bdstr_t bd_addr_str;
-  bdaddr_to_string(remote_bd_addr, bd_addr_str, sizeof(bd_addr_str));
-  LOG(INFO) << __func__ << ": remote_bd_addr=" << bd_addr_str << ", acl status="
-            << (state == BT_ACL_STATE_CONNECTED ? "ACL Connected"
-                                                : "ACL Disconnected");
+  LOG(INFO) << __func__ << ": remote_bd_addr=" << *remote_bd_addr
+            << ", acl status=" << (state == BT_ACL_STATE_CONNECTED
+                                       ? "ACL Connected"
+                                       : "ACL Disconnected");
 }
 
 static void dut_mode_recv(uint16_t opcode, uint8_t* buf, uint8_t len) {
@@ -681,7 +677,7 @@
   char buf[64];
   get_str(&p, buf);  // arg1
   RawAddress bd_addr;
-  bool valid_bd_addr = string_to_bdaddr(buf, &bd_addr);
+  bool valid_bd_addr = RawAddress::FromString(buf, bd_addr);
   uint16_t ctrl_psm = get_hex(&p, 0);  // arg2
   uint16_t sec_mask = get_int(&p, 0);  // arg3
   printf("%s: mcap_handle=%d, ctrl_psm=0x%04x, secMask=0x%04x, bd_addr=%s\n",
@@ -698,7 +694,7 @@
   char buf[64];
   get_str(&p, buf);  // arg1
   RawAddress bd_addr;
-  bool valid_bd_addr = string_to_bdaddr(buf, &bd_addr);
+  bool valid_bd_addr = RawAddress::FromString(buf, bd_addr);
   printf("%s: bd_addr=%s\n", __func__, buf);
   if (!valid_bd_addr) {
     printf("%s: Invalid Parameters\n", __func__);
@@ -717,7 +713,7 @@
   char buf[64];
   get_str(&p, buf);  // arg1
   RawAddress bd_addr;
-  bool valid_bd_addr = string_to_bdaddr(buf, &bd_addr);
+  bool valid_bd_addr = RawAddress::FromString(buf, bd_addr);
   uint16_t mdep_handle = get_int(&p, 0);  // arg2
   uint16_t data_psm = get_hex(&p, 0);     // arg3
   uint16_t mdl_id = get_int(&p, 0);       // arg4
@@ -747,7 +743,7 @@
   char buf[64];
   get_str(&p, buf);  // arg1
   RawAddress bd_addr;
-  bool valid_bd_addr = string_to_bdaddr(buf, &bd_addr);
+  bool valid_bd_addr = RawAddress::FromString(buf, bd_addr);
   printf("%s: bd_addr=%s\n", __func__, buf);
   if (!valid_bd_addr) {
     printf("%s: Invalid Parameters\n", __func__);
@@ -766,7 +762,7 @@
   char buf[64];
   get_str(&p, buf);  // arg1
   RawAddress bd_addr;
-  bool valid_bd_addr = string_to_bdaddr(buf, &bd_addr);
+  bool valid_bd_addr = RawAddress::FromString(buf, bd_addr);
   printf("%s: bd_addr=%s\n", __func__, buf);
   if (!valid_bd_addr) {
     printf("%s: Invalid Parameters\n", __func__);
@@ -785,7 +781,7 @@
   char buf[64];
   get_str(&p, buf);  // arg1
   RawAddress bd_addr;
-  bool valid_bd_addr = string_to_bdaddr(buf, &bd_addr);
+  bool valid_bd_addr = RawAddress::FromString(buf, bd_addr);
   uint16_t mdl_id = get_int(&p, 0);  // arg2
   printf("%s: bd_addr=%s, mdl_id=%d\n", __func__, buf, mdl_id);
   if (!valid_bd_addr) {
@@ -805,7 +801,7 @@
   char buf[64];
   get_str(&p, buf);  // arg1
   RawAddress bd_addr;
-  bool valid_bd_addr = string_to_bdaddr(buf, &bd_addr);
+  bool valid_bd_addr = RawAddress::FromString(buf, bd_addr);
   uint16_t mdl_id = get_int(&p, 0);  // arg2
   printf("%s: bd_addr=%s, mdl_id=%d\n", __func__, buf, mdl_id);
   if (!valid_bd_addr || !mdl_id) {
@@ -830,7 +826,7 @@
   char buf[64];
   get_str(&p, buf);  // arg1
   RawAddress bd_addr;
-  bool valid_bd_addr = string_to_bdaddr(buf, &bd_addr);
+  bool valid_bd_addr = RawAddress::FromString(buf, bd_addr);
   uint16_t data_psm = get_hex(&p, 0);  // arg1
   uint16_t mdl_id = get_int(&p, 0);    // arg2
   printf("%s: data_psm=0x%04x, mdl_id=%d\n", __func__, data_psm, mdl_id);
@@ -854,7 +850,7 @@
 
 static void do_pairing(char* p) {
   RawAddress bd_addr;
-  if (!string_to_bdaddr(p, &bd_addr)) {
+  if (!RawAddress::FromString(p, bd_addr)) {
     LOG(ERROR) << "Invalid Bluetooth address " << p;
     return;
   }
diff --git a/system/types/Android.bp b/system/types/Android.bp
new file mode 100644
index 0000000..e5bf4cf
--- /dev/null
+++ b/system/types/Android.bp
@@ -0,0 +1,25 @@
+// Bluetooth types
+cc_library_static {
+    name: "libbluetooth-types",
+    defaults: ["fluoride_types_defaults"],
+    cflags: [
+        /* we export all classes, so change default visibility, instead of having EXPORT_SYMBOL on each class*/
+        "-fvisibility=default",
+    ],
+    host_supported: true,
+    srcs: [
+        "raw_address.cc",
+    ],
+    export_include_dirs: ["./"],
+}
+
+// ========================================================
+cc_test {
+    name: "net_test_types",
+    test_suites: ["device-tests"],
+    defaults: ["fluoride_defaults"],
+    host_supported: true,
+    srcs: [
+        "test/raw_address_unittest.cc",
+    ],
+}
\ No newline at end of file
diff --git a/system/types/raw_address.cc b/system/types/raw_address.cc
new file mode 100644
index 0000000..f8b77e5
--- /dev/null
+++ b/system/types/raw_address.cc
@@ -0,0 +1,72 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2017 The Android Open Source Project
+ *
+ *  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 "raw_address.h"
+
+#include <base/strings/string_split.h>
+#include <base/strings/stringprintf.h>
+#include <stdint.h>
+#include <algorithm>
+#include <vector>
+
+static_assert(sizeof(RawAddress) == 6, "RawAddress must be 6 bytes long!");
+
+const RawAddress RawAddress::kAny{{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
+const RawAddress RawAddress::kEmpty{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
+
+RawAddress::RawAddress(const uint8_t (&addr)[6]) {
+  std::copy(addr, addr + kLength, address);
+};
+
+bool RawAddress::operator==(const RawAddress& rhl) const {
+  return std::memcmp(address, rhl.address, sizeof(address)) == 0;
+}
+
+std::string RawAddress::ToString() const {
+  return base::StringPrintf("%02x:%02x:%02x:%02x:%02x:%02x", address[0],
+                            address[1], address[2], address[3], address[4],
+                            address[5]);
+}
+
+bool RawAddress::FromString(const std::string& from, RawAddress& to) {
+  RawAddress new_addr;
+  if (from.length() != 17) return false;
+
+  std::vector<std::string> byte_tokens =
+      base::SplitString(from, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+
+  if (byte_tokens.size() != 6) return false;
+
+  for (int i = 0; i < 6; i++) {
+    const auto& token = byte_tokens[i];
+
+    if (token.length() != 2) return false;
+
+    char* temp = nullptr;
+    new_addr.address[i] = strtol(token.c_str(), &temp, 16);
+    if (*temp != '\0') return false;
+  }
+
+  to = new_addr;
+  return true;
+}
+
+bool RawAddress::IsValidAddress(const std::string& address) {
+  RawAddress tmp;
+  return RawAddress::FromString(address, tmp);
+}
diff --git a/system/types/raw_address.h b/system/types/raw_address.h
new file mode 100644
index 0000000..01e9796
--- /dev/null
+++ b/system/types/raw_address.h
@@ -0,0 +1,54 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2017 The Android Open Source Project
+ *
+ *  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 <string>
+
+/** Bluetooth Address */
+class RawAddress final {
+ public:
+  static constexpr unsigned int kLength = 6;
+
+  uint8_t address[kLength];
+
+  RawAddress() = default;
+  RawAddress(const uint8_t (&addr)[6]);
+
+  bool operator==(const RawAddress& rhl) const;
+  bool operator!=(const RawAddress& rhs) const { return !(*this == rhs); }
+
+  bool IsEmpty() const { return *this == kEmpty; }
+
+  std::string ToString() const;
+
+  // Converts |string| to RawAddress and places it in |to|. If |from| does
+  // not represent a Bluetooth address, |to| is not modified and this function
+  // returns false. Otherwise, it returns true.
+  static bool FromString(const std::string& from, RawAddress& to);
+
+  static bool IsValidAddress(const std::string& address);
+
+  static const RawAddress kEmpty;  // 00:00:00:00:00:00
+  static const RawAddress kAny;    // FF:FF:FF:FF:FF:FF
+};
+
+inline std::ostream& operator<<(std::ostream& os, const RawAddress& a) {
+  os << a.ToString();
+  return os;
+}
diff --git a/system/types/test/raw_address_unittest.cc b/system/types/test/raw_address_unittest.cc
new file mode 100644
index 0000000..717fb99
--- /dev/null
+++ b/system/types/test/raw_address_unittest.cc
@@ -0,0 +1,95 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2017 The Android Open Source Project
+ *
+ *  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 "raw_address.h"
+
+static const char* test_addr = "12:34:56:78:9a:bc";
+static const char* test_addr2 = "cb:a9:87:65:43:21";
+
+TEST(RawAddressUnittest, test_is_empty) {
+  RawAddress empty;
+  RawAddress::FromString("00:00:00:00:00:00", empty);
+  ASSERT_TRUE(empty.IsEmpty());
+
+  RawAddress not_empty;
+  RawAddress::FromString("00:00:00:00:00:01", not_empty);
+  ASSERT_FALSE(not_empty.IsEmpty());
+}
+
+TEST(RawAddressUnittest, test_to_from_str) {
+  RawAddress bdaddr;
+  RawAddress::FromString(test_addr, bdaddr);
+
+  ASSERT_EQ(0x12, bdaddr.address[0]);
+  ASSERT_EQ(0x34, bdaddr.address[1]);
+  ASSERT_EQ(0x56, bdaddr.address[2]);
+  ASSERT_EQ(0x78, bdaddr.address[3]);
+  ASSERT_EQ(0x9A, bdaddr.address[4]);
+  ASSERT_EQ(0xBC, bdaddr.address[5]);
+
+  std::string ret = bdaddr.ToString();
+
+  ASSERT_STREQ(test_addr, ret.c_str());
+}
+
+TEST(RawAddressTest, test_equals) {
+  RawAddress bdaddr1;
+  RawAddress bdaddr2;
+  RawAddress bdaddr3;
+  RawAddress::FromString(test_addr, bdaddr1);
+  RawAddress::FromString(test_addr, bdaddr2);
+  EXPECT_TRUE(bdaddr1 == bdaddr2);
+
+  RawAddress::FromString(test_addr2, bdaddr3);
+  EXPECT_FALSE(bdaddr2 == bdaddr3);
+}
+
+TEST(RawAddressTest, test_copy) {
+  RawAddress bdaddr1;
+  RawAddress bdaddr2;
+  RawAddress::FromString(test_addr, bdaddr1);
+  bdaddr2 = bdaddr1;
+
+  EXPECT_TRUE(bdaddr1 == bdaddr2);
+}
+
+TEST(RawAddressTest, IsValidAddress) {
+  EXPECT_FALSE(RawAddress::IsValidAddress(""));
+  EXPECT_FALSE(RawAddress::IsValidAddress("000000000000"));
+  EXPECT_FALSE(RawAddress::IsValidAddress("00:00:00:00:0000"));
+  EXPECT_FALSE(RawAddress::IsValidAddress("00:00:00:00:00:0"));
+  EXPECT_FALSE(RawAddress::IsValidAddress("00:00:00:00:00:0;"));
+  EXPECT_TRUE(RawAddress::IsValidAddress("00:00:00:00:00:00"));
+  EXPECT_TRUE(RawAddress::IsValidAddress("AB:cd:00:00:00:00"));
+  EXPECT_FALSE(RawAddress::IsValidAddress("aB:cD:eF:Gh:iJ:Kl"));
+}
+
+TEST(RawAddressTest, BdAddrFromString) {
+  RawAddress addr;
+  memset(&addr, 0, sizeof(addr));
+
+  EXPECT_TRUE(RawAddress::FromString("00:00:00:00:00:00", addr));
+  const RawAddress result0 = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
+  EXPECT_EQ(0, memcmp(&addr, &result0, sizeof(addr)));
+
+  EXPECT_TRUE(RawAddress::FromString("ab:01:4C:d5:21:9f", addr));
+  const RawAddress result1 = {{0xab, 0x01, 0x4c, 0xd5, 0x21, 0x9f}};
+  EXPECT_EQ(0, memcmp(&addr, &result1, sizeof(addr)));
+}
diff --git a/system/vendor_libs/test_vendor_lib/Android.bp b/system/vendor_libs/test_vendor_lib/Android.bp
index 88cd778..70b46e6 100644
--- a/system/vendor_libs/test_vendor_lib/Android.bp
+++ b/system/vendor_libs/test_vendor_lib/Android.bp
@@ -36,6 +36,9 @@
         "libchrome",
         "liblog",
     ],
+    static_libs: [
+        "libbluetooth-types",
+    ]
 }
 
 // test-vendor unit tests for host
@@ -66,6 +69,9 @@
         "liblog",
         "libchrome",
     ],
+    static_libs: [
+        "libbluetooth-types",
+    ],
     cflags: [
         "-fvisibility=hidden",
         "-Wall",