am f88e742e: Correct the logic of UIPC thread id check

* commit 'f88e742ea5f95a529a1758cb00aea0e58fdb9863':
  Correct the logic of UIPC thread id check
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..92b837b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+buildtools
+out
+third_party
diff --git a/.gn b/.gn
new file mode 100644
index 0000000..947ebac
--- /dev/null
+++ b/.gn
@@ -0,0 +1,22 @@
+#
+#  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.
+#
+
+# This file is used by the GN meta build system to find the root of the source
+# tree and to set startup options. For documentation on the values set in this
+# file, run "gn help dotfile" at the command line.
+
+buildconfig = "//build/config/BUILDCONFIG.gn"
+secondary_source = "//build/secondary/"
diff --git a/Android.mk b/Android.mk
index c5d3d16..36b5807 100644
--- a/Android.mk
+++ b/Android.mk
@@ -17,9 +17,11 @@
 bdroid_CFLAGS += -DBLUEDROID_DEBUG
 endif
 
+bdroid_CFLAGS += -DEXPORT_SYMBOL="__attribute__((visibility(\"default\")))"
+
 bdroid_CFLAGS += \
+  -fvisibility=hidden \
   -Wall \
-  -Wno-unused-parameter \
   -Wunused-but-set-variable \
   -UNDEBUG \
   -DLOG_NDEBUG=1
diff --git a/BUILD.gn b/BUILD.gn
new file mode 100644
index 0000000..10cefaa
--- /dev/null
+++ b/BUILD.gn
@@ -0,0 +1,28 @@
+#
+#  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.
+#
+
+# This is the root build file for GN. GN will start processing by loading this
+# file, and recursively load all dependencies until all dependencies are either
+# resolved or known not to exist (which will cause the build to fail). So if
+# you add a new build file, there must be some path of dependencies from this
+# file to your new one or GN won't know about it.
+
+# This pulls in main/BUILD.gn and all of its dependencies.
+group("bluetooth") {
+  deps = [
+    "//main:bluetooth.default",
+  ]
+}
diff --git a/audio_a2dp_hw/BUILD.gn b/audio_a2dp_hw/BUILD.gn
new file mode 100644
index 0000000..2c5024a
--- /dev/null
+++ b/audio_a2dp_hw/BUILD.gn
@@ -0,0 +1,27 @@
+#
+#  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.
+#
+
+shared_library("audio.a2dp.default") {
+  sources = [
+    "audio_a2dp_hw.c"
+  ]
+
+  include_dirs = [
+    "include",
+    "//",
+    "//utils/include",
+  ]
+}
diff --git a/audio_a2dp_hw/audio_a2dp_hw.c b/audio_a2dp_hw/audio_a2dp_hw.c
index bd153a3..53396cb 100644
--- a/audio_a2dp_hw/audio_a2dp_hw.c
+++ b/audio_a2dp_hw/audio_a2dp_hw.c
@@ -199,7 +199,6 @@
 {
     int ret;
     int skt_fd;
-    struct sockaddr_un remote;
     int len;
 
     INFO("connect to %s (sz %zu)", path, buffer_sz);
@@ -235,8 +234,6 @@
 static int skt_read(int fd, void *p, size_t len)
 {
     int read;
-    struct pollfd pfd;
-    struct timespec ts;
 
     FNLOG();
 
@@ -366,7 +363,6 @@
 
 static int a2dp_read_audio_config(struct a2dp_stream_common *common)
 {
-    char cmd = A2DP_CTRL_GET_AUDIO_CONFIG;
     uint32_t sample_rate;
     uint8_t channel_count;
 
@@ -652,8 +648,8 @@
 
 static int out_set_format(struct audio_stream *stream, audio_format_t format)
 {
+    UNUSED(stream);
     UNUSED(format);
-    struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
     DEBUG("setting format not yet supported (0x%x)", format);
     return -ENOSYS;
 }
@@ -678,8 +674,8 @@
 
 static int out_dump(const struct audio_stream *stream, int fd)
 {
+    UNUSED(stream);
     UNUSED(fd);
-    struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
     FNLOG();
     return 0;
 }
@@ -741,9 +737,8 @@
 
 static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
 {
+    UNUSED(stream);
     UNUSED(keys);
-    struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
-
     FNLOG();
 
     /* add populating param here */
@@ -1014,7 +1009,6 @@
     struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev;
     struct a2dp_stream_out *out;
     int ret = 0;
-    int i;
     UNUSED(address);
     UNUSED(handle);
     UNUSED(devices);
@@ -1138,8 +1132,7 @@
 
 static int adev_init_check(const struct audio_hw_device *dev)
 {
-    struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device*)dev;
-
+    UNUSED(dev);
     FNLOG();
 
     return 0;
@@ -1320,7 +1313,6 @@
                      hw_device_t** device)
 {
     struct a2dp_audio_device *adev;
-    int ret;
 
     INFO(" adev_open in A2dp_hw module");
     FNLOG();
diff --git a/bta/BUILD.gn b/bta/BUILD.gn
new file mode 100644
index 0000000..756a80d
--- /dev/null
+++ b/bta/BUILD.gn
@@ -0,0 +1,114 @@
+#
+#  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.
+#
+
+static_library("bta") {
+  sources = [
+    "ag/bta_ag_act.c",
+    "ag/bta_ag_api.c",
+    "ag/bta_ag_at.c",
+    "ag/bta_ag_cfg.c",
+    "ag/bta_ag_ci.c",
+    "ag/bta_ag_cmd.c",
+    "ag/bta_ag_main.c",
+    "ag/bta_ag_rfc.c",
+    "ag/bta_ag_sco.c",
+    "ag/bta_ag_sdp.c",
+    "ar/bta_ar.c",
+    "av/bta_av_aact.c",
+    "av/bta_av_act.c",
+    "av/bta_av_api.c",
+    "av/bta_av_cfg.c",
+    "av/bta_av_ci.c",
+    "av/bta_av_main.c",
+    "av/bta_av_sbc.c",
+    "av/bta_av_ssm.c",
+    "dm/bta_dm_act.c",
+    "dm/bta_dm_api.c",
+    "dm/bta_dm_cfg.c",
+    "dm/bta_dm_ci.c",
+    "dm/bta_dm_main.c",
+    "dm/bta_dm_pm.c",
+    "dm/bta_dm_sco.c",
+    "gatt/bta_gattc_act.c",
+    "gatt/bta_gattc_api.c",
+    "gatt/bta_gattc_cache.c",
+    "gatt/bta_gattc_ci.c",
+    "gatt/bta_gattc_main.c",
+    "gatt/bta_gattc_utils.c",
+    "gatt/bta_gatts_act.c",
+    "gatt/bta_gatts_api.c",
+    "gatt/bta_gatts_main.c",
+    "gatt/bta_gatts_utils.c",
+    "hf_client/bta_hf_client_act.c",
+    "hf_client/bta_hf_client_api.c",
+    "hf_client/bta_hf_client_at.c",
+    "hf_client/bta_hf_client_cmd.c",
+    "hf_client/bta_hf_client_main.c",
+    "hf_client/bta_hf_client_rfc.c",
+    "hf_client/bta_hf_client_sdp.c",
+    "hf_client/bta_hf_client_sco.c",
+    "hh/bta_hh_act.c",
+    "hh/bta_hh_api.c",
+    "hh/bta_hh_cfg.c",
+    "hh/bta_hh_le.c",
+    "hh/bta_hh_main.c",
+    "hh/bta_hh_utils.c",
+    "hl/bta_hl_act.c",
+    "hl/bta_hl_api.c",
+    "hl/bta_hl_ci.c",
+    "hl/bta_hl_main.c",
+    "hl/bta_hl_sdp.c",
+    "hl/bta_hl_utils.c",
+    "jv/bta_jv_act.c",
+    "jv/bta_jv_api.c",
+    "jv/bta_jv_cfg.c",
+    "jv/bta_jv_main.c",
+    "mce/bta_mce_act.c",
+    "mce/bta_mce_api.c",
+    "mce/bta_mce_cfg.c",
+    "mce/bta_mce_main.c",
+    "pan/bta_pan_act.c",
+    "pan/bta_pan_api.c",
+    "pan/bta_pan_ci.c",
+    "pan/bta_pan_main.c",
+    "sdp/bta_sdp.c",
+    "sdp/bta_sdp_act.c",
+    "sdp/bta_sdp_api.c",
+    "sdp/bta_sdp_cfg.c",
+    "sys/bta_sys_conn.c",
+    "sys/bta_sys_main.c",
+    "sys/utl.c",
+  ]
+
+  include_dirs = [
+    "dm",
+    "hh",
+    "include",
+    "sys",
+    "//",
+    "//btcore/include",
+    "//gki/common",
+    "//gki/ulinux",
+    "//hci/include",
+    "//include",
+    "//stack/include",
+    "//stack/btm",
+    "//osi/include",
+    "//udrv/include",
+    "//utils/include",
+    "//vnd/include",
+  ]
+}
diff --git a/bta/ag/bta_ag_main.c b/bta/ag/bta_ag_main.c
index b550191..a3c1784 100644
--- a/bta/ag/bta_ag_main.c
+++ b/bta/ag/bta_ag_main.c
@@ -321,7 +321,7 @@
             p_scb->codec_updated = FALSE;
 #endif
             /* set up timers */
-            p_scb->act_timer.param = (UINT32) p_scb;
+            p_scb->act_timer.param = p_scb;
             p_scb->act_timer.p_cback = bta_ag_timer_cback;
 #if (BTM_WBS_INCLUDED == TRUE)
             /* set eSCO mSBC setting to T2 as the preferred */
@@ -650,7 +650,7 @@
 
         /* Start timer to han */
         p_scb->colli_timer.p_cback = (TIMER_CBACK*)&bta_ag_colli_timer_cback;
-        p_scb->colli_timer.param = (INT32)p_scb;
+        p_scb->colli_timer.param = p_scb;
         bta_sys_start_timer(&p_scb->colli_timer, 0, BTA_AG_COLLISION_TIMER);
         p_scb->colli_tmr_on = TRUE;
     }
diff --git a/bta/ag/bta_ag_sco.c b/bta/ag/bta_ag_sco.c
index af6c9bc..c7b3023 100644
--- a/bta/ag/bta_ag_sco.c
+++ b/bta/ag/bta_ag_sco.c
@@ -693,7 +693,7 @@
 
         /* Start timer to handle timeout */
         p_scb->cn_timer.p_cback = (TIMER_CBACK*)&bta_ag_cn_timer_cback;
-        p_scb->cn_timer.param = (INT32)p_scb;
+        p_scb->cn_timer.param = p_scb;
         bta_sys_start_timer(&p_scb->cn_timer, 0, BTA_AG_CODEC_NEGO_TIMEOUT);
     }
     else
diff --git a/bta/av/bta_av_act.c b/bta/av/bta_av_act.c
index 75e0900..5d7588e 100644
--- a/bta/av/bta_av_act.c
+++ b/bta/av/bta_av_act.c
@@ -33,6 +33,7 @@
 #include "utl.h"
 #include "l2c_api.h"
 #include "osi/include/list.h"
+#include "osi/include/osi.h"
 #if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
 #include "bta_ar_api.h"
 #endif
@@ -1467,7 +1468,12 @@
                         /* Possible collision : need to avoid outgoing processing while the timer is running */
                         p_cb->p_scb[xx]->coll_mask = BTA_AV_COLL_INC_TMR;
 
-                        p_cb->acp_sig_tmr.param = (UINT32)xx;
+
+                        // TODO(armansito): Why is this variable called "xx" and
+                        // why is it a signed integer? The callback reinterprets
+                        // it as a UINT8 and then reassigns it as param that
+                        // way, so should this be unsigned?
+                        p_cb->acp_sig_tmr.param = INT_TO_PTR(xx);
                         p_cb->acp_sig_tmr.p_cback = (TIMER_CBACK*)&bta_av_acp_sig_timer_cback;
                         bta_sys_start_timer(&p_cb->acp_sig_tmr, 0, BTA_AV_ACP_SIG_TIME_VAL);
                     }
@@ -1564,7 +1570,7 @@
 *******************************************************************************/
 static void bta_av_acp_sig_timer_cback (TIMER_LIST_ENT *p_tle)
 {
-    UINT8   inx = (UINT8)p_tle->param;
+    UINT8   inx = PTR_TO_UINT(p_tle->param);
     tBTA_AV_CB  *p_cb = &bta_av_cb;
     tBTA_AV_SCB *p_scb = NULL;
     tBTA_AV_API_OPEN  *p_buf;
@@ -1587,7 +1593,7 @@
                     /* We are still doing SDP. Run the timer again. */
                     p_scb->coll_mask |= BTA_AV_COLL_INC_TMR;
 
-                    p_cb->acp_sig_tmr.param = (UINT32)inx;
+                    p_cb->acp_sig_tmr.param = UINT_TO_PTR(inx);
                     p_cb->acp_sig_tmr.p_cback = (TIMER_CBACK *)&bta_av_acp_sig_timer_cback;
                     bta_sys_start_timer(&p_cb->acp_sig_tmr, 0, BTA_AV_ACP_SIG_TIME_VAL);
                 }
diff --git a/bta/av/bta_av_main.c b/bta/av/bta_av_main.c
index 9a40929..3552911 100644
--- a/bta/av/bta_av_main.c
+++ b/bta/av/bta_av_main.c
@@ -397,25 +397,6 @@
 }
 
 /*******************************************************************************
-**
-** Function         bta_av_free_scb
-**
-** Description      free stream control block,
-**
-**
-** Returns          void
-**
-*******************************************************************************/
-static void bta_av_free_scb(tBTA_AV_SCB *p_scb)
-{
-    // NOTE(google) This free currently is not called
-    assert(p_scb != NULL);
-
-    list_free(p_scb->a2d_list);
-    GKI_freebuf(p_scb);
-}
-
-/*******************************************************************************
 *******************************************************************************/
 void bta_av_conn_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data)
 {
diff --git a/bta/dm/bta_dm_act.c b/bta/dm/bta_dm_act.c
index 5775296..abf2240 100644
--- a/bta/dm/bta_dm_act.c
+++ b/bta/dm/bta_dm_act.c
@@ -41,6 +41,7 @@
 
 #define LOG_TAG "bt_bta_dm"
 #include "osi/include/log.h"
+#include "osi/include/osi.h"
 
 #if (GAP_INCLUDED == TRUE)
 #include "gap_api.h"
@@ -451,7 +452,7 @@
     else
     {
         bta_dm_cb.disable_timer.p_cback = (TIMER_CBACK*)&bta_dm_disable_timer_cback;
-        bta_dm_cb.disable_timer.param = 0;
+        bta_dm_cb.disable_timer.param = INT_TO_PTR(0);
         bta_sys_start_timer(&bta_dm_cb.disable_timer, 0, 5000);
     }
 
@@ -479,7 +480,7 @@
 
     APPL_TRACE_EVENT(" bta_dm_disable_timer_cback trial %d ", p_tle->param);
 
-    if(BTM_GetNumAclLinks() && p_tle->param == 0)
+    if(BTM_GetNumAclLinks() && PTR_TO_INT(p_tle->param) == 0)
     {
         for(i=0; i<bta_dm_cb.device_list.count; i++)
         {
@@ -495,7 +496,7 @@
         if (trigger_disc)
         {
             bta_dm_cb.disable_timer.p_cback = (TIMER_CBACK*)&bta_dm_disable_timer_cback;
-            bta_dm_cb.disable_timer.param = 1;
+            bta_dm_cb.disable_timer.param = INT_TO_PTR(1);
             bta_sys_start_timer(&bta_dm_cb.disable_timer, 0, 1500);
         }
     }
@@ -2076,7 +2077,6 @@
 {
 
     tSDP_UUID    uuid;
-    UINT16       num_attrs = 1;
     tBTA_DM_MSG *p_msg;
 
     memset (&uuid, 0, sizeof(tSDP_UUID));
@@ -4367,8 +4367,6 @@
     tBTM_STATUS status = BTM_SUCCESS;
     tBTA_DM_SEC sec_event;
     char *p_name = NULL;
-    UINT8 i;
-    tBT_DEVICE_TYPE dev_type;
 
     if (!bta_dm_cb.p_sec_cback)
         return BTM_NOT_AUTHORIZED;
diff --git a/bta/dm/bta_dm_pm.c b/bta/dm/bta_dm_pm.c
index 43c9a5a..d0615bc 100644
--- a/bta/dm/bta_dm_pm.c
+++ b/bta/dm/bta_dm_pm.c
@@ -154,7 +154,6 @@
 {
 
     UINT8 i,j;
-    UINT16 policy_setting;
     UINT8 *p = NULL;
 #if (BTM_SSR_INCLUDED == TRUE)
     int               index = BTA_DM_PM_SSR0;
diff --git a/bta/hf_client/bta_hf_client_main.c b/bta/hf_client/bta_hf_client_main.c
index 27c00cb..e582963 100644
--- a/bta/hf_client/bta_hf_client_main.c
+++ b/bta/hf_client/bta_hf_client_main.c
@@ -19,7 +19,14 @@
 
 #include <string.h>
 #include <stdlib.h>
+
+// TODO(armansito): cutils/properties.h is only being used to pull-in runtime
+// settings on Android. Remove this conditional include once we have a generic
+// way to obtain system properties.
+#if !defined(OS_GENERIC)
 #include <cutils/properties.h>
+#endif  // !defined(OS_GENERIC)
+
 #include "bt_utils.h"
 #include "bta_api.h"
 #include "bta_sys.h"
@@ -372,7 +379,12 @@
 *******************************************************************************/
 static void bta_hf_client_api_enable(tBTA_HF_CLIENT_DATA *p_data)
 {
+    // TODO(armansito): For non-Android systems we need a common method of
+    // loading system properties. Remove the conditionally compiled code once we
+    // have that in place.
+#if !defined(OS_GENERIC)
     char value[PROPERTY_VALUE_MAX];
+#endif  // !defined(OS_GENERIC)
 
     /* initialize control block */
     memset(&bta_hf_client_cb, 0, sizeof(tBTA_HF_CLIENT_CB));
@@ -380,12 +392,17 @@
     /* store callback function */
     bta_hf_client_cb.p_cback = p_data->api_enable.p_cback;
 
+    // TODO(armansito): For non-Android systems we need a common method of
+    // loading system properties. Remove the conditionally compiled code once we
+    // have that in place.
+#if !defined(OS_GENERIC)
     /* check if mSBC support enabled */
     property_get("ro.bluetooth.hfp.ver", value, "0");
     if (strcmp(value,"1.6") == 0)
     {
        bta_hf_client_cb.msbc_enabled = TRUE;
     }
+#endif  // !defined(OS_GENERIC)
 
     bta_hf_client_cb.scb.negotiated_codec = BTM_SCO_CODEC_CVSD;
 
diff --git a/bta/hl/bta_hl_sdp.c b/bta/hl/bta_hl_sdp.c
index f5b3fd1..f6cb909 100644
--- a/bta/hl/bta_hl_sdp.c
+++ b/bta/hl/bta_hl_sdp.c
@@ -50,7 +50,7 @@
         {
             return(FALSE);
         }
-        SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
+
         item_cnt=0;
 
         for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr && (item_cnt < 4) ; p_sattr = p_sattr->p_next_attr)
diff --git a/bta/hl/bta_hl_utils.c b/bta/hl/bta_hl_utils.c
index 0a0f326..3fa142b 100644
--- a/bta/hl/bta_hl_utils.c
+++ b/bta/hl/bta_hl_utils.c
@@ -1170,8 +1170,6 @@
 
     for (i=0; i < BTA_HL_NUM_MCLS ; i ++)
     {
-        BTA_HL_GET_MCL_CB_PTR(app_idx, i);
-
         if (bta_hl_cb.acb[app_idx].mcb[i].in_use &&
             (!memcmp (bta_hl_cb.acb[app_idx].mcb[i].bd_addr, p_bd_addr, BD_ADDR_LEN)))
         {
diff --git a/bta/jv/bta_jv_act.c b/bta/jv/bta_jv_act.c
index b7ea751..ea14d6d 100644
--- a/bta/jv/bta_jv_act.c
+++ b/bta/jv/bta_jv_act.c
@@ -25,6 +25,7 @@
 #include <arpa/inet.h>
 #include <pthread.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include "osi/include/allocator.h"
 #include "bt_types.h"
@@ -40,13 +41,14 @@
 #include "sdp_api.h"
 #include "l2c_api.h"
 #include "port_api.h"
-#include <string.h>
 #include "rfcdefs.h"
 #include "avct_api.h"
 #include "avdt_api.h"
 #include "gap_api.h"
 #include "l2c_api.h"
 
+#include "osi/include/osi.h"
+
 
 /* one of these exists for each client */
 struct fc_client {
@@ -75,22 +77,6 @@
 static struct fc_client *fc_clients;
 static struct fc_channel *fc_channels;
 static uint32_t fc_next_id;
-static pthread_once_t fc_init_once = PTHREAD_ONCE_INIT;
-
-
-static void fc_init_work(void)
-{
-    fc_clients = NULL;
-    fc_channels = NULL;
-    fc_next_id = 0;
-
-    //more init here if needed...
-}
-
-static void fc_init(void)
-{
-    pthread_once(&fc_init_once,  fc_init_work);
-}
 
 
 static void fcchan_conn_chng_cbk(UINT16 chan, BD_ADDR bd_addr, BOOLEAN connected,
@@ -543,8 +529,6 @@
             /* rfc handle bd addr retrieval requires core stack handle */
             if (bRfcHandle)
             {
-                UINT32 hi = ((jv_handle & BTA_JV_RFC_HDL_MASK) & ~BTA_JV_RFCOMM_MASK) - 1;
-                UINT32 si = BTA_JV_RFC_HDL_TO_SIDX(jv_handle);
                 for (j = 0; j < BTA_JV_MAX_RFC_CONN; j++)
                 {
                     if (jv_handle == bta_jv_cb.port_cb[j].handle)
@@ -869,7 +853,6 @@
 static void bta_jv_start_discovery_cback(UINT16 result, void * user_data)
 {
     tBTA_JV_STATUS status;
-    UINT8          old_sdp_act = bta_jv_cb.sdp_active;
 
     APPL_TRACE_DEBUG("bta_jv_start_discovery_cback res: 0x%x", result);
 
@@ -1229,7 +1212,6 @@
     tL2CAP_CFG_INFO cfg;
     tBTA_JV_L2CAP_START evt_data;
     tBTA_JV_API_L2CAP_SERVER *ls = &(p_data->l2cap_server);
-    INT32   use_etm = FALSE;
     UINT8 chan_mode_mask = GAP_FCR_CHAN_OPT_BASIC;
     tL2CAP_ERTM_INFO    *ertm_info = NULL;
 
@@ -1670,7 +1652,7 @@
             return 1;
         }
     }
-    APPL_TRACE_DEBUG("find_rfc_pcb: cannot find rfc_cb from user data:%d", (UINT32)user_data);
+    APPL_TRACE_DEBUG("find_rfc_pcb: cannot find rfc_cb from user data: %u", PTR_TO_UINT(user_data));
     return 0;
 }
 
@@ -1705,38 +1687,6 @@
 
 /*******************************************************************************
 **
-** Function     bta_jv_get_num_rfc_listen
-**
-** Description  when a RFCOMM connection goes down, make sure that there's only
-**              one port stays listening on this scn.
-**
-** Returns
-**
-*******************************************************************************/
-static UINT8 bta_jv_get_num_rfc_listen(tBTA_JV_RFC_CB *p_cb)
-{
-    UINT8   listen=1;
-
-    if (p_cb->max_sess > 1)
-    {
-        listen = 0;
-        for (UINT8 i=0; i<p_cb->max_sess; i++)
-        {
-            if (p_cb->rfc_hdl[i] != 0)
-            {
-                const tBTA_JV_PCB *p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[i] - 1];
-                if (BTA_JV_ST_SR_LISTEN == p_pcb->state)
-                {
-                    listen++;
-                }
-            }
-        }
-    }
-    return listen;
-}
-
-/*******************************************************************************
-**
 ** Function     bta_jv_port_mgmt_sr_cback
 **
 ** Description  callback for port mamangement function of rfcomm
@@ -2555,7 +2505,6 @@
 static void fcchan_data_cbk(UINT16 chan, BD_ADDR bd_addr, BT_HDR *p_buf)
 {
     tBTA_JV evt_data;
-    tBTA_JV evt_open;
     struct fc_channel *tc;
     struct fc_client *t = NULL;
     tBTA_JV_L2CAP_CBACK *sock_cback = NULL;
@@ -2686,7 +2635,6 @@
     tBTA_JV_API_L2CAP_SERVER *ss = &(p_data->l2cap_server);
     tBTA_JV_L2CAP_START evt_data;
     struct fc_client *t;
-    uint16_t handle;
 
     evt_data.handle = GAP_INVALID_HANDLE;
     evt_data.status = BTA_JV_FAILURE;
diff --git a/bta/sdp/bta_sdp_act.c b/bta/sdp/bta_sdp_act.c
index f3e6005..7755c04 100644
--- a/bta/sdp/bta_sdp_act.c
+++ b/bta/sdp/bta_sdp_act.c
@@ -94,11 +94,9 @@
 
 static void bta_create_mns_sdp_record(bluetooth_sdp_record *record, tSDP_DISC_REC *p_rec)
 {
-    tSDP_DISCOVERY_DB *db = p_bta_sdp_cfg->p_sdp_db;
     tSDP_DISC_ATTR *p_attr;
     tSDP_PROTOCOL_ELEM pe;
     UINT16 pversion = 0;
-    UINT8 offset = 0;
     record->mns.hdr.type = SDP_TYPE_MAP_MNS;
     record->mns.hdr.service_name_length = 0;
     record->mns.hdr.service_name = NULL;
@@ -136,7 +134,6 @@
 
 static void bta_create_mas_sdp_record(bluetooth_sdp_record *record, tSDP_DISC_REC *p_rec)
 {
-    tSDP_DISCOVERY_DB *db = p_bta_sdp_cfg->p_sdp_db;
     tSDP_DISC_ATTR *p_attr;
     tSDP_PROTOCOL_ELEM pe;
     UINT16 pversion = -1;
@@ -190,7 +187,6 @@
 
 static void bta_create_pse_sdp_record(bluetooth_sdp_record *record, tSDP_DISC_REC *p_rec)
 {
-    tSDP_DISCOVERY_DB *db = p_bta_sdp_cfg->p_sdp_db;
     tSDP_DISC_ATTR *p_attr;
     UINT16 pversion;
     tSDP_PROTOCOL_ELEM pe;
@@ -237,7 +233,6 @@
 
 static void bta_create_ops_sdp_record(bluetooth_sdp_record *record, tSDP_DISC_REC *p_rec)
 {
-    tSDP_DISCOVERY_DB *db = p_bta_sdp_cfg->p_sdp_db;
     tSDP_DISC_ATTR *p_attr, *p_sattr;
     tSDP_PROTOCOL_ELEM pe;
     UINT16 pversion = -1;
@@ -350,9 +345,7 @@
 
 static void bta_create_raw_sdp_record(bluetooth_sdp_record *record, tSDP_DISC_REC *p_rec)
 {
-    tSDP_DISCOVERY_DB *db = p_bta_sdp_cfg->p_sdp_db;
     tSDP_DISC_ATTR *p_attr;
-    UINT16 pversion;
     tSDP_PROTOCOL_ELEM pe;
 
     record->hdr.type = SDP_TYPE_RAW;
@@ -393,7 +386,6 @@
     tSDP_DISC_REC *p_rec = NULL;
     tBTA_SDP_SEARCH_COMP evt_data = {0}; // We need to zero-initialize
     tBTA_SDP_STATUS status = BTA_SDP_FAILURE;
-    UINT16 uuid16 = 0;
     int count = 0;
     tBT_UUID su;
     APPL_TRACE_DEBUG("%s() -  res: 0x%x", __func__, result);
diff --git a/bta/sys/bta_sys_main.c b/bta/sys/bta_sys_main.c
index b03c2d1..f05ddac 100644
--- a/bta/sys/bta_sys_main.c
+++ b/bta/sys/bta_sys_main.c
@@ -24,6 +24,7 @@
 #define LOG_TAG "bt_bta_sys_main"
 
 #include <assert.h>
+#include <pthread.h>
 #include <string.h>
 
 #include "osi/include/alarm.h"
diff --git a/btcore/BUILD.gn b/btcore/BUILD.gn
new file mode 100644
index 0000000..56719ad
--- /dev/null
+++ b/btcore/BUILD.gn
@@ -0,0 +1,57 @@
+#
+#  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.
+#
+
+static_library("btcore") {
+  sources = [
+    "src/bdaddr.c",
+    "src/counter.c",
+    "src/device_class.c",
+    "src/module.c",
+    "src/property.c",
+    "src/uuid.c",
+  ]
+
+  include_dirs = [
+    "include",
+    "//osi/include",
+    "//",
+  ]
+}
+
+executable("net_test_btcore") {
+  testonly = true
+  sources = [
+    "test/bdaddr_test.cpp",
+    "test/counter_test.cpp",
+    "test/device_class_test.cpp",
+    "test/property_test.cpp",
+    "test/uuid_test.cpp",
+    "//osi/test/AllocationTestHarness.cpp",
+  ]
+
+  include_dirs = [
+    "include",
+    "//",
+  ]
+
+  deps = [
+    "//btcore",
+    "//osi",
+    "//third_party/gtest:gtest_main",
+  ]
+
+  libs = [ "-lpthread", "-lrt", "-ldl" ]
+}
diff --git a/btcore/src/counter.c b/btcore/src/counter.c
index 08aa518..89f967d 100644
--- a/btcore/src/counter.c
+++ b/btcore/src/counter.c
@@ -21,6 +21,8 @@
 #include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <pthread.h>
+#include <stdarg.h>
 #include <string.h>
 #include <sys/eventfd.h>
 
@@ -142,7 +144,7 @@
   return future_new_immediate(FUTURE_SUCCESS);
 }
 
-module_t counter_module = {
+EXPORT_SYMBOL module_t counter_module = {
   .name = COUNTER_MODULE,
   .init = counter_init,
   .start_up = NULL,
diff --git a/btif/BUILD.gn b/btif/BUILD.gn
new file mode 100644
index 0000000..cee6c03
--- /dev/null
+++ b/btif/BUILD.gn
@@ -0,0 +1,89 @@
+#
+#  Copyright (C) 2015 Google, Inc.
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at:
+#
+#  http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#
+
+static_library("btif") {
+  sources = [
+    "src/btif_av.c",
+    "src/btif_config.c",
+    "src/btif_config_transcode.cpp",
+    "src/btif_core.c",
+    "src/btif_debug.c",
+    "src/btif_debug_btsnoop.c",
+    "src/btif_debug_conn.c",
+    "src/btif_dm.c",
+    "src/btif_gatt.c",
+    "src/btif_gatt_client.c",
+    "src/btif_gatt_multi_adv_util.c",
+    "src/btif_gatt_server.c",
+    "src/btif_gatt_test.c",
+    "src/btif_gatt_util.c",
+    "src/btif_hf.c",
+    "src/btif_hf_client.c",
+    "src/btif_hh.c",
+    "src/btif_hl.c",
+    "src/btif_mce.c",
+    "src/btif_media_task.c",
+    "src/btif_pan.c",
+    "src/btif_profile_queue.c",
+    "src/btif_rc.c",
+    "src/btif_sdp.c",
+    "src/btif_sdp_server.c",
+    "src/btif_sm.c",
+    "src/btif_sock.c",
+    "src/btif_sock_l2cap.c",
+    "src/btif_sock_rfc.c",
+    "src/btif_sock_sco.c",
+    "src/btif_sock_sdp.c",
+    "src/btif_sock_thread.c",
+    "src/btif_sock_util.c",
+    "src/btif_storage.c",
+    "src/btif_util.c",
+    "src/stack_manager.c",
+  ]
+
+  # BTIF callouts
+  sources += [
+    "co/bta_ag_co.c",
+    "co/bta_dm_co.c",
+    "co/bta_av_co.c",
+    "co/bta_hh_co.c",
+    "co/bta_hl_co.c",
+    "co/bta_pan_co.c",
+    "co/bta_gattc_co.c",
+    "co/bta_gatts_co.c",
+  ]
+
+  include_dirs = [
+    "include",
+    "//",
+    "//audio_a2dp_hw",
+    "//bta/include",
+    "//bta/sys",
+    "//btcore/include",
+    "//embdrv/sbc/encoder/include",
+    "//gki/common",
+    "//hci/include",
+    "//osi/include",
+    "//stack/a2dp",
+    "//stack/btm",
+    "//stack/include",
+    "//third_party/tinyxml2",
+    "//include",
+    "//udrv/include",
+    "//utils/include",
+    "//vnd/include",
+  ]
+}
diff --git a/btif/co/bta_hh_co.c b/btif/co/bta_hh_co.c
index b5c845a..bc4db01 100644
--- a/btif/co/bta_hh_co.c
+++ b/btif/co/bta_hh_co.c
@@ -518,8 +518,6 @@
 {
     UNUSED(app_id);
 
-    unsigned idx = 0;
-
     bdstr_t bdstr;
     sprintf(bdstr, "%02x:%02x:%02x:%02x:%02x:%02x",
         remote_bda[0], remote_bda[1], remote_bda[2],
diff --git a/btif/src/bluetooth.c b/btif/src/bluetooth.c
index f842e5c..e056061 100644
--- a/btif/src/bluetooth.c
+++ b/btif/src/bluetooth.c
@@ -486,7 +486,7 @@
     .open = open_bluetooth_stack,
 };
 
-struct hw_module_t HAL_MODULE_INFO_SYM = {
+EXPORT_SYMBOL struct hw_module_t HAL_MODULE_INFO_SYM = {
     .tag = HARDWARE_MODULE_TAG,
     .version_major = 1,
     .version_minor = 0,
diff --git a/btif/src/btif_av.c b/btif/src/btif_av.c
index ee02ee6..3727d65 100644
--- a/btif/src/btif_av.c
+++ b/btif/src/btif_av.c
@@ -329,7 +329,7 @@
 
             BTIF_TRACE_DEBUG("BTA_AV_RC_OPEN_EVT received w/o AV");
             memset(&tle_av_open_on_rc, 0, sizeof(tle_av_open_on_rc));
-            tle_av_open_on_rc.param = (UINT32)btif_initiate_av_open_tmr_hdlr;
+            tle_av_open_on_rc.param = btif_initiate_av_open_tmr_hdlr;
             btu_start_timer(&tle_av_open_on_rc, BTU_TTYPE_USER_FUNC,
                             BTIF_TIMEOUT_AV_OPEN_ON_RC_SECS);
             btif_rc_handler(event, p_data);
diff --git a/btif/src/btif_config.c b/btif/src/btif_config.c
index 3cbff50..f47b37f 100644
--- a/btif/src/btif_config.c
+++ b/btif/src/btif_config.c
@@ -23,6 +23,7 @@
 #include <pthread.h>
 #include <stdio.h>
 #include <string.h>
+#include <unistd.h>
 
 #include "osi/include/alarm.h"
 #include "osi/include/allocator.h"
@@ -143,7 +144,7 @@
   return future_new_immediate(FUTURE_SUCCESS);
 }
 
-const module_t btif_config_module = {
+EXPORT_SYMBOL const module_t btif_config_module = {
   .name = BTIF_CONFIG_MODULE,
   .init = init,
   .start_up = NULL,
diff --git a/btif/src/btif_core.c b/btif/src/btif_core.c
index d552e5c..82ce13d 100644
--- a/btif/src/btif_core.c
+++ b/btif/src/btif_core.c
@@ -27,7 +27,6 @@
  ***********************************************************************************/
 
 #include <ctype.h>
-#include <cutils/properties.h>
 #include <dirent.h>
 #include <fcntl.h>
 #include <hardware/bluetooth.h>
@@ -35,6 +34,16 @@
 #include <string.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <unistd.h>
+
+/**
+ * TODO(armansito): On OSs other than Android, the sys/properties.h system
+ * does not exist. Remove this conditional include once we have a generic way
+ * to obtain system properties.
+ */
+#if !defined(OS_GENERIC)
+#include <cutils/properties.h>
+#endif  /* !defined(OS_GENERIC) */
 
 #define LOG_TAG "bt_btif_core"
 #include "btcore/include/bdaddr.h"
@@ -321,6 +330,13 @@
     char val[256];
     uint8_t valid_bda = FALSE;
     int val_size = 0;
+
+  /**
+   * TODO(armansito): On OSs other than Android, the sys/properties.h system
+   * does not exist. Remove this conditional include once we have a generic way
+   * to obtain system properties.
+   */
+#if !defined(OS_GENERIC)
     const uint8_t null_bdaddr[BD_ADDR_LEN] = {0,0,0,0,0,0};
 
     /* Get local bdaddr storage path from property */
@@ -369,6 +385,7 @@
             local_addr->address[0], local_addr->address[1], local_addr->address[2],
             local_addr->address[3], local_addr->address[4], local_addr->address[5]);
     }
+#endif  /* !defined(OS_GENERIC) */
 
     /* Generate new BDA if necessary */
     if (!valid_bda)
@@ -391,8 +408,16 @@
         BTIF_TRACE_DEBUG("No preset BDA. Generating BDA: %s for prop %s",
              (char*)bdstr, PERSIST_BDADDR_PROPERTY);
 
+
+  /**
+   * TODO(armansito): On OSs other than Android, the sys/properties.h system
+   * does not exist. Remove this conditional include once we have a generic way
+   * to obtain system properties.
+   */
+#if !defined(OS_GENERIC)
         if (property_set(PERSIST_BDADDR_PROPERTY, (char*)bdstr) < 0)
             BTIF_TRACE_ERROR("Failed to set random BDA in prop %s",PERSIST_BDADDR_PROPERTY);
+#endif  /* !defined(OS_GENERIC) */
     }
 
     //save the bd address to config file
@@ -849,9 +874,6 @@
                 local_le_features.version_supported = cmn_vsc_cb.version_supported;
                 local_le_features.total_trackable_advertisers =
                     cmn_vsc_cb.total_trackable_advertisers;
-
-                local_le_features.extended_scan_support = cmn_vsc_cb.extended_scan_support > 0;
-                local_le_features.debug_logging_supported = cmn_vsc_cb.debug_logging_supported > 0;
                 memcpy(prop.val, &local_le_features, prop.len);
                 #endif
             }
diff --git a/btif/src/btif_dm.c b/btif/src/btif_dm.c
index 351a312..24aad27 100644
--- a/btif/src/btif_dm.c
+++ b/btif/src/btif_dm.c
@@ -37,7 +37,15 @@
 
 #include <hardware/bluetooth.h>
 
+/**
+ * TODO(armansito): cutils/properties.h is only being used to pull-in runtime
+ * settings on Android. Remove this conditional include once we have a generic
+ * way to obtain system properties.
+ */
+#if !defined(OS_GENERIC)
 #include <cutils/properties.h>
+#endif  /* !defined(OS_GENERIC) */
+
 #include "gki.h"
 #include "btu.h"
 #include "btcore/include/bdaddr.h"
@@ -2722,6 +2730,12 @@
 #ifdef BTIF_DM_OOB_TEST
 void btif_dm_load_local_oob(void)
 {
+  /**
+   * TODO(armansito): On OSs other than Android, the sys/properties.h system
+   * does not exist. Remove this conditional include once we have a generic way
+   * to obtain system properties.
+   */
+#if !defined(OS_GENERIC)
     char prop_oob[PROPERTY_VALUE_MAX];
     property_get("service.brcm.bt.oob", prop_oob, "3");
     BTIF_TRACE_DEBUG("btif_dm_load_local_oob prop_oob = %s",prop_oob);
@@ -2734,14 +2748,21 @@
             BTIF_TRACE_DEBUG("btif_dm_load_local_oob: read OOB, call BTA_DmLocalOob()");
             BTA_DmLocalOob();
         }
-#else
+#else  /* (BTM_OOB_INCLUDED != TRUE) */
         BTIF_TRACE_ERROR("BTM_OOB_INCLUDED is FALSE!!(btif_dm_load_local_oob)");
-#endif
+#endif  /* (BTM_OOB_INCLUDED == TRUE) */
     }
+#endif  /* !defined(OS_GENERIC) */
 }
 
 void btif_dm_proc_loc_oob(BOOLEAN valid, BT_OCTET16 c, BT_OCTET16 r)
 {
+  /**
+   * TODO(armansito): On OSs other than Android, the sys/properties.h system
+   * does not exist. Remove this conditional include once we have a generic way
+   * to obtain system properties.
+   */
+#if !defined(OS_GENERIC)
     FILE *fp;
     char *path_a = "/data/misc/bluedroid/LOCAL/a.key";
     char *path_b = "/data/misc/bluedroid/LOCAL/b.key";
@@ -2777,9 +2798,17 @@
             }
         }
     }
+#endif  /* !defined(OS_GENERIC) */
 }
+
 BOOLEAN btif_dm_proc_rmt_oob(BD_ADDR bd_addr,  BT_OCTET16 p_c, BT_OCTET16 p_r)
 {
+  /**
+   * TODO(armansito): On OSs other than Android, the sys/properties.h system
+   * does not exist. Remove this conditional include once we have a generic way
+   * to obtain system properties.
+   */
+#if !defined(OS_GENERIC)
     char t[128];
     FILE *fp;
     char *path_a = "/data/misc/bluedroid/LOCAL/a.key";
@@ -2830,6 +2859,9 @@
     }
     BTIF_TRACE_DEBUG("btif_dm_proc_rmt_oob result=%d",result);
     return result;
+#else  /* defined(OS_GENERIC) */
+    return FALSE;
+#endif  /* !defined(OS_GENERIC) */
 }
 #endif /*  BTIF_DM_OOB_TEST */
 #if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
@@ -3229,6 +3261,12 @@
 }
 
 static char* btif_get_default_local_name() {
+  /**
+   * TODO(armansito): On OSs other than Android, the sys/properties.h system
+   * does not exist. Remove this conditional include once we have a generic way
+   * to obtain system properties.
+   */
+#if !defined(OS_GENERIC)
     if (btif_default_local_name[0] == '\0')
     {
         int max_len = sizeof(btif_default_local_name) - 1;
@@ -3244,5 +3282,6 @@
         }
         btif_default_local_name[max_len] = '\0';
     }
+#endif  /* !defined(OS_GENERIC) */
     return btif_default_local_name;
 }
diff --git a/btif/src/btif_gatt_client.c b/btif/src/btif_gatt_client.c
index 295f74a..1c8f179 100644
--- a/btif/src/btif_gatt_client.c
+++ b/btif/src/btif_gatt_client.c
@@ -247,7 +247,7 @@
 static bt_status_t btif_gattc_multi_adv_disable(int client_if);
 static void btif_multi_adv_stop_cb(void *p_tle)
 {
-    int client_if = ((TIMER_LIST_ENT*)p_tle)->data;
+    int client_if = PTR_TO_INT(((TIMER_LIST_ENT*)p_tle)->data);
     btif_gattc_multi_adv_disable(client_if); // Does context switch
 }
 
diff --git a/btif/src/btif_gatt_multi_adv_util.c b/btif/src/btif_gatt_multi_adv_util.c
index 63bca08..692945d 100644
--- a/btif/src/btif_gatt_multi_adv_util.c
+++ b/btif/src/btif_gatt_multi_adv_util.c
@@ -633,8 +633,8 @@
                 btu_stop_timer_oneshot(&p_multi_adv_data_cb->inst_cb[cbindex].tle_limited_timer);
 
             memset(&p_multi_adv_data_cb->inst_cb[cbindex].tle_limited_timer, 0, sizeof(TIMER_LIST_ENT));
-            p_multi_adv_data_cb->inst_cb[cbindex].tle_limited_timer.param = (UINT32)cb;
-            p_multi_adv_data_cb->inst_cb[cbindex].tle_limited_timer.data = (UINT32)client_if;
+            p_multi_adv_data_cb->inst_cb[cbindex].tle_limited_timer.param = cb;
+            p_multi_adv_data_cb->inst_cb[cbindex].tle_limited_timer.data = INT_TO_PTR(client_if);
             btu_start_timer_oneshot(&p_multi_adv_data_cb->inst_cb[cbindex].tle_limited_timer,
                     BTU_TTYPE_USER_FUNC, p_multi_adv_data_cb->inst_cb[cbindex].timeout_s);
         }
diff --git a/btif/src/btif_hf.c b/btif/src/btif_hf.c
index ede52a7..69b76a5 100644
--- a/btif/src/btif_hf.c
+++ b/btif/src/btif_hf.c
@@ -29,6 +29,7 @@
 #include <hardware/bt_hf.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 
 #define LOG_TAG "bt_btif_hf"
 #include "btif_common.h"
diff --git a/btif/src/btif_hf_client.c b/btif/src/btif_hf_client.c
index ee78a8a..0fe3699 100644
--- a/btif/src/btif_hf_client.c
+++ b/btif/src/btif_hf_client.c
@@ -30,7 +30,15 @@
 #include <hardware/bt_hf_client.h>
 #include <stdlib.h>
 #include <string.h>
+
+/**
+ * TODO(armansito): On OSs other than Android, the sys/properties.h system
+ * does not exist. Remove this conditional include once we have a generic way
+ * to obtain system properties.
+ */
+#if !defined(OS_GENERIC)
 #include <cutils/properties.h>
+#endif  /* !defined(OS_GENERIC) */
 
 #define LOG_TAG "bt_btif_hfc"
 #include "btif_common.h"
@@ -71,9 +79,19 @@
 **  Static variables
 ************************************************************************************/
 static bthf_client_callbacks_t *bt_hf_client_callbacks = NULL;
-char   btif_hf_client_version[PROPERTY_VALUE_MAX];
 static UINT32 btif_hf_client_features = 0;
 
+/**
+ * TODO(armansito): On OSs other than Android, the sys/properties.h system
+ * does not exist. Since that is how the HFP version is currently obtained, on
+ * systems other than Android, hardcode 1.5 as the profile version for now,
+ * until there is a generic way to obtain these configuration properties.
+ */
+#if defined(OS_GENERIC)
+const char btif_hf_client_version[] = "1.5";
+#else  /* !defined(OS_GENERIC) */
+char btif_hf_client_version[PROPERTY_VALUE_MAX];
+#endif  /* defined(OS_GENERIC) */
 
 #define CHECK_BTHF_CLIENT_INIT() if (bt_hf_client_callbacks == NULL)\
     {\
@@ -937,7 +955,14 @@
 {
     BTIF_TRACE_EVENT("%s enable:%d", __FUNCTION__, b_enable);
 
+/**
+ * TODO(armansito): On OSs other than Android, the sys/properties.h system
+ * does not exist. Since that is how the HFP version is currently obtained, on
+ * systems other than Android we're hardcoding the version to 1.5 above.
+ */
+#if !defined(OS_GENERIC)
     property_get("ro.bluetooth.hfp.ver", btif_hf_client_version, "1.5");
+#endif  /* !defined(OS_GENERIC) */
 
      if (b_enable)
      {
diff --git a/btif/src/btif_hh.c b/btif/src/btif_hh.c
index 3b9220a..26102e6 100644
--- a/btif/src/btif_hh.c
+++ b/btif/src/btif_hh.c
@@ -30,6 +30,7 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <string.h>
+#include <unistd.h>
 
 #define LOG_TAG "bt_btif_hh"
 
@@ -433,7 +434,7 @@
     {
         BTIF_TRACE_DEBUG("Start VUP timer ");
         memset(&p_dev->vup_timer, 0, sizeof(TIMER_LIST_ENT));
-        p_dev->vup_timer.param = (UINT32)btif_hh_tmr_hdlr;
+        p_dev->vup_timer.param = btif_hh_tmr_hdlr;
         btu_start_timer(&p_dev->vup_timer, BTU_TTYPE_USER_FUNC,
                         BTIF_TIMEOUT_VUP_SECS);
     }
diff --git a/btif/src/btif_hl.c b/btif/src/btif_hl.c
index 9d0c0d7..2f370a5 100644
--- a/btif/src/btif_hl.c
+++ b/btif/src/btif_hl.c
@@ -358,7 +358,7 @@
     {
         BTIF_TRACE_DEBUG("Start CCH timer ");
         memset(&p_mcb->cch_timer, 0, sizeof(TIMER_LIST_ENT));
-        p_mcb->cch_timer.param = (UINT32)btif_hl_tmr_hdlr;
+        p_mcb->cch_timer.param = btif_hl_tmr_hdlr;
         btu_start_timer(&p_mcb->cch_timer, BTU_TTYPE_USER_FUNC,
                         BTIF_TIMEOUT_CCH_NO_DCH_SECS);
     }
@@ -1214,10 +1214,9 @@
 
     if (btif_hl_find_app_idx(app_id, &app_idx) )
     {
-        BTIF_HL_GET_APP_CB_PTR(app_idx);
         if (btif_hl_find_mcl_idx(app_idx, bd_addr, &mcl_idx))
         {
-            p_mcb  =BTIF_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+            p_mcb = BTIF_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
 
             BTIF_TRACE_DEBUG("app_idx=%d mcl_idx=%d",app_idx, mcl_idx);
             BTIF_TRACE_DEBUG("valid_spd_idx=%d sdp_idx=%d",p_mcb->valid_sdp_idx, p_mcb->sdp_idx);
@@ -1227,7 +1226,7 @@
                 num_mdeps = p_rec->num_mdeps;
                 BTIF_TRACE_DEBUG("num_mdeps=%d", num_mdeps);
 
-                for (i=0; i< num_mdeps; i++)
+                for (i = 0; i < num_mdeps; i++)
                 {
                     BTIF_TRACE_DEBUG("p_rec->mdep_cfg[%d].mdep_role=%d",i, p_rec->mdep_cfg[i].mdep_role);
                     BTIF_TRACE_DEBUG("p_rec->mdep_cfg[%d].data_type =%d",i, p_rec->mdep_cfg[i].data_type );
@@ -2592,8 +2591,6 @@
         BTIF_TRACE_DEBUG("app_idx=%d", app_idx);
         if (btif_hl_find_mcl_idx(app_idx, p_data->cch_open_cfm.bd_addr, &mcl_idx))
         {
-            BTIF_HL_GET_APP_CB_PTR(app_idx);
-
             p_mcb = BTIF_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
             BTIF_TRACE_DEBUG("mcl_idx=%d, mcl_handle=%d", mcl_idx,p_data->cch_open_cfm.mcl_handle);
             p_mcb->mcl_handle = p_data->cch_open_cfm.mcl_handle;
@@ -2779,9 +2776,6 @@
 
     if (btif_hl_find_mcl_idx_using_app_idx(p_data->dch_open_ind.mcl_handle, orig_app_idx, &mcl_idx ))
     {
-        BTIF_HL_GET_APP_CB_PTR(orig_app_idx);
-        BTIF_HL_GET_MCL_CB_PTR(orig_app_idx, mcl_idx);
-
         if (btif_hl_find_avail_mdl_idx(orig_app_idx, mcl_idx, &mdl_idx))
         {
             p_dcb = BTIF_HL_GET_MDL_CB_PTR(orig_app_idx, mcl_idx, mdl_idx);
@@ -2858,8 +2852,6 @@
 
     if (btif_hl_find_mcl_idx_using_app_idx(p_data->dch_open_cfm.mcl_handle, app_idx, &mcl_idx ))
     {
-        BTIF_HL_GET_APP_CB_PTR(app_idx);
-        BTIF_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
         p_pcb = BTIF_HL_GET_PCB_PTR(app_idx, mcl_idx);
 
         if (btif_hl_find_avail_mdl_idx(app_idx, mcl_idx, &mdl_idx))
@@ -2932,8 +2924,6 @@
 
     if (btif_hl_find_mcl_idx_using_app_idx(p_data->dch_reconnect_cfm.mcl_handle, app_idx, &mcl_idx ))
     {
-        BTIF_HL_GET_APP_CB_PTR(app_idx);
-        BTIF_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
         p_pcb = BTIF_HL_GET_PCB_PTR(app_idx, mcl_idx);
 
         if (btif_hl_find_avail_mdl_idx(app_idx, mcl_idx, &mdl_idx))
@@ -3011,7 +3001,6 @@
         p_acb = BTIF_HL_GET_APP_CB_PTR(app_idx);
         BTIF_TRACE_DEBUG("btif_hl_proc_dch_reconnect_ind: app_idx = %d, mcl_idx = %d",
                                 app_idx, mcl_idx);
-        BTIF_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
 
         if (btif_hl_find_avail_mdl_idx(app_idx, mcl_idx, &mdl_idx))
         {
@@ -3280,9 +3269,6 @@
     BOOLEAN                         send_chan_cb=TRUE;
     tBTA_HL_REG_PARAM               reg_param;
     btif_hl_app_cb_t                *p_acb;
-    bthl_app_reg_state_t            reg_state = BTHL_APP_REG_STATE_REG_FAILED;
-    UINT8                           preg_idx;
-    bt_status_t                     bt_status;
 
     BTIF_TRACE_DEBUG("%s event %d", __FUNCTION__, event);
     btif_hl_display_calling_process_name();
@@ -4163,7 +4149,6 @@
     if (btif_hl_find_app_idx(((UINT8)app_id), &app_idx))
     {
         evt_param.unreg.app_idx = app_idx;
-        BTIF_HL_GET_APP_CB_PTR(app_idx);
         reg_counter --;
         len = sizeof(btif_hl_unreg_t);
         status = btif_transfer_context (btif_hl_proc_cb_evt, BTIF_HL_UNREG_APP,
@@ -4393,9 +4378,6 @@
 
     if(btif_hl_find_app_idx_using_mdepId(mdep_id,&app_idx))
     {
-
-        BTIF_HL_GET_APP_CB_PTR(app_idx);
-
         p_mdl = BTIF_HL_GET_MDL_CFG_PTR(app_idx, item_idx);
         if (p_mdl)
         {
diff --git a/btif/src/btif_pan.c b/btif/src/btif_pan.c
index c3dec2a..256568c 100644
--- a/btif/src/btif_pan.c
+++ b/btif/src/btif_pan.c
@@ -46,6 +46,7 @@
 #include <sys/prctl.h>
 #include <linux/if_tun.h>
 #include <linux/if_ether.h>
+#include <unistd.h>
 
 #define LOG_TAG "bt_btif_pan"
 #include "btif_common.h"
@@ -389,7 +390,7 @@
     btpan_cb.flow = enable;
     if (enable) {
         btsock_thread_add_fd(pan_pth, btpan_cb.tap_fd, 0, SOCK_THREAD_FD_RD, 0);
-        bta_dmexecutecallback(btu_exec_tap_fd_read, (void *)btpan_cb.tap_fd);
+        bta_dmexecutecallback(btu_exec_tap_fd_read, INT_TO_PTR(btpan_cb.tap_fd));
     }
 }
 
@@ -659,7 +660,7 @@
 #define IS_EXCEPTION(e) ((e) & (POLLHUP | POLLRDHUP | POLLERR | POLLNVAL))
 static void btu_exec_tap_fd_read(void *p_param) {
     struct pollfd ufd;
-    int fd = (int)p_param;
+    int fd = PTR_TO_INT(p_param);
 
     if (fd == INVALID_FD || fd != btpan_cb.tap_fd)
         return;
@@ -758,5 +759,5 @@
         btpan_tap_close(fd);
         btif_pan_close_all_conns();
     } else if (flags & SOCK_THREAD_FD_RD)
-        bta_dmexecutecallback(btu_exec_tap_fd_read, (void *)fd);
+        bta_dmexecutecallback(btu_exec_tap_fd_read, INT_TO_PTR(fd));
 }
diff --git a/btif/src/btif_rc.c b/btif/src/btif_rc.c
index e4bf771..10b6738 100644
--- a/btif/src/btif_rc.c
+++ b/btif/src/btif_rc.c
@@ -26,7 +26,10 @@
  *****************************************************************************/
 #include <hardware/bluetooth.h>
 #include <fcntl.h>
+#include <pthread.h>
 #include <string.h>
+#include <unistd.h>
+
 #include "bta_api.h"
 #include "bta_av_api.h"
 #include "avrc_defs.h"
diff --git a/btif/src/btif_sdp.c b/btif/src/btif_sdp.c
index f728605..b14d6cb 100644
--- a/btif/src/btif_sdp.c
+++ b/btif/src/btif_sdp.c
@@ -108,12 +108,12 @@
         }
         case BTA_SDP_CREATE_RECORD_USER_EVT:
         {
-            on_create_record_event((int)user_data);
+            on_create_record_event(PTR_TO_INT(user_data));
             break;
         }
         case BTA_SDP_REMOVE_RECORD_USER_EVT:
         {
-            on_remove_record_event((int)user_data);
+            on_remove_record_event(PTR_TO_INT(user_data));
             break;
         }
         default:
@@ -147,7 +147,6 @@
 
 static bt_status_t search(bt_bdaddr_t *bd_addr, const uint8_t *uuid)
 {
-    bdstr_t bdstr;
     tSDP_UUID sdp_uuid;
     sdp_uuid.len = 16;
     memcpy(sdp_uuid.uu.uuid128, uuid, sizeof(sdp_uuid.uu.uuid128));
diff --git a/btif/src/btif_sdp_server.c b/btif/src/btif_sdp_server.c
index 5be23f0..f22df99 100644
--- a/btif/src/btif_sdp_server.c
+++ b/btif/src/btif_sdp_server.c
@@ -32,13 +32,13 @@
 #include <pthread.h>
 
 #define LOG_TAG "BTIF_SDP_SERVER"
-#include "allocator.h"
 #include "btif_common.h"
 #include "btif_util.h"
 #include "bta_sdp_api.h"
 #include "bta_sys.h"
-#include "utl.h"
 #include "btif_sock_util.h"
+#include "osi/include/allocator.h"
+#include "utl.h"
 
 static pthread_mutex_t sdp_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
 
@@ -184,7 +184,6 @@
  *   user2_ptr. */
 static int alloc_sdp_slot(bluetooth_sdp_record* in_record) {
     int i;
-    char* tmp_ptr = NULL;
     int record_size = get_sdp_records_size(in_record, 1);
     bluetooth_sdp_record* record = osi_malloc(record_size);
 
@@ -281,7 +280,7 @@
     if(handle < 0)
         return BT_STATUS_FAIL;
 
-    BTA_SdpCreateRecordByUser((void*) handle);
+    BTA_SdpCreateRecordByUser(INT_TO_PTR(handle));
 
     *record_handle = handle;
 
@@ -298,7 +297,7 @@
 
     /* Pass the actual record handle */
     if(handle > 0) {
-        BTA_SdpRemoveRecordByUser((void*) handle);
+        BTA_SdpRemoveRecordByUser(INT_TO_PTR(handle));
         return BT_STATUS_SUCCESS;
     }
     BTIF_TRACE_DEBUG("Sdp Server %s - record already removed - or never created", __FUNCTION__);
diff --git a/btif/src/btif_sock_l2cap.c b/btif/src/btif_sock_l2cap.c
index 04c5b67..f42c65a 100644
--- a/btif/src/btif_sock_l2cap.c
+++ b/btif/src/btif_sock_l2cap.c
@@ -53,9 +53,6 @@
 #define asrt(s) if (!(s)) APPL_TRACE_ERROR("## %s assert %s failed at line:%d ##",__FUNCTION__, \
         #s, __LINE__)
 
-static pthread_mutex_t slot_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
-
-
 struct packet {
     struct packet *next, *prev;
     uint32_t len;
@@ -290,13 +287,6 @@
     osi_free(sock);
 }
 
-static void btsock_l2cap_free(l2cap_socket *sock)
-{
-    pthread_mutex_lock(&state_lock);
-    btsock_l2cap_free_l(sock);
-    pthread_mutex_unlock(&state_lock);
-}
-
 static l2cap_socket *btsock_l2cap_alloc_l(const char *name, const bt_bdaddr_t *addr,
         char is_server, int flags)
 {
@@ -369,18 +359,6 @@
     return NULL;
 }
 
-static l2cap_socket *btsock_l2cap_alloc(const char *name, const bt_bdaddr_t *addr,
-        char is_server, int flags)
-{
-    l2cap_socket *ret;
-
-    pthread_mutex_lock(&state_lock);
-    ret = btsock_l2cap_alloc_l(name, addr, is_server, flags);
-    pthread_mutex_unlock(&state_lock);
-
-    return ret;
-}
-
 bt_status_t btsock_l2cap_init(int handle)
 {
     APPL_TRACE_DEBUG("btsock_l2cap_init...");
@@ -539,7 +517,7 @@
 
         //if we do not set a callback, this socket will be dropped */
         *(p_open->p_p_cback) = (void*)btsock_l2cap_cbk;
-        *(p_open->p_user_data) = (void*)accept_rs->id;
+        *(p_open->p_user_data) = UINT_TO_PTR(accept_rs->id);
 
         //start monitor the socket
         btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP, SOCK_THREAD_FD_EXCEPTION, sock->id);
@@ -720,7 +698,6 @@
 
         } else {
 
-            tBTA_JV_DATA_IND *p_data_ind = &evt->data_ind;
             UINT8 buffer[L2CAP_MAX_SDU_LENGTH];
             UINT32  count;
 
@@ -744,29 +721,29 @@
 
 static void btsock_l2cap_cbk(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_data)
 {
-    int rc;
+    uint32_t sock_id = PTR_TO_UINT(user_data);
 
     switch (event) {
     case BTA_JV_L2CAP_START_EVT:
-        on_srv_l2cap_listen_started(&p_data->l2c_start, (uint32_t)user_data);
+        on_srv_l2cap_listen_started(&p_data->l2c_start, sock_id);
         break;
 
     case BTA_JV_L2CAP_CL_INIT_EVT:
-        on_cl_l2cap_init(&p_data->l2c_cl_init, (uint32_t)user_data);
+        on_cl_l2cap_init(&p_data->l2c_cl_init, sock_id);
         break;
 
     case BTA_JV_L2CAP_OPEN_EVT:
-        on_l2cap_connect(p_data, (uint32_t)user_data);
-        BTA_JvSetPmProfile(p_data->l2c_open.handle,BTA_JV_PM_ID_1,BTA_JV_CONN_OPEN);
+        on_l2cap_connect(p_data, sock_id);
+        BTA_JvSetPmProfile(p_data->l2c_open.handle, BTA_JV_PM_ID_1,BTA_JV_CONN_OPEN);
         break;
 
     case BTA_JV_L2CAP_CLOSE_EVT:
-        APPL_TRACE_DEBUG("BTA_JV_L2CAP_CLOSE_EVT: user_data:%d", (uint32_t)user_data);
-        on_l2cap_close(&p_data->l2c_close, (uint32_t)user_data);
+        APPL_TRACE_DEBUG("BTA_JV_L2CAP_CLOSE_EVT: id: %u", sock_id);
+        on_l2cap_close(&p_data->l2c_close, sock_id);
         break;
 
     case BTA_JV_L2CAP_DATA_IND_EVT:
-        on_l2cap_data_ind(p_data, (uint32_t)user_data);
+        on_l2cap_data_ind(p_data, sock_id);
         APPL_TRACE_DEBUG("BTA_JV_L2CAP_DATA_IND_EVT");
         break;
 
@@ -779,21 +756,21 @@
         break;
 
     case BTA_JV_L2CAP_WRITE_EVT:
-        APPL_TRACE_DEBUG("BTA_JV_L2CAP_WRITE_EVT id: %d", (int)user_data);
-        on_l2cap_write_done((void*)p_data->l2c_write.req_id, (uint32_t)user_data);
+        APPL_TRACE_DEBUG("BTA_JV_L2CAP_WRITE_EVT: id: %u", sock_id);
+        on_l2cap_write_done(UINT_TO_PTR(p_data->l2c_write.req_id), sock_id);
         break;
 
     case BTA_JV_L2CAP_WRITE_FIXED_EVT:
-        APPL_TRACE_DEBUG("BTA_JV_L2CAP_WRITE_FIXED_EVT id: %d", (int)user_data);
-        on_l2cap_write_fixed_done((void*)p_data->l2c_write_fixed.req_id, (uint32_t)user_data);
+        APPL_TRACE_DEBUG("BTA_JV_L2CAP_WRITE_FIXED_EVT: id: %u", sock_id);
+        on_l2cap_write_fixed_done(UINT_TO_PTR(p_data->l2c_write_fixed.req_id), sock_id);
         break;
 
     case BTA_JV_L2CAP_CONG_EVT:
-        on_l2cap_outgoing_congest(&p_data->l2c_cong, (uint32_t)user_data);
+        on_l2cap_outgoing_congest(&p_data->l2c_cong, sock_id);
         break;
 
     default:
-        APPL_TRACE_ERROR("unhandled event %d, slot id:%d", event, (uint32_t)user_data);
+        APPL_TRACE_ERROR("unhandled event %d, slot id: %u", event, sock_id);
         break;
     }
 }
@@ -852,7 +829,7 @@
     if (sock->fixed_chan) {
 
         if (BTA_JvL2capStartServerLE(sock->security, 0, NULL, sock->channel,
-                L2CAP_DEFAULT_MTU, NULL, btsock_l2cap_cbk, (void*)sock->id)
+                L2CAP_DEFAULT_MTU, NULL, btsock_l2cap_cbk, UINT_TO_PTR(sock->id))
                 != BTA_JV_SUCCESS)
             stat = BT_STATUS_FAIL;
 
@@ -860,12 +837,12 @@
         /* If we have a channel specified in the request, just start the server,
          * else we request a PSM and start the server after we receive a PSM. */
         if(sock->channel < 0) {
-            if(BTA_JvGetChannelId(BTA_JV_CONN_TYPE_L2CAP, (void*)sock->id, 0)
+            if(BTA_JvGetChannelId(BTA_JV_CONN_TYPE_L2CAP, UINT_TO_PTR(sock->id), 0)
                     != BTA_JV_SUCCESS)
                 stat = BT_STATUS_FAIL;
         } else {
             if (BTA_JvL2capStartServer(sock->security, 0, &obex_l2c_etm_opt,
-                    sock->channel, L2CAP_MAX_SDU_LENGTH, &cfg, btsock_l2cap_cbk, (void*)sock->id)
+                    sock->channel, L2CAP_MAX_SDU_LENGTH, &cfg, btsock_l2cap_cbk, UINT_TO_PTR(sock->id))
                     != BTA_JV_SUCCESS)
                 stat = BT_STATUS_FAIL;
         }
@@ -921,13 +898,13 @@
         if (fixed_chan) {
             if (BTA_JvL2capConnectLE(sock->security, 0, NULL, channel,
                     L2CAP_DEFAULT_MTU, NULL, sock->addr.address, btsock_l2cap_cbk,
-                    (void*)sock->id) != BTA_JV_SUCCESS)
+                    UINT_TO_PTR(sock->id)) != BTA_JV_SUCCESS)
                 stat = BT_STATUS_FAIL;
 
         } else {
             if (BTA_JvL2capConnect(sock->security, 0, &obex_l2c_etm_opt,
                     channel, L2CAP_MAX_SDU_LENGTH, &cfg, sock->addr.address,
-                    btsock_l2cap_cbk, (void*)sock->id) != BTA_JV_SUCCESS)
+                    btsock_l2cap_cbk, UINT_TO_PTR(sock->id)) != BTA_JV_SUCCESS)
                 stat = BT_STATUS_FAIL;
         }
     }
@@ -1027,21 +1004,28 @@
                          * be wrong
                          * UPDATE: Since we are responsible for freeing the buffer in the
                          * write_complete_ind, it is OK to use malloc. */
-
                         int count = recv(fd, buffer, L2CAP_MAX_SDU_LENGTH,
                                 MSG_NOSIGNAL | MSG_DONTWAIT);
                         APPL_TRACE_DEBUG("btsock_l2cap_signaled - %d bytes received from socket",
                                 count);
+
+                        // TODO(armansito): |buffer|, which is created above via
+                        // malloc, is being cast below to UINT32 to be used as
+                        // the |req_id| parameter of BTA_JvL2capWriteFixed and
+                        // BTA_JvL2capWrite. The "id" then gets freed in an
+                        // obscure callback elsewhere. We need to watch out for
+                        // this type of unsafe practice, as this is error prone
+                        // and difficult to follow.
                         if (sock->fixed_chan) {
                             if(BTA_JvL2capWriteFixed(sock->channel, (BD_ADDR*)&sock->addr,
-                                    (UINT32)buffer, btsock_l2cap_cbk, buffer, count,
-                                    (void *)user_id) != BTA_JV_SUCCESS) {
+                                    PTR_TO_UINT(buffer), btsock_l2cap_cbk, buffer, count,
+                                    UINT_TO_PTR(user_id)) != BTA_JV_SUCCESS) {
                                 // On fail, free the buffer
                                 on_l2cap_write_fixed_done(buffer, user_id);
                             }
                         } else {
-                            if(BTA_JvL2capWrite(sock->handle, (UINT32)buffer, buffer, count,
-                                    (void *)user_id) != BTA_JV_SUCCESS) {
+                            if(BTA_JvL2capWrite(sock->handle, PTR_TO_UINT(buffer), buffer, count,
+                                    UINT_TO_PTR(user_id)) != BTA_JV_SUCCESS) {
                                 // On fail, free the buffer
                                 on_l2cap_write_done(buffer, user_id);
                             }
diff --git a/btif/src/btif_sock_rfc.c b/btif/src/btif_sock_rfc.c
index f80ed56..0637156 100644
--- a/btif/src/btif_sock_rfc.c
+++ b/btif/src/btif_sock_rfc.c
@@ -23,11 +23,12 @@
 #include <features.h>
 #include <hardware/bluetooth.h>
 #include <hardware/bt_sock.h>
+#include <pthread.h>
 #include <string.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <sys/types.h>
-#include <pthread.h>
+#include <unistd.h>
 
 #include "bta_api.h"
 #include "bt_target.h"
@@ -287,7 +288,7 @@
     goto out;
   }
   APPL_TRACE_DEBUG("BTA_JvGetChannelId: service_name: %s - channel: %d", service_name, channel);
-  BTA_JvGetChannelId(BTA_JV_CONN_TYPE_RFCOMM, (void*) slot->id, channel);
+  BTA_JvGetChannelId(BTA_JV_CONN_TYPE_RFCOMM, UINT_TO_PTR(slot->id), channel);
   *sock_fd = slot->app_fd;    // Transfer ownership of fd to caller.
   /*TODO:
    * We are leaking one of the app_fd's - either the listen socket, or the connection socket.
@@ -602,7 +603,7 @@
 }
 
 static void jv_dm_cback(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_data) {
-  uint32_t id = (uintptr_t)user_data;
+  uint32_t id = PTR_TO_UINT(user_data);
   switch(event) {
     case BTA_JV_GET_SCN_EVT:
     {
@@ -628,13 +629,13 @@
         } else {
           if(rs->is_service_uuid_valid == true) {
             // We already have data for SDP record, create it (RFC-only profiles)
-            BTA_JvCreateRecordByUser((void *)rs->id);
+            BTA_JvCreateRecordByUser(UINT_TO_PTR(rs->id));
           } else {
             APPL_TRACE_DEBUG("is_service_uuid_valid==false - don't set SDP-record, "
                     "just start the RFCOMM server", rs->id);
             //now start the rfcomm server after sdp & channel # assigned
             BTA_JvRfcommStartServer(rs->security, rs->role, rs->scn, MAX_RFC_SESSION,
-                    rfcomm_cback, (void*)rs->id);
+                    rfcomm_cback, UINT_TO_PTR(rs->id));
           }
         }
       } else if(rs) {
diff --git a/btif/src/btif_sock_sco.c b/btif/src/btif_sock_sco.c
index 9012527..e9bff91 100644
--- a/btif/src/btif_sock_sco.c
+++ b/btif/src/btif_sock_sco.c
@@ -22,15 +22,17 @@
 #include <errno.h>
 #include <hardware/bluetooth.h>
 #include <hardware/bt_sock.h>
+#include <pthread.h>
 #include <string.h>
 #include <sys/socket.h>
 #include <sys/types.h>
+#include <unistd.h>
 
 #include "btif_common.h"
 #include "osi/include/allocator.h"
 #include "osi/include/list.h"
-#include "osi/include/osi.h"
 #include "osi/include/log.h"
+#include "osi/include/osi.h"
 #include "osi/include/socket.h"
 #include "osi/include/thread.h"
 
diff --git a/btif/src/btif_sock_util.c b/btif/src/btif_sock_util.c
index baa3ed3..4ce5270 100644
--- a/btif/src/btif_sock_util.c
+++ b/btif/src/btif_sock_util.c
@@ -163,8 +163,14 @@
     return ret_len;
 }
 
-
+// TODO(armansito): I'm not sure why the osi log macros aren't being used here,
+// but for now just redefine PRINT for non-Android platforms.
+#if defined(OS_GENERIC)
+#define PRINT(s) fprintf(stderr, "%s\n", s)
+#else  // !defined(OS_GENERIC)
 #define PRINT(s) __android_log_write(ANDROID_LOG_DEBUG, NULL, s)
+#endif  // defined(OS_GENERIC)
+
 static const char* hex_table = "0123456789abcdef";
 static inline void byte2hex(const char* data, char** str)
 {
diff --git a/btif/src/btif_storage.c b/btif/src/btif_storage.c
index ff7e7aa..ca89077 100644
--- a/btif/src/btif_storage.c
+++ b/btif/src/btif_storage.c
@@ -1193,7 +1193,6 @@
 {
     int device_type;
     int addr_type;
-    UINT32 i;
     bt_bdaddr_t bd_addr;
     BD_ADDR bta_bd_addr;
     bool device_added = false;
diff --git a/build/BUILD.gn b/build/BUILD.gn
new file mode 100644
index 0000000..5f55f57
--- /dev/null
+++ b/build/BUILD.gn
@@ -0,0 +1,72 @@
+#
+#  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.
+#
+
+declare_args() {
+  # Include path for hardware/bluetooth.h
+  libhw_include_path = ""
+  core_include_path = ""
+}
+
+config("default_include_dirs") {
+  # TODO(armansito): Remove "core_include_path" once the cutils includes have
+  # been removed.
+  assert(libhw_include_path != "", "libhardware_include_path build argument wasn't provided.")
+  assert(core_include_path != "", "core_include_path build argument wasn't provided.")
+  include_dirs = [
+    libhw_include_path,
+    core_include_path,
+  ]
+}
+
+config("linux") {
+  # TODO(keybuk): AndroidConfig.h or equivalent
+
+  cflags = [
+    "-Wall",
+    "-Werror",
+    "-g",
+    "-O0",
+    "-fpic",
+    "-fdata-sections",
+    "-ffunction-sections",
+    "-fvisibility=hidden",
+  ]
+
+  cflags_c = [
+    "-std=c99"
+  ]
+
+  defines = [
+    "_FORTIFY_SOURCE=2",
+    "_GNU_SOURCE",
+    "HAS_NO_BDROID_BUILDCFG",
+    "LOG_NDEBUG=1",
+    "EXPORT_SYMBOL=__attribute__((visibility(\"default\")))",
+
+    # This is a macro to that can be used by source code to detect if the
+    # current build is done by GN or via Android.mk. This is a temporary
+    # workaround until we can remove all Android-specific dependencies.
+    "OS_GENERIC",
+  ]
+}
+
+config("pic") {
+  cflags = [ "-fPIC" ]
+}
+
+config("gc") {
+  ldflags = [ "-Wl,--gc-sections" ]
+}
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn
new file mode 100644
index 0000000..419d62f
--- /dev/null
+++ b/build/config/BUILDCONFIG.gn
@@ -0,0 +1,49 @@
+#
+#  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.
+#
+
+set_default_toolchain("//build/toolchain/gcc")
+
+set_defaults("executable") {
+  configs = [
+    "//build:linux",
+    "//build:gc",
+    "//build:default_include_dirs",
+  ]
+}
+
+set_defaults("shared_library") {
+  configs = [
+    "//build:linux",
+    "//build:gc",
+    "//build:default_include_dirs",
+  ]
+}
+
+set_defaults("source_set") {
+  configs = [
+    "//build:linux",
+    "//build:gc",
+    "//build:default_include_dirs",
+  ]
+}
+
+set_defaults("static_library") {
+  configs = [
+    "//build:linux",
+    "//build:gc",
+    "//build:default_include_dirs",
+  ]
+}
diff --git a/build/secondary/third_party/gtest/BUILD.gn b/build/secondary/third_party/gtest/BUILD.gn
new file mode 100644
index 0000000..c1112d9
--- /dev/null
+++ b/build/secondary/third_party/gtest/BUILD.gn
@@ -0,0 +1,77 @@
+#
+#  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.
+#
+
+config("gtest_config") {
+  # Gtest headers need to be able to find themselves.
+  include_dirs = [ "include" ]
+
+  defines = [ "GTEST_HAS_RTTI=0" ]
+}
+
+config("gtest_direct_config") {
+  visibility = [ ":*" ]
+  defines = [ "UNIT_TEST" ]
+}
+
+static_library("gtest") {
+  testonly = true
+  sources = [
+    "include/gtest/gtest-death-test.h",
+    "include/gtest/gtest-message.h",
+    "include/gtest/gtest-param-test.h",
+    "include/gtest/gtest-printers.h",
+    "include/gtest/gtest-spi.h",
+    "include/gtest/gtest-test-part.h",
+    "include/gtest/gtest-typed-test.h",
+    "include/gtest/gtest.h",
+    "include/gtest/gtest_pred_impl.h",
+    "include/gtest/internal/gtest-death-test-internal.h",
+    "include/gtest/internal/gtest-filepath.h",
+    "include/gtest/internal/gtest-internal.h",
+    "include/gtest/internal/gtest-linked_ptr.h",
+    "include/gtest/internal/gtest-param-util-generated.h",
+    "include/gtest/internal/gtest-param-util.h",
+    "include/gtest/internal/gtest-port.h",
+    "include/gtest/internal/gtest-string.h",
+    "include/gtest/internal/gtest-tuple.h",
+    "include/gtest/internal/gtest-type-util.h",
+
+    "src/gtest-all.cc",
+    "src/gtest-death-test.cc",
+    "src/gtest-filepath.cc",
+    "src/gtest-internal-inl.h",
+    "src/gtest-port.cc",
+    "src/gtest-printers.cc",
+    "src/gtest-test-part.cc",
+    "src/gtest-typed-test.cc",
+    "src/gtest.cc",
+  ]
+
+  include_dirs = [ "." ]
+
+  all_dependent_configs = [ ":gtest_config" ]
+  public_configs = [ ":gtest_direct_config" ]
+}
+
+source_set("gtest_main") {
+  testonly = true
+  sources = [
+    "src/gtest_main.cc",
+  ]
+  deps = [
+    ":gtest",
+  ]
+}
diff --git a/build/secondary/third_party/tinyxml2/BUILD.gn b/build/secondary/third_party/tinyxml2/BUILD.gn
new file mode 100644
index 0000000..335960b
--- /dev/null
+++ b/build/secondary/third_party/tinyxml2/BUILD.gn
@@ -0,0 +1,23 @@
+#
+#  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.
+#
+
+static_library("tinyxml2") {
+  sources = [
+    "tinyxml2.cpp"
+  ]
+
+  include_dirs = [ "." ]
+}
diff --git a/build/toolchain/gcc/BUILD.gn b/build/toolchain/gcc/BUILD.gn
new file mode 100644
index 0000000..ecf9057
--- /dev/null
+++ b/build/toolchain/gcc/BUILD.gn
@@ -0,0 +1,96 @@
+#
+#  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.
+#
+cc = "gcc"
+cxx = "g++"
+
+toolchain("gcc") {
+  tool("cc") {
+    depfile = "{{output}}.d"
+    command = "$cc -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}} -o {{output}}"
+    depsformat = "gcc"
+    description = "CC {{output}}"
+    outputs = [
+      "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
+    ]
+  }
+
+  tool("cxx") {
+    depfile = "{{output}}.d"
+    command = "$cxx -MMD -MF $depfile {{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}} -c {{source}} -o {{output}}"
+    depsformat = "gcc"
+    description = "CXX {{output}}"
+    outputs = [
+      "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o",
+    ]
+  }
+
+  tool("alink") {
+    rspfile = "{{output}}.rsp"
+    command = "rm -f {{output}} && ar rcs {{output}} @$rspfile"
+    description = "AR {{target_output_name}}{{output_extension}}"
+    rspfile_content = "{{inputs}}"
+    outputs = [
+      "{{target_out_dir}}/{{target_output_name}}{{output_extension}}",
+    ]
+    default_output_extension = ".a"
+
+    output_prefix = "lib"
+  }
+
+  tool("solink") {
+    soname = "{{target_output_name}}{{output_extension}}"  # e.g. "libfoo.so".
+    rspfile = soname + ".rsp"
+
+    command = "$cxx -shared {{ldflags}} -o $soname -Wl,-soname=$soname @$rspfile"
+    rspfile_content = "-Wl,--whole-archive {{inputs}} {{solibs}} -Wl,--no-whole-archive {{libs}}"
+
+    description = "SOLINK $soname"
+
+    # Use this for {{output_extension}} expansions unless a target manually
+    # overrides it (in which case {{output_extension}} will be what the target
+    # specifies).
+    default_output_extension = ".so"
+
+    outputs = [
+      soname,
+    ]
+    link_output = soname
+    depend_output = soname
+
+    output_prefix = "lib"
+  }
+
+  tool("link") {
+    outfile = "{{target_output_name}}{{output_extension}}"
+    rspfile = "$outfile.rsp"
+    command = "$cxx {{ldflags}} -o $outfile -Wl,--start-group @$rspfile {{solibs}} -Wl,--end-group {{libs}}"
+    description = "LINK $outfile"
+    rspfile_content = "{{inputs}}"
+    outputs = [
+      outfile,
+    ]
+  }
+
+  tool("stamp") {
+    command = "touch {{output}}"
+    description = "STAMP {{output}}"
+  }
+
+  tool("copy") {
+    command = "cp -af {{source}} {{output}}"
+    description = "COPY {{source}} {{output}}"
+  }
+}
diff --git a/device/BUILD.gn b/device/BUILD.gn
new file mode 100644
index 0000000..1ca0288
--- /dev/null
+++ b/device/BUILD.gn
@@ -0,0 +1,54 @@
+#
+#  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.
+#
+
+static_library("device") {
+  sources = [
+    "src/classic/peer.c",
+    "src/controller.c"
+  ]
+
+  include_dirs = [
+    "//",
+    "//btcore/include",
+    "//gki/common",
+    "//hci/include",
+    "//include",
+    "//osi/include",
+    "//stack/include",
+  ]
+}
+
+executable("net_test_device") {
+  testonly = true
+  sources = [
+    "//osi/test/AllocationTestHarness.cpp",
+    "test/classic/peer_test.cpp",
+  ]
+
+  include_dirs = [
+    "//",
+    "//osi/include",
+  ]
+
+  deps = [
+    "//device",
+    "//btcore",
+    "//osi",
+    "//third_party/gtest:gtest_main",
+  ]
+
+  libs = [ "-lpthread", "-lrt", "-ldl" ]
+}
diff --git a/device/src/classic/peer.c b/device/src/classic/peer.c
index 6d1a7b5..d2de679 100644
--- a/device/src/classic/peer.c
+++ b/device/src/classic/peer.c
@@ -68,7 +68,7 @@
   return NULL;
 }
 
-const module_t classic_peer_module = {
+EXPORT_SYMBOL const module_t classic_peer_module = {
   .name = CLASSIC_PEER_MODULE,
   .init = init,
   .start_up = NULL,
diff --git a/device/src/controller.c b/device/src/controller.c
index 5101625..89c0133 100644
--- a/device/src/controller.c
+++ b/device/src/controller.c
@@ -250,7 +250,7 @@
   return future_new_immediate(FUTURE_SUCCESS);
 }
 
-const module_t controller_module = {
+EXPORT_SYMBOL const module_t controller_module = {
   .name = CONTROLLER_MODULE,
   .init = NULL,
   .start_up = start_up,
diff --git a/embdrv/sbc/BUILD.gn b/embdrv/sbc/BUILD.gn
new file mode 100644
index 0000000..7c9387c
--- /dev/null
+++ b/embdrv/sbc/BUILD.gn
@@ -0,0 +1,64 @@
+#
+#  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.
+#
+
+source_set("sbc_decoder") {
+  sources = [
+    "decoder/srce/alloc.c",
+    "decoder/srce/bitalloc.c",
+    "decoder/srce/bitalloc-sbc.c",
+    "decoder/srce/bitstream-decode.c",
+    "decoder/srce/decoder-oina.c",
+    "decoder/srce/decoder-private.c",
+    "decoder/srce/decoder-sbc.c",
+    "decoder/srce/dequant.c",
+    "decoder/srce/framing.c",
+    "decoder/srce/framing-sbc.c",
+    "decoder/srce/oi_codec_version.c",
+    "decoder/srce/synthesis-8-generated.c",
+    "decoder/srce/synthesis-dct8.c",
+    "decoder/srce/synthesis-sbc.c",
+  ]
+
+  include_dirs = [
+    "decoder/include",
+  ]
+}
+
+source_set("sbc_encoder") {
+  sources = [
+    "encoder/srce/sbc_analysis.c",
+    "encoder/srce/sbc_dct.c",
+    "encoder/srce/sbc_dct_coeffs.c",
+    "encoder/srce/sbc_enc_bit_alloc_mono.c",
+    "encoder/srce/sbc_enc_bit_alloc_ste.c",
+    "encoder/srce/sbc_enc_coeffs.c",
+    "encoder/srce/sbc_encoder.c",
+    "encoder/srce/sbc_packing.c",
+  ]
+
+  include_dirs = [
+    "encoder/include",
+    "//include",
+    "//stack/include",
+  ]
+}
+
+static_library("sbc") {
+  deps = [
+    ":sbc_decoder",
+    ":sbc_encoder",
+  ]
+}
diff --git a/gki/BUILD.gn b/gki/BUILD.gn
new file mode 100644
index 0000000..95993ac
--- /dev/null
+++ b/gki/BUILD.gn
@@ -0,0 +1,30 @@
+#
+#  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.
+#
+
+static_library("gki") {
+  sources = [
+    "common/gki_buffer.c",
+    "ulinux/gki_ulinux.c",
+  ]
+
+  include_dirs = [
+    "common",
+    "ulinux",
+    "//",
+    "//include",
+    "//stack/include",
+  ]
+}
diff --git a/gki/common/gki.h b/gki/common/gki.h
index cf1c48c..f0df9e3 100644
--- a/gki/common/gki.h
+++ b/gki/common/gki.h
@@ -27,7 +27,7 @@
 */
 typedef void (TIMER_CBACK)(void *p_tle);
 #ifndef TIMER_PARAM_TYPE
-#define TIMER_PARAM_TYPE    UINT32
+#define TIMER_PARAM_TYPE void*
 #endif
 /* Define a timer list entry
 */
diff --git a/gki/ulinux/gki_ulinux.c b/gki/ulinux/gki_ulinux.c
index 72ad479..c8e9953 100644
--- a/gki/ulinux/gki_ulinux.c
+++ b/gki/ulinux/gki_ulinux.c
@@ -51,7 +51,7 @@
 }
 
 // Temp module until GKI dies
-const module_t gki_module = {
+EXPORT_SYMBOL const module_t gki_module = {
   .name = GKI_MODULE,
   .init = init,
   .start_up = NULL,
diff --git a/hci/Android.mk b/hci/Android.mk
index af87285..a36d6b7 100644
--- a/hci/Android.mk
+++ b/hci/Android.mk
@@ -44,6 +44,7 @@
 include $(BUILD_STATIC_LIBRARY)
 
 #####################################################
+ifeq (,$(strip $(SANITIZE_TARGET)))
 include $(CLEAR_VARS)
 
 LOCAL_C_INCLUDES := \
@@ -78,3 +79,4 @@
 LOCAL_STATIC_LIBRARIES := libbt-hci libosi libcutils libbtcore
 
 include $(BUILD_NATIVE_TEST)
+endif # SANITIZE_TARGET
diff --git a/hci/BUILD.gn b/hci/BUILD.gn
new file mode 100644
index 0000000..c199ff0
--- /dev/null
+++ b/hci/BUILD.gn
@@ -0,0 +1,77 @@
+#
+#  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.
+#
+
+static_library("hci") {
+  sources = [
+    "src/btsnoop.c",
+    "src/btsnoop_mem.c",
+    "src/btsnoop_net.c",
+    "src/buffer_allocator.c",
+    "src/hci_audio.c",
+    "src/hci_hal.c",
+    "src/hci_hal_h4.c",
+    "src/hci_hal_mct.c",
+    "src/hci_inject.c",
+    "src/hci_layer.c",
+    "src/hci_packet_factory.c",
+    "src/hci_packet_parser.c",
+    "src/low_power_manager.c",
+    "src/packet_fragmenter.c",
+    "src/vendor.c",
+  ]
+
+  include_dirs = [
+    "include",
+    "//",
+    "//include",
+    "//btcore/include",
+    "//gki/common",
+    "//osi/include",
+    "//stack/include",
+  ]
+}
+
+executable("net_test_hci") {
+  testonly = true
+  sources = [
+    "//osi/test/AllocationTestHarness.cpp",
+    "//osi/test/AlarmTestHarness.cpp",
+    "test/hci_hal_h4_test.cpp",
+    "test/hci_hal_mct_test.cpp",
+    "test/hci_layer_test.cpp",
+    "test/low_power_manager_test.cpp",
+    "test/packet_fragmenter_test.cpp",
+  ]
+
+  include_dirs = [
+    "//",
+    "//include",
+    "//btcore/include",
+    "//hci/include",
+    "//osi/include",
+    "//osi/test",
+    "//stack/include",
+  ]
+
+  deps = [
+    "//hci",
+    "//osi",
+    "//btcore",
+    "//third_party/gtest:gtest_main",
+  ]
+
+  libs = [ "-lpthread", "-lrt", "-ldl" ]
+}
diff --git a/hci/src/btsnoop.c b/hci/src/btsnoop.c
index 990623e..b768f70 100644
--- a/hci/src/btsnoop.c
+++ b/hci/src/btsnoop.c
@@ -80,7 +80,7 @@
   return NULL;
 }
 
-const module_t btsnoop_module = {
+EXPORT_SYMBOL const module_t btsnoop_module = {
   .name = BTSNOOP_MODULE,
   .init = NULL,
   .start_up = start_up,
diff --git a/hci/src/btsnoop_net.c b/hci/src/btsnoop_net.c
index c601da8..173638d 100644
--- a/hci/src/btsnoop_net.c
+++ b/hci/src/btsnoop_net.c
@@ -27,6 +27,7 @@
 #include <sys/prctl.h>
 #include <sys/socket.h>
 #include <sys/types.h>
+#include <unistd.h>
 
 #include "osi/include/osi.h"
 #include "osi/include/log.h"
diff --git a/hci/src/hci_hal_h4.c b/hci/src/hci_hal_h4.c
index 836937d..fd3ad83 100644
--- a/hci/src/hci_hal_h4.c
+++ b/hci/src/hci_hal_h4.c
@@ -21,6 +21,7 @@
 #include <assert.h>
 #include <errno.h>
 #include <string.h>
+#include <unistd.h>
 
 #include "osi/include/eager_reader.h"
 #include "hci_hal.h"
diff --git a/hci/src/hci_hal_mct.c b/hci/src/hci_hal_mct.c
index 9b3707c..25fa53a 100644
--- a/hci/src/hci_hal_mct.c
+++ b/hci/src/hci_hal_mct.c
@@ -21,6 +21,7 @@
 #include <assert.h>
 #include <errno.h>
 #include <string.h>
+#include <unistd.h>
 
 #include "bt_vendor_lib.h"
 #include "osi/include/eager_reader.h"
diff --git a/hci/src/hci_layer.c b/hci/src/hci_layer.c
index 89d5cc9..62e3ad6 100644
--- a/hci/src/hci_layer.c
+++ b/hci/src/hci_layer.c
@@ -19,11 +19,19 @@
 #define LOG_TAG "bt_hci"
 
 #include <assert.h>
-#include <cutils/properties.h>
+#include <pthread.h>
 #include <string.h>
 #include <signal.h>
 #include <string.h>
 #include <sys/types.h>
+#include <unistd.h>
+
+// TODO(armansito): cutils/properties.h is only being used to pull-in runtime
+// settings on Android. Remove this conditional include once we have a generic
+// way to obtain system properties.
+#if !defined(OS_GENERIC)
+#include <cutils/properties.h>
+#endif  // !defined(OS_GENERIC)
 
 #include "buffer_allocator.h"
 #include "btsnoop.h"
@@ -175,12 +183,19 @@
 
   pthread_mutex_init(&commands_pending_response_lock, NULL);
 
+  // TODO(armansito): cutils/properties.h is only being used to pull-in runtime
+  // settings on Android. Remove this conditional include once we have a generic
+  // way to obtain system properties. For now, always use the default timeout on
+  // non-Android builds.
+  period_ms_t startup_timeout_ms = DEFAULT_STARTUP_TIMEOUT_MS;
+
+#if !defined(OS_GENERIC)
   // Grab the override startup timeout ms, if present.
-  period_ms_t startup_timeout_ms;
   char timeout_prop[PROPERTY_VALUE_MAX];
   if (!property_get("bluetooth.enable_timeout_ms", timeout_prop, STRING_VALUE_OF(DEFAULT_STARTUP_TIMEOUT_MS))
       || (startup_timeout_ms = atoi(timeout_prop)) < 100)
     startup_timeout_ms = DEFAULT_STARTUP_TIMEOUT_MS;
+#endif  // !defined(OS_GENERIC)
 
   startup_timer = non_repeating_timer_new(startup_timeout_ms, startup_timer_expired, NULL);
   if (!startup_timer) {
@@ -317,7 +332,7 @@
   return NULL;
 }
 
-const module_t hci_module = {
+EXPORT_SYMBOL const module_t hci_module = {
   .name = HCI_MODULE,
   .init = NULL,
   .start_up = start_up,
diff --git a/include/bt_target.h b/include/bt_target.h
index f712d2c..57ff43d 100644
--- a/include/bt_target.h
+++ b/include/bt_target.h
@@ -753,7 +753,7 @@
 
 
 #ifndef TIMER_PARAM_TYPE
-#define TIMER_PARAM_TYPE    UINT32
+#define TIMER_PARAM_TYPE void*
 #endif
 
 /******************************************************************************
diff --git a/main/BUILD.gn b/main/BUILD.gn
new file mode 100644
index 0000000..a80e31d
--- /dev/null
+++ b/main/BUILD.gn
@@ -0,0 +1,78 @@
+#
+#  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.
+#
+
+shared_library("bluetooth.default") {
+  # HAL layer
+  sources = [
+    "//btif/src/bluetooth.c",
+  ]
+
+  # platform specific
+  sources += [
+    "bte_main.c",
+    "bte_init.c",
+    "bte_logmsg.c",
+    "bte_conf.c",
+    "stack_config.c",
+  ]
+
+  include_dirs = [
+    "//",
+    "//bta/include",
+    "//bta/sys",
+    "//bta/dm",
+    "//btcore/include",
+    "//osi/include",
+    "//gki/common",
+    "//gki/ulinux",
+    "//include",
+    "//stack/include",
+    "//stack/l2cap",
+    "//stack/a2dp",
+    "//stack/btm",
+    "//stack/avdt",
+    "//hci",
+    "//hci/include",
+    "//udrv/include",
+    "//btif/include",
+    "//btif/co",
+    "//hci/includ",
+    "//vnd/include",
+    "//brcm/include",
+    "//embdrv/sbc/encoder/include",
+    "//embdrv/sbc/decoder/include",
+    "//audio_a2dp_hw",
+    "//utils/include",
+  ]
+
+  deps = [
+    "//audio_a2dp_hw:audio.a2dp.default",
+    "//bta",
+    "//btcore",
+    "//btif",
+    "//device",
+    "//embdrv/sbc",
+    "//gki",
+    "//hci",
+    "//osi",
+    "//stack",
+    "//third_party/tinyxml2",
+    "//udrv",
+    "//utils",
+  ]
+
+  libs = [ "-lpthread", "-lrt", "-ldl" ]
+}
diff --git a/main/bte_logmsg.c b/main/bte_logmsg.c
index 3258f47..e302cbe 100644
--- a/main/bte_logmsg.c
+++ b/main/bte_logmsg.c
@@ -59,10 +59,19 @@
 #include "smp_api.h"
 #endif
 
+// TODO(armansito): Work-around until we figure out a way to generate logs in a
+// platform-independent manner.
+#if defined(OS_GENERIC)
+#define LOGI0(t,s) fprintf(stderr, "%s\n", s)
+#define LOGD0(t,s) fprintf(stderr, "%s\n", s)
+#define LOGW0(t,s) fprintf(stderr, "%s\n", s)
+#define LOGE0(t,s) fprintf(stderr, "%s\n", s)
+#else  // !defined(OS_GENERIC)
 #define LOGI0(t,s) __android_log_write(ANDROID_LOG_INFO, t, s)
 #define LOGD0(t,s) __android_log_write(ANDROID_LOG_DEBUG, t, s)
 #define LOGW0(t,s) __android_log_write(ANDROID_LOG_WARN, t, s)
 #define LOGE0(t,s) __android_log_write(ANDROID_LOG_ERROR, t, s)
+#endif  // defined(OS_GENERIC)
 
 #ifndef DEFAULT_CONF_TRACE_LEVEL
 #define DEFAULT_CONF_TRACE_LEVEL BT_TRACE_LEVEL_WARNING
@@ -249,7 +258,7 @@
   return NULL;
 }
 
-const module_t bte_logmsg_module = {
+EXPORT_SYMBOL const module_t bte_logmsg_module = {
   .name = BTE_LOGMSG_MODULE,
   .init = init,
   .start_up = NULL,
diff --git a/main/bte_main.c b/main/bte_main.c
index d08d6f6..4f6c1b0 100644
--- a/main/bte_main.c
+++ b/main/bte_main.c
@@ -27,7 +27,6 @@
 #define LOG_TAG "bt_main"
 
 #include <assert.h>
-#include <cutils/properties.h>
 #include <fcntl.h>
 #include <hardware/bluetooth.h>
 #include <pthread.h>
diff --git a/main/stack_config.c b/main/stack_config.c
index 6e1431e..06e15d1 100644
--- a/main/stack_config.c
+++ b/main/stack_config.c
@@ -53,7 +53,7 @@
   return future_new_immediate(FUTURE_SUCCESS);
 }
 
-const module_t stack_config_module = {
+EXPORT_SYMBOL const module_t stack_config_module = {
   .name = STACK_CONFIG_MODULE,
   .init = init,
   .start_up = NULL,
diff --git a/osi/Android.mk b/osi/Android.mk
index 52dc2cf..ee55c5c 100644
--- a/osi/Android.mk
+++ b/osi/Android.mk
@@ -48,7 +48,7 @@
     ./src/socket.c \
     ./src/thread.c
 
-LOCAL_CFLAGS := -std=c99 -Wall -Werror -UNDEBUG
+LOCAL_CFLAGS := -std=c99 -Wall -Werror -UNDEBUG -fvisibility=hidden
 # Many .h files have redefined typedefs
 LOCAL_CLANG_CFLAGS += -Wno-error=typedef-redefinition
 LOCAL_MODULE := libosi
diff --git a/osi/BUILD.gn b/osi/BUILD.gn
new file mode 100644
index 0000000..3c12636
--- /dev/null
+++ b/osi/BUILD.gn
@@ -0,0 +1,76 @@
+#
+#  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.
+#
+
+static_library("osi") {
+  sources = [
+    "src/alarm.c",
+    "src/allocation_tracker.c",
+    "src/allocator.c",
+    "src/array.c",
+    "src/buffer.c",
+    "src/compat.c",
+    "src/config.c",
+    "src/data_dispatcher.c",
+    "src/eager_reader.c",
+    "src/fixed_queue.c",
+    "src/future.c",
+    "src/hash_functions.c",
+    "src/hash_map.c",
+    "src/list.c",
+    "src/non_repeating_timer.c",
+    "src/reactor.c",
+    "src/semaphore.c",
+    "src/socket.c",
+    "src/thread.c",
+  ]
+
+  include_dirs = [
+    "include",
+    "//"
+  ]
+}
+
+executable("net_test_osi") {
+  testonly = true
+  sources = [
+    "test/AlarmTestHarness.cpp",
+    "test/AllocationTestHarness.cpp",
+    "test/alarm_test.cpp",
+    "test/allocation_tracker_test.cpp",
+    "test/array_test.cpp",
+    "test/atomic_test.cpp",
+    "test/config_test.cpp",
+    "test/data_dispatcher_test.cpp",
+    "test/eager_reader_test.cpp",
+    "test/future_test.cpp",
+    "test/hash_map_test.cpp",
+    "test/list_test.cpp",
+    "test/reactor_test.cpp",
+    "test/thread_test.cpp",
+  ]
+
+  include_dirs = [
+    "include",
+    "//",
+  ]
+
+  deps = [
+    "//osi",
+    "//third_party/gtest:gtest_main",
+  ]
+
+  libs = [ "-lpthread", "-lrt" ]
+}
diff --git a/osi/include/log.h b/osi/include/log.h
index a5de1cf..4493ee9 100644
--- a/osi/include/log.h
+++ b/osi/include/log.h
@@ -18,6 +18,25 @@
 
 #pragma once
 
+/*
+ * TODO(armansito): Work-around until we figure out a way to generate logs in a
+ * platform-independent manner.
+ */
+#if defined(OS_GENERIC)
+
+/* syslog didn't work well here since we would be redefining LOG_DEBUG. */
+#include <stdio.h>
+
+#define LOGWRAPPER(fmt, args...) fprintf(stderr, fmt "\n", ## args)
+
+#define LOG_VERBOSE(...) LOGWRAPPER(__VA_ARGS__)
+#define LOG_DEBUG(...) LOGWRAPPER(__VA_ARGS__)
+#define LOG_INFO(...) LOGWRAPPER(__VA_ARGS__)
+#define LOG_WARN(...) LOGWRAPPER(__VA_ARGS__)
+#define LOG_ERROR(...) LOGWRAPPER(__VA_ARGS__)
+
+#else  /* !defined(OS_GENERIC) */
+
 #include <cutils/log.h>
 
 #define LOG_VERBOSE(...) ALOGV(__VA_ARGS__)
@@ -25,3 +44,6 @@
 #define LOG_INFO(...)    ALOGI(__VA_ARGS__)
 #define LOG_WARN(...)    ALOGW(__VA_ARGS__)
 #define LOG_ERROR(...)   ALOGE(__VA_ARGS__)
+
+
+#endif  /* defined(OS_GENERIC) */
diff --git a/osi/include/osi.h b/osi/include/osi.h
index c035bf8..673f4e8 100644
--- a/osi/include/osi.h
+++ b/osi/include/osi.h
@@ -20,3 +20,14 @@
 #define COMPILE_ASSERT(x) char * DUMMY_PTR = !(x)
 
 typedef uint32_t timeout_t;
+
+// Macros for safe integer to pointer conversion. In the C language, data is
+// commonly cast to opaque pointer containers and back for generic parameter
+// passing in callbacks. These macros should be used sparingly in new code
+// (never in C++ code). Whenever integers need to be passed as a pointer, use
+// these macros.
+#define PTR_TO_UINT(p) ((unsigned int) ((uintptr_t) (p)))
+#define UINT_TO_PTR(u) ((void *) ((uintptr_t) (u)))
+
+#define PTR_TO_INT(p) ((int) ((intptr_t) (p)))
+#define INT_TO_PTR(i) ((void *) ((intptr_t) (i)))
diff --git a/osi/src/alarm.c b/osi/src/alarm.c
index a9cd4dd..5139167 100644
--- a/osi/src/alarm.c
+++ b/osi/src/alarm.c
@@ -26,6 +26,7 @@
 #include <string.h>
 #include <signal.h>
 #include <time.h>
+#include <pthread.h>
 
 #include "osi/include/alarm.h"
 #include "osi/include/allocator.h"
@@ -42,7 +43,7 @@
   // a guarantee to its caller that the callback will not be in progress when it
   // returns.
   pthread_mutex_t callback_lock;
-  period_ms_t created;
+  period_ms_t creation_time;
   period_ms_t period;
   period_ms_t deadline;
   bool is_periodic;
@@ -143,7 +144,7 @@
 
   pthread_mutex_lock(&monitor);
 
-  alarm->created = now();
+  alarm->creation_time = now();
   alarm->is_periodic = is_periodic;
   alarm->period = period;
   alarm->callback = cb;
@@ -255,7 +256,7 @@
 
   // Calculate the next deadline for this alarm
   period_ms_t just_now = now();
-  period_ms_t ms_into_period = alarm->is_periodic ? ((just_now - alarm->created) % alarm->period) : 0;
+  period_ms_t ms_into_period = alarm->is_periodic ? ((just_now - alarm->creation_time) % alarm->period) : 0;
   alarm->deadline = just_now + (alarm->period - ms_into_period);
 
   // Add it into the timer list sorted by deadline (earliest deadline first).
diff --git a/osi/src/config.c b/osi/src/config.c
index 11a5baf..46acab0 100644
--- a/osi/src/config.c
+++ b/osi/src/config.c
@@ -24,6 +24,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 #include <sys/stat.h>
 
 #include "osi/include/allocator.h"
diff --git a/osi/src/eager_reader.c b/osi/src/eager_reader.c
index 63b190e..6f6fe86 100644
--- a/osi/src/eager_reader.c
+++ b/osi/src/eager_reader.c
@@ -22,6 +22,7 @@
 #include <errno.h>
 #include <stddef.h>
 #include <string.h>
+#include <unistd.h>
 #include <sys/eventfd.h>
 
 #include "osi/include/allocator.h"
diff --git a/osi/src/reactor.c b/osi/src/reactor.c
index 08b5098..68b0984 100644
--- a/osi/src/reactor.c
+++ b/osi/src/reactor.c
@@ -25,6 +25,7 @@
 #include <string.h>
 #include <sys/epoll.h>
 #include <sys/eventfd.h>
+#include <unistd.h>
 
 #include "osi/include/allocator.h"
 #include "osi/include/list.h"
diff --git a/osi/src/semaphore.c b/osi/src/semaphore.c
index 5ee9926..c9b117d 100644
--- a/osi/src/semaphore.c
+++ b/osi/src/semaphore.c
@@ -24,6 +24,7 @@
 #include <malloc.h>
 #include <string.h>
 #include <sys/eventfd.h>
+#include <unistd.h>
 
 #include "osi/include/allocator.h"
 #include "osi/include/osi.h"
diff --git a/profile/src/manager.c b/profile/src/manager.c
index 9e56b65..6e3d45c 100644
--- a/profile/src/manager.c
+++ b/profile/src/manager.c
@@ -57,7 +57,7 @@
   return NULL;
 }
 
-const module_t profile_manager_module = {
+EXPORT_SYMBOL const module_t profile_manager_module = {
   .name = PROFILE_MANAGER_MODULE,
   .init = init,
   .start_up = NULL,
diff --git a/service/Android.mk b/service/Android.mk
new file mode 100644
index 0000000..f450840
--- /dev/null
+++ b/service/Android.mk
@@ -0,0 +1,59 @@
+#
+#  Copyright (C) 2015 Google
+#
+#  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.
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+BASE_SRC := \
+	base/base64.cpp \
+	base/string_split.cpp \
+	base/string_number_conversions.cpp \
+	modp_b64/modp_b64.cpp
+
+CORE_SRC := \
+	a2dp_source.cpp \
+	logging_helpers.cpp \
+	core_stack.cpp \
+	uuid.cpp \
+	gatt_server.cpp
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := uuid_test.cpp uuid.cpp
+LOCAL_CFLAGS += -std=c++11
+LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE := uuid_test_bd
+include $(BUILD_HOST_NATIVE_TEST)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+    $(BASE_SRC) \
+    $(CORE_SRC) \
+    host.cpp \
+    main.cpp
+
+LOCAL_C_INCLUDES += \
+        $(LOCAL_PATH)/../
+
+LOCAL_CFLAGS += -std=c++11
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := bthost
+LOCAL_REQUIRED_MODULES = bluetooth.default
+LOCAL_SHARED_LIBRARIES += \
+    libhardware \
+    libcutils \
+    liblog
+
+include $(BUILD_EXECUTABLE)
diff --git a/service/a2dp_source.cpp b/service/a2dp_source.cpp
new file mode 100644
index 0000000..6cde92a
--- /dev/null
+++ b/service/a2dp_source.cpp
@@ -0,0 +1,82 @@
+//
+//  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 "a2dp_source.h"
+
+#define LOG_TAG "A2dpSource"
+#include "osi/include/log.h"
+
+#include "core_stack.h"
+#include "logging_helpers.h"
+#include "osi/include/osi.h"
+
+namespace {
+
+void ConnectionStateCallback(btav_connection_state_t state,
+                             UNUSED_ATTR bt_bdaddr_t *bd_addr) {
+  LOG_INFO("%s: %s", __func__, BtAvConnectionStateText(state));
+}
+
+void AudioStateCallback(btav_audio_state_t state,
+                        UNUSED_ATTR bt_bdaddr_t *bd_addr) {
+  LOG_INFO("%s: %s", __func__, BtAvAudioStateText(state));
+}
+
+void AudioConfigCallback(UNUSED_ATTR bt_bdaddr_t *bd_addr,
+                         UNUSED_ATTR uint32_t sample_rate,
+                         UNUSED_ATTR uint8_t channel_count) {
+  // I think these are used for audio sink only?
+  // TODO(icoolidge): revisit.
+}
+
+btav_callbacks_t av_callbacks = {
+    sizeof(btav_callbacks_t), ConnectionStateCallback, AudioStateCallback,
+    AudioConfigCallback,
+};
+
+}  // namespace
+
+namespace bluetooth {
+
+A2dpSource::A2dpSource(CoreStack *bt) : av_(nullptr), bt_(bt) {
+  // TODO(icoolidge): DCHECK(bt);
+}
+
+int A2dpSource::Start() {
+  // Get the interface to the a2dp source profile.
+  const void *interface = bt_->GetInterface(BT_PROFILE_ADVANCED_AUDIO_ID);
+  if (!interface) {
+    LOG_ERROR("Error getting audio source interface");
+    return -1;
+  }
+
+  av_ = reinterpret_cast<const btav_interface_t *>(interface);
+
+  bt_status_t btstat = av_->init(&av_callbacks);
+  if (btstat != BT_STATUS_SUCCESS && btstat != BT_STATUS_DONE) {
+    LOG_ERROR("Failed to initialize audio source interface: %s %d",
+              BtStatusText(btstat), btstat);
+    return -1;
+  }
+  return 0;
+}
+
+int A2dpSource::Stop() {
+  // TODO(icoolidge): DCHECK(av_);
+  av_->cleanup();
+  return 0;
+}
+
+}  // namespace bluetooth
diff --git a/service/a2dp_source.h b/service/a2dp_source.h
new file mode 100644
index 0000000..557b98f
--- /dev/null
+++ b/service/a2dp_source.h
@@ -0,0 +1,44 @@
+//
+//  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 "hardware/bt_av.h"
+
+namespace bluetooth {
+
+class CoreStack;
+
+// This class is just experimental to test out BlueDroid A2DP
+// interface, capability, and functionality.
+class A2dpSource {
+ public:
+  explicit A2dpSource(CoreStack* bt);
+
+  // Enables the A2DP source profile in the stack.
+  // Creates audio Unix sockets. (see audio_a2dp_hw.h)
+  int Start();
+
+  // Disables the A2DP source profile in the stack.
+  int Stop();
+
+ private:
+  const btav_interface_t* av_;
+  // Weak reference.
+  CoreStack* bt_;
+};
+
+}  // namespace bluetooth
diff --git a/service/base/base64.cpp b/service/base/base64.cpp
new file mode 100644
index 0000000..704d678
--- /dev/null
+++ b/service/base/base64.cpp
@@ -0,0 +1,37 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/base64.h"
+
+#include "modp_b64/modp_b64.h"
+
+namespace base {
+
+void Base64Encode(const std::string& input, std::string* output) {
+  std::string temp;
+  temp.resize(modp_b64_encode_len(input.size()));  // makes room for null byte
+
+  // modp_b64_encode_len() returns at least 1, so temp[0] is safe to use.
+  size_t output_size = modp_b64_encode(&(temp[0]), input.data(), input.size());
+
+  temp.resize(output_size);  // strips off null byte
+  output->swap(temp);
+}
+
+bool Base64Decode(const std::string& input, std::string* output) {
+  std::string temp;
+  temp.resize(modp_b64_decode_len(input.size()));
+
+  // does not null terminate result since result is binary data!
+  size_t input_size = input.size();
+  size_t output_size = modp_b64_decode(&(temp[0]), input.data(), input_size);
+  if (output_size == MODP_B64_ERROR)
+    return false;
+
+  temp.resize(output_size);
+  output->swap(temp);
+  return true;
+}
+
+}  // namespace base
diff --git a/service/base/base64.h b/service/base/base64.h
new file mode 100644
index 0000000..38923af
--- /dev/null
+++ b/service/base/base64.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_BASE64_H__
+#define BASE_BASE64_H__
+
+#include <string>
+
+namespace base {
+
+// Encodes the input string in base64. The encoding can be done in-place.
+void Base64Encode(const std::string& input, std::string* output);
+
+// Decodes the base64 input string.  Returns true if successful and false
+// otherwise. The output string is only modified if successful. The decoding can
+// be done in-place.
+bool Base64Decode(const std::string& input, std::string* output);
+
+}  // namespace base
+
+#endif  // BASE_BASE64_H__
diff --git a/service/base/string_number_conversions.cpp b/service/base/string_number_conversions.cpp
new file mode 100644
index 0000000..62c3d48
--- /dev/null
+++ b/service/base/string_number_conversions.cpp
@@ -0,0 +1,87 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/string_number_conversions.h"
+
+#include <stdlib.h>
+
+#include <limits>
+
+namespace base {
+
+// Utility to convert a character to a digit in a given base
+template<typename CHAR, int BASE, bool BASE_LTE_10> class BaseCharToDigit {
+};
+
+// Faster specialization for bases <= 10
+template<typename CHAR, int BASE> class BaseCharToDigit<CHAR, BASE, true> {
+ public:
+  static bool Convert(CHAR c, uint8_t* digit) {
+    if (c >= '0' && c < '0' + BASE) {
+      *digit = static_cast<uint8_t>(c - '0');
+      return true;
+    }
+    return false;
+  }
+};
+
+// Specialization for bases where 10 < base <= 36
+template<typename CHAR, int BASE> class BaseCharToDigit<CHAR, BASE, false> {
+ public:
+  static bool Convert(CHAR c, uint8_t* digit) {
+    if (c >= '0' && c <= '9') {
+      *digit = c - '0';
+    } else if (c >= 'a' && c < 'a' + BASE - 10) {
+      *digit = c - 'a' + 10;
+    } else if (c >= 'A' && c < 'A' + BASE - 10) {
+      *digit = c - 'A' + 10;
+    } else {
+      return false;
+    }
+    return true;
+  }
+};
+
+template<int BASE, typename CHAR> bool CharToDigit(CHAR c, uint8_t* digit) {
+  return BaseCharToDigit<CHAR, BASE, BASE <= 10>::Convert(c, digit);
+}
+
+template<typename STR>
+bool HexStringToBytesT(const STR& input, std::vector<uint8_t>* output) {
+  output->clear();
+  size_t count = input.size();
+  if (count == 0 || (count % 2) != 0)
+    return false;
+  for (uintptr_t i = 0; i < count / 2; ++i) {
+    uint8_t msb = 0;  // most significant 4 bits
+    uint8_t lsb = 0;  // least significant 4 bits
+    if (!CharToDigit<16>(input[i * 2], &msb) ||
+        !CharToDigit<16>(input[i * 2 + 1], &lsb))
+      return false;
+    output->push_back((msb << 4) | lsb);
+  }
+  return true;
+}
+
+
+std::string HexEncode(const void* bytes, size_t size) {
+  static const char kHexChars[] = "0123456789ABCDEF";
+
+  // Each input byte creates two output hex characters.
+  std::string ret(size * 2, '\0');
+
+  for (size_t i = 0; i < size; ++i) {
+    char b = reinterpret_cast<const char*>(bytes)[i];
+    ret[(i * 2)] = kHexChars[(b >> 4) & 0xf];
+    ret[(i * 2) + 1] = kHexChars[b & 0xf];
+  }
+  return ret;
+}
+
+
+bool HexStringToBytes(const std::string& input, std::vector<uint8_t>* output) {
+  return HexStringToBytesT(input, output);
+}
+
+}  // namespace base
diff --git a/service/base/string_number_conversions.h b/service/base/string_number_conversions.h
new file mode 100644
index 0000000..7d1d737
--- /dev/null
+++ b/service/base/string_number_conversions.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_STRINGS_STRING_NUMBER_CONVERSIONS_H_
+#define BASE_STRINGS_STRING_NUMBER_CONVERSIONS_H_
+
+#include <string>
+#include <vector>
+
+namespace base {
+
+// Hex encoding ----------------------------------------------------------------
+
+// Returns a hex string representation of a binary buffer. The returned hex
+// string will be in upper case. This function does not check if |size| is
+// within reasonable limits since it's written with trusted data in mind.  If
+// you suspect that the data you want to format might be large, the absolute
+// max size for |size| should be is
+//   std::numeric_limits<size_t>::max() / 2
+std::string HexEncode(const void* bytes, size_t size);
+
+// Similar to the previous functions, except that output is a vector of bytes.
+// |*output| will contain as many bytes as were successfully parsed prior to the
+// error.  There is no overflow, but input.size() must be evenly divisible by 2.
+// Leading 0x or +/- are not allowed.
+bool HexStringToBytes(const std::string& input,
+                      std::vector<uint8_t>* output);
+
+}  // namespace base
+
+#endif  // BASE_STRINGS_STRING_NUMBER_CONVERSIONS_H_
diff --git a/service/base/string_split.cpp b/service/base/string_split.cpp
new file mode 100644
index 0000000..670f2e4
--- /dev/null
+++ b/service/base/string_split.cpp
@@ -0,0 +1,36 @@
+//
+//  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 "string_split.h"
+
+namespace base {
+
+std::vector<std::string> SplitString(const std::string& input, char delimiter) {
+  std::vector<std::string> output;
+  size_t token_start = 0;
+  for (size_t i = 0; i <= input.size(); ++i) {
+    // Token is the whole string if no delimiter found.
+    if (i == input.size() || input[i] == delimiter) {
+      size_t token_length = i - token_start;
+      // Qualified tokens: substring, end text after token, non-empty whole input.
+      if (i != input.size() || !output.empty() || token_length)
+        output.emplace_back(input, token_start, token_length);
+      token_start = i + 1;
+    }
+  }
+  return output;
+}
+
+}  // namespace base
diff --git a/service/base/string_split.h b/service/base/string_split.h
new file mode 100644
index 0000000..ee1a13f
--- /dev/null
+++ b/service/base/string_split.h
@@ -0,0 +1,25 @@
+//
+//  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 <string>
+#include <vector>
+
+namespace base {
+
+std::vector<std::string> SplitString(const std::string& input, char delimiter);
+
+}  // namespace base
diff --git a/service/core_stack.cpp b/service/core_stack.cpp
new file mode 100644
index 0000000..d40d64b
--- /dev/null
+++ b/service/core_stack.cpp
@@ -0,0 +1,287 @@
+//
+//  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 "core_stack.h"
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <condition_variable>
+#include <mutex>
+#include <string>
+
+#define LOG_TAG "BluetoothBase"
+#include "osi/include/log.h"
+
+#include "hardware/bluetooth.h"
+#include "hardware/hardware.h"
+#include "logging_helpers.h"
+#include "osi/include/osi.h"
+
+namespace {
+
+std::mutex mutex;
+std::condition_variable synchronize;
+bool instantiated = false;
+
+void AdapterStateChangedCallback(bt_state_t state) {
+  LOG_INFO("Bluetooth state:%s", BtStateText(state));
+  if (state == BT_STATE_ON)
+    synchronize.notify_one();
+}
+
+void CallbackThreadCallback(bt_cb_thread_evt evt) {
+  LOG_INFO("%s: %s", __func__, BtEventText(evt));
+}
+
+// TODO(icoolidge): Audit how these os callouts should be
+// implemented (or nulled) for systems w/out wakelocks.
+bool SetWakeAlarmCallback(uint64_t delay_millis,
+                          UNUSED_ATTR bool should_wake,
+                          alarm_cb cb,
+                          void *data) {
+  static timer_t timer;
+  static bool timer_created;
+
+  if (!timer_created) {
+    struct sigevent sigevent;
+    memset(&sigevent, 0, sizeof(sigevent));
+    sigevent.sigev_notify = SIGEV_THREAD;
+    sigevent.sigev_notify_function = (void (*)(union sigval))cb;
+    sigevent.sigev_value.sival_ptr = data;
+    timer_create(CLOCK_MONOTONIC, &sigevent, &timer);
+    timer_created = true;
+  }
+
+  struct itimerspec new_value;
+  new_value.it_value.tv_sec = delay_millis / 1000;
+  new_value.it_value.tv_nsec = (delay_millis % 1000) * 1000 * 1000;
+  new_value.it_interval.tv_sec = 0;
+  new_value.it_interval.tv_nsec = 0;
+  timer_settime(timer, 0, &new_value, nullptr);
+
+  return true;
+}
+
+// Dummy implementation due to no wakelocks.
+int AcquireWakeLock(UNUSED_ATTR const char *lock_name) {
+  return BT_STATUS_SUCCESS;
+}
+
+// Dummy implementation due to no wakelocks.
+int ReleaseWakeLock(UNUSED_ATTR const char *lock_name) {
+  return BT_STATUS_SUCCESS;
+}
+
+void GenericDevicePropertiesCallback(bt_status_t status,
+                                     bt_bdaddr_t *remote_address,
+                                     int num_properties,
+                                     bt_property_t *properties) {
+  if (status != BT_STATUS_SUCCESS) {
+    LOG_ERROR("%s: %s", __func__, BtStatusText(status));
+    return;
+  }
+
+  if (!remote_address) {
+    LOG_INFO("Local adapter properties:");
+  }
+
+  for (int i = 0; i < num_properties; ++i) {
+    bt_property_t *prop = &properties[i];
+    switch (prop->type) {
+      case BT_PROPERTY_BDADDR: {
+        std::string text =
+            BtAddrString(reinterpret_cast<bt_bdaddr_t *>(prop->val));
+        LOG_INFO("%s: %s", BtPropertyText(prop->type), text.c_str());
+        break;
+      }
+      case BT_PROPERTY_ADAPTER_SCAN_MODE: {
+        bt_scan_mode_t *mode = reinterpret_cast<bt_scan_mode_t *>(prop->val);
+        LOG_INFO("%s: %s", BtPropertyText(prop->type), BtScanModeText(*mode));
+        std::lock_guard<std::mutex> lock(mutex);
+        synchronize.notify_one();
+        break;
+      }
+      case BT_PROPERTY_BDNAME: {
+        bt_bdname_t *name = reinterpret_cast<bt_bdname_t *>(prop->val);
+        LOG_INFO("%s: %s", BtPropertyText(prop->type),
+                 reinterpret_cast<char *>(name->name));
+        std::lock_guard<std::mutex> lock(mutex);
+        synchronize.notify_one();
+        break;
+      }
+      default:
+        LOG_INFO("%s: %s", __func__, BtPropertyText(prop->type));
+        break;
+    }
+  }
+}
+
+void AclStateChangedCallback(bt_status_t status, bt_bdaddr_t *remote_bd_addr,
+                             bt_acl_state_t state) {
+  if (status != BT_STATUS_SUCCESS) {
+    LOG_ERROR("%s: %s", __func__, BtStatusText(status));
+    return;
+  }
+
+  std::string text = BtAddrString(remote_bd_addr);
+  LOG_INFO("%s: %s: %s", __func__, text.c_str(), BtAclText(state));
+}
+
+void LocalAdapterPropertiesCallback(bt_status_t status, int num_properties,
+                                    bt_property_t *properties) {
+  GenericDevicePropertiesCallback(status, nullptr, num_properties, properties);
+}
+
+bt_callbacks_t bt_callbacks = {
+  sizeof(bt_callbacks_t),
+  AdapterStateChangedCallback,
+  LocalAdapterPropertiesCallback,
+  GenericDevicePropertiesCallback,
+  nullptr, /* device_found_cb */
+  nullptr, /* discovery_state_changed_cb */
+  nullptr, /* pin_request_cb  */
+  nullptr, /* ssp_request_cb  */
+  nullptr, /* bond_state_changed_cb */
+  AclStateChangedCallback,
+  CallbackThreadCallback,
+  nullptr, /* dut_mode_recv_cb */
+  nullptr, /* le_test_mode_cb */
+  nullptr  /* energy_info_cb */
+};
+
+bt_os_callouts_t callouts = {
+  sizeof(bt_os_callouts_t),
+  SetWakeAlarmCallback,
+  AcquireWakeLock,
+  ReleaseWakeLock
+};
+
+}  // namespace
+
+namespace bluetooth {
+
+CoreStack::CoreStack() : adapter_(nullptr), hal_(nullptr) {
+  std::lock_guard<std::mutex> lock(mutex);
+  // TODO(icoolidge): DCHECK(!instantiated);
+  instantiated = true;
+}
+
+bool CoreStack::Initialize() {
+  std::unique_lock<std::mutex> lock(mutex);
+
+  // Load the bluetooth module.
+  const hw_module_t *module;
+  int status = hw_get_module(BT_HARDWARE_MODULE_ID, &module);
+  if (status) {
+    LOG_ERROR("Error getting bluetooth module");
+    return false;
+  }
+
+  // Open the bluetooth device.
+  hw_device_t *device;
+  status = module->methods->open(module, BT_HARDWARE_MODULE_ID, &device);
+  if (status) {
+    LOG_ERROR("Error opening bluetooth module");
+    return false;
+  }
+
+  // TODO(icoolidge): Audit initialization and teardown.
+  adapter_ = reinterpret_cast<bluetooth_device_t *>(device);
+  hal_ = adapter_->get_bluetooth_interface();
+
+  // Bind module callbacks to local handlers.
+  status = hal_->init(&bt_callbacks);
+  if (status != BT_STATUS_SUCCESS) {
+    LOG_ERROR("Error binding callbacks");
+    return false;
+  }
+
+  status = hal_->set_os_callouts(&callouts);
+  if (status != BT_STATUS_SUCCESS) {
+    LOG_ERROR("Error binding OS callbacks");
+    return false;
+  }
+
+  status = hal_->enable();
+  if (status) {
+    LOG_ERROR("Enable failed: %d", status);
+    return false;
+  }
+
+  synchronize.wait(lock);
+  LOG_INFO("CoreStack::Initialize success");
+  return true;
+}
+
+bool CoreStack::SetAdapterName(const std::string &name) {
+  bt_bdname_t n;
+  snprintf(reinterpret_cast<char *>(n.name), sizeof(n.name), "%s",
+           name.c_str());
+  bt_property_t prop;
+  prop.len = sizeof(n);
+  prop.val = &n;
+  prop.type = BT_PROPERTY_BDNAME;
+
+  std::unique_lock<std::mutex> lock(mutex);
+
+  int status = hal_->set_adapter_property(&prop);
+  if (status) {
+    LOG_ERROR("%s: prop change failed: %d", __func__, status);
+    return false;
+  }
+
+  synchronize.wait(lock);
+  return true;
+}
+
+bool CoreStack::SetClassicDiscoverable() {
+  bt_scan_mode_t mode = BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
+  bt_property_t disc;
+  disc.len = sizeof(mode);
+  disc.val = &mode;
+  disc.type = BT_PROPERTY_ADAPTER_SCAN_MODE;
+
+  std::unique_lock<std::mutex> lock(mutex);
+
+  int status = hal_->set_adapter_property(&disc);
+  if (status) {
+    LOG_ERROR("Prop change failed: %d", status);
+    return false;
+  }
+
+  synchronize.wait(lock);
+  return true;
+}
+
+const void *CoreStack::GetInterface(const char *profile) {
+  std::unique_lock<std::mutex> lock(mutex);
+  // Get the interface to the GATT profile.
+  const void *interface = hal_->get_profile_interface(profile);
+  if (!interface) {
+    LOG_ERROR("Error getting %s interface", profile);
+    return nullptr;
+  }
+  return interface;
+}
+
+CoreStack::~CoreStack() {
+  // TODO(icoolidge): Disable bluetooth hardware, clean up library state.
+  std::lock_guard<std::mutex> lock(mutex);
+  instantiated = false;
+}
+
+}  // namespace bluetooth
diff --git a/service/core_stack.h b/service/core_stack.h
new file mode 100644
index 0000000..8b5671a
--- /dev/null
+++ b/service/core_stack.h
@@ -0,0 +1,57 @@
+//
+//  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 <string>
+
+#include "hardware/bluetooth.h"
+
+namespace bluetooth {
+
+// This represents the core Bluetooth stack,
+// with high level operations that affect many profiles.
+// It is also used to access profile interfaces.
+class CoreStack {
+ public:
+  CoreStack();
+  ~CoreStack();
+
+  // Initialize the bluetooth stack and device.
+  bool Initialize();
+
+  // Set the device name.
+  // This can be referenced in BLE GAP advertisements.
+  bool SetAdapterName(const std::string& name);
+
+  // Allow activated classic profiles to be discovered.
+  bool SetClassicDiscoverable();
+
+  // Get an interface for a profile (BLE GATT, A2DP, etc).
+  const void *GetInterface(const char* profile);
+
+ private:
+  // Prevent copy and assignment.
+  CoreStack& operator=(const CoreStack& rhs) = delete;
+  CoreStack(const CoreStack& rhs) = delete;
+
+  // Our libhardware handle.
+  bluetooth_device_t *adapter_;
+
+  // Common bluetooth interface handle.
+  const bt_interface_t *hal_;
+};
+
+}  // namespace bluetooth
diff --git a/service/gatt_server.cpp b/service/gatt_server.cpp
new file mode 100644
index 0000000..54e407e
--- /dev/null
+++ b/service/gatt_server.cpp
@@ -0,0 +1,704 @@
+//
+//  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 "gatt_server.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <array>
+#include <condition_variable>
+#include <map>
+#include <memory>
+#include <mutex>
+#include <set>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#define LOG_TAG "GattServer"
+#include "osi/include/log.h"
+
+#include "core_stack.h"
+#include "hardware/bluetooth.h"
+#include "hardware/bt_gatt.h"
+#include "logging_helpers.h"
+#include "osi/include/osi.h"
+#include "uuid.h"
+
+namespace {
+
+const size_t kMaxGattAttributeSize = 512;
+// TODO(icoolidge): Difficult to generalize without knowing how many attributes.
+const int kNumBlueDroidHandles = 60;
+
+// TODO(icoolidge): Support multiple instances
+static bluetooth::gatt::ServerInternals *internal = nullptr;
+
+enum { kPipeReadEnd = 0, kPipeWriteEnd = 1, kPipeNumEnds = 2 };
+
+}  // namespace
+
+namespace bluetooth {
+namespace gatt {
+
+struct Characteristic {
+  Uuid uuid;
+  int blob_section;
+  std::vector<uint8_t> blob;
+
+  // Support synchronized blob updates by latching under mutex.
+  std::vector<uint8_t> next_blob;
+  bool next_blob_pending;
+  bool notify;
+};
+
+struct ServerInternals {
+  ServerInternals();
+  ~ServerInternals();
+  int Initialize(CoreStack *bt);
+
+  // This maps API attribute UUIDs to BlueDroid handles.
+  std::map<Uuid, int> uuid_to_attribute;
+
+  // The attribute cache, indexed by BlueDroid handles.
+  std::unordered_map<int, Characteristic> characteristics;
+
+  // Associate a control attribute with its value attribute.
+  std::unordered_map<int, int> controlled_blobs;
+
+  ScanResults scan_results;
+
+  Uuid last_write;
+  const btgatt_interface_t *gatt;
+  int server_if;
+  int client_if;
+  int service_handle;
+  btgatt_srvc_id_t service_id;
+  std::set<int> connections;
+
+  std::mutex lock;
+  std::condition_variable api_synchronize;
+  int pipefd[kPipeNumEnds];
+};
+
+}  // namespace gatt
+}  // namespace bluetooth
+
+namespace {
+
+/** Callback invoked in response to register_server */
+void RegisterServerCallback(int status, int server_if, bt_uuid_t *app_uuid) {
+  LOG_INFO("%s: status:%d server_if:%d app_uuid:%p", __func__, status,
+           server_if, app_uuid);
+
+  internal->server_if = server_if;
+
+  btgatt_srvc_id_t service_id;
+  service_id.id.uuid = *app_uuid;
+  service_id.id.inst_id = 0;
+  service_id.is_primary = true;
+
+  bt_status_t btstat = internal->gatt->server->add_service(
+      server_if, &service_id, kNumBlueDroidHandles);
+}
+
+void ServiceAddedCallback(int status, int server_if, btgatt_srvc_id_t *srvc_id,
+                          int srvc_handle) {
+  LOG_INFO("%s: status:%d server_if:%d gatt_srvc_id:%u srvc_handle:%d",
+           __func__, status, server_if, srvc_id->id.inst_id, srvc_handle);
+
+  std::lock_guard<std::mutex> lock(internal->lock);
+  internal->server_if = server_if;
+  internal->service_handle = srvc_handle;
+  internal->service_id = *srvc_id;
+  // This finishes the Initialize call.
+  internal->api_synchronize.notify_one();
+}
+
+void RequestReadCallback(int conn_id, int trans_id, bt_bdaddr_t *bda,
+                         int attr_handle, int attribute_offset_octets,
+                         bool is_long) {
+  std::lock_guard<std::mutex> lock(internal->lock);
+
+  bluetooth::gatt::Characteristic &ch = internal->characteristics[attr_handle];
+
+  // Latch next_blob to blob on a 'fresh' read.
+  if (ch.next_blob_pending && attribute_offset_octets == 0 &&
+      ch.blob_section == 0) {
+    std::swap(ch.blob, ch.next_blob);
+    ch.next_blob_pending = false;
+  }
+
+  const size_t blob_offset_octets =
+      std::min(ch.blob.size(), ch.blob_section * kMaxGattAttributeSize);
+  const size_t blob_remaining = ch.blob.size() - blob_offset_octets;
+  const size_t attribute_size = std::min(kMaxGattAttributeSize, blob_remaining);
+
+  std::string addr(BtAddrString(bda));
+  LOG_INFO(
+      "%s: connection:%d (%s) reading attr:%d attribute_offset_octets:%d "
+      "blob_section:%u (is_long:%u)",
+      __func__, conn_id, addr.c_str(), attr_handle, attribute_offset_octets,
+      ch.blob_section, is_long);
+
+  btgatt_response_t response;
+  response.attr_value.len = 0;
+
+  if (attribute_offset_octets < static_cast<int>(attribute_size)) {
+    std::copy(ch.blob.begin() + blob_offset_octets + attribute_offset_octets,
+              ch.blob.begin() + blob_offset_octets + attribute_size,
+              response.attr_value.value);
+    response.attr_value.len = attribute_size - attribute_offset_octets;
+  }
+
+  response.attr_value.handle = attr_handle;
+  response.attr_value.offset = attribute_offset_octets;
+  response.attr_value.auth_req = 0;
+  internal->gatt->server->send_response(conn_id, trans_id, 0, &response);
+}
+
+void RequestWriteCallback(int conn_id, int trans_id, bt_bdaddr_t *bda,
+                          int attr_handle, int attribute_offset, int length,
+                          bool need_rsp, bool is_prep, uint8_t *value) {
+  std::string addr(BtAddrString(bda));
+  LOG_INFO(
+      "%s: connection:%d (%s:trans:%d) write attr:%d attribute_offset:%d "
+      "length:%d "
+      "need_resp:%u is_prep:%u",
+      __func__, conn_id, addr.c_str(), trans_id, attr_handle, attribute_offset,
+      length, need_rsp, is_prep);
+
+  std::lock_guard<std::mutex> lock(internal->lock);
+
+  bluetooth::gatt::Characteristic &ch = internal->characteristics[attr_handle];
+
+  ch.blob.resize(attribute_offset + length);
+
+  std::copy(value, value + length, ch.blob.begin() + attribute_offset);
+
+  auto target_blob = internal->controlled_blobs.find(attr_handle);
+  // If this is a control attribute, adjust offset of the target blob.
+  if (target_blob != internal->controlled_blobs.end() && ch.blob.size() == 1u) {
+    internal->characteristics[target_blob->second].blob_section = ch.blob[0];
+    LOG_INFO("%s: updating attribute %d blob_section to %u", __func__,
+             target_blob->second, ch.blob[0]);
+  } else if (!is_prep) {
+    // This is a single frame characteristic write.
+    // Notify upwards because we're done now.
+    const bluetooth::Uuid::Uuid128Bit &attr_uuid = ch.uuid.GetFullBigEndian();
+    int status = write(internal->pipefd[kPipeWriteEnd], attr_uuid.data(),
+                       attr_uuid.size());
+    if (-1 == status)
+      LOG_ERROR("%s: write failed: %s", __func__, strerror(errno));
+  } else {
+    // This is a multi-frame characteristic write.
+    // Wait for an 'RequestExecWriteCallback' to notify completion.
+    internal->last_write = ch.uuid;
+  }
+
+  // Respond only if needed.
+  if (!need_rsp) return;
+
+  btgatt_response_t response;
+  response.attr_value.handle = attr_handle;
+  response.attr_value.offset = attribute_offset;
+  response.attr_value.len = length;
+  response.attr_value.auth_req = 0;
+  internal->gatt->server->send_response(conn_id, trans_id, 0, &response);
+}
+
+void RequestExecWriteCallback(int conn_id, int trans_id, bt_bdaddr_t *bda,
+                              int exec_write) {
+  std::string addr(BtAddrString(bda));
+  LOG_INFO("%s: connection:%d (%s:trans:%d) exec_write:%d", __func__, conn_id,
+           addr.c_str(), trans_id, exec_write);
+
+  if (!exec_write)
+    return;
+
+  std::lock_guard<std::mutex> lock(internal->lock);
+  // Communicate the attribute UUID as notification of a write update.
+  const bluetooth::Uuid::Uuid128Bit uuid =
+      internal->last_write.GetFullBigEndian();
+  int status = write(internal->pipefd[kPipeWriteEnd], uuid.data(), uuid.size());
+  if (-1 == status)
+    LOG_ERROR("%s: write failed: %s", __func__, strerror(errno));
+}
+
+void ConnectionCallback(int conn_id, int server_if, int connected,
+                        bt_bdaddr_t *bda) {
+  std::string addr(BtAddrString(bda));
+  LOG_INFO("%s: connection:%d server_if:%d connected:%d addr:%s", __func__,
+           conn_id, server_if, connected, addr.c_str());
+  if (connected == 1) {
+    internal->connections.insert(conn_id);
+  } else if (connected == 0) {
+    internal->connections.erase(conn_id);
+  }
+}
+
+void CharacteristicAddedCallback(int status, int server_if, bt_uuid_t *uuid,
+                                 int srvc_handle, int char_handle) {
+  LOG_INFO("%s: status:%d server_if:%d service_handle:%d char_handle:%d",
+           __func__, status, server_if, srvc_handle, char_handle);
+
+  bluetooth::Uuid id(*uuid);
+
+  std::lock_guard<std::mutex> lock(internal->lock);
+
+  internal->uuid_to_attribute[id] = char_handle;
+  internal->characteristics[char_handle].uuid = id;
+  internal->characteristics[char_handle].blob_section = 0;
+
+  // This terminates an AddCharacteristic.
+  internal->api_synchronize.notify_one();
+}
+
+void DescriptorAddedCallback(int status, int server_if, bt_uuid_t *uuid,
+                             int srvc_handle, int descr_handle) {
+  LOG_INFO(
+      "%s: status:%d server_if:%d service_handle:%d uuid[0]:%u "
+      "descr_handle:%d",
+      __func__, status, server_if, srvc_handle, uuid->uu[0], descr_handle);
+}
+
+void ServiceStartedCallback(int status, int server_if, int srvc_handle) {
+  LOG_INFO("%s: status:%d server_if:%d srvc_handle:%d", __func__, status,
+           server_if, srvc_handle);
+
+  // The UUID provided here is unimportant, and is only used to satisfy
+  // BlueDroid.
+  // It must be different than any other registered UUID.
+  bt_uuid_t client_id = internal->service_id.id.uuid;
+  ++client_id.uu[15];
+
+  bt_status_t btstat = internal->gatt->client->register_client(&client_id);
+  if (btstat != BT_STATUS_SUCCESS) {
+    LOG_ERROR("%s: Failed to register client", __func__);
+  }
+}
+
+void RegisterClientCallback(int status, int client_if, bt_uuid_t *app_uuid) {
+  LOG_INFO("%s: status:%d client_if:%d uuid[0]:%u", __func__, status,
+           client_if, app_uuid->uu[0]);
+  internal->client_if = client_if;
+
+  // Setup our advertisement. This has no callback.
+  bt_status_t btstat = internal->gatt->client->set_adv_data(
+      client_if, false, /* beacon, not scan response */
+      false,            /* name */
+      false,            /* no txpower */
+      2, 2,             /* interval */
+      0,                /* appearance */
+      0, nullptr,       /* no mfg data */
+      0, nullptr,       /* no service data */
+      0, nullptr /* no service id yet */);
+  if (btstat != BT_STATUS_SUCCESS) {
+    LOG_ERROR("Failed to set advertising data");
+    return;
+  }
+
+  // TODO(icoolidge): Deprecated, use multi-adv interface.
+  // This calls back to ListenCallback.
+  btstat = internal->gatt->client->listen(client_if, true);
+  if (btstat != BT_STATUS_SUCCESS) {
+    LOG_ERROR("Failed to start listening");
+  }
+}
+
+void ListenCallback(int status, int client_if) {
+  LOG_INFO("%s: status:%d client_if:%d", __func__, status, client_if);
+  // This terminates a Start call.
+  std::lock_guard<std::mutex> lock(internal->lock);
+  internal->api_synchronize.notify_one();
+}
+
+void ServiceStoppedCallback(int status, int server_if, int srvc_handle) {
+  LOG_INFO("%s: status:%d server_if:%d srvc_handle:%d", __func__, status,
+           server_if, srvc_handle);
+  // This terminates a Stop call.
+  // TODO(icoolidge): make this symmetric with start
+  std::lock_guard<std::mutex> lock(internal->lock);
+  internal->api_synchronize.notify_one();
+}
+
+void ScanResultCallback(bt_bdaddr_t *bda, int rssi, uint8_t *adv_data) {
+  std::string addr(BtAddrString(bda));
+  (void)adv_data;
+  std::lock_guard<std::mutex> lock(internal->lock);
+  internal->scan_results[addr] = rssi;
+}
+
+void ClientConnectCallback(int conn_id, int status, int client_if,
+                           bt_bdaddr_t *bda) {
+  std::string addr(BtAddrString(bda));
+  LOG_INFO("%s: conn_id:%d status:%d client_if:%d %s", __func__, conn_id,
+           status, client_if, addr.c_str());
+}
+
+void ClientDisconnectCallback(int conn_id, int status, int client_if,
+                              bt_bdaddr_t *bda) {
+  std::string addr(BtAddrString(bda));
+  LOG_INFO("%s: conn_id:%d status:%d client_if:%d %s", __func__, conn_id,
+           status, client_if, addr.c_str());
+}
+
+void IndicationSentCallback(UNUSED_ATTR int conn_id,
+                            UNUSED_ATTR int status) {
+  // TODO(icoolidge): what to do
+}
+
+void ResponseConfirmationCallback(UNUSED_ATTR int status,
+                                  UNUSED_ATTR int handle) {
+  // TODO(icoolidge): what to do
+}
+
+const btgatt_server_callbacks_t gatt_server_callbacks = {
+    RegisterServerCallback,
+    ConnectionCallback,
+    ServiceAddedCallback,
+    nullptr, /* included_service_added_cb */
+    CharacteristicAddedCallback,
+    DescriptorAddedCallback,
+    ServiceStartedCallback,
+    ServiceStoppedCallback,
+    nullptr, /* service_deleted_cb */
+    RequestReadCallback,
+    RequestWriteCallback,
+    RequestExecWriteCallback,
+    ResponseConfirmationCallback,
+    IndicationSentCallback,
+    nullptr, /* congestion_cb*/
+    nullptr, /* mtu_changed_cb */
+};
+
+// TODO(eisenbach): Refactor GATT interface to not require servers
+// to refer to the client interface.
+const btgatt_client_callbacks_t gatt_client_callbacks = {
+    RegisterClientCallback,
+    ScanResultCallback,
+    ClientConnectCallback,
+    ClientDisconnectCallback,
+    nullptr, /* search_complete_cb; */
+    nullptr, /* search_result_cb; */
+    nullptr, /* get_characteristic_cb; */
+    nullptr, /* get_descriptor_cb; */
+    nullptr, /* get_included_service_cb; */
+    nullptr, /* register_for_notification_cb; */
+    nullptr, /* notify_cb; */
+    nullptr, /* read_characteristic_cb; */
+    nullptr, /* write_characteristic_cb; */
+    nullptr, /* read_descriptor_cb; */
+    nullptr, /* write_descriptor_cb; */
+    nullptr, /* execute_write_cb; */
+    nullptr, /* read_remote_rssi_cb; */
+    ListenCallback,
+    nullptr, /* configure_mtu_cb; */
+    nullptr, /* scan_filter_cfg_cb; */
+    nullptr, /* scan_filter_param_cb; */
+    nullptr, /* scan_filter_status_cb; */
+    nullptr, /* multi_adv_enable_cb */
+    nullptr, /* multi_adv_update_cb; */
+    nullptr, /* multi_adv_data_cb*/
+    nullptr, /* multi_adv_disable_cb; */
+    nullptr, /* congestion_cb; */
+    nullptr, /* batchscan_cfg_storage_cb; */
+    nullptr, /* batchscan_enb_disable_cb; */
+    nullptr, /* batchscan_reports_cb; */
+    nullptr, /* batchscan_threshold_cb; */
+    nullptr, /* track_adv_event_cb; */
+};
+
+const btgatt_callbacks_t gatt_callbacks = {
+    /** Set to sizeof(btgatt_callbacks_t) */
+    sizeof(btgatt_callbacks_t),
+
+    /** GATT Client callbacks */
+    &gatt_client_callbacks,
+
+    /** GATT Server callbacks */
+    &gatt_server_callbacks};
+
+}  // namespace
+
+namespace bluetooth {
+namespace gatt {
+
+int ServerInternals::Initialize(CoreStack *bt) {
+  // Get the interface to the GATT profile.
+  gatt = reinterpret_cast<const btgatt_interface_t *>(
+      bt->GetInterface(BT_PROFILE_GATT_ID));
+  if (!gatt) {
+    LOG_ERROR("Error getting GATT interface");
+    return -1;
+  }
+
+  bt_status_t btstat = gatt->init(&gatt_callbacks);
+  if (btstat != BT_STATUS_SUCCESS) {
+    LOG_ERROR("Failed to initialize gatt interface");
+    return -1;
+  }
+
+  int status = pipe(pipefd);
+  if (status == -1) {
+    LOG_ERROR("pipe creation failed: %s", strerror(errno));
+    return -1;
+  }
+
+  return 0;
+}
+
+ServerInternals::ServerInternals()
+    : gatt(nullptr),
+      server_if(0),
+      client_if(0),
+      service_handle(0),
+      pipefd{INVALID_FD, INVALID_FD} {}
+
+ServerInternals::~ServerInternals() {
+  if (pipefd[0] != INVALID_FD)
+    close(pipefd[0]);
+  if (pipefd[1] != INVALID_FD)
+    close(pipefd[1]);
+}
+
+Server::Server() : internal_(nullptr) {}
+
+Server::~Server() {}
+
+bool Server::Initialize(const Uuid &service_id, int *gatt_pipe, CoreStack *bt) {
+  internal_.reset(new ServerInternals);
+  if (!internal_) {
+    LOG_ERROR("Error creating internals");
+    return false;
+  }
+  internal = internal_.get();
+
+  std::unique_lock<std::mutex> lock(internal_->lock);
+  int status = internal_->Initialize(bt);
+  if (status) {
+    LOG_ERROR("Error initializing internals");
+    return false;
+  }
+
+  bt_uuid_t uuid = service_id.GetBlueDroid();
+
+  bt_status_t btstat = internal_->gatt->server->register_server(&uuid);
+  if (btstat != BT_STATUS_SUCCESS) {
+    LOG_ERROR("Failed to register server");
+    return false;
+  }
+
+  internal_->api_synchronize.wait(lock);
+  // TODO(icoolidge): Better error handling.
+  if (internal_->server_if == 0) {
+    LOG_ERROR("Initialization of server failed");
+    return false;
+  }
+
+  *gatt_pipe = internal_->pipefd[kPipeReadEnd];
+  LOG_INFO("Server Initialize succeeded");
+  return true;
+}
+
+bool Server::SetAdvertisement(const std::vector<Uuid> &ids,
+                              const std::vector<uint8_t> &service_data,
+                              bool transmit_name) {
+  std::vector<uint8_t> id_data;
+  auto mutable_service_data = service_data;
+
+  for (const Uuid &id : ids) {
+    const auto le_id = id.GetFullLittleEndian();
+    id_data.insert(id_data.end(), le_id.begin(), le_id.end());
+  }
+
+  std::lock_guard<std::mutex> lock(internal_->lock);
+
+  // Setup our advertisement. This has no callback.
+  bt_status_t btstat = internal->gatt->client->set_adv_data(
+      internal_->client_if, false, /* beacon, not scan response */
+      transmit_name,               /* name */
+      false,                       /* no txpower */
+      2, 2,                        /* interval */
+      0,                           /* appearance */
+      0, nullptr,                  /* no mfg data */
+      mutable_service_data.size(),
+      reinterpret_cast<char *>(mutable_service_data.data()), id_data.size(),
+      reinterpret_cast<char *>(id_data.data()));
+  if (btstat != BT_STATUS_SUCCESS) {
+    LOG_ERROR("Failed to set advertising data");
+    return false;
+  }
+  return true;
+}
+
+bool Server::SetScanResponse(const std::vector<Uuid> &ids,
+                            const std::vector<uint8_t> &service_data,
+                            bool transmit_name) {
+  std::vector<uint8_t> id_data;
+  auto mutable_service_data = service_data;
+
+  for (const Uuid &id : ids) {
+    const auto le_id = id.GetFullLittleEndian();
+    id_data.insert(id_data.end(), le_id.begin(), le_id.end());
+  }
+
+  std::lock_guard<std::mutex> lock(internal_->lock);
+
+  // Setup our advertisement. This has no callback.
+  bt_status_t btstat = internal->gatt->client->set_adv_data(
+      internal_->client_if, true, /* scan response */
+      transmit_name,              /* name */
+      false,                      /* no txpower */
+      2, 2,                       /* interval */
+      0,                          /* appearance */
+      0, nullptr,                 /* no mfg data */
+      mutable_service_data.size(),
+      reinterpret_cast<char *>(mutable_service_data.data()), id_data.size(),
+      reinterpret_cast<char *>(id_data.data()));
+  if (btstat != BT_STATUS_SUCCESS) {
+    LOG_ERROR("Failed to set scan response data");
+    return false;
+  }
+  return true;
+}
+
+bool Server::AddCharacteristic(const Uuid &id, int properties, int permissions) {
+  bt_uuid_t char_id = id.GetBlueDroid();
+
+  std::unique_lock<std::mutex> lock(internal->lock);
+  bt_status_t btstat = internal->gatt->server->add_characteristic(
+      internal->server_if, internal->service_handle, &char_id, properties,
+      permissions);
+  internal_->api_synchronize.wait(lock);
+  const int handle = internal->uuid_to_attribute[id];
+  internal->characteristics[handle].notify = properties & kPropertyNotify;
+  return true;
+}
+
+bool Server::AddBlob(const Uuid &id, const Uuid &control_id, int properties,
+                    int permissions) {
+  bt_uuid_t char_id = id.GetBlueDroid();
+  bt_uuid_t ctrl_id = control_id.GetBlueDroid();
+
+  std::unique_lock<std::mutex> lock(internal->lock);
+
+  // First, add the primary attribute (characteristic value)
+  bt_status_t btstat = internal->gatt->server->add_characteristic(
+      internal->server_if, internal->service_handle, &char_id, properties,
+      permissions);
+  internal->api_synchronize.wait(lock);
+
+  // Next, add the secondary attribute (blob control).
+  // Control attributes have fixed permissions/properties.
+  const int kControlPermissions = kPermissionRead | kPermissionWrite;
+  const int kControlProperties = kPropertyRead | kPropertyWrite;
+
+  btstat = internal->gatt->server->add_characteristic(
+      internal->server_if, internal->service_handle, &ctrl_id,
+      kControlProperties, kControlPermissions);
+  internal->api_synchronize.wait(lock);
+
+  // Finally, associate the control attribute with the value attribute.
+  // Also, initialize the control attribute to a readable zero.
+  const int control_attribute = internal->uuid_to_attribute[control_id];
+  const int blob_attribute = internal->uuid_to_attribute[id];
+  internal->controlled_blobs[control_attribute] = blob_attribute;
+  internal->characteristics[blob_attribute].notify = properties & kPropertyNotify;
+
+  Characteristic &ctrl = internal->characteristics[control_attribute];
+  ctrl.next_blob.clear();
+  ctrl.next_blob.push_back(0);
+  ctrl.next_blob_pending = true;
+  ctrl.blob_section = 0;
+  ctrl.notify = false;
+  return true;
+}
+
+bool Server::Start() {
+  std::unique_lock<std::mutex> lock(internal_->lock);
+  bt_status_t btstat = internal_->gatt->server->start_service(
+      internal_->server_if, internal_->service_handle, GATT_TRANSPORT_LE);
+  internal_->api_synchronize.wait(lock);
+  return true;
+}
+
+bool Server::Stop() {
+  std::unique_lock<std::mutex> lock(internal_->lock);
+  bt_status_t btstat = internal_->gatt->server->stop_service(
+      internal_->server_if, internal_->service_handle);
+  internal_->api_synchronize.wait(lock);
+  return true;
+}
+
+bool Server::ScanEnable() {
+  bt_status_t btstat = internal_->gatt->client->scan(true);
+  if (btstat) {
+    LOG_ERROR("Enable scan failed: %d", btstat);
+    return false;
+  }
+  return true;
+}
+
+bool Server::ScanDisable() {
+  bt_status_t btstat = internal_->gatt->client->scan(false);
+  if (btstat) {
+    LOG_ERROR("Disable scan failed: %d", btstat);
+    return false;
+  }
+  return true;
+}
+
+bool Server::GetScanResults(ScanResults *results) {
+  std::lock_guard<std::mutex> lock(internal_->lock);
+  *results = internal_->scan_results;
+  return true;
+}
+
+bool Server::SetCharacteristicValue(const Uuid &id,
+                              const std::vector<uint8_t> &value) {
+  std::lock_guard<std::mutex> lock(internal->lock);
+  const int attribute_id = internal->uuid_to_attribute[id];
+  Characteristic &ch = internal->characteristics[attribute_id];
+  ch.next_blob = value;
+  ch.next_blob_pending = true;
+
+  if (!ch.notify)
+    return true;
+
+  for (auto connection : internal->connections) {
+    char dummy = 0;
+    internal_->gatt->server->send_indication(internal->server_if,
+                                             attribute_id,
+                                             connection,
+                                             sizeof(dummy),
+                                             true,
+                                             &dummy);
+  }
+  return true;
+}
+
+bool Server::GetCharacteristicValue(const Uuid &id, std::vector<uint8_t> *value) {
+  std::lock_guard<std::mutex> lock(internal_->lock);
+  const int attribute_id = internal_->uuid_to_attribute[id];
+  *value = internal_->characteristics[attribute_id].blob;
+  return true;
+}
+
+}  // namespace gatt
+}  // namespace bluetooth
diff --git a/service/gatt_server.h b/service/gatt_server.h
new file mode 100644
index 0000000..2328395
--- /dev/null
+++ b/service/gatt_server.h
@@ -0,0 +1,117 @@
+//
+//  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 <array>
+#include <memory>
+#include <unordered_map>
+#include <vector>
+
+#include "hardware/bluetooth.h"
+#include "hardware/bt_gatt.h"
+#include "uuid.h"
+
+namespace bluetooth {
+
+class CoreStack;
+
+namespace gatt {
+
+// Attribute permission values
+const int kPermissionRead = 0x1;
+const int kPermissionReadEncrypted = 0x2;
+const int kPermissionReadEncryptedMitm = 0x4;
+const int kPermissionWrite = 0x10;
+const int kPermissionWriteEnecrypted = 0x20;
+const int KPermissionWriteEncryptedMitm = 0x40;
+const int kPermissionWriteSigned = 0x80;
+const int kPermissionWriteSignedMitm = 0x100;
+
+// GATT characteristic properties bit-field values
+const int kPropertyBroadcast = 0x1;
+const int kPropertyRead = 0x2;
+const int kPropertyWriteNoResponse = 0x4;
+const int kPropertyWrite = 0x8;
+const int kPropertyNotify = 0x10;
+const int kPropertyIndicate = 0x20;
+const int kPropertySignedWrite = 0x40;
+const int kPropertyExtendedProps = 0x80;
+
+// A mapping from string bluetooth addresses to RSSI measurements.
+typedef std::unordered_map<std::string, int> ScanResults;
+
+class ServerInternals;
+
+// Server is threadsafe and internally locked.
+// Asynchronous IO is identified via a gatt_pipe FD,
+// and synchronously read with 'GetCharacteristicValue'
+class Server {
+ public:
+  Server();
+  ~Server();
+
+  // Register GATT interface, initialize internal state,
+  // and open a pipe for characteristic write notification.
+  bool Initialize(const Uuid &service_id, int *gatt_pipe, CoreStack *bt);
+
+  // Control the content of service advertisement.
+  bool SetAdvertisement(const std::vector<Uuid> &ids,
+                        const std::vector<uint8_t> &service_data,
+                        bool transmit_name);
+
+  // Control the content of service scan response.
+  bool SetScanResponse(const std::vector<Uuid> &ids,
+                       const std::vector<uint8_t> &service_data,
+                       bool transmit_name);
+
+  // Add an ordinary characteristic for reading and/or writing.
+  bool AddCharacteristic(const Uuid &id, int properties, int permissions);
+
+  // Add a special 'blob' characteristic with a corresponding control
+  // attribute to manipulate which part of the blob the attribute represents.
+  bool AddBlob(const Uuid &id, const Uuid &control_id, int properties,
+               int permissions);
+
+  // Put a new value into a characeteristic.
+  // It will be read from a client starting at the next 0-offset read.
+  bool SetCharacteristicValue(const Uuid &id, const std::vector<uint8_t> &value);
+
+  // Get the current value of a characteristic.
+  bool GetCharacteristicValue(const Uuid &id, std::vector<uint8_t> *value);
+
+  // Start this service. Activate advertisements, allow connections.
+  // Characteristics should all be created before this.
+  bool Start();
+
+  // Cease advertisements and disallow connections.
+  bool Stop();
+
+  // Enable LE scan. Scan results will be cached internally.
+  bool ScanEnable();
+
+  // Disable LE scan.
+  bool ScanDisable();
+
+  // Copy out the cached scan results.
+  bool GetScanResults(ScanResults *results);
+
+ private:
+  // Internal data.
+  std::unique_ptr<ServerInternals> internal_;
+};
+
+}  // namespace gatt
+}  // namespace bluetooth
diff --git a/service/host.cpp b/service/host.cpp
new file mode 100644
index 0000000..fb38f18
--- /dev/null
+++ b/service/host.cpp
@@ -0,0 +1,313 @@
+//
+//  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 "host.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include <algorithm>
+
+#define LOG_TAG "BluetoothHost"
+#include "osi/include/log.h"
+
+#include "base/base64.h"
+#include "base/string_number_conversions.h"
+#include "base/string_split.h"
+#include "core_stack.h"
+#include "gatt_server.h"
+#include "uuid.h"
+
+namespace {
+
+// IPC API is according to:
+// https://docs.google.com/document/d/1eRnku-jAyVU1wGJsLT2CzWi0-8bs2g49s1b3FR_GApM
+const char kSetAdapterNameCommand[] = "set-device-name";
+const char kCreateServiceCommand[] = "create-service";
+const char kDestroyServiceCommand[] = "destroy-service";
+const char kAddCharacteristicCommand[] = "add-characteristic";
+const char kSetCharacteristicValueCommand[] = "set-characteristic-value";
+const char kSetAdvertisementCommand[] = "set-advertisement";
+const char kSetScanResponseCommand[] = "set-scan-response";
+const char kStartServiceCommand[] = "start-service";
+const char kStopServiceCommand[] = "stop-service";
+const char kWriteCharacteristicCommand[] = "write-characteristic";
+
+// Useful values for indexing Host::pfds_
+// Not super general considering that we should be able to support
+// many GATT FDs owned by one Host.
+enum {
+  kFdIpc = 0,
+  kFdGatt = 1,
+  kPossibleFds = 2,
+};
+
+bool TokenBool(const std::string& text) {
+  return text == "true";
+}
+
+}  // namespace
+
+namespace bluetooth {
+
+Host::Host(int sockfd, CoreStack* bt)
+    : bt_(bt), pfds_(1, {sockfd, POLLIN, 0}) {}
+
+Host::~Host() {
+  close(pfds_[0].fd);
+}
+
+bool Host::EventLoop() {
+  while (true) {
+    int status =
+        TEMP_FAILURE_RETRY(ppoll(pfds_.data(), pfds_.size(), nullptr, nullptr));
+    if (status < 1) {
+      LOG_ERROR("ppoll error");
+      return false;
+    }
+
+    if (pfds_[kFdIpc].revents && !OnMessage()) {
+      return false;
+    }
+
+    if (pfds_.size() == kPossibleFds &&
+        pfds_[kFdGatt].revents &&
+        !OnGattWrite()) {
+      return false;
+    }
+  }
+  return true;
+}
+
+bool Host::OnSetAdapterName(const std::string& name) {
+  std::string decoded_data;
+  base::Base64Decode(name, &decoded_data);
+  return bt_->SetAdapterName(decoded_data);
+}
+
+bool Host::OnCreateService(const std::string& service_uuid) {
+  gatt_servers_[service_uuid] = std::unique_ptr<gatt::Server>(new gatt::Server);
+
+  int gattfd;
+  bool status =
+      gatt_servers_[service_uuid]->Initialize(Uuid(service_uuid), &gattfd, bt_);
+  if (!status) {
+    LOG_ERROR("Failed to initialize bluetooth");
+    return false;
+  }
+  pfds_.resize(kPossibleFds);
+  pfds_[kFdGatt] = {gattfd, POLLIN, 0};
+  return true;
+}
+
+bool Host::OnDestroyService(const std::string& service_uuid) {
+  gatt_servers_.erase(service_uuid);
+  close(pfds_[1].fd);
+  pfds_.resize(1);
+  return true;
+}
+
+bool Host::OnAddCharacteristic(const std::string& service_uuid,
+                               const std::string& characteristic_uuid,
+                               const std::string& control_uuid,
+                               const std::string& options) {
+  const std::vector<std::string> option_tokens(
+      base::SplitString(options, '.'));
+
+  int properties_mask = 0;
+  int permissions_mask = 0;
+
+  if (std::find(option_tokens.begin(), option_tokens.end(), "notify") !=
+      option_tokens.end()) {
+    permissions_mask |= gatt::kPermissionRead;
+    properties_mask |= gatt::kPropertyRead;
+    properties_mask |= gatt::kPropertyNotify;
+  }
+  if (std::find(option_tokens.begin(), option_tokens.end(), "read") !=
+      option_tokens.end()) {
+    permissions_mask |= gatt::kPermissionRead;
+    properties_mask |= gatt::kPropertyRead;
+  }
+  if (std::find(option_tokens.begin(), option_tokens.end(), "write") !=
+      option_tokens.end()) {
+    permissions_mask |= gatt::kPermissionWrite;
+    properties_mask |= gatt::kPropertyWrite;
+  }
+
+  if (control_uuid.empty()) {
+    gatt_servers_[service_uuid]->AddCharacteristic(
+        Uuid(characteristic_uuid), properties_mask, permissions_mask);
+  } else {
+    gatt_servers_[service_uuid]->AddBlob(Uuid(characteristic_uuid),
+                                         Uuid(control_uuid), properties_mask,
+                                         permissions_mask);
+  }
+  return true;
+}
+
+bool Host::OnSetCharacteristicValue(const std::string& service_uuid,
+                                    const std::string& characteristic_uuid,
+                                    const std::string& value) {
+  std::string decoded_data;
+  base::Base64Decode(value, &decoded_data);
+  std::vector<uint8_t> blob_data(decoded_data.begin(), decoded_data.end());
+  gatt_servers_[service_uuid]->SetCharacteristicValue(Uuid(characteristic_uuid),
+                                                      blob_data);
+  return true;
+}
+
+bool Host::OnSetAdvertisement(const std::string& service_uuid,
+                              const std::string& advertise_uuids,
+                              const std::string& advertise_data,
+                              const std::string& transmit_name) {
+  LOG_INFO("%s: service:%s uuids:%s data:%s", __func__, service_uuid.c_str(),
+           advertise_uuids.c_str(), advertise_data.c_str());
+
+  const std::vector<std::string> advertise_uuid_tokens(
+      base::SplitString(advertise_uuids, '.'));
+
+  // string -> vector<Uuid>
+  std::vector<Uuid> ids;
+  for (const auto& uuid_token : advertise_uuid_tokens)
+    ids.emplace_back(uuid_token);
+
+  std::string decoded_data;
+  base::Base64Decode(advertise_data, &decoded_data);
+  std::vector<uint8_t> blob_data(decoded_data.begin(), decoded_data.end());
+  gatt_servers_[service_uuid]->SetAdvertisement(ids, blob_data,
+                                                TokenBool(transmit_name));
+  return true;
+}
+
+bool Host::OnSetScanResponse(const std::string& service_uuid,
+                             const std::string& scan_response_uuids,
+                             const std::string& scan_response_data,
+                             const std::string& transmit_name) {
+  const std::vector<std::string> scan_response_uuid_tokens(
+      base::SplitString(scan_response_uuids, '.'));
+
+  // string -> vector<Uuid>
+  std::vector<Uuid> ids;
+  for (const auto& uuid_token : scan_response_uuid_tokens)
+    ids.emplace_back(uuid_token);
+
+  std::string decoded_data;
+  base::Base64Decode(scan_response_data, &decoded_data);
+  std::vector<uint8_t> blob_data(decoded_data.begin(), decoded_data.end());
+  gatt_servers_[service_uuid]->SetScanResponse(ids, blob_data,
+                                               TokenBool(transmit_name));
+  return true;
+}
+
+bool Host::OnStartService(const std::string& service_uuid) {
+  return gatt_servers_[service_uuid]->Start();
+}
+
+bool Host::OnStopService(const std::string& service_uuid) {
+  return gatt_servers_[service_uuid]->Stop();
+}
+
+bool Host::OnMessage() {
+  std::string ipc_msg;
+  int size = recv(pfds_[kFdIpc].fd, &ipc_msg[0], 0, MSG_PEEK | MSG_TRUNC);
+  if (-1 == size) {
+    LOG_ERROR("Error reading datagram size: %s", strerror(errno));
+    return false;
+  } else if (0 == size) {
+    LOG_INFO("%s:%d: Connection closed", __func__, __LINE__);
+    return false;
+  }
+
+  ipc_msg.resize(size);
+  size = read(pfds_[kFdIpc].fd, &ipc_msg[0], ipc_msg.size());
+  if (-1 == size) {
+    LOG_ERROR("Error reading IPC: %s", strerror(errno));
+    return false;
+  } else if (0 == size) {
+    LOG_INFO("%s:%d: Connection closed", __func__, __LINE__);
+    return false;
+  }
+
+  const std::vector<std::string> tokens(base::SplitString(ipc_msg, '|'));
+  switch (tokens.size()) {
+    case 2:
+      if (tokens[0] == kSetAdapterNameCommand)
+        return OnSetAdapterName(tokens[1]);
+      if (tokens[0] == kCreateServiceCommand)
+        return OnCreateService(tokens[1]);
+      if (tokens[0] == kDestroyServiceCommand)
+        return OnDestroyService(tokens[1]);
+      if (tokens[0] == kStartServiceCommand)
+        return OnStartService(tokens[1]);
+      if (tokens[0] == kStopServiceCommand)
+        return OnStopService(tokens[1]);
+      break;
+    case 4:
+      if (tokens[0] == kSetCharacteristicValueCommand)
+        return OnSetCharacteristicValue(tokens[1], tokens[2], tokens[3]);
+      break;
+    case 5:
+      if (tokens[0] == kSetAdvertisementCommand)
+        return OnSetAdvertisement(tokens[1], tokens[2], tokens[3], tokens[4]);
+      if (tokens[0] == kSetScanResponseCommand)
+        return OnSetScanResponse(tokens[1], tokens[2], tokens[3], tokens[4]);
+      if (tokens[0] == kAddCharacteristicCommand)
+        return OnAddCharacteristic(tokens[1], tokens[2], tokens[3], tokens[4]);
+      break;
+    default:
+      break;
+  }
+
+  LOG_ERROR("Malformed IPC message: %s", ipc_msg.c_str());
+  return false;
+}
+
+bool Host::OnGattWrite() {
+  Uuid::Uuid128Bit id;
+  int r = read(pfds_[kFdGatt].fd, id.data(), id.size());
+  if (r != id.size()) {
+    LOG_ERROR("Error reading GATT attribute ID");
+    return false;
+  }
+
+  std::vector<uint8_t> value;
+  // TODO(icoolidge): Generalize this for multiple clients.
+  auto server = gatt_servers_.begin();
+  server->second->GetCharacteristicValue(Uuid(id), &value);
+  const std::string value_string(value.begin(), value.end());
+  std::string encoded_value;
+  base::Base64Encode(value_string, &encoded_value);
+
+  std::string transmit(kWriteCharacteristicCommand);
+  transmit += "|" + server->first;
+  transmit += "|" + base::HexEncode(id.data(), id.size());
+  transmit += "|" + encoded_value;
+
+  r = write(pfds_[kFdIpc].fd, transmit.data(), transmit.size());
+  if (-1 == r) {
+    LOG_ERROR("Error replying to IPC: %s", strerror(errno));
+    return false;
+  }
+
+  return true;
+}
+
+}  // namespace bluetooth
diff --git a/service/host.h b/service/host.h
new file mode 100644
index 0000000..e695717
--- /dev/null
+++ b/service/host.h
@@ -0,0 +1,102 @@
+//
+//  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 <poll.h>
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+
+#include "gatt_server.h"
+#include "uuid.h"
+
+namespace bluetooth {
+
+class CoreStack;
+
+// This implements a single threaded event loop which dispatches
+// reads from a set of FDs (pfds_) to a set of handlers.
+// Reads from the GATT pipe read end will result in a write to
+// to the IPC socket, and vise versa.
+class Host {
+ public:
+  // Host owns the passed sockfd.
+  Host(int sockfd, CoreStack* bt);
+  ~Host();
+
+  // Synchronously handle all events on input FDs.
+  bool EventLoop();
+
+ private:
+  // Handler for IPC message receives.
+  // Decodes protocol and dispatches to another handler.
+  bool OnMessage();
+
+  // Handler for GATT characteristic writes.
+  // Encodes to protocol and transmits IPC.
+  bool OnGattWrite();
+
+  // Applies adapter name changes to stack.
+  bool OnSetAdapterName(const std::string& name);
+
+  // Handles service creation.
+  bool OnCreateService(const std::string& service_uuid);
+
+  // Handles service destruction.
+  bool OnDestroyService(const std::string& service_uuid);
+
+  // Creates a characteristic for a service.
+  bool OnAddCharacteristic(const std::string& service_uuid,
+                           const std::string& characteristic_uuid,
+                           const std::string& control_uuid,
+                           const std::string& options);
+
+  // Sets the value of a characetistic.
+  bool OnSetCharacteristicValue(const std::string& service_uuid,
+                                const std::string& characteristic_uuid,
+                                const std::string& value);
+
+  // Applies settings to service advertisement.
+  bool OnSetAdvertisement(const std::string& service_uuid,
+                          const std::string& advertise_uuids,
+                          const std::string& advertise_data,
+                          const std::string& transmit_name);
+
+  // Applies settings to scan response.
+  bool OnSetScanResponse(const std::string& service_uuid,
+                         const std::string& advertise_uuids,
+                         const std::string& advertise_data,
+                         const std::string& transmit_name);
+
+  // Starts service (advertisement and connections)
+  bool OnStartService(const std::string& service_uuid);
+
+  // Stops service.
+  bool OnStopService(const std::string& service_uuid);
+
+  // weak reference.
+  CoreStack *bt_;
+
+  // File descripters that we will block against.
+  std::vector<struct pollfd> pfds_;
+
+  // Container for multiple GATT servers. Currently only one is supported.
+  // TODO(icoolidge): support many to one for real.
+  std::unordered_map<std::string, std::unique_ptr<gatt::Server>> gatt_servers_;
+};
+
+}  // namespace bluetooth
diff --git a/service/logging_helpers.cpp b/service/logging_helpers.cpp
new file mode 100644
index 0000000..59cde12
--- /dev/null
+++ b/service/logging_helpers.cpp
@@ -0,0 +1,135 @@
+//
+//  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 "logging_helpers.h"
+
+#include <string.h>
+
+#include <string>
+
+#define CASE_RETURN_TEXT(code) \
+  case code:                   \
+    return #code
+
+const char *BtAvConnectionStateText(const btav_connection_state_t state) {
+  switch (state) {
+    CASE_RETURN_TEXT(BTAV_CONNECTION_STATE_DISCONNECTED);
+    CASE_RETURN_TEXT(BTAV_CONNECTION_STATE_CONNECTING);
+    CASE_RETURN_TEXT(BTAV_CONNECTION_STATE_CONNECTED);
+    CASE_RETURN_TEXT(BTAV_CONNECTION_STATE_DISCONNECTING);
+    default:
+      return "Invalid AV connection state";
+  }
+}
+
+const char *BtAvAudioStateText(const btav_audio_state_t state) {
+  switch (state) {
+    CASE_RETURN_TEXT(BTAV_AUDIO_STATE_REMOTE_SUSPEND);
+    CASE_RETURN_TEXT(BTAV_AUDIO_STATE_STOPPED);
+    CASE_RETURN_TEXT(BTAV_AUDIO_STATE_STARTED);
+    default:
+      return "Invalid audio state";
+  }
+}
+
+const char *BtTransportText(const btgatt_transport_t t) {
+  switch(t) {
+    CASE_RETURN_TEXT(GATT_TRANSPORT_AUTO);
+    CASE_RETURN_TEXT(GATT_TRANSPORT_BREDR);
+    CASE_RETURN_TEXT(GATT_TRANSPORT_LE);
+    default:
+      return "unknown transport";
+  }
+}
+
+const char *BtStateText(const bt_state_t state) {
+  switch (state) {
+    CASE_RETURN_TEXT(BT_STATE_OFF);
+    CASE_RETURN_TEXT(BT_STATE_ON);
+    default:
+      return "unknown state code";
+  }
+}
+
+const char *BtScanModeText(const bt_scan_mode_t mode) {
+  switch (mode) {
+    CASE_RETURN_TEXT(BT_SCAN_MODE_NONE);
+    CASE_RETURN_TEXT(BT_SCAN_MODE_CONNECTABLE);
+    CASE_RETURN_TEXT(BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
+    default:
+      return "unknown scan mode";
+  }
+}
+
+const char *BtStatusText(const bt_status_t status) {
+  switch (status) {
+    CASE_RETURN_TEXT(BT_STATUS_SUCCESS);
+    CASE_RETURN_TEXT(BT_STATUS_FAIL);
+    CASE_RETURN_TEXT(BT_STATUS_NOT_READY);
+    CASE_RETURN_TEXT(BT_STATUS_NOMEM);
+    CASE_RETURN_TEXT(BT_STATUS_DONE);
+    CASE_RETURN_TEXT(BT_STATUS_BUSY);
+    CASE_RETURN_TEXT(BT_STATUS_UNSUPPORTED);
+    default:
+      return "unknown status code";
+  }
+}
+
+const char *BtPropertyText(const bt_property_type_t prop) {
+  switch (prop) {
+    CASE_RETURN_TEXT(BT_PROPERTY_BDNAME);
+    CASE_RETURN_TEXT(BT_PROPERTY_BDADDR);
+    CASE_RETURN_TEXT(BT_PROPERTY_UUIDS);
+    CASE_RETURN_TEXT(BT_PROPERTY_CLASS_OF_DEVICE);
+    CASE_RETURN_TEXT(BT_PROPERTY_TYPE_OF_DEVICE);
+    CASE_RETURN_TEXT(BT_PROPERTY_SERVICE_RECORD);
+    CASE_RETURN_TEXT(BT_PROPERTY_ADAPTER_SCAN_MODE);
+    CASE_RETURN_TEXT(BT_PROPERTY_ADAPTER_BONDED_DEVICES);
+    CASE_RETURN_TEXT(BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT);
+    CASE_RETURN_TEXT(BT_PROPERTY_REMOTE_FRIENDLY_NAME);
+    CASE_RETURN_TEXT(BT_PROPERTY_REMOTE_RSSI);
+    CASE_RETURN_TEXT(BT_PROPERTY_REMOTE_VERSION_INFO);
+    CASE_RETURN_TEXT(BT_PROPERTY_LOCAL_LE_FEATURES);
+    CASE_RETURN_TEXT(BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP);
+    default:
+      return "Invalid property";
+  }
+}
+
+const char *BtEventText(const bt_cb_thread_evt evt) {
+  switch (evt) {
+    CASE_RETURN_TEXT(ASSOCIATE_JVM);
+    CASE_RETURN_TEXT(DISASSOCIATE_JVM);
+    default:
+      return "unknown state code";
+  }
+}
+
+const char *BtAclText(const bt_acl_state_t code) {
+  switch (code) {
+    CASE_RETURN_TEXT(BT_ACL_STATE_CONNECTED);
+    CASE_RETURN_TEXT(BT_ACL_STATE_DISCONNECTED);
+    default:
+      return "unknown ACL code";
+  }
+}
+
+std::string BtAddrString(const bt_bdaddr_t *addr) {
+  char buffer[20];
+  snprintf(buffer, sizeof(buffer), "%02X:%02X:%02X:%02X:%02X:%02X",
+           addr->address[0], addr->address[1], addr->address[2],
+           addr->address[3], addr->address[4], addr->address[5]);
+  return std::string(buffer);
+}
diff --git a/service/logging_helpers.h b/service/logging_helpers.h
new file mode 100644
index 0000000..6baafa8
--- /dev/null
+++ b/service/logging_helpers.h
@@ -0,0 +1,45 @@
+//
+//  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 <string.h>
+
+#include <string>
+
+#include "hardware/bluetooth.h"
+#include "hardware/bt_av.h"
+#include "hardware/bt_gatt_types.h"
+
+const char *BtAvConnectionStateText(const btav_connection_state_t state);
+
+const char *BtAvAudioStateText(const btav_audio_state_t state);
+
+const char *BtTransportText(const btgatt_transport_t t);
+
+const char *BtStateText(const bt_state_t state);
+
+const char *BtScanModeText(const bt_scan_mode_t mode);
+
+const char *BtStatusText(const bt_status_t status);
+
+const char *BtPropertyText(const bt_property_type_t prop);
+
+const char *BtEventText(const bt_cb_thread_evt evt);
+
+const char *BtAclText(const bt_acl_state_t state);
+
+// TODO(icoolidge): Address object.
+std::string BtAddrString(const bt_bdaddr_t *addr);
diff --git a/service/main.cpp b/service/main.cpp
new file mode 100644
index 0000000..a818f74
--- /dev/null
+++ b/service/main.cpp
@@ -0,0 +1,77 @@
+//
+//  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 <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define LOG_TAG "BtHost"
+#include "osi/include/log.h"
+// For system properties
+// TODO(icoolidge): abstraction or non-cutils stub.
+#include <cutils/properties.h>
+// For init socket environment variable decode
+// TODO(icoolidge): abstraction or remove.
+#include <cutils/sockets.h>
+
+#include "core_stack.h"
+#include "host.h"
+
+namespace {
+
+const char kDisableProperty[] = "persist.bluetooth.disable";
+const char kSocketFromInit[] = "bluetooth";
+
+}  // namespace
+
+int main() {
+  char disable_value[PROPERTY_VALUE_MAX];
+  int status = property_get(kDisableProperty, disable_value, nullptr);
+  if (status && !strcmp(disable_value, "1")) {
+    LOG_INFO("service disabled");
+    return EXIT_SUCCESS;
+  }
+
+  int server_socket = android_get_control_socket(kSocketFromInit);
+  if (server_socket == -1) {
+    LOG_ERROR("failed to get socket from init");
+    return EXIT_FAILURE;
+  }
+
+  status = listen(server_socket, SOMAXCONN);
+  if (status == -1) {
+    LOG_ERROR("listen failed: %s", strerror(errno));
+    return EXIT_FAILURE;
+  }
+
+  bluetooth::CoreStack bt;
+  bt.Initialize();
+
+  // TODO(icoolidge): accept simultaneous clients
+  while (true) {
+    int client_socket = accept4(server_socket, nullptr, nullptr, SOCK_NONBLOCK);
+    if (status == -1) {
+      LOG_ERROR("accept failed: %s", strerror(errno));
+      return EXIT_FAILURE;
+    }
+
+    LOG_INFO("client connected: %d", client_socket);
+    bluetooth::Host bluetooth_host(client_socket, &bt);
+    bluetooth_host.EventLoop();
+  }
+
+  close(server_socket);
+  return EXIT_SUCCESS;
+}
diff --git a/service/modp_b64/LICENSE b/service/modp_b64/LICENSE
new file mode 100644
index 0000000..55af76f
--- /dev/null
+++ b/service/modp_b64/LICENSE
@@ -0,0 +1,33 @@
+ * MODP_B64 - High performance base64 encoder/decoder
+ * Version 1.3 -- 17-Mar-2006
+ * http://modp.com/release/base64
+ *
+ * Copyright (c) 2005, 2006  Nick Galbreath -- nickg [at] modp [dot] com
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *   Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ *   Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ *   Neither the name of the modp.com nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/service/modp_b64/README.chromium b/service/modp_b64/README.chromium
new file mode 100644
index 0000000..35b9e54
--- /dev/null
+++ b/service/modp_b64/README.chromium
@@ -0,0 +1,15 @@
+Name: modp base64 decoder
+Short Name: stringencoders
+URL: http://code.google.com/p/stringencoders/
+Version: unknown
+License: BSD
+Security Critical: yes
+
+Description:
+The modp_b64.c file was modified to remove the inclusion of modp's config.h
+and to fix compilation errors that occur under VC8.  The file was renamed
+modp_b64.cc to force it to be compiled as C++ so that the inclusion of
+basictypes.h could be possible.
+
+The modp_b64.cc and modp_b64.h files were modified to make them safe on
+64-bit systems.
diff --git a/service/modp_b64/modp_b64.cpp b/service/modp_b64/modp_b64.cpp
new file mode 100644
index 0000000..e5f6cf1
--- /dev/null
+++ b/service/modp_b64/modp_b64.cpp
@@ -0,0 +1,265 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
+/* vi: set expandtab shiftwidth=4 tabstop=4: */
+/**
+ * \file
+ * <PRE>
+ * MODP_B64 - High performance base64 encoder/decoder
+ * Version 1.3 -- 17-Mar-2006
+ * http://modp.com/release/base64
+ *
+ * Copyright &copy; 2005, 2006  Nick Galbreath -- nickg [at] modp [dot] com
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *   Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ *   Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ *   Neither the name of the modp.com nor the names of its
+ *   contributors may be used to endorse or promote products derived from
+ *   this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This is the standard "new" BSD license:
+ * http://www.opensource.org/licenses/bsd-license.php
+ * </PRE>
+ */
+
+/* public header */
+#include "modp_b64.h"
+
+/*
+ * If you are ripping this out of the library, comment out the next
+ * line and uncomment the next lines as approrpiate
+ */
+//#include "config.h"
+
+/* if on motoral, sun, ibm; uncomment this */
+/* #define WORDS_BIGENDIAN 1 */
+/* else for Intel, Amd; uncomment this */
+/* #undef WORDS_BIGENDIAN */
+
+#include "modp_b64_data.h"
+
+#define BADCHAR 0x01FFFFFF
+
+/**
+ * you can control if we use padding by commenting out this
+ * next line.  However, I highly recommend you use padding and not
+ * using it should only be for compatability with a 3rd party.
+ * Also, 'no padding' is not tested!
+ */
+#define DOPAD 1
+
+/*
+ * if we aren't doing padding
+ * set the pad character to NULL
+ */
+#ifndef DOPAD
+#undef CHARPAD
+#define CHARPAD '\0'
+#endif
+
+size_t modp_b64_encode(char* dest, const char* str, size_t len)
+{
+    size_t i = 0;
+    uint8_t* p = (uint8_t*) dest;
+
+    /* unsigned here is important! */
+    uint8_t t1, t2, t3;
+
+    if (len > 2) {
+        for (; i < len - 2; i += 3) {
+            t1 = str[i]; t2 = str[i+1]; t3 = str[i+2];
+            *p++ = e0[t1];
+            *p++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
+            *p++ = e1[((t2 & 0x0F) << 2) | ((t3 >> 6) & 0x03)];
+            *p++ = e2[t3];
+        }
+    }
+
+    switch (len - i) {
+    case 0:
+        break;
+    case 1:
+        t1 = str[i];
+        *p++ = e0[t1];
+        *p++ = e1[(t1 & 0x03) << 4];
+        *p++ = CHARPAD;
+        *p++ = CHARPAD;
+        break;
+    default: /* case 2 */
+        t1 = str[i]; t2 = str[i+1];
+        *p++ = e0[t1];
+        *p++ = e1[((t1 & 0x03) << 4) | ((t2 >> 4) & 0x0F)];
+        *p++ = e2[(t2 & 0x0F) << 2];
+        *p++ = CHARPAD;
+    }
+
+    *p = '\0';
+    return p - (uint8_t*)dest;
+}
+
+#ifdef WORDS_BIGENDIAN   /* BIG ENDIAN -- SUN / IBM / MOTOROLA */
+int modp_b64_decode(char* dest, const char* src, int len)
+{
+    if (len == 0) return 0;
+
+#ifdef DOPAD
+    /* if padding is used, then the message must be at least
+       4 chars and be a multiple of 4.
+       there can be at most 2 pad chars at the end */
+    if (len < 4 || (len % 4 != 0)) return MODP_B64_ERROR;
+    if (src[len-1] == CHARPAD) {
+        len--;
+        if (src[len -1] == CHARPAD) {
+            len--;
+        }
+    }
+#endif  /* DOPAD */
+
+    size_t i;
+    int leftover = len % 4;
+    size_t chunks = (leftover == 0) ? len / 4 - 1 : len /4;
+
+    uint8_t* p = (uint8_t*) dest;
+    uint32_t x = 0;
+    uint32_t* destInt = (uint32_t*) p;
+    uint32_t* srcInt = (uint32_t*) src;
+    uint32_t y = *srcInt++;
+    for (i = 0; i < chunks; ++i) {
+        x = d0[y >> 24 & 0xff] | d1[y >> 16 & 0xff] |
+            d2[y >> 8 & 0xff] | d3[y & 0xff];
+
+        if (x >= BADCHAR)  return MODP_B64_ERROR;
+        *destInt = x << 8;
+        p += 3;
+        destInt = (uint32_t*)p;
+        y = *srcInt++;
+    }
+
+    switch (leftover) {
+    case 0:
+        x = d0[y >> 24 & 0xff] | d1[y >> 16 & 0xff] |
+            d2[y >>  8 & 0xff] | d3[y & 0xff];
+        if (x >= BADCHAR)  return MODP_B64_ERROR;
+        *p++ = ((uint8_t*)&x)[1];
+        *p++ = ((uint8_t*)&x)[2];
+        *p = ((uint8_t*)&x)[3];
+        return (chunks+1)*3;
+    case 1:
+        x = d3[y >> 24];
+        *p =  (uint8_t)x;
+        break;
+    case 2:
+        x = d3[y >> 24] *64 + d3[(y >> 16) & 0xff];
+        *p =  (uint8_t)(x >> 4);
+        break;
+    default:  /* case 3 */
+        x = (d3[y >> 24] *64 + d3[(y >> 16) & 0xff])*64 +
+            d3[(y >> 8) & 0xff];
+        *p++ = (uint8_t) (x >> 10);
+        *p = (uint8_t) (x >> 2);
+        break;
+    }
+
+    if (x >= BADCHAR) return MODP_B64_ERROR;
+    return 3*chunks + (6*leftover)/8;
+}
+
+#else /* LITTLE  ENDIAN -- INTEL AND FRIENDS */
+
+size_t modp_b64_decode(char* dest, const char* src, size_t len)
+{
+    if (len == 0) return 0;
+
+#ifdef DOPAD
+    /*
+     * if padding is used, then the message must be at least
+     * 4 chars and be a multiple of 4
+     */
+    if (len < 4 || (len % 4 != 0)) return MODP_B64_ERROR; /* error */
+    /* there can be at most 2 pad chars at the end */
+    if (src[len-1] == CHARPAD) {
+        len--;
+        if (src[len -1] == CHARPAD) {
+            len--;
+        }
+    }
+#endif
+
+    size_t i;
+    int leftover = len % 4;
+    size_t chunks = (leftover == 0) ? len / 4 - 1 : len /4;
+
+    uint8_t* p = (uint8_t*)dest;
+    uint32_t x = 0;
+    uint32_t* destInt = (uint32_t*) p;
+    uint32_t* srcInt = (uint32_t*) src;
+    uint32_t y = *srcInt++;
+    for (i = 0; i < chunks; ++i) {
+        x = d0[y & 0xff] |
+            d1[(y >> 8) & 0xff] |
+            d2[(y >> 16) & 0xff] |
+            d3[(y >> 24) & 0xff];
+
+        if (x >= BADCHAR) return MODP_B64_ERROR;
+        *destInt = x ;
+        p += 3;
+        destInt = (uint32_t*)p;
+        y = *srcInt++;}
+
+
+    switch (leftover) {
+    case 0:
+        x = d0[y & 0xff] |
+            d1[(y >> 8) & 0xff] |
+            d2[(y >> 16) & 0xff] |
+            d3[(y >> 24) & 0xff];
+
+        if (x >= BADCHAR) return MODP_B64_ERROR;
+        *p++ =  ((uint8_t*)(&x))[0];
+        *p++ =  ((uint8_t*)(&x))[1];
+        *p =    ((uint8_t*)(&x))[2];
+        return (chunks+1)*3;
+        break;
+    case 1:  /* with padding this is an impossible case */
+        x = d0[y & 0xff];
+        *p = *((uint8_t*)(&x)); // i.e. first char/byte in int
+        break;
+    case 2: // * case 2, 1  output byte */
+        x = d0[y & 0xff] | d1[y >> 8 & 0xff];
+        *p = *((uint8_t*)(&x)); // i.e. first char
+        break;
+    default: /* case 3, 2 output bytes */
+        x = d0[y & 0xff] |
+            d1[y >> 8 & 0xff ] |
+            d2[y >> 16 & 0xff];  /* 0x3c */
+        *p++ =  ((uint8_t*)(&x))[0];
+        *p =  ((uint8_t*)(&x))[1];
+        break;
+    }
+
+    if (x >= BADCHAR) return MODP_B64_ERROR;
+
+    return 3*chunks + (6*leftover)/8;
+}
+
+#endif  /* if bigendian / else / endif */
diff --git a/service/modp_b64/modp_b64.h b/service/modp_b64/modp_b64.h
new file mode 100644
index 0000000..3270e5f
--- /dev/null
+++ b/service/modp_b64/modp_b64.h
@@ -0,0 +1,171 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
+/* vi: set expandtab shiftwidth=4 tabstop=4: */
+
+/**
+ * \file
+ * <PRE>
+ * High performance base64 encoder / decoder
+ * Version 1.3 -- 17-Mar-2006
+ *
+ * Copyright &copy; 2005, 2006, Nick Galbreath -- nickg [at] modp [dot] com
+ * All rights reserved.
+ *
+ * http://modp.com/release/base64
+ *
+ * Released under bsd license.  See modp_b64.c for details.
+ * </pre>
+ *
+ * The default implementation is the standard b64 encoding with padding.
+ * It's easy to change this to use "URL safe" characters and to remove
+ * padding.  See the modp_b64.c source code for details.
+ *
+ */
+
+#ifndef MODP_B64
+#define MODP_B64
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Encode a raw binary string into base 64.
+ * src contains the bytes
+ * len contains the number of bytes in the src
+ * dest should be allocated by the caller to contain
+ *   at least modp_b64_encode_len(len) bytes (see below)
+ *   This will contain the null-terminated b64 encoded result
+ * returns length of the destination string plus the ending null byte
+ *    i.e.  the result will be equal to strlen(dest) + 1
+ *
+ * Example
+ * 
+ * \code
+ * char* src = ...;
+ * int srclen = ...; //the length of number of bytes in src
+ * char* dest = (char*) malloc(modp_b64_encode_len);
+ * int len = modp_b64_encode(dest, src, sourcelen);
+ * if (len == -1) {
+ *   printf("Error\n");
+ * } else {
+ *   printf("b64 = %s\n", dest);
+ * }
+ * \endcode
+ *
+ */
+size_t modp_b64_encode(char* dest, const char* str, size_t len);
+
+/**
+ * Decode a base64 encoded string
+ *
+ * src should contain exactly len bytes of b64 characters.
+ *     if src contains -any- non-base characters (such as white
+ *     space, -1 is returned.
+ *
+ * dest should be allocated by the caller to contain at least
+ *    len * 3 / 4 bytes.
+ *
+ * Returns the length (strlen) of the output, or -1 if unable to
+ * decode
+ *
+ * \code
+ * char* src = ...;
+ * int srclen = ...; // or if you don't know use strlen(src)
+ * char* dest = (char*) malloc(modp_b64_decode_len(srclen));
+ * int len = modp_b64_decode(dest, src, sourcelen);
+ * if (len == -1) { error }
+ * \endcode
+ */
+size_t modp_b64_decode(char* dest, const char* src, size_t len);
+
+/**
+ * Given a source string of length len, this returns the amount of
+ * memory the destination string should have.
+ *
+ * remember, this is integer math
+ * 3 bytes turn into 4 chars
+ * ceiling[len / 3] * 4 + 1
+ *
+ * +1 is for any extra null.
+ */
+#define modp_b64_encode_len(A) ((A+2)/3 * 4 + 1)
+
+/**
+ * Given a base64 string of length len,
+ *   this returns the amount of memory required for output string
+ *  It maybe be more than the actual number of bytes written.
+ * NOTE: remember this is integer math
+ * this allocates a bit more memory than traditional versions of b64
+ * decode  4 chars turn into 3 bytes
+ * floor[len * 3/4] + 2
+ */
+#define modp_b64_decode_len(A) (A / 4 * 3 + 2)
+
+/**
+ * Will return the strlen of the output from encoding.
+ * This may be less than the required number of bytes allocated.
+ *
+ * This allows you to 'deserialized' a struct
+ * \code
+ * char* b64encoded = "...";
+ * int len = strlen(b64encoded);
+ *
+ * struct datastuff foo;
+ * if (modp_b64_encode_strlen(sizeof(struct datastuff)) != len) {
+ *    // wrong size
+ *    return false;
+ * } else {
+ *    // safe to do;
+ *    if (modp_b64_decode((char*) &foo, b64encoded, len) == -1) {
+ *      // bad characters
+ *      return false;
+ *    }
+ * }
+ * // foo is filled out now
+ * \endcode
+ */
+#define modp_b64_encode_strlen(A) ((A + 2)/ 3 * 4)
+
+#define MODP_B64_ERROR ((size_t)-1)
+
+#ifdef __cplusplus
+}
+
+#include <string>
+
+inline std::string& modp_b64_encode(std::string& s)
+{
+    std::string x(modp_b64_encode_len(s.size()), '\0');
+    size_t d = modp_b64_encode(const_cast<char*>(x.data()), s.data(), (int)s.size());
+    x.erase(d, std::string::npos);
+    s.swap(x);
+    return s;
+}
+
+/**
+ * base 64 decode a string (self-modifing)
+ * On failure, the string is empty.
+ *
+ * This function is for C++ only (duh)
+ *
+ * \param[in,out] s the string to be decoded
+ * \return a reference to the input string
+ */
+inline std::string& modp_b64_decode(std::string& s)
+{
+    std::string x(modp_b64_decode_len(s.size()), '\0');
+    size_t d = modp_b64_decode(const_cast<char*>(x.data()), s.data(), (int)s.size());
+    if (d == MODP_B64_ERROR) {
+        x.clear();
+    } else {
+        x.erase(d, std::string::npos);
+    }
+    s.swap(x);
+    return s;
+}
+
+#endif /* __cplusplus */
+
+#endif /* MODP_B64 */
diff --git a/service/modp_b64/modp_b64_data.h b/service/modp_b64/modp_b64_data.h
new file mode 100644
index 0000000..9a777b8
--- /dev/null
+++ b/service/modp_b64/modp_b64_data.h
@@ -0,0 +1,482 @@
+//#include "build/build_config.h"
+#include <stdint.h>
+
+#define CHAR62 '+'
+#define CHAR63 '/'
+#define CHARPAD '='
+static const char e0[256] = {
+ 'A',  'A',  'A',  'A',  'B',  'B',  'B',  'B',  'C',  'C',
+ 'C',  'C',  'D',  'D',  'D',  'D',  'E',  'E',  'E',  'E',
+ 'F',  'F',  'F',  'F',  'G',  'G',  'G',  'G',  'H',  'H',
+ 'H',  'H',  'I',  'I',  'I',  'I',  'J',  'J',  'J',  'J',
+ 'K',  'K',  'K',  'K',  'L',  'L',  'L',  'L',  'M',  'M',
+ 'M',  'M',  'N',  'N',  'N',  'N',  'O',  'O',  'O',  'O',
+ 'P',  'P',  'P',  'P',  'Q',  'Q',  'Q',  'Q',  'R',  'R',
+ 'R',  'R',  'S',  'S',  'S',  'S',  'T',  'T',  'T',  'T',
+ 'U',  'U',  'U',  'U',  'V',  'V',  'V',  'V',  'W',  'W',
+ 'W',  'W',  'X',  'X',  'X',  'X',  'Y',  'Y',  'Y',  'Y',
+ 'Z',  'Z',  'Z',  'Z',  'a',  'a',  'a',  'a',  'b',  'b',
+ 'b',  'b',  'c',  'c',  'c',  'c',  'd',  'd',  'd',  'd',
+ 'e',  'e',  'e',  'e',  'f',  'f',  'f',  'f',  'g',  'g',
+ 'g',  'g',  'h',  'h',  'h',  'h',  'i',  'i',  'i',  'i',
+ 'j',  'j',  'j',  'j',  'k',  'k',  'k',  'k',  'l',  'l',
+ 'l',  'l',  'm',  'm',  'm',  'm',  'n',  'n',  'n',  'n',
+ 'o',  'o',  'o',  'o',  'p',  'p',  'p',  'p',  'q',  'q',
+ 'q',  'q',  'r',  'r',  'r',  'r',  's',  's',  's',  's',
+ 't',  't',  't',  't',  'u',  'u',  'u',  'u',  'v',  'v',
+ 'v',  'v',  'w',  'w',  'w',  'w',  'x',  'x',  'x',  'x',
+ 'y',  'y',  'y',  'y',  'z',  'z',  'z',  'z',  '0',  '0',
+ '0',  '0',  '1',  '1',  '1',  '1',  '2',  '2',  '2',  '2',
+ '3',  '3',  '3',  '3',  '4',  '4',  '4',  '4',  '5',  '5',
+ '5',  '5',  '6',  '6',  '6',  '6',  '7',  '7',  '7',  '7',
+ '8',  '8',  '8',  '8',  '9',  '9',  '9',  '9',  '+',  '+',
+ '+',  '+',  '/',  '/',  '/',  '/'
+};
+
+static const char e1[256] = {
+ 'A',  'B',  'C',  'D',  'E',  'F',  'G',  'H',  'I',  'J',
+ 'K',  'L',  'M',  'N',  'O',  'P',  'Q',  'R',  'S',  'T',
+ 'U',  'V',  'W',  'X',  'Y',  'Z',  'a',  'b',  'c',  'd',
+ 'e',  'f',  'g',  'h',  'i',  'j',  'k',  'l',  'm',  'n',
+ 'o',  'p',  'q',  'r',  's',  't',  'u',  'v',  'w',  'x',
+ 'y',  'z',  '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',
+ '8',  '9',  '+',  '/',  'A',  'B',  'C',  'D',  'E',  'F',
+ 'G',  'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',  'P',
+ 'Q',  'R',  'S',  'T',  'U',  'V',  'W',  'X',  'Y',  'Z',
+ 'a',  'b',  'c',  'd',  'e',  'f',  'g',  'h',  'i',  'j',
+ 'k',  'l',  'm',  'n',  'o',  'p',  'q',  'r',  's',  't',
+ 'u',  'v',  'w',  'x',  'y',  'z',  '0',  '1',  '2',  '3',
+ '4',  '5',  '6',  '7',  '8',  '9',  '+',  '/',  'A',  'B',
+ 'C',  'D',  'E',  'F',  'G',  'H',  'I',  'J',  'K',  'L',
+ 'M',  'N',  'O',  'P',  'Q',  'R',  'S',  'T',  'U',  'V',
+ 'W',  'X',  'Y',  'Z',  'a',  'b',  'c',  'd',  'e',  'f',
+ 'g',  'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',  'p',
+ 'q',  'r',  's',  't',  'u',  'v',  'w',  'x',  'y',  'z',
+ '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',  '8',  '9',
+ '+',  '/',  'A',  'B',  'C',  'D',  'E',  'F',  'G',  'H',
+ 'I',  'J',  'K',  'L',  'M',  'N',  'O',  'P',  'Q',  'R',
+ 'S',  'T',  'U',  'V',  'W',  'X',  'Y',  'Z',  'a',  'b',
+ 'c',  'd',  'e',  'f',  'g',  'h',  'i',  'j',  'k',  'l',
+ 'm',  'n',  'o',  'p',  'q',  'r',  's',  't',  'u',  'v',
+ 'w',  'x',  'y',  'z',  '0',  '1',  '2',  '3',  '4',  '5',
+ '6',  '7',  '8',  '9',  '+',  '/'
+};
+
+static const char e2[256] = {
+ 'A',  'B',  'C',  'D',  'E',  'F',  'G',  'H',  'I',  'J',
+ 'K',  'L',  'M',  'N',  'O',  'P',  'Q',  'R',  'S',  'T',
+ 'U',  'V',  'W',  'X',  'Y',  'Z',  'a',  'b',  'c',  'd',
+ 'e',  'f',  'g',  'h',  'i',  'j',  'k',  'l',  'm',  'n',
+ 'o',  'p',  'q',  'r',  's',  't',  'u',  'v',  'w',  'x',
+ 'y',  'z',  '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',
+ '8',  '9',  '+',  '/',  'A',  'B',  'C',  'D',  'E',  'F',
+ 'G',  'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',  'P',
+ 'Q',  'R',  'S',  'T',  'U',  'V',  'W',  'X',  'Y',  'Z',
+ 'a',  'b',  'c',  'd',  'e',  'f',  'g',  'h',  'i',  'j',
+ 'k',  'l',  'm',  'n',  'o',  'p',  'q',  'r',  's',  't',
+ 'u',  'v',  'w',  'x',  'y',  'z',  '0',  '1',  '2',  '3',
+ '4',  '5',  '6',  '7',  '8',  '9',  '+',  '/',  'A',  'B',
+ 'C',  'D',  'E',  'F',  'G',  'H',  'I',  'J',  'K',  'L',
+ 'M',  'N',  'O',  'P',  'Q',  'R',  'S',  'T',  'U',  'V',
+ 'W',  'X',  'Y',  'Z',  'a',  'b',  'c',  'd',  'e',  'f',
+ 'g',  'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',  'p',
+ 'q',  'r',  's',  't',  'u',  'v',  'w',  'x',  'y',  'z',
+ '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',  '8',  '9',
+ '+',  '/',  'A',  'B',  'C',  'D',  'E',  'F',  'G',  'H',
+ 'I',  'J',  'K',  'L',  'M',  'N',  'O',  'P',  'Q',  'R',
+ 'S',  'T',  'U',  'V',  'W',  'X',  'Y',  'Z',  'a',  'b',
+ 'c',  'd',  'e',  'f',  'g',  'h',  'i',  'j',  'k',  'l',
+ 'm',  'n',  'o',  'p',  'q',  'r',  's',  't',  'u',  'v',
+ 'w',  'x',  'y',  'z',  '0',  '1',  '2',  '3',  '4',  '5',
+ '6',  '7',  '8',  '9',  '+',  '/'
+};
+
+
+
+#ifdef WORDS_BIGENDIAN
+
+
+/* SPECIAL DECODE TABLES FOR BIG ENDIAN (IBM/MOTOROLA/SUN) CPUS */
+
+static const uint32_t d0[256] = {
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x00f80000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00fc0000,
+0x00d00000, 0x00d40000, 0x00d80000, 0x00dc0000, 0x00e00000, 0x00e40000,
+0x00e80000, 0x00ec0000, 0x00f00000, 0x00f40000, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
+0x00040000, 0x00080000, 0x000c0000, 0x00100000, 0x00140000, 0x00180000,
+0x001c0000, 0x00200000, 0x00240000, 0x00280000, 0x002c0000, 0x00300000,
+0x00340000, 0x00380000, 0x003c0000, 0x00400000, 0x00440000, 0x00480000,
+0x004c0000, 0x00500000, 0x00540000, 0x00580000, 0x005c0000, 0x00600000,
+0x00640000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x00680000, 0x006c0000, 0x00700000, 0x00740000, 0x00780000,
+0x007c0000, 0x00800000, 0x00840000, 0x00880000, 0x008c0000, 0x00900000,
+0x00940000, 0x00980000, 0x009c0000, 0x00a00000, 0x00a40000, 0x00a80000,
+0x00ac0000, 0x00b00000, 0x00b40000, 0x00b80000, 0x00bc0000, 0x00c00000,
+0x00c40000, 0x00c80000, 0x00cc0000, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff
+};
+
+
+static const uint32_t d1[256] = {
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x0003e000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x0003f000,
+0x00034000, 0x00035000, 0x00036000, 0x00037000, 0x00038000, 0x00039000,
+0x0003a000, 0x0003b000, 0x0003c000, 0x0003d000, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
+0x00001000, 0x00002000, 0x00003000, 0x00004000, 0x00005000, 0x00006000,
+0x00007000, 0x00008000, 0x00009000, 0x0000a000, 0x0000b000, 0x0000c000,
+0x0000d000, 0x0000e000, 0x0000f000, 0x00010000, 0x00011000, 0x00012000,
+0x00013000, 0x00014000, 0x00015000, 0x00016000, 0x00017000, 0x00018000,
+0x00019000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x0001a000, 0x0001b000, 0x0001c000, 0x0001d000, 0x0001e000,
+0x0001f000, 0x00020000, 0x00021000, 0x00022000, 0x00023000, 0x00024000,
+0x00025000, 0x00026000, 0x00027000, 0x00028000, 0x00029000, 0x0002a000,
+0x0002b000, 0x0002c000, 0x0002d000, 0x0002e000, 0x0002f000, 0x00030000,
+0x00031000, 0x00032000, 0x00033000, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff
+};
+
+
+static const uint32_t d2[256] = {
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x00000f80, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000fc0,
+0x00000d00, 0x00000d40, 0x00000d80, 0x00000dc0, 0x00000e00, 0x00000e40,
+0x00000e80, 0x00000ec0, 0x00000f00, 0x00000f40, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
+0x00000040, 0x00000080, 0x000000c0, 0x00000100, 0x00000140, 0x00000180,
+0x000001c0, 0x00000200, 0x00000240, 0x00000280, 0x000002c0, 0x00000300,
+0x00000340, 0x00000380, 0x000003c0, 0x00000400, 0x00000440, 0x00000480,
+0x000004c0, 0x00000500, 0x00000540, 0x00000580, 0x000005c0, 0x00000600,
+0x00000640, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x00000680, 0x000006c0, 0x00000700, 0x00000740, 0x00000780,
+0x000007c0, 0x00000800, 0x00000840, 0x00000880, 0x000008c0, 0x00000900,
+0x00000940, 0x00000980, 0x000009c0, 0x00000a00, 0x00000a40, 0x00000a80,
+0x00000ac0, 0x00000b00, 0x00000b40, 0x00000b80, 0x00000bc0, 0x00000c00,
+0x00000c40, 0x00000c80, 0x00000cc0, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff
+};
+
+
+static const uint32_t d3[256] = {
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x0000003e, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x0000003f,
+0x00000034, 0x00000035, 0x00000036, 0x00000037, 0x00000038, 0x00000039,
+0x0000003a, 0x0000003b, 0x0000003c, 0x0000003d, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
+0x00000001, 0x00000002, 0x00000003, 0x00000004, 0x00000005, 0x00000006,
+0x00000007, 0x00000008, 0x00000009, 0x0000000a, 0x0000000b, 0x0000000c,
+0x0000000d, 0x0000000e, 0x0000000f, 0x00000010, 0x00000011, 0x00000012,
+0x00000013, 0x00000014, 0x00000015, 0x00000016, 0x00000017, 0x00000018,
+0x00000019, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x0000001a, 0x0000001b, 0x0000001c, 0x0000001d, 0x0000001e,
+0x0000001f, 0x00000020, 0x00000021, 0x00000022, 0x00000023, 0x00000024,
+0x00000025, 0x00000026, 0x00000027, 0x00000028, 0x00000029, 0x0000002a,
+0x0000002b, 0x0000002c, 0x0000002d, 0x0000002e, 0x0000002f, 0x00000030,
+0x00000031, 0x00000032, 0x00000033, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff
+};
+
+
+#else
+
+
+/* SPECIAL DECODE TABLES FOR LITTLE ENDIAN (INTEL) CPUS */
+
+static const uint32_t d0[256] = {
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x000000f8, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x000000fc,
+0x000000d0, 0x000000d4, 0x000000d8, 0x000000dc, 0x000000e0, 0x000000e4,
+0x000000e8, 0x000000ec, 0x000000f0, 0x000000f4, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
+0x00000004, 0x00000008, 0x0000000c, 0x00000010, 0x00000014, 0x00000018,
+0x0000001c, 0x00000020, 0x00000024, 0x00000028, 0x0000002c, 0x00000030,
+0x00000034, 0x00000038, 0x0000003c, 0x00000040, 0x00000044, 0x00000048,
+0x0000004c, 0x00000050, 0x00000054, 0x00000058, 0x0000005c, 0x00000060,
+0x00000064, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x00000068, 0x0000006c, 0x00000070, 0x00000074, 0x00000078,
+0x0000007c, 0x00000080, 0x00000084, 0x00000088, 0x0000008c, 0x00000090,
+0x00000094, 0x00000098, 0x0000009c, 0x000000a0, 0x000000a4, 0x000000a8,
+0x000000ac, 0x000000b0, 0x000000b4, 0x000000b8, 0x000000bc, 0x000000c0,
+0x000000c4, 0x000000c8, 0x000000cc, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff
+};
+
+
+static const uint32_t d1[256] = {
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x0000e003, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x0000f003,
+0x00004003, 0x00005003, 0x00006003, 0x00007003, 0x00008003, 0x00009003,
+0x0000a003, 0x0000b003, 0x0000c003, 0x0000d003, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
+0x00001000, 0x00002000, 0x00003000, 0x00004000, 0x00005000, 0x00006000,
+0x00007000, 0x00008000, 0x00009000, 0x0000a000, 0x0000b000, 0x0000c000,
+0x0000d000, 0x0000e000, 0x0000f000, 0x00000001, 0x00001001, 0x00002001,
+0x00003001, 0x00004001, 0x00005001, 0x00006001, 0x00007001, 0x00008001,
+0x00009001, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x0000a001, 0x0000b001, 0x0000c001, 0x0000d001, 0x0000e001,
+0x0000f001, 0x00000002, 0x00001002, 0x00002002, 0x00003002, 0x00004002,
+0x00005002, 0x00006002, 0x00007002, 0x00008002, 0x00009002, 0x0000a002,
+0x0000b002, 0x0000c002, 0x0000d002, 0x0000e002, 0x0000f002, 0x00000003,
+0x00001003, 0x00002003, 0x00003003, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff
+};
+
+
+static const uint32_t d2[256] = {
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x00800f00, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00c00f00,
+0x00000d00, 0x00400d00, 0x00800d00, 0x00c00d00, 0x00000e00, 0x00400e00,
+0x00800e00, 0x00c00e00, 0x00000f00, 0x00400f00, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
+0x00400000, 0x00800000, 0x00c00000, 0x00000100, 0x00400100, 0x00800100,
+0x00c00100, 0x00000200, 0x00400200, 0x00800200, 0x00c00200, 0x00000300,
+0x00400300, 0x00800300, 0x00c00300, 0x00000400, 0x00400400, 0x00800400,
+0x00c00400, 0x00000500, 0x00400500, 0x00800500, 0x00c00500, 0x00000600,
+0x00400600, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x00800600, 0x00c00600, 0x00000700, 0x00400700, 0x00800700,
+0x00c00700, 0x00000800, 0x00400800, 0x00800800, 0x00c00800, 0x00000900,
+0x00400900, 0x00800900, 0x00c00900, 0x00000a00, 0x00400a00, 0x00800a00,
+0x00c00a00, 0x00000b00, 0x00400b00, 0x00800b00, 0x00c00b00, 0x00000c00,
+0x00400c00, 0x00800c00, 0x00c00c00, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff
+};
+
+
+static const uint32_t d3[256] = {
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x003e0000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x003f0000,
+0x00340000, 0x00350000, 0x00360000, 0x00370000, 0x00380000, 0x00390000,
+0x003a0000, 0x003b0000, 0x003c0000, 0x003d0000, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x00000000,
+0x00010000, 0x00020000, 0x00030000, 0x00040000, 0x00050000, 0x00060000,
+0x00070000, 0x00080000, 0x00090000, 0x000a0000, 0x000b0000, 0x000c0000,
+0x000d0000, 0x000e0000, 0x000f0000, 0x00100000, 0x00110000, 0x00120000,
+0x00130000, 0x00140000, 0x00150000, 0x00160000, 0x00170000, 0x00180000,
+0x00190000, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x001a0000, 0x001b0000, 0x001c0000, 0x001d0000, 0x001e0000,
+0x001f0000, 0x00200000, 0x00210000, 0x00220000, 0x00230000, 0x00240000,
+0x00250000, 0x00260000, 0x00270000, 0x00280000, 0x00290000, 0x002a0000,
+0x002b0000, 0x002c0000, 0x002d0000, 0x002e0000, 0x002f0000, 0x00300000,
+0x00310000, 0x00320000, 0x00330000, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff,
+0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff
+};
+
+
+#endif
diff --git a/service/uuid.cpp b/service/uuid.cpp
new file mode 100644
index 0000000..13e21a1
--- /dev/null
+++ b/service/uuid.cpp
@@ -0,0 +1,86 @@
+//
+//  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 "uuid.h"
+
+#include <algorithm>
+#include <array>
+#include <stack>
+#include <string>
+
+namespace bluetooth {
+
+void Uuid::InitializeDefault() {
+  // Initialize to base bluetooth UUID.
+  id_ = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+         0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
+}
+
+Uuid::Uuid() {
+  InitializeDefault();
+}
+
+Uuid::Uuid(const std::string& uuid) {
+  InitializeDefault();
+  const int start_index = uuid.size() == 4 ? 2 : 0;
+  const size_t copy_size = std::min(id_.size(), uuid.size() / 2);
+  for (size_t i = 0; i < copy_size; ++i) {
+    std::string octet_text(uuid, i * 2, 2);
+    id_[start_index + i] = std::stoul(octet_text, 0, 16);
+  }
+}
+
+Uuid::Uuid(const bt_uuid_t& uuid) {
+  std::reverse_copy(uuid.uu, uuid.uu + sizeof(uuid.uu), id_.begin());
+}
+
+Uuid::Uuid(const Uuid::Uuid16Bit& uuid) {
+  InitializeDefault();
+  std::copy(uuid.begin(), uuid.end(), id_.begin() + kUuid16Octets);
+}
+
+Uuid::Uuid(const Uuid::Uuid32Bit& uuid) {
+  InitializeDefault();
+  std::copy(uuid.begin(), uuid.end(), id_.begin());
+}
+
+Uuid::Uuid(const Uuid::Uuid128Bit& uuid) : id_(uuid) {}
+
+const Uuid::Uuid128Bit Uuid::GetFullBigEndian() const {
+  return id_;
+}
+
+const Uuid::Uuid128Bit Uuid::GetFullLittleEndian() const {
+  Uuid::Uuid128Bit ret;
+  std::reverse_copy(id_.begin(), id_.end(), ret.begin());
+  return ret;
+}
+
+const bt_uuid_t Uuid::GetBlueDroid() const {
+  bt_uuid_t ret;
+  std::reverse_copy(id_.begin(), id_.end(), ret.uu);
+  return ret;
+}
+
+bool Uuid::operator<(const Uuid& rhs) const {
+  return std::lexicographical_compare(id_.begin(), id_.end(), rhs.id_.begin(),
+                                      rhs.id_.end());
+}
+
+bool Uuid::operator==(const Uuid& rhs) const {
+  return std::equal(id_.begin(), id_.end(), rhs.id_.begin());
+}
+
+}  // namespace bluetooth
diff --git a/service/uuid.h b/service/uuid.h
new file mode 100644
index 0000000..0226ef6
--- /dev/null
+++ b/service/uuid.h
@@ -0,0 +1,69 @@
+//
+//  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 <array>
+#include <string>
+
+#include "hardware/bluetooth.h"
+
+namespace bluetooth {
+
+class Uuid {
+ public:
+  enum Type {
+    kUuid128Octets = 16,
+    kUuid32Octets = 4,
+    kUuid16Octets = 2,
+  };
+
+  typedef std::array<uint8_t, Uuid::kUuid16Octets> Uuid16Bit;
+  typedef std::array<uint8_t, Uuid::kUuid32Octets> Uuid32Bit;
+  typedef std::array<uint8_t, Uuid::kUuid128Octets> Uuid128Bit;
+
+  // Construct a Bluetooth 'base' UUID.
+  Uuid();
+
+  // BlueDroid constructor.
+  explicit Uuid(const bt_uuid_t& uuid);
+
+  // String constructor. Only hex ASCII accepted.
+  explicit Uuid(const std::string& uuid);
+
+  // std::array variants constructors.
+  explicit Uuid(const Uuid::Uuid16Bit& uuid);
+  explicit Uuid(const Uuid::Uuid32Bit& uuid);
+  explicit Uuid(const Uuid::Uuid128Bit& uuid);
+
+  // Provide the full network-byte-ordered blob.
+  const Uuid128Bit GetFullBigEndian() const;
+
+  // Provide blob in Little endian (BlueDroid expects this).
+  const Uuid128Bit GetFullLittleEndian() const;
+
+  // Helper for bluedroid LE type.
+  const bt_uuid_t GetBlueDroid() const;
+
+  bool operator<(const Uuid& rhs) const;
+  bool operator==(const Uuid& rhs) const;
+
+ private:
+  void InitializeDefault();
+  // Network-byte-ordered ID.
+  Uuid128Bit id_;
+};
+
+}  // namespace bluetooth
diff --git a/service/uuid_test.cpp b/service/uuid_test.cpp
new file mode 100644
index 0000000..a04c336
--- /dev/null
+++ b/service/uuid_test.cpp
@@ -0,0 +1,123 @@
+//
+//  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 <algorithm>
+#include <array>
+#include <stdint.h>
+
+#include <gtest/gtest.h>
+
+#include "uuid.h"
+
+using namespace bluetooth;
+
+namespace {
+
+const std::array<uint8_t, Uuid::kUuid128Octets> kBtSigBaseUuid = {
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+      0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb, }
+};
+
+}  // namespace
+
+// Verify that an uninitialized Uuid is equal
+// To the BT SIG Base UUID.
+TEST(UuidTest, DefaultUuid) {
+  Uuid uuid;
+  ASSERT_TRUE(uuid.GetFullBigEndian() == kBtSigBaseUuid);
+}
+
+// Verify that we initialize a 16-bit UUID in a
+// way consistent with how we read it.
+TEST(UuidTest, Init16Bit) {
+  auto my_uuid_16 = kBtSigBaseUuid;
+  my_uuid_16[2] = 0xde;
+  my_uuid_16[3] = 0xad;
+  Uuid uuid(Uuid::Uuid16Bit({{ 0xde, 0xad }}));
+  ASSERT_TRUE(uuid.GetFullBigEndian() == my_uuid_16);
+}
+
+// Verify that we initialize a 16-bit UUID in a
+// way consistent with how we read it.
+TEST(UuidTest, Init16BitString) {
+  auto my_uuid_16 = kBtSigBaseUuid;
+  my_uuid_16[2] = 0xde;
+  my_uuid_16[3] = 0xad;
+  Uuid uuid("dead");
+  ASSERT_TRUE(uuid.GetFullBigEndian() == my_uuid_16);
+}
+
+
+// Verify that we initialize a 32-bit UUID in a
+// way consistent with how we read it.
+TEST(UuidTest, Init32Bit) {
+  auto my_uuid_32 = kBtSigBaseUuid;
+  my_uuid_32[0] = 0xde;
+  my_uuid_32[1] = 0xad;
+  my_uuid_32[2] = 0xbe;
+  my_uuid_32[3] = 0xef;
+  Uuid uuid(Uuid::Uuid32Bit({{ 0xde, 0xad, 0xbe, 0xef }}));
+  ASSERT_TRUE(uuid.GetFullBigEndian() == my_uuid_32);
+}
+
+// Verify correct reading of a 32-bit UUID initialized from string.
+TEST(UuidTest, Init32BitString) {
+  auto my_uuid_32 = kBtSigBaseUuid;
+  my_uuid_32[0] = 0xde;
+  my_uuid_32[1] = 0xad;
+  my_uuid_32[2] = 0xbe;
+  my_uuid_32[3] = 0xef;
+  Uuid uuid("deadbeef");
+  ASSERT_TRUE(uuid.GetFullBigEndian() == my_uuid_32);
+}
+
+// Verify that we initialize a 128-bit UUID in a
+// way consistent with how we read it.
+TEST(UuidTest, Init128Bit) {
+  auto my_uuid_128 = kBtSigBaseUuid;
+  for (int i = 0; i < static_cast<int>(my_uuid_128.size()); ++i) {
+    my_uuid_128[i] = i;
+  }
+
+  Uuid uuid(my_uuid_128);
+  ASSERT_TRUE(uuid.GetFullBigEndian() == my_uuid_128);
+}
+
+// Verify that we initialize a 128-bit UUID in a
+// way consistent with how we read it as LE.
+TEST(UuidTest, Init128BitLittleEndian) {
+  auto my_uuid_128 = kBtSigBaseUuid;
+  for (int i = 0; i < static_cast<int>(my_uuid_128.size()); ++i) {
+    my_uuid_128[i] = i;
+  }
+
+  Uuid uuid(my_uuid_128);
+  std::reverse(my_uuid_128.begin(), my_uuid_128.end());
+  ASSERT_TRUE(uuid.GetFullLittleEndian() == my_uuid_128);
+}
+
+// Verify that we initialize a 128-bit UUID in a
+// way consistent with how we read it.
+TEST(UuidTest, Init128BitString) {
+  auto my_uuid_128 = kBtSigBaseUuid;
+  for (int i = 0; i < static_cast<int>(my_uuid_128.size()); ++i) {
+    my_uuid_128[i] = i;
+  }
+
+  std::string uuid_text("000102030405060708090A0B0C0D0E0F");
+  ASSERT_TRUE(uuid_text.size() == (16 * 2));
+  Uuid uuid(uuid_text);
+  ASSERT_TRUE(uuid.GetFullBigEndian() == my_uuid_128);
+}
diff --git a/stack/BUILD.gn b/stack/BUILD.gn
new file mode 100644
index 0000000..f8ea514
--- /dev/null
+++ b/stack/BUILD.gn
@@ -0,0 +1,169 @@
+#
+#  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.
+#
+
+static_library("stack") {
+  sources = [
+    "a2dp/a2d_api.c",
+    "a2dp/a2d_sbc.c",
+    "avrc/avrc_api.c",
+    "avrc/avrc_sdp.c",
+    "avrc/avrc_opt.c",
+    "avrc/avrc_bld_tg.c",
+    "avrc/avrc_bld_ct.c",
+    "avrc/avrc_pars_tg.c",
+    "avrc/avrc_pars_ct.c",
+    "avrc/avrc_utils.c",
+    "hid/hidh_api.c",
+    "hid/hidh_conn.c",
+    "bnep/bnep_main.c",
+    "bnep/bnep_utils.c",
+    "bnep/bnep_api.c",
+    "hcic/hciblecmds.c",
+    "hcic/hcicmds.c",
+    "btm/btm_ble.c",
+    "btm/btm_sec.c",
+    "btm/btm_inq.c",
+    "btm/btm_ble_addr.c",
+    "btm/btm_ble_bgconn.c",
+    "btm/btm_main.c",
+    "btm/btm_dev.c",
+    "btm/btm_ble_gap.c",
+    "btm/btm_ble_adv_filter.c",
+    "btm/btm_ble_multi_adv.c",
+    "btm/btm_ble_batchscan.c",
+    "btm/btm_ble_cont_energy.c",
+    "btm/btm_ble_privacy.c",
+    "btm/btm_acl.c",
+    "btm/btm_sco.c",
+    "btm/btm_pm.c",
+    "btm/btm_devctl.c",
+    "rfcomm/rfc_utils.c",
+    "rfcomm/port_rfc.c",
+    "rfcomm/rfc_l2cap_if.c",
+    "rfcomm/rfc_mx_fsm.c",
+    "rfcomm/port_utils.c",
+    "rfcomm/rfc_port_fsm.c",
+    "rfcomm/rfc_port_if.c",
+    "rfcomm/port_api.c",
+    "rfcomm/rfc_ts_frames.c",
+    "mcap/mca_dact.c",
+    "mcap/mca_dsm.c",
+    "mcap/mca_l2c.c",
+    "mcap/mca_main.c",
+    "mcap/mca_csm.c",
+    "mcap/mca_cact.c",
+    "mcap/mca_api.c",
+    "gatt/gatt_sr.c",
+    "gatt/gatt_cl.c",
+    "gatt/gatt_api.c",
+    "gatt/gatt_auth.c",
+    "gatt/gatt_utils.c",
+    "gatt/gatt_main.c",
+    "gatt/att_protocol.c",
+    "gatt/gatt_attr.c",
+    "gatt/gatt_db.c",
+    "avct/avct_api.c",
+    "avct/avct_l2c.c",
+    "avct/avct_lcb.c",
+    "avct/avct_ccb.c",
+    "avct/avct_lcb_act.c",
+    "smp/smp_main.c",
+    "smp/smp_l2c.c",
+    "smp/smp_cmac.c",
+    "smp/smp_utils.c",
+    "smp/smp_act.c",
+    "smp/smp_keys.c",
+    "smp/smp_api.c",
+    "smp/aes.c",
+    "smp/smp_br_main.c",
+    "smp/p_256_curvepara.c",
+    "smp/p_256_ecc_pp.c",
+    "smp/p_256_multprecision.c",
+    "avdt/avdt_ccb.c",
+    "avdt/avdt_scb_act.c",
+    "avdt/avdt_msg.c",
+    "avdt/avdt_ccb_act.c",
+    "avdt/avdt_api.c",
+    "avdt/avdt_scb.c",
+    "avdt/avdt_ad.c",
+    "avdt/avdt_l2c.c",
+    "sdp/sdp_server.c",
+    "sdp/sdp_main.c",
+    "sdp/sdp_db.c",
+    "sdp/sdp_utils.c",
+    "sdp/sdp_api.c",
+    "sdp/sdp_discovery.c",
+    "pan/pan_main.c",
+    "srvc/srvc_battery.c",
+    "srvc/srvc_battery_int.h",
+    "srvc/srvc_dis.c",
+    "srvc/srvc_dis_int.h",
+    "srvc/srvc_eng.c",
+    "srvc/srvc_eng_int.h",
+    "pan/pan_api.c",
+    "pan/pan_utils.c",
+    "btu/btu_hcif.c",
+    "btu/btu_init.c",
+    "btu/btu_task.c",
+    "l2cap/l2c_fcr.c",
+    "l2cap/l2c_ucd.c",
+    "l2cap/l2c_main.c",
+    "l2cap/l2c_api.c",
+    "l2cap/l2c_utils.c",
+    "l2cap/l2c_csm.c",
+    "l2cap/l2c_link.c",
+    "l2cap/l2c_ble.c",
+    "l2cap/l2cap_client.c",
+    "gap/gap_api.c",
+    "gap/gap_ble.c",
+    "gap/gap_conn.c",
+    "gap/gap_utils.c",
+  ]
+
+  include_dirs = [
+    "include",
+    "avct",
+    "btm",
+    "avrc",
+    "l2cap",
+    "avdt",
+    "gatt",
+    "gap",
+    "pan",
+    "bnep",
+    "hid",
+    "sdp",
+    "smp",
+    "srvc",
+    "//btcore/include",
+    "//vnd/include",
+    "//vnd/ble",
+    "//btif/include",
+    "//hci/include",
+    "//include",
+    "//gki/common",
+    "//gki/ulinux",
+    "//osi/include",
+    "//udrv/include",
+    "//rpc/include",
+    "//hcis",
+    "//ctrlr/include",
+    "//bta/include",
+    "//bta/sys",
+    "//utils/include",
+    "//",
+  ]
+}
diff --git a/stack/a2dp/a2d_sbc.c b/stack/a2dp/a2d_sbc.c
index 4b786b4..fd7c816 100644
--- a/stack/a2dp/a2d_sbc.c
+++ b/stack/a2dp/a2d_sbc.c
@@ -284,8 +284,9 @@
         status = A2D_INVALID_PARAMS;
     else
     {
-        losc    = *p_info++;
-        *p_info++;
+        losc    = *p_info;
+        *p_info += 2;
+
         /* If the function is called for the wrong Media Type or Media Codec Type */
         if(losc != A2D_SBC_INFO_LEN || *p_info != A2D_MEDIA_CT_SBC)
             status = A2D_WRONG_CODEC;
diff --git a/stack/avdt/avdt_ccb.c b/stack/avdt/avdt_ccb.c
index 09ed39a..0cad57c 100644
--- a/stack/avdt/avdt_ccb.c
+++ b/stack/avdt/avdt_ccb.c
@@ -386,7 +386,7 @@
             memcpy(p_ccb->peer_addr, bd_addr, BD_ADDR_LEN);
             GKI_init_q(&p_ccb->cmd_q);
             GKI_init_q(&p_ccb->rsp_q);
-            p_ccb->timer_entry.param = (UINT32) p_ccb;
+            p_ccb->timer_entry.param = p_ccb;
             AVDT_TRACE_DEBUG("avdt_ccb_alloc %d", i);
             break;
         }
diff --git a/stack/avdt/avdt_scb.c b/stack/avdt/avdt_scb.c
index 696fcca..2a2ab4a 100644
--- a/stack/avdt/avdt_scb.c
+++ b/stack/avdt/avdt_scb.c
@@ -620,7 +620,7 @@
 #endif
             }
 #endif
-            p_scb->timer_entry.param = (UINT32) p_scb;
+            p_scb->timer_entry.param = p_scb;
             AVDT_TRACE_DEBUG("avdt_scb_alloc hdl=%d, psc_mask:0x%x", i+1, p_cs->cfg.psc_mask);
             break;
         }
diff --git a/stack/bnep/bnep_utils.c b/stack/bnep/bnep_utils.c
index 1db329d..0cf3b3f 100644
--- a/stack/bnep/bnep_utils.c
+++ b/stack/bnep/bnep_utils.c
@@ -120,7 +120,7 @@
         {
             memset ((UINT8 *)p_bcb, 0, sizeof (tBNEP_CONN));
 
-            p_bcb->conn_tle.param = (UINT32) p_bcb;
+            p_bcb->conn_tle.param = p_bcb;
 
             memcpy ((UINT8 *)(p_bcb->rem_bda), (UINT8 *)p_rem_bda, BD_ADDR_LEN);
             p_bcb->handle = xx + 1;
diff --git a/stack/btm/btm_acl.c b/stack/btm/btm_acl.c
index 9337697..59a311f 100644
--- a/stack/btm/btm_acl.c
+++ b/stack/btm/btm_acl.c
@@ -795,7 +795,7 @@
                 btsnd_hcic_disconnect(p_dev_rec->hci_handle, HCI_ERR_PEER_USER);
             }
             BTM_TRACE_ERROR("btm_acl_encrypt_change: tBTM_SEC_DEV:0x%x rs_disc_pending=%d",
-                (UINT32)p_dev_rec, p_dev_rec->rs_disc_pending);
+                            PTR_TO_UINT(p_dev_rec), p_dev_rec->rs_disc_pending);
             p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING;     /* reset flag */
         }
 #endif
@@ -1528,7 +1528,7 @@
             btsnd_hcic_disconnect(p_dev_rec->hci_handle, HCI_ERR_PEER_USER);
         }
         BTM_TRACE_ERROR("tBTM_SEC_DEV:0x%x rs_disc_pending=%d",
-                         (UINT32)p_dev_rec, p_dev_rec->rs_disc_pending);
+                        PTR_TO_UINT(p_dev_rec), p_dev_rec->rs_disc_pending);
         p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING;     /* reset flag */
     }
 
diff --git a/stack/btm/btm_ble.c b/stack/btm/btm_ble.c
index 5954898..0101b97 100644
--- a/stack/btm/btm_ble.c
+++ b/stack/btm/btm_ble.c
@@ -683,7 +683,6 @@
 BOOLEAN BTM_ReadConnectedTransportAddress(BD_ADDR remote_bda, tBT_TRANSPORT transport)
 {
     tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev(remote_bda);
-    tACL_CONN *p = btm_bda_to_acl(remote_bda, transport);
 
     /* if no device can be located, return */
     if (p_dev_rec == NULL)
@@ -1467,61 +1466,6 @@
 }
 
 /*******************************************************************************
-** Function         btm_enc_proc_ltk
-** Description      send LTK reply when it's ready.
-*******************************************************************************/
-static void btm_enc_proc_ltk(tSMP_ENC *p)
-{
-    UINT8   i;
-    BTM_TRACE_DEBUG ("btm_enc_proc_ltk");
-    if (p && p->param_len == BT_OCTET16_LEN)
-    {
-        for (i = 0; i < (BT_OCTET16_LEN - btm_cb.key_size); i ++)
-            p->param_buf[BT_OCTET16_LEN - i - 1] = 0;
-        btsnd_hcic_ble_ltk_req_reply(btm_cb.enc_handle, p->param_buf);
-    }
-}
-
-/*******************************************************************************
-** Function         btm_enc_proc_slave_y
-** Description      calculate LTK when Y is ready
-*******************************************************************************/
-static void btm_enc_proc_slave_y(tSMP_ENC *p)
-{
-    UINT16  div, y;
-    UINT8   *pp = p->param_buf;
-    tBTM_CB *p_cb = &btm_cb;
-    tSMP_ENC output;
-    tBTM_SEC_DEV_REC *p_dev_rec;
-
-    BTM_TRACE_DEBUG ("btm_enc_proc_slave_y");
-    if (p != NULL)
-    {
-        STREAM_TO_UINT16(y, pp);
-
-        div = p_cb->ediv ^ y;
-        p_dev_rec = btm_find_dev_by_handle (p_cb->enc_handle);
-
-        if ( p_dev_rec &&
-             p_dev_rec->ble.keys.div == div )
-        {
-            BTM_TRACE_DEBUG ("LTK request OK");
-            /* calculating LTK , LTK = E er(div) */
-            SMP_Encrypt(p_cb->devcb.ble_encryption_key_value, BT_OCTET16_LEN, (UINT8 *)&div, 2, &output);
-            btm_enc_proc_ltk(&output);
-        }
-        else
-        {
-            BTM_TRACE_DEBUG ("LTK request failed - send negative reply");
-            btsnd_hcic_ble_ltk_req_neg_reply(p_cb->enc_handle);
-            if (p_dev_rec)
-                btm_ble_link_encrypted(p_dev_rec->bd_addr, 0);
-
-        }
-    }
-}
-
-/*******************************************************************************
 **
 ** Function         btm_ble_ltk_request_reply
 **
@@ -1535,7 +1479,6 @@
 {
     tBTM_SEC_DEV_REC    *p_rec = btm_find_dev (bda);
     tBTM_CB *p_cb = &btm_cb;
-    tSMP_ENC output;
 
     if (p_rec == NULL)
     {
diff --git a/stack/btm/btm_ble_bgconn.c b/stack/btm/btm_ble_bgconn.c
index 116b8fc..f66ef9f 100644
--- a/stack/btm/btm_ble_bgconn.c
+++ b/stack/btm/btm_ble_bgconn.c
@@ -521,6 +521,7 @@
 #endif
                 if (!btsnd_hcic_ble_set_scan_enable(TRUE, TRUE)) /* duplicate filtering enabled */
                      return FALSE;
+
                  /* mark up inquiry status flag */
                  p_cb->scan_activity |= BTM_LE_SELECT_CONN_ACTIVE;
                  p_cb->wl_state |= BTM_BLE_WL_SCAN;
diff --git a/stack/btm/btm_ble_gap.c b/stack/btm/btm_ble_gap.c
index 43d0f36..153b598 100644
--- a/stack/btm/btm_ble_gap.c
+++ b/stack/btm/btm_ble_gap.c
@@ -486,6 +486,7 @@
     return status;
 }
 
+#if BLE_VND_INCLUDED == TRUE
 /*******************************************************************************
 **
 ** Function         btm_vsc_brcm_features_complete
@@ -497,7 +498,6 @@
 *******************************************************************************/
 static void btm_ble_vendor_capability_vsc_cmpl_cback (tBTM_VSC_CMPL *p_vcs_cplt_params)
 {
-#if BLE_VND_INCLUDED == TRUE
     UINT8 status = 0xFF;
     UINT8 *p;
 
@@ -555,15 +555,15 @@
     if (btm_cb.cmn_ble_vsc_cb.max_irk_list_sz > 0 &&
         controller_get_interface()->get_ble_resolving_list_max_size() == 0)
         btm_ble_resolving_list_init(btm_cb.cmn_ble_vsc_cb.max_irk_list_sz);
-#endif
+#endif  /* (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE) */
 
     if (btm_cb.cmn_ble_vsc_cb.tot_scan_results_strg > 0)
         btm_ble_batchscan_init();
 
     if (p_ctrl_le_feature_rd_cmpl_cback != NULL)
         p_ctrl_le_feature_rd_cmpl_cback(status);
-#endif
 }
+#endif  /* BLE_VND_INCLUDED == TRUE */
 
 /*******************************************************************************
 **
diff --git a/stack/btm/btm_dev.c b/stack/btm/btm_dev.c
index c8265e4..9f57522 100644
--- a/stack/btm/btm_dev.c
+++ b/stack/btm/btm_dev.c
@@ -479,7 +479,6 @@
 #if BLE_INCLUDED == TRUE
     tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
     tBTM_SEC_DEV_REC temp_rec = *p_target_rec;
-    BD_ADDR dummy_bda = {0};
 
     BTM_TRACE_DEBUG("%s", __func__);
 
diff --git a/stack/btm/btm_devctl.c b/stack/btm/btm_devctl.c
index 3a70788..896bef5 100644
--- a/stack/btm/btm_devctl.c
+++ b/stack/btm/btm_devctl.c
@@ -262,9 +262,6 @@
 *******************************************************************************/
 static void btm_decode_ext_features_page (UINT8 page_number, const UINT8 *p_features)
 {
-    UINT8 last;
-    UINT8 first;
-
     BTM_TRACE_DEBUG ("btm_decode_ext_features_page page: %d", page_number);
     switch (page_number)
     {
diff --git a/stack/btm/btm_sec.c b/stack/btm/btm_sec.c
index e735299..b8d0eaf 100644
--- a/stack/btm/btm_sec.c
+++ b/stack/btm/btm_sec.c
@@ -103,10 +103,8 @@
 
 static BOOLEAN btm_sec_queue_encrypt_request  (BD_ADDR bd_addr, tBT_TRANSPORT transport,
                                          tBTM_SEC_CALLBACK *p_callback, void *p_ref_data);
-static void btm_sec_clean_pending_req_queue (BD_ADDR remote_bda, tBT_TRANSPORT transport) ;
 static void btm_sec_check_pending_enc_req (tBTM_SEC_DEV_REC  *p_dev_rec, tBT_TRANSPORT transport,
                                             UINT8 encr_enable);
-static BOOLEAN btm_sec_acceptor_rejects_bonding (tBTM_SEC_DEV_REC *p_dev_rec);
 
 static BOOLEAN btm_sec_use_smp_br_chnl(tBTM_SEC_DEV_REC *p_dev_rec);
 static BOOLEAN btm_sec_is_master(tBTM_SEC_DEV_REC *p_dev_rec);
@@ -3996,7 +3994,7 @@
                 p_dev_rec->sec_state = 0;
 
             btm_cb.p_collided_dev_rec = p_dev_rec;
-            btm_cb.sec_collision_tle.param = (UINT32) btm_sec_collision_timeout;
+            btm_cb.sec_collision_tle.param = UINT_TO_PTR(btm_sec_collision_timeout);
             btu_start_timer (&btm_cb.sec_collision_tle, BTU_TTYPE_USER_FUNC, BT_1SEC_TIMEOUT);
         }
     }
@@ -4491,7 +4489,7 @@
                         /* Start timer with 0 to initiate connection with new LCB */
                         /* because L2CAP will delete current LCB with this event  */
                         btm_cb.p_collided_dev_rec = p_dev_rec;
-                        btm_cb.sec_collision_tle.param = (UINT32) btm_sec_connect_after_reject_timeout;
+                        btm_cb.sec_collision_tle.param = UINT_TO_PTR(btm_sec_connect_after_reject_timeout);
                         btu_start_timer (&btm_cb.sec_collision_tle, BTU_TTYPE_USER_FUNC, 0);
                     }
                     else
@@ -4549,7 +4547,7 @@
                 /* Start timer with 0 to initiate connection with new LCB */
                 /* because L2CAP will delete current LCB with this event  */
                 btm_cb.p_collided_dev_rec = p_dev_rec;
-                btm_cb.sec_collision_tle.param = (UINT32) btm_sec_connect_after_reject_timeout;
+                btm_cb.sec_collision_tle.param = UINT_TO_PTR(btm_sec_connect_after_reject_timeout);
                 btu_start_timer (&btm_cb.sec_collision_tle, BTU_TTYPE_USER_FUNC, 0);
             }
 
@@ -6218,38 +6216,6 @@
 
 /*******************************************************************************
 **
-** Function         btm_sec_clean_pending_req_queue
-**
-** Description      This function cleans up the pending security request when the
-**                  link to the target device dropped.
-**
-** Returns          void
-**
-*******************************************************************************/
-static void btm_sec_clean_pending_req_queue (BD_ADDR remote_bda, tBT_TRANSPORT transport)
-{
-    tBTM_SEC_QUEUE_ENTRY    *p_e;
-    BUFFER_Q                *bq = &btm_cb.sec_pending_q;
-
-    p_e = (tBTM_SEC_QUEUE_ENTRY *)GKI_getfirst(bq);
-
-    if (p_e != NULL)
-    {
-        if (memcmp(p_e->bd_addr, remote_bda, BD_ADDR_LEN) == 0
-#if BLE_INCLUDED == TRUE
-            && p_e->transport == transport
-#endif
-            )
-        {
-            (*p_e->p_callback) (remote_bda, transport, p_e->p_ref_data, BTM_ERR_PROCESSING);
-            GKI_remove_from_queue(bq, (void *)p_e);
-        }
-        p_e = (tBTM_SEC_QUEUE_ENTRY *) GKI_getnext ((void *)p_e);
-    }
-}
-
-/*******************************************************************************
-**
 ** Function         btm_sec_is_serv_level0
 **
 ** Description      This function is called to check if the service corresponding
diff --git a/stack/btu/btu_task.c b/stack/btu/btu_task.c
index e2b899e..41170f0 100644
--- a/stack/btu/btu_task.c
+++ b/stack/btu/btu_task.c
@@ -19,6 +19,7 @@
 #define LOG_TAG "bt_btu_task"
 
 #include <assert.h>
+#include <pthread.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
diff --git a/stack/gap/gap_conn.c b/stack/gap/gap_conn.c
index 67b8922..6c6c5e7 100644
--- a/stack/gap/gap_conn.c
+++ b/stack/gap/gap_conn.c
@@ -127,7 +127,6 @@
 {
     tGAP_CCB    *p_ccb;
     UINT16       cid;
-    tBT_UUID    bt_uuid = {2, {GAP_PROTOCOL_ID}};
 
     GAP_TRACE_EVENT ("GAP_CONN - Open Request");
 
@@ -235,7 +234,7 @@
             p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE;
 
         /* Check if L2CAP started the connection process */
-        if (p_rem_bda && ((cid = L2CA_CONNECT_REQ (p_ccb->psm, p_rem_bda, &p_ccb->ertm_info, &bt_uuid)) != 0))
+        if (p_rem_bda && ((cid = L2CA_CONNECT_REQ (p_ccb->psm, p_rem_bda, &p_ccb->ertm_info)) != 0))
         {
             p_ccb->connection_id = cid;
             return (p_ccb->gap_handle);
@@ -739,7 +738,6 @@
 {
     UINT16       xx;
     tGAP_CCB     *p_ccb;
-    tBT_UUID    bt_uuid = {2, {GAP_PROTOCOL_ID}};
 
     /* See if we have a CCB listening for the connection */
     for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++)
@@ -770,7 +768,7 @@
     p_ccb->connection_id = l2cap_cid;
 
     /* Send response to the L2CAP layer. */
-    L2CA_CONNECT_RSP (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK, &p_ccb->ertm_info, &bt_uuid);
+    L2CA_CONNECT_RSP (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK, &p_ccb->ertm_info);
 
     GAP_TRACE_EVENT("GAP_CONN - Rcvd L2CAP conn ind, CID: 0x%x", p_ccb->connection_id);
 
diff --git a/stack/gatt/gatt_attr.c b/stack/gatt/gatt_attr.c
index a175129..659a864 100644
--- a/stack/gatt/gatt_attr.c
+++ b/stack/gatt/gatt_attr.c
@@ -485,7 +485,6 @@
 *******************************************************************************/
 void GATT_ConfigServiceChangeCCC (BD_ADDR remote_bda, BOOLEAN enable, tBT_TRANSPORT transport)
 {
-    UINT16              conn_id = GATT_INVALID_CONN_ID;
     tGATT_PROFILE_CLCB   *p_clcb = gatt_profile_find_clcb_by_bd_addr (remote_bda, transport);
 
     if (p_clcb == NULL)
diff --git a/stack/hid/hidh_conn.c b/stack/hid/hidh_conn.c
index 0cc6976..7b3db4a 100644
--- a/stack/hid/hidh_conn.c
+++ b/stack/hid/hidh_conn.c
@@ -43,6 +43,8 @@
 #include "hidh_int.h"
 #include "bt_utils.h"
 
+#include "osi/include/osi.h"
+
 static UINT8 find_conn_by_cid (UINT16 cid);
 static void hidh_conn_retry (UINT8 dhandle);
 
@@ -301,10 +303,16 @@
 *******************************************************************************/
 void hidh_proc_repage_timeout (TIMER_LIST_ENT *p_tle)
 {
-    hidh_conn_initiate( (UINT8) p_tle->param ) ;
-    hh_cb.devices[p_tle->param].conn_tries++;
-    hh_cb.callback( (UINT8) p_tle->param, hh_cb.devices[p_tle->param].addr,
-                    HID_HDEV_EVT_RETRYING, hh_cb.devices[p_tle->param].conn_tries, NULL ) ;
+    tHID_HOST_DEV_CTB *device;
+    UINT8 dhandle = PTR_TO_UINT(p_tle->param);
+
+    hidh_conn_initiate(dhandle);
+
+    device = &hh_cb.devices[dhandle];
+    device->conn_tries++;
+
+    hh_cb.callback(dhandle, device->addr, HID_HDEV_EVT_RETRYING,
+                   device->conn_tries, NULL ) ;
 }
 
 /*******************************************************************************
@@ -321,11 +329,12 @@
 {
     tHID_HOST_DEV_CTB *p_dev = (tHID_HOST_DEV_CTB *) p_ref_data;
     UINT8 dhandle;
-    UINT32 reason;
     UNUSED(bd_addr);
     UNUSED (transport);
 
-    dhandle = ((UINT32)p_dev - (UINT32)&(hh_cb.devices[0]))/ sizeof(tHID_HOST_DEV_CTB);
+    // TODO(armansito): This kind of math to determine a device handle is way
+    // too dirty and unnecessary. Why can't |p_dev| store it's handle?
+    dhandle = (PTR_TO_UINT(p_dev) - PTR_TO_UINT(&(hh_cb.devices[0])))/ sizeof(tHID_HOST_DEV_CTB);
     if( res == BTM_SUCCESS && p_dev->conn.conn_state == HID_CONN_STATE_SECURITY )
     {
         HIDH_TRACE_EVENT ("HID-Host Originator security pass.");
@@ -653,7 +662,7 @@
             (hh_cb.devices[dhandle].attr_mask & HID_NORMALLY_CONNECTABLE))
         {
             hh_cb.devices[dhandle].conn_tries = 0;
-            hh_cb.devices[dhandle].conn.timer_entry.param = (UINT32) dhandle;
+            hh_cb.devices[dhandle].conn.timer_entry.param = UINT_TO_PTR(dhandle);
             btu_start_timer (&(hh_cb.devices[dhandle].conn.timer_entry), BTU_TTYPE_HID_HOST_REPAGE_TO, HID_HOST_REPAGE_WIN);
             hh_cb.callback( dhandle,  hh_cb.devices[dhandle].addr, HID_HDEV_EVT_CLOSE, disc_res, NULL);
         }
@@ -1086,7 +1095,7 @@
     tHID_HOST_DEV_CTB *p_dev = &hh_cb.devices[dhandle];
 
     p_dev->conn.conn_state = HID_CONN_STATE_UNUSED;
-    p_dev->conn.timer_entry.param = (UINT32) dhandle;
+    p_dev->conn.timer_entry.param = UINT_TO_PTR(dhandle);
 #if (HID_HOST_REPAGE_WIN > 0)
     btu_start_timer (&(p_dev->conn.timer_entry), BTU_TTYPE_HID_HOST_REPAGE_TO, HID_HOST_REPAGE_WIN);
 #else
diff --git a/stack/include/l2c_api.h b/stack/include/l2c_api.h
index 837dbc8..b431d56 100644
--- a/stack/include/l2c_api.h
+++ b/stack/include/l2c_api.h
@@ -319,8 +319,8 @@
 
 #define L2CA_REGISTER(a,b,c)        L2CA_Register(a,(tL2CAP_APPL_INFO *)b)
 #define L2CA_DEREGISTER(a)          L2CA_Deregister(a)
-#define L2CA_CONNECT_REQ(a,b,c,d)   L2CA_ErtmConnectReq(a,b,c)
-#define L2CA_CONNECT_RSP(a,b,c,d,e,f,g) L2CA_ErtmConnectRsp(a,b,c,d,e,f)
+#define L2CA_CONNECT_REQ(a,b,c)   L2CA_ErtmConnectReq(a,b,c)
+#define L2CA_CONNECT_RSP(a,b,c,d,e,f) L2CA_ErtmConnectRsp(a,b,c,d,e,f)
 #define L2CA_CONFIG_REQ(a,b)        L2CA_ConfigReq(a,b)
 #define L2CA_CONFIG_RSP(a,b)        L2CA_ConfigRsp(a,b)
 #define L2CA_DISCONNECT_REQ(a)      L2CA_DisconnectReq(a)
diff --git a/stack/l2cap/l2c_ble.c b/stack/l2cap/l2c_ble.c
index 2460bd4..f7d65f0 100644
--- a/stack/l2cap/l2c_ble.c
+++ b/stack/l2cap/l2c_ble.c
@@ -263,7 +263,6 @@
 void l2cble_scanner_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type,
                                UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
 {
-    int i;
     tL2C_LCB            *p_lcb;
     tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_or_alloc_dev (bda);
 
@@ -372,7 +371,6 @@
 void l2cble_advertiser_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type,
                                   UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
 {
-    int i;
     tL2C_LCB            *p_lcb;
     tBTM_SEC_DEV_REC    *p_dev_rec;
     UNUSED(type);
@@ -480,9 +478,13 @@
 static void l2cble_start_conn_update (tL2C_LCB *p_lcb)
 {
     UINT16 min_conn_int, max_conn_int, slave_latency, supervision_tout;
-    tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev(p_lcb->remote_bd_addr);
     tACL_CONN *p_acl_cb = btm_bda_to_acl(p_lcb->remote_bd_addr, BT_TRANSPORT_LE);
 
+    // TODO(armansito): The return value of this call wasn't being used but the
+    // logic of this function might be depending on its side effects. We should
+    // verify if this call is needed at all and remove it otherwise.
+    btm_find_or_alloc_dev(p_lcb->remote_bd_addr);
+
     if (p_lcb->conn_update_mask & L2C_BLE_UPDATE_PENDING) return;
 
     if (p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE)
diff --git a/stack/rfcomm/rfc_utils.c b/stack/rfcomm/rfc_utils.c
index e2cff28..0014c9b 100644
--- a/stack/rfcomm/rfc_utils.c
+++ b/stack/rfcomm/rfc_utils.c
@@ -224,7 +224,7 @@
 
     RFCOMM_TRACE_EVENT ("rfc_timer_start - timeout:%d", timeout);
 
-    p_tle->param = (UINT32)p_mcb;
+    p_tle->param = p_mcb;
 
     btu_start_timer (p_tle, BTU_TTYPE_RFCOMM_MFC, timeout);
 }
@@ -258,7 +258,7 @@
 
     RFCOMM_TRACE_EVENT ("rfc_port_timer_start - timeout:%d", timeout);
 
-    p_tle->param = (UINT32)p_port;
+    p_tle->param = p_port;
 
     btu_start_timer (p_tle, BTU_TTYPE_RFCOMM_PORT, timeout);
 }
diff --git a/stack/sdp/sdp_api.c b/stack/sdp/sdp_api.c
index 6e84ded..5a69816 100644
--- a/stack/sdp/sdp_api.c
+++ b/stack/sdp/sdp_api.c
@@ -37,6 +37,8 @@
 #include "sdpint.h"
 #include "btu.h"
 
+#include "osi/include/osi.h"
+
 /**********************************************************************
 **   C L I E N T    F U N C T I O N    P R O T O T Y P E S            *
 ***********************************************************************/
@@ -73,7 +75,7 @@
         num_attr > SDP_MAX_ATTR_FILTERS || num_uuid > SDP_MAX_UUID_FILTERS)
     {
         SDP_TRACE_ERROR("SDP_InitDiscoveryDb Illegal param: p_db 0x%x, len %d, num_uuid %d, num_attr %d",
-                         (UINT32)p_db, len, num_uuid, num_attr);
+                        PTR_TO_UINT(p_db), len, num_uuid, num_attr);
 
         return(FALSE);
     }
diff --git a/stack/sdp/sdp_utils.c b/stack/sdp/sdp_utils.c
index 238896f..f18eb88 100644
--- a/stack/sdp/sdp_utils.c
+++ b/stack/sdp/sdp_utils.c
@@ -122,7 +122,7 @@
         {
             memset (p_ccb, 0, sizeof (tCONN_CB));
 
-            p_ccb->timer_entry.param = (UINT32) p_ccb;
+            p_ccb->timer_entry.param = p_ccb;
 
             return (p_ccb);
         }
diff --git a/udrv/BUILD.gn b/udrv/BUILD.gn
new file mode 100644
index 0000000..6b94bfe
--- /dev/null
+++ b/udrv/BUILD.gn
@@ -0,0 +1,31 @@
+#
+#  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.
+#
+
+source_set("udrv") {
+  sources = [
+    "ulinux/uipc.c"
+  ]
+
+  include_dirs = [
+    "include",
+    "uipc",
+    "//audio_a2dp_hw",
+    "//include",
+    "//gki/common",
+    "//stack/include",
+    "//utils/include",
+  ]
+}
diff --git a/utils/BUILD.gn b/utils/BUILD.gn
new file mode 100644
index 0000000..2b7dc59
--- /dev/null
+++ b/utils/BUILD.gn
@@ -0,0 +1,27 @@
+#
+#  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.
+#
+
+static_library("utils") {
+  sources = [
+    "src/bt_utils.c"
+  ]
+
+  include_dirs = [
+    "include",
+    "//",
+    "//stack/include",
+  ]
+}
diff --git a/utils/src/bt_utils.c b/utils/src/bt_utils.c
index 53a53de..2420716 100644
--- a/utils/src/bt_utils.c
+++ b/utils/src/bt_utils.c
@@ -27,7 +27,13 @@
 
 #define LOG_TAG "bt_utils"
 
+// TODO(armansito): cutils/properties.h is only being used to pull-in runtime
+// settings on Android. Remove this conditional include once we have a generic
+// way to obtain system properties.
+#if !defined(OS_GENERIC)
 #include <cutils/properties.h>
+#endif  // !defined(OS_GENERIC)
+
 #include <cutils/sched_policy.h>
 #include <errno.h>
 #include <pthread.h>
@@ -73,7 +79,7 @@
   return NULL;
 }
 
-const module_t bt_utils_module = {
+EXPORT_SYMBOL const module_t bt_utils_module = {
   .name = BT_UTILS_MODULE,
   .init = init,
   .start_up = NULL,
@@ -84,7 +90,10 @@
   }
 };
 
-
+// TODO(armansito): Remove this conditional code once there is a generic way
+// to obtain system properties. System properties are only available on
+// Android. Don't do the following check if this is a generic build.
+#if !defined(OS_GENERIC)
 /*****************************************************************************
 **
 ** Function        check_do_scheduling_group
@@ -104,6 +113,7 @@
         }
     }
 }
+#endif  // !defined(OS_GENERIC)
 
 /*****************************************************************************
 **
@@ -122,11 +132,18 @@
     pthread_mutex_lock(&gIdxLock);
     g_TaskIdx = high_task;
 
+    // TODO(armansito): Remove this conditional check once we find a solution
+    // for system/core on non-Android platforms.
+#if defined(OS_GENERIC)
+    rc = -1;
+#else  // !defined(OS_GENERIC)
     pthread_once(&g_DoSchedulingGroupOnce[g_TaskIdx], check_do_scheduling_group);
     if (g_DoSchedulingGroup[g_TaskIdx]) {
         // set_sched_policy does not support tid == 0
         rc = set_sched_policy(tid, SP_AUDIO_SYS);
     }
+#endif  // defined(OS_GENERIC)
+
     g_TaskIDs[high_task] = tid;
     pthread_mutex_unlock(&gIdxLock);