隐藏api内部实现细节的两种方式:
-
头文件 + shared library
下面引用Android Framwork层 Bluetooth service 如何获取Native层 BT Statck api Interface示例 (做了部分删减)来说明:
// in com_android_bluetooth_btservice_AdapterService.cpp
int hal_util_load_bt_library(const bt_interface_t** interface) {
const char* sym = BLUETOOTH_INTERFACE_STRING; //"bluetoothInterface"
bt_interface_t* itf = nullptr;
// The library name is not set by default, so the preset library name is used.
void* handle = dlopen("libbluetooth.so", RTLD_NOW);
// Get the address of the bt_interface_t.
itf = (bt_interface_t*)dlsym(handle, sym);
// Success.
ALOGI("%s: loaded Bluetooth library successfully", __func__);
*interface = itf;
return 0;
上面这段代码通过dlopen加载Shared libbluetooth.so,然后通过dlsym 获取bluetoothInterface
下面接着看看bluetoothInterface 的类型声明和定义实现
// in bluetooth.h
/** Represents the standard Bluetooth DM interface. */
typedef struct {
/** set to sizeof(bt_interface_t) */
size_t size;
int (*init)(bt_callbacks_t* callbacks, bool guest_mode,
bool is_common_criteria_mode, int config_compare_result,
const char** init_flags, bool is_atv);
/** Enable Bluetooth. */
int (*enable)();
/** Disable Bluetooth. */
int (*disable)(void);
/** Closes the interface. */
void (*cleanup)(void);
......
......
......
int (*config_clear)(void);
void (*interop_database_clear)(void);
void (*interop_database_add)(uint16_t feature, const RawAddress* addr,
size_t len);
bluetooth::avrcp::ServiceInterface* (*get_avrcp_service)(void);
std::string (*obfuscate_address)(const RawAddress& address);
int (*get_metric_id)(const RawAddress& address);
int (*set_dynamic_audio_buffer_size)(int codec, int size);
int (*generate_local_oob_data)(tBT_TRANSPORT transport);
bool (*allow_low_latency_audio)(bool allowed, const RawAddress& address);
int (*clear_event_filter)();
} bt_interface_t;
// in bluetooth_interface.cc
EXPORT_SYMBOL bt_interface_t bluetoothInterface = {
sizeof(bluetoothInterface),
init,
enable,
disable,
cleanup,
get_adapter_properties,
get_adapter_property,
set_adapter_property,
get_remote_device_properties,
get_remote_device_property,
set_remote_device_property,
nullptr,
get_remote_services,
......
......
interop_database_clear,
interop_database_add,
get_avrcp_service,
obfuscate_address,
get_metric_id,
set_dynamic_audio_buffer_size,
generate_local_oob_data,
allow_low_latency_audio
};
可以看到后续所有api 都是通过bluetoothInterface来获取,仅提供so和头文件供使用者调用就可以实现具体实现的隐藏。
-
类接口的抽象封装
头文件中暴露的是基类接口声明,实现在具体实现类,使用的地方不会明显看到实现细节
对外暴露的接口类声明
// 接口类
class HearingAid {
public:
virtual ~HearingAid() = default;
static void Initialize(bluetooth::hearing_aid::HearingAidCallbacks* callbacks,
base::Closure initCb);
static void CleanUp();
static bool IsHearingAidRunning();
static HearingAid* Get();
static void DebugDump(int fd);
static void AddFromStorage(const HearingDevice& dev_info,
uint16_t is_acceptlisted);
static int GetDeviceCount();
virtual void Connect(const RawAddress& address) = 0;
virtual void Disconnect(const RawAddress& address) = 0;
virtual void AddToAcceptlist(const RawAddress& address) = 0;
virtual void SetVolume(int8_t volume) = 0;
};
具体实现类
// 具体实现类
class HearingAidImpl : public HearingAid {
......
}
抽象类 与 实现类 方法关联:
通过instance来完成,静态方法可以从下面定义中明显看出由instance的实现完成;
动态方法调用,借由Get方法来获取隐藏的实现类的示例instance,动态绑定逻辑
// 抽象类 与 实现类 方法关联
void HearingAid::Initialize(
bluetooth::hearing_aid::HearingAidCallbacks* callbacks, Closure initCb) {
if (instance) {
LOG(ERROR) << "Already initialized!";
}
audioReceiver = &audioReceiverImpl;
instance = new HearingAidImpl(callbacks, initCb);
HearingAidAudioSource::Initialize();
}
bool HearingAid::IsHearingAidRunning() { return instance; }
HearingAid* HearingAid::Get() {
CHECK(instance);
return instance;
};
void HearingAid::AddFromStorage(const HearingDevice& dev_info,
uint16_t is_acceptlisted) {
if (!instance) {
LOG(ERROR) << "Not initialized yet";
}
instance->AddFromStorage(dev_info, is_acceptlisted);
};
调用的地方
// 直接调用HearingAid的静态方法Initialize
void Init(HearingAidCallbacks* callbacks) override {
DVLOG(2) << __func__;
this->callbacks = callbacks;
do_in_main_thread(
FROM_HERE,
Bind(&HearingAid::Initialize, this,
jni_thread_wrapper(FROM_HERE,
Bind(&btif_storage_load_bonded_hearing_aids))));
}
// 调用 HearingAid动态方法Connect,通过Get获取出来的instance 实际是HearingAid 的基类HearingAidImpl,由动态方法绑定关系,最终运行时调用的就是实现类示例instance的Connect
void Connect(const RawAddress& address) override {
DVLOG(2) << __func__ << " address: " << address;
do_in_main_thread(FROM_HERE, Bind(&HearingAid::Connect,
Unretained(HearingAid::Get()), address));
}
关于动态绑定的理解可以看看 C++ Primer Plus Chapter 13 中Static and Dynamic Binding内容
上面do_in_main_thread,Bind等功能,属于chromium,android底层很多地方使用了这个库的函数功能,多线程task ,threadloop机制等,也是一种巧妙的设计,后面再研究下其源码细节进行说明。
附:上面源码下载方式
git clone "https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/packages/modules/Bluetooth"
网友评论