Android 源码学习 -- 隐藏api实现

隐藏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"

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 第一条 了解Objective-C预言起源 起源:Smalltalk 类型:使用消息结构的语言 区别:使用消息结构...
    刘二狗的无聊生活阅读 4,415评论 0 0
  • 让自己习惯C++ 条款01:视C++为一个语言联邦 C++可视为: C:以C为基础。 面向对象的C++:添加面向对...
    Cloudox_阅读 8,257评论 0 3
  • 2018.01.20 堆栈原理:问题描述编程语言书籍中经常解释值类型被创建在栈上,引用类型被创建在堆上,但是并没有...
    深眸灵瞳阅读 3,619评论 0 1
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,442评论 19 139
  • 面试必背 会舍弃、总结概括——根据我这些年面试和看面试题搜集过来的知识点汇总而来 建议根据我的写的面试应对思路中的...
    luoyangzk阅读 11,787评论 6 173