| # Gabeldorsche Style Guide |
| |
| [TOC] |
| |
| ## Base |
| |
| In general, when not mentioned in this document, developers should follow the |
| Google C++ and Google Java style guide as much as possible. |
| |
| ### Google C++ Style Guide |
| |
| C++ Style Guide: https://google.github.io/styleguide/cppguide.html |
| |
| ### Android and Google Java Style Guide |
| |
| 1. Android Java Style Guide: |
| https://source.android.com/setup/contribute/code-style |
| |
| 2. when not covered by (1), see External Java Style Guide: |
| https://google.github.io/styleguide/javaguide.html |
| |
| line length limit is 120 characters for C++ and Java |
| |
| ### Python Style Guide |
| |
| The GD stack uses the Google Python Style Guide: |
| |
| * http://google.github.io/styleguide/pyguide.html |
| |
| with the following modifications as shown in the |
| [.style.yapf](https://android.googlesource.com/platform/packages/modules/Bluetooth/system/+/refs/heads/master/.style.yapf) definition: |
| |
| ```yapf |
| based_on_style: google |
| indent_width: 4 |
| column_limit: 120 |
| ``` |
| |
| ## Build files |
| |
| * One build target for the entire stack in packages/modules/Bluetooth/system (i.e. one cc_library()) |
| * If only part of the stack needs to be compiled, configure it using the |
| “target” configuration in Android.bp |
| * One build target for all unit tests (i.e. one cc_test) |
| * When needed, filgroup() can be created in Android.bp in sub-directories. The |
| main build target should use these filegroups() to build the main output |
| library. |
| * All targets must have host_supported == true unless it is dependent on the |
| OS |
| * If the stack needs to be compiled using other build system, then the build |
| files should also live in packages/modules/Bluetooth/system |
| |
| ## Namespace and include |
| |
| * Namespace must follow directory names |
| * Top level namespace for internal code is “bluetooth” |
| * Top level namespace for externally visible code is “android::bluetooth” |
| * Include path must be relative to the root directory of the stack. Normally |
| it is packages/modules/Bluetooth/system, for GD refactor code, it is packages/modules/Bluetooth/system/gd |
| |
| ## Multiple implementations of the same header |
| |
| Since GD interact with many lower level components that are platform dependent, |
| frequently there is need to implement the same header multiple times for |
| different platform or hardware. When doing this: |
| |
| * Avoid #define macros as much as possible. Instead put code into different |
| source files and selectively compile them for different targets. |
| * Convention of operating system used: |
| * android/ |
| * All Android devices that use HIDL |
| * linux/ |
| * All non-Android linux devices |
| * linux_generic/ |
| * Android and non-Android linux devices |
| |
| ## Directory structure |
| |
| Root directory under Android tree: |
| [**packages/modules/Bluetooth/system/gd/**](https://android.googlesource.com/platform/packages/modules/Bluetooth/system/+/refs/heads/master/gd/) |
| |
| * Directory structure should be as flat as possible |
| * Each file should contain at most one class |
| * Header, source code, and unit test should live in the same directory with |
| the following naming guideline: |
| * Source: bb.cc |
| * Header: bb.h |
| * Test: bb_test.cc |
| * Each profile should have its own directory and module |
| * Source and sink, server and client profiles should live in two sub folders |
| of the same common directory where common code can be stored. However, |
| source and sink must have separate modules |
| * Module file is also the external API header |
| * Prefer underscore over dashes |
| |
| ### Example: utility library with OS dependent implementation |
| |
| * os/: OS dependent classes such as Alarm, Thread, Handler |
| * Android.bp: Build file that defines file groups that would include |
| different source files based on compile time target |
| * alarm.h: common header for alarm |
| * linux_generic/: Implementations for generic Linux OS |
| * alarm.cc: Linux generic implementation of alarm.h using timer_fd |
| * alarm_test.cc: unit test for alarm.h |
| * fuzz/: library needed for fuzz tests in the os/ library |
| |
| ### Example: module with hardware dependent implementation |
| |
| * hal/: Hardware abstraction layer such as HCI interfaces, Audio interfaces |
| * Android.bp: Build file that defines file groups that would include |
| different source files based on compile time target |
| * hci_hal.h: common library header |
| * hci_hal_android_hidl.cc: implementation of hci_hal.h using Android HIDL |
| * hci_hal_android_hidl_test.cc: unit tests for the Android HIDL |
| implementation |
| * hci_hal_host.cc: implementation of hci_hal.h using linux Bluetooth HCI |
| socket |
| * hci_hal_host_rootcanal.cc: implementation of hci_hal.h using root-canal |
| emulator |
| * hci_hal_host_test.cc: unit tests for the socket based HAL (root-canal) |
| emulator implementation |
| * facade.proto: gRPC automation interface definition for this layer |
| * facade.h/cc: an implementation of the above gRPC interface for the GD |
| stack |
| * cert/: certification tests for this module |
| * fuzz/: library needed for fuzz tests in the hal/ module |
| |
| ### Example: similar protocol with the same base |
| |
| * l2cap/: L2CAP layer, splitted among classic and LE |
| * classic/: Classic L2CAP module |
| * cert/: certification tests for this module |
| * internal/: internal code to be used only in classic |
| * Source code and headers being exported to other modules |
| * le/: LE L2CAP module |
| * cert/: certification tests for this module |
| * internal/: internal code to be used only in classic |
| * Source code and headers being exported to other modules |
| * internal/: L2CAP internal code that should not be used by sources |
| outside L2CAP |
| * data_pipeline_manager.h |
| * data_pipeline_manager.cc |
| * data_pipeline_manager_mock.h: Mock of this class, used in unit tests |
| * dynamic_channel_allocator.h |
| * dynamic_channel_allocator.cc |
| * dynamic_channel_allocator_test.cc: GTest unit test of this class |
| * dynamic_channel_allocator_fuzz_test.cc: Fuzz test of this class |
| * *.h/.cc: Common headers and sources that is exposed to other modules |
| |
| ### Example: protocol or profiles with client and server side implementations |
| |
| * a2dp/: A2DP profile |
| * sink/: A2DP sink module (e.g. headset) |
| * source/: A2DP source module (e.g. phone) |
| * avrcp/ |
| * controller/: AVRCP peripheral module (e.g. carkit) |
| * target/: AVRCP target module (e.g. Phone) |
| * hfp/ |
| * hf/: Handsfree device (e.g. headset) |
| * ag/: Audio gateway (e.g. phone) |
| |
| ## External libraries |
| |
| To maintain high portability, we are trying to stick with C++ STL as much as |
| possible. Hence, before including an external library, please ask the team for |
| review. |
| |
| Examples of currently used libraries: |
| |
| * boringssl: Google's openssl implementation |
| * small parts of libchrome, to be removed or replaced eventually |
| * base::OnceCallback |
| * base::Callback |
| * base::BindOnce |
| * base::Bind |
| * google-breakpad: host binary crash handler |
| * libbacktrace: print stacktrace on crash on host |
| |
| ## Exposed symbols |
| |
| Given that entire Fluoride library is held in libbluetooth.so dynamic library |
| file, we need a way to load this library and extract entry points to it. The |
| only symbols that should be exposed are: |
| |
| * An entry point to a normal running adapter module libbluetooth.so |
| * A header library to all exposed API service to profiles and layers |
| * An entry point to a certification interface, libbluetooth\_certification.so |
| * A header library to this certification stack |
| |
| ## Logging |
| |
| Gabeldorsche uses `printf` style logging with macros defined in `os/log.h`. Five |
| log levels are available. |
| |
| * LOG_VERBOSE(fmt, args...): Will be disabled by default |
| * LOG_INFO(fmt, args...): Will be disabled by default |
| * LOG_INFO(fmt, args...): Enabled |
| * LOG_WARN(fmt, args...): Enabled |
| * LOG_ERROR(fmt, args...): Enabled |
| * LOG_ALWAYS_FATAL(fmt, args...): Enabled, will always crash |
| * ASSERT(condition): Enabled, will crash when condition is false |
| * ASSERT_LOG(conditon, fmt, args...): Enabled, will crash and print log when |
| condition is false |
| |
| In general, errors that are caused by remote device should never crash our stack |
| and should be logged using LOG_WARN() only. Recoverable errors due to our stack |
| or badly behaved bluetooth controller firmware should be logged using |
| LOG_ERROR() before recovery. Non-recoverable errors should be logged as |
| LOG_ALWAYS_FATAL() to crash the stack and restart. |