Binder - 获取ServiceManager服务

当进程注册服务(addService)和获取服务(getService)时,都需要先调用defaultServiceManager()方法来获取ServiceManager服务

//资源路径:/frameworks/native/libs/binder/IServiceManager.cpp
sp<IServiceManager> defaultServiceManager()
{
  //单例模式,不为空直接返回
  if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
  {
    AutoMutex _l(gDefaultServiceManagerLock);
    //当尝试获取SM时,SM可能为准备就绪,这时通过sleep 1秒后,循环尝试获取直到成功
    while (gDefaultServiceManager == NULL) {
      //SM的创建过程,可以分为3个步骤
      gDefaultServiceManager = interface_cast<IServiceManager>(
        ProcessState::self()->getContextObject(NULL));
      if (gDefaultServiceManager == NULL)
        sleep(1);
    }
  }
  return gDefaultServiceManager;
}

①ProcessState::self() 获取ProcessState对象

1)打开驱动;2)设置线程最大数15;3)mmap,分配大小为1M-8k内存地址空间

//资源路径:/frameworks/native/libs/binder/ProcessState.cpp
sp<ProcessState> ProcessState::self()
{
  //单例模式,不为空直接返回
  if (gProcess != NULL) {
    return gProcess;
  }
  //实例化ProcessState
  gProcess = new ProcessState;
  return gProcess;
}

#define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))
#define DEFAULT_MAX_BINDER_THREADS 15

ProcessState::ProcessState()
  : mDriverFD(open_driver())
{
    // mmap the binder, providing a chunk of virtual address space to receive transactions.
    //通过内存映射,给binder分配一块大小为(1M-8k)的虚拟地址空间,用来接收事务
    mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
}

static int open_driver()
{
  //打开/dev/binder设备,建立与内核的Binder驱动的交互通道
  int fd = open("/dev/binder", O_RDWR);
  //设置最大能支持的线程数为15
  size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
  //通过ioctl设置binder驱动能支持的最大线程数
  result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
}

②ProcessState::getContextObject 创建BpBinder对象

1)创建一个BpBinder(SM的代理对象)

//资源路径:/frameworks/native/libs/binder/ProcessState.cpp
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
  //参数为0,获取SM服务
  return getStrongProxyForHandle(0);
}

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
  //查找handle对应的资源项
  handle_entry* e = lookupHandleLocked(handle);
  if (b == NULL || !e->refs->attemptIncWeak(this)) {
    if (handle == 0) {
      //handle为0时,通过PING_TRANSACTION看SM进程是否能访问(ping操作测试binder是否准备就绪)
      status_t status = IPCThreadState::self()->transact(
                        0, IBinder::PING_TRANSACTION, data, NULL, 0);
    }
    //当handle值对应的IBinder不存在或弱引用无效时,创建BpBinder对象
    b = new BpBinder(handle);
  }
}

③interface_cast 获取BpServiceManager

//资源路径:/frameworks/native/include/binder/IInterface.h
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
  //泛型,等价于 IServiceManager::asInterface
  //IServiceManager中找不到asInterface函数,是通过模板函数来定义的
  return INTERFACE::asInterface(obj);
}
//资源路径:/frameworks/native/include/binder/IServiceManager.h
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
//资源路径:/frameworks/native/include/binder/IInterface.h
//INTERFACE替换成ServiceManager,NAME替换成"android.os.IServiceManager"
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       
    const android::String16 I##INTERFACE::descriptor(NAME);             
    const android::String16&                                            
            I##INTERFACE::getInterfaceDescriptor() const {              
        return I##INTERFACE::descriptor;                               
    }                                                                   
    android::sp<I##INTERFACE> I##INTERFACE::asInterface(   
                //obj是传来的BpBinder
            const android::sp<android::IBinder>& obj)                   
    {                                                                   
        android::sp<I##INTERFACE> intr;                                 
        if (obj != NULL) {                                              
            intr = static_cast<I##INTERFACE*>(                          
                obj->queryLocalInterface(                               
                        I##INTERFACE::descriptor).get());               
            if (intr == NULL) {     
                //等价于new BpServiceManager(BpBinder)
                intr = new Bp##INTERFACE(obj);                          
            }                                                           
        }                                                               
        return intr;                                                    
    }                                                                   
    I##INTERFACE::I##INTERFACE() { }                                    
    I##INTERFACE::~I##INTERFACE() { }

BpServiceManager

//资源路径:/frameworks/native/libs/binder/IServiceManager.cpp
class BpServiceManager : public BpInterface<IServiceManager>
{
  public:
    BpServiceManager(const sp<IBinder>& impl)
        : BpInterface<IServiceManager>(impl)
}
//资源路径:/frameworks/native/include/binder/IInterface.h
template<typename INTERFACE>
inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
    : BpRefBase(remote)
//资源路径:/frameworks/native/libs/binder/Binder.cpp
//mRemote指向new BpBinder(0),从而BpServiceManager能够利用Binder进行通信
BpRefBase::BpRefBase(const sp<IBinder>& o)
   : mRemote(o.get()), mRefs(NULL), mState(0)

获取ServiceManager服务 => defaultServiceManager => new BpServiceManager(new BpBinder(0))
BpServiceManager为客户端代理对象,封装服务要用的接口和方法
BpBinder为ServiceManager代理对象,具有跨进程的能力

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容