隱藏api內(nèi)部實(shí)現(xiàn)細(xì)節(jié)的兩種方式:
-
頭文件 + shared library
下面引用Android Framwork層 Bluetooth service 如何獲取Native層 BT Statck api Interface示例 (做了部分刪減)來(lái)說(shuō)明:
// 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;
上面這段代碼通過(guò)dlopen加載Shared libbluetooth.so衡便,然后通過(guò)dlsym 獲取bluetoothInterface
下面接著看看bluetoothInterface 的類(lèi)型聲明和定義實(shí)現(xiàn)
// 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
};
可以看到后續(xù)所有api 都是通過(guò)bluetoothInterface來(lái)獲取称龙,僅提供so和頭文件供使用者調(diào)用就可以實(shí)現(xiàn)具體實(shí)現(xiàn)的隱藏。
-
類(lèi)接口的抽象封裝
頭文件中暴露的是基類(lèi)接口聲明刻诊,實(shí)現(xiàn)在具體實(shí)現(xiàn)類(lèi),使用的地方不會(huì)明顯看到實(shí)現(xiàn)細(xì)節(jié)
對(duì)外暴露的接口類(lèi)聲明
// 接口類(lèi)
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;
};
具體實(shí)現(xiàn)類(lèi)
// 具體實(shí)現(xiàn)類(lèi)
class HearingAidImpl : public HearingAid {
......
}
抽象類(lèi) 與 實(shí)現(xiàn)類(lèi) 方法關(guān)聯(lián):
通過(guò)instance來(lái)完成憨募,靜態(tài)方法可以從下面定義中明顯看出由instance的實(shí)現(xiàn)完成薯鳍;
動(dòng)態(tài)方法調(diào)用,借由Get方法來(lái)獲取隱藏的實(shí)現(xiàn)類(lèi)的示例instance月而,動(dòng)態(tài)綁定邏輯
// 抽象類(lèi) 與 實(shí)現(xiàn)類(lèi) 方法關(guān)聯(lián)
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);
};
調(diào)用的地方
// 直接調(diào)用HearingAid的靜態(tài)方法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))));
}
// 調(diào)用 HearingAid動(dòng)態(tài)方法Connect汗洒,通過(guò)Get獲取出來(lái)的instance 實(shí)際是HearingAid 的基類(lèi)HearingAidImpl,由動(dòng)態(tài)方法綁定關(guān)系父款,最終運(yùn)行時(shí)調(diào)用的就是實(shí)現(xiàn)類(lèi)示例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));
}
關(guān)于動(dòng)態(tài)綁定的理解可以看看 C++ Primer Plus Chapter 13 中Static and Dynamic Binding內(nèi)容
上面do_in_main_thread溢谤,Bind等功能瞻凤,屬于chromium,android底層很多地方使用了這個(gè)庫(kù)的函數(shù)功能世杀,多線程task 阀参,threadloop機(jī)制等,也是一種巧妙的設(shè)計(jì)瞻坝,后面再研究下其源碼細(xì)節(jié)進(jìn)行說(shuō)明蛛壳。
附:上面源碼下載方式
git clone "https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/packages/modules/Bluetooth"