From cac9ab3fdd7b44e43765b0cb1a2f2bb80c3a7939 Mon Sep 17 00:00:00 2001
From: Abhishek Pandit-Subedi <abhishekpandit@google.com>
Date: Tue, 2 Mar 2021 22:33:18 +0000
Subject: [PATCH] Add option to build libbluetooth as staticlib

For ChromeOS/Linux, we want to build a static libbluetooth to make it
easier to find build breakages earlier and to simplify some of the build
issues. This change adds a compile time define to choose between using
dlsym to load libbluetooth and using extern to access the symbols
directly.

Bug: 176847256
Tag: #floss
Test: atest --host bluetooth_test_gd
Change-Id: I818c0f4a7baf414e73dc6f6ae73bb3e3bc3f357f
---
 BUILD.gn                         |   7 ++
 system/btcore/src/hal_util.cc    |  10 +++
 system/btif/src/stack_manager.cc | 117 +++++++++++++++++++++++--------
 system/main/BUILD.gn             |   9 ++-
 4 files changed, 112 insertions(+), 31 deletions(-)

diff --git a/BUILD.gn b/BUILD.gn
index 902a9cd9a3c..88a7616a7cb 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -114,6 +114,13 @@ config("target_defaults") {
     "FALLTHROUGH_INTENDED=[[clang::fallthrough]]",
   ]
 
+  # If not configured as a dynamic library, default to static library
+  if (!(defined(use.bt_dynlib) && use.bt_dynlib)) {
+    defines = [
+      "STATIC_LIBBLUETOOTH",
+    ]
+  }
+
   if (!(defined(use.bt_nonstandard_codecs) && use.bt_nonstandard_codecs)) {
     defines += [ "EXCLUDE_NONSTANDARD_CODECS" ]
   }
diff --git a/system/btcore/src/hal_util.cc b/system/btcore/src/hal_util.cc
index d0433486fac..616bd2b46f4 100644
--- a/system/btcore/src/hal_util.cc
+++ b/system/btcore/src/hal_util.cc
@@ -31,6 +31,7 @@ using base::StringPrintf;
 
 #define BLUETOOTH_LIBRARY_NAME "libbluetooth.so"
 
+#if !defined(STATIC_LIBBLUETOOTH)
 int hal_util_load_bt_library(const bt_interface_t** interface) {
   const char* sym = BLUETOOTH_INTERFACE_STRING;
   bt_interface_t* itf = nullptr;
@@ -65,3 +66,12 @@ error:
 
   return -EINVAL;
 }
+#else
+extern bt_interface_t bluetoothInterface;
+
+int hal_util_load_bt_library(const bt_interface_t** interface) {
+  *interface = &bluetoothInterface;
+
+  return 0;
+}
+#endif
diff --git a/system/btif/src/stack_manager.cc b/system/btif/src/stack_manager.cc
index f7a649a37b3..f5c42f954b5 100644
--- a/system/btif/src/stack_manager.cc
+++ b/system/btif/src/stack_manager.cc
@@ -21,6 +21,10 @@
 #include "stack_manager.h"
 
 #include <hardware/bluetooth.h>
+#if defined(STATIC_LIBBLUETOOTH)
+#include <cstdlib>
+#include <cstring>
+#endif
 
 #include "btcore/include/module.h"
 #include "btcore/include/osi_module.h"
@@ -137,6 +141,58 @@ static bool get_stack_is_running() { return stack_is_running; }
 
 // Internal functions
 
+#ifdef STATIC_LIBBLUETOOTH
+extern const module_t bt_utils_module;
+extern const module_t bte_logmsg_module;
+extern const module_t btif_config_module;
+extern const module_t btsnoop_module;
+extern const module_t bt_utils_module;
+extern const module_t controller_module;
+extern const module_t gd_idle_module;
+extern const module_t gd_shim_module;
+extern const module_t hci_module;
+extern const module_t interop_module;
+extern const module_t osi_module;
+extern const module_t stack_config_module;
+
+struct module_lookup {
+  const char* name;
+  const module_t* module;
+};
+
+const struct module_lookup module_table[] = {
+    {BTE_LOGMSG_MODULE, &bte_logmsg_module},
+    {BTIF_CONFIG_MODULE, &btif_config_module},
+    {BTSNOOP_MODULE, &btsnoop_module},
+    {BT_UTILS_MODULE, &bt_utils_module},
+    {CONTROLLER_MODULE, &controller_module},
+    {GD_IDLE_MODULE, &gd_idle_module},
+    {GD_SHIM_MODULE, &gd_shim_module},
+    {HCI_MODULE, &hci_module},
+    {INTEROP_MODULE, &interop_module},
+    {OSI_MODULE, &osi_module},
+    {STACK_CONFIG_MODULE, &stack_config_module},
+    {NULL, NULL},
+};
+
+inline const module_t* get_local_module(const char* name) {
+  size_t len = strlen(name);
+
+  for (const struct module_lookup* l = module_table; l->module; l++) {
+    if (strncmp(l->name, name, len) == 0) {
+      return l->module;
+    }
+  }
+
+  abort();
+  return nullptr;
+}
+#else
+inline const module_t* get_local_module(const char* name) {
+  return get_module(name);
+}
+#endif
+
 // Synchronous function to initialize the stack
 static void event_init_stack(void* context) {
   semaphore_t* semaphore = (semaphore_t*)context;
@@ -148,17 +204,17 @@ static void event_init_stack(void* context) {
   } else {
     module_management_start();
 
-    module_init(get_module(OSI_MODULE));
-    module_init(get_module(BT_UTILS_MODULE));
+    module_init(get_local_module(OSI_MODULE));
+    module_init(get_local_module(BT_UTILS_MODULE));
     if (bluetooth::shim::is_any_gd_enabled()) {
-      module_start_up(get_module(GD_IDLE_MODULE));
+      module_start_up(get_local_module(GD_IDLE_MODULE));
     }
-    module_init(get_module(BTIF_CONFIG_MODULE));
+    module_init(get_local_module(BTIF_CONFIG_MODULE));
     btif_init_bluetooth();
 
-    module_init(get_module(INTEROP_MODULE));
+    module_init(get_local_module(INTEROP_MODULE));
     bte_main_init();
-    module_init(get_module(STACK_CONFIG_MODULE));
+    module_init(get_local_module(STACK_CONFIG_MODULE));
 
     // stack init is synchronous, so no waiting necessary here
     stack_is_initialized = true;
@@ -193,13 +249,13 @@ static void event_start_up_stack(UNUSED_ATTR void* context) {
 
   if (bluetooth::shim::is_any_gd_enabled()) {
     LOG_INFO("%s Gd shim module enabled", __func__);
-    module_shut_down(get_module(GD_IDLE_MODULE));
-    module_start_up(get_module(GD_SHIM_MODULE));
-    module_start_up(get_module(BTIF_CONFIG_MODULE));
+    module_shut_down(get_local_module(GD_IDLE_MODULE));
+    module_start_up(get_local_module(GD_SHIM_MODULE));
+    module_start_up(get_local_module(BTIF_CONFIG_MODULE));
   } else {
-    module_start_up(get_module(BTIF_CONFIG_MODULE));
-    module_start_up(get_module(BTSNOOP_MODULE));
-    module_start_up(get_module(HCI_MODULE));
+    module_start_up(get_local_module(BTIF_CONFIG_MODULE));
+    module_start_up(get_local_module(BTSNOOP_MODULE));
+    module_start_up(get_local_module(HCI_MODULE));
   }
 
   get_btm_client_interface().lifecycle.btm_init();
@@ -225,7 +281,7 @@ static void event_start_up_stack(UNUSED_ATTR void* context) {
 
   bta_sys_init();
   bta_ar_init();
-  module_init(get_module(BTE_LOGMSG_MODULE));
+  module_init(get_local_module(BTE_LOGMSG_MODULE));
 
   main_thread_start_up();
 
@@ -236,9 +292,9 @@ static void event_start_up_stack(UNUSED_ATTR void* context) {
   bta_set_forward_hw_failures(true);
   btm_acl_device_down();
   if (bluetooth::shim::is_gd_controller_enabled()) {
-    CHECK(module_start_up(get_module(GD_CONTROLLER_MODULE)));
+    CHECK(module_start_up(get_local_module(GD_CONTROLLER_MODULE)));
   } else {
-    CHECK(module_start_up(get_module(CONTROLLER_MODULE)));
+    CHECK(module_start_up(get_local_module(CONTROLLER_MODULE)));
   }
   BTM_reset_complete();
 
@@ -284,13 +340,13 @@ static void event_shut_down_stack(UNUSED_ATTR void* context) {
   bta_set_forward_hw_failures(false);
   BTA_dm_on_hw_off();
 
-  module_shut_down(get_module(BTIF_CONFIG_MODULE));
+  module_shut_down(get_local_module(BTIF_CONFIG_MODULE));
 
   future_await(local_hack_future);
 
   main_thread_shut_down();
 
-  module_clean_up(get_module(BTE_LOGMSG_MODULE));
+  module_clean_up(get_local_module(BTE_LOGMSG_MODULE));
 
   gatt_free();
   l2c_free();
@@ -300,16 +356,17 @@ static void event_shut_down_stack(UNUSED_ATTR void* context) {
 
   if (bluetooth::shim::is_any_gd_enabled()) {
     LOG_INFO("%s Gd shim module disabled", __func__);
-    module_shut_down(get_module(GD_SHIM_MODULE));
-    module_start_up(get_module(GD_IDLE_MODULE));
+    module_shut_down(get_local_module(GD_SHIM_MODULE));
+    module_start_up(get_local_module(GD_IDLE_MODULE));
   } else {
-    module_shut_down(get_module(HCI_MODULE));
-    module_shut_down(get_module(BTSNOOP_MODULE));
+    module_shut_down(get_local_module(HCI_MODULE));
+    module_shut_down(get_local_module(BTSNOOP_MODULE));
   }
 
-  module_shut_down(get_module(CONTROLLER_MODULE));  // Doesn't do any work, just
-                                                    // puts it in a restartable
-                                                    // state
+  module_shut_down(
+      get_local_module(CONTROLLER_MODULE));  // Doesn't do any work, just
+                                             // puts it in a restartable
+                                             // state
 
   hack_future = future_new();
   do_in_jni_thread(FROM_HERE, base::Bind(event_signal_stack_down, nullptr));
@@ -339,13 +396,13 @@ static void event_clean_up_stack(void* context) {
 
   btif_cleanup_bluetooth();
 
-  module_clean_up(get_module(STACK_CONFIG_MODULE));
-  module_clean_up(get_module(INTEROP_MODULE));
+  module_clean_up(get_local_module(STACK_CONFIG_MODULE));
+  module_clean_up(get_local_module(INTEROP_MODULE));
 
-  module_clean_up(get_module(BTIF_CONFIG_MODULE));
-  module_clean_up(get_module(BT_UTILS_MODULE));
-  module_clean_up(get_module(OSI_MODULE));
-  module_shut_down(get_module(GD_IDLE_MODULE));
+  module_clean_up(get_local_module(BTIF_CONFIG_MODULE));
+  module_clean_up(get_local_module(BT_UTILS_MODULE));
+  module_clean_up(get_local_module(OSI_MODULE));
+  module_shut_down(get_local_module(GD_IDLE_MODULE));
   module_management_stop();
   LOG_INFO("%s finished", __func__);
 
diff --git a/system/main/BUILD.gn b/system/main/BUILD.gn
index a4fd1fc3277..b4112111e02 100644
--- a/system/main/BUILD.gn
+++ b/system/main/BUILD.gn
@@ -18,7 +18,14 @@ config("libbluetooth_config") {
   include_dirs = [ "../include" ]
 }
 
-shared_library("bluetooth") {
+# Configure libbluetooth as either dynamic or static library
+if (defined(use.bt_dynlib) && use.bt_dynlib) {
+  lib_type = "shared_library"
+} else {
+  lib_type = "static_library"
+}
+
+target(lib_type, "bluetooth") {
   # HAL layer
   sources = [ "//bt/btif/src/bluetooth.cc" ]
 
-- 
GitLab