Linux 角度看binder原理(五)

Linux 角度看binder原理(五)

获取service

const sp<IMediaPlayerService>
IMediaDeathNotifier::getMediaPlayerService()
{
    ALOGV("getMediaPlayerService");
    Mutex::Autolock _l(sServiceLock);
    if (sMediaPlayerService == 0) {
        sp<IServiceManager> sm = defaultServiceManager();//拿到BpServiceManager
        sp<IBinder> binder;
        do {
            binder = sm->getService(String16("media.player"));//获取MediaPlayerService
            if (binder != 0) {
                break;
            }
            ALOGW("Media player service not published, waiting...");
            usleep(500000); // 0.5 s 
        } while (true);
​
        if (sDeathNotifier == NULL) {
            sDeathNotifier = new DeathNotifier();
        }
        binder->linkToDeath(sDeathNotifier);//设置死亡通知
        sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);//创建代理对象。
    }
    ALOGE_IF(sMediaPlayerService == 0, "no media player service!?");
    return sMediaPlayerService;
}
​

首先获取了ServiceManage,这个过程上一篇中已经讲过了。通过 sm->getService获取media.player这个服务,如果拿不到binder那么就sleep0.5s继续循环。getService这个过程和获取ServiceManager很像。

sm->getService
/ complexity, this could be attempted.
sp<IBinder> ServiceManagerShim::getService(const String16& name) const
{
    static bool gSystemBootCompleted = false;
​
    sp<IBinder> svc = checkService(name);
    if (svc != nullptr) return svc;
        .........
}
sp<IBinder> ServiceManagerShim::checkService(const String16& name) const
{
    sp<IBinder> ret;
    if (!mTheRealServiceManager->checkService(String8(name).c_str(), &ret).isOk()) {
        return nullptr;
    }
    return ret;
}

上一篇中知道defaultServiceManager获取到的是BpServiceManager的封装类ServiceManagerShim,获取服务的调用getService->checkService->mTheRealServiceManager.checkService,mTheRealServiceManager就是BpServiceManager,又到了aidl生成的文件。

​
::android::binder::Status BpServiceManager::checkService(const ::std::string& name, ::android::sp<::android::IBinder>* _aidl_return) {
  ::android::Parcel _aidl_data;
  _aidl_data.markForBinder(remoteStrong());
  ::android::Parcel _aidl_reply;
  ::android::status_t _aidl_ret_status = ::android::OK;
  ::android::binder::Status _aidl_status;
  _aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  _aidl_ret_status = _aidl_data.writeUtf8AsUtf16(name);//将数据写入_aidl_data
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  _aidl_ret_status = remote()->transact(BnServiceManager::TRANSACTION_checkService, _aidl_data, &_aidl_reply, 0);//调用transact传送数据
  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && IServiceManager::getDefaultImpl())) {
     return IServiceManager::getDefaultImpl()->checkService(name, _aidl_return);
  }
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  _aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  if (!_aidl_status.isOk()) {
    return _aidl_status;
  }
  _aidl_ret_status = _aidl_reply.readNullableStrongBinder(_aidl_return);//获取binder对象
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  _aidl_error:
  _aidl_status.setFromStatusT(_aidl_ret_status);
  return _aidl_status;
}
​

在上一篇中已经讲了remote()->transact,调用链为BpBinder->transact() ->IPCThreadState::self()->transact() ->IPCThreadState::writeTransactionData->IPCThreadState::waitForResponse->BinderCallback-> IPCThreadState::getAndExecuteCommand->IPCThreadState::executeCommand->BnServiceManager::onTransact

//BnServiceManager::onTransact
case BnServiceManager::TRANSACTION_checkService:
  {
    ::std::string in_name;
    ::android::sp<::android::IBinder> _aidl_return;
    if (!(_aidl_data.checkInterface(this))) {
      _aidl_ret_status = ::android::BAD_TYPE;
      break;
    }
    _aidl_ret_status = _aidl_data.readUtf8FromUtf16(&in_name);
    if (((_aidl_ret_status) != (::android::OK))) {
      break;
    }
    ::android::binder::Status _aidl_status(checkService(in_name, &_aidl_return));
    _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
    if (((_aidl_ret_status) != (::android::OK))) {
      break;
    }
    if (!_aidl_status.isOk()) {
      break;
    }
    _aidl_ret_status = _aidl_reply->writeStrongBinder(_aidl_return);
    if (((_aidl_ret_status) != (::android::OK))) {
      break;
    }
  }
  break;
​
​

和addservice一样,这里调用了checkService,最后将调用结果返回。

​
::android::binder::Status BpServiceManager::checkService(const ::std::string& name, ::android::sp<::android::IBinder>* _aidl_return) {
  ::android::Parcel _aidl_data;
  _aidl_data.markForBinder(remoteStrong());
  ::android::Parcel _aidl_reply;
  ::android::status_t _aidl_ret_status = ::android::OK;
  ::android::binder::Status _aidl_status;
  _aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
 
  ...........
    
  _aidl_ret_status = remote()->transact(BnServiceManager::TRANSACTION_checkService, _aidl_data, &_aidl_reply, 0);
  
............
  
  _aidl_ret_status = _aidl_reply.readNullableStrongBinder(_aidl_return);
  
............
  
  return _aidl_status;
}

也是通过IPC调用回到了ServiceManager中

Status ServiceManager::checkService(const std::string& name, sp<IBinder>* outBinder) {
    *outBinder = tryGetService(name, false);
    // returns ok regardless of result for legacy reasons
    return Status::ok();
}
​
sp<IBinder> ServiceManager::tryGetService(const std::string& name, bool startIfNotFound) {
    auto ctx = mAccess->getCallingContext();
​
    sp<IBinder> out;
    Service* service = nullptr;
    if (auto it = mNameToService.find(name); it != mNameToService.end()) {//从mNameToService中查询当前名字的服务,就是在addservice添加的地方
        service = &(it->second);
​
        if (!service->allowIsolated) {
            uid_t appid = multiuser_get_app_id(ctx.uid);
            bool isIsolated = appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END;
​
            if (isIsolated) {
                return nullptr;
            }
        }
        out = service->binder;
    }
​
    if (!mAccess->canFind(ctx, name)) {
        return nullptr;
    }
​
    if (!out && startIfNotFound) {
        tryStartService(name);//如果没有启动就启动
    }
​
    if (out) {
        // Setting this guarantee each time we hand out a binder ensures that the client-checking
        // loop knows about the event even if the client immediately drops the service
        service->guaranteeClient = true;
    }
​
    return out;
}

到了ServiceManager中,其实就应该知道我们注册的时候是通过addservice将服务保存到了mNameToService中,现在查询肯定也是通过mNameToService来查询这个服务。拿到服务之后返回,在BpServiceManager中通过readNullableStrongBinder来读取binder。

#frameworks/native/libs/binder/Parcel.cpp
status_t Parcel::readNullableStrongBinder(sp<IBinder>* val) const
{
    return unflattenBinder(val);
}
​
​
status_t Parcel::unflattenBinder(sp<IBinder>* out) const
{
   ..........
​
#ifdef BINDER_WITH_KERNEL_IPC
    const flat_binder_object* flat = readObject(false);
​
    if (flat) {
        switch (flat->hdr.type) {
            case BINDER_TYPE_BINDER: {//如果是本地对象直接获取,这时候flat_binder_object->cookie指向BBinder
                sp<IBinder> binder =
                        sp<IBinder>::fromExisting(reinterpret_cast<IBinder*>(flat->cookie));
                return finishUnflattenBinder(binder, out);
            }
            case BINDER_TYPE_HANDLE: {//如果是远程对象调用 ProcessState::self()->getStrongProxyForHandle创建BpBinder,flat->handle就是远程binder对象的handle
                sp<IBinder> binder =
                    ProcessState::self()->getStrongProxyForHandle(flat->handle);
                return finishUnflattenBinder(binder, out);
            }
        }
    }
    return BAD_TYPE;
#else  // BINDER_WITH_KERNEL_IPC
    LOG_ALWAYS_FATAL("Binder kernel driver disabled at build time");
    return INVALID_OPERATION;
#endif // BINDER_WITH_KERNEL_IPC
}
​
status_t Parcel::finishUnflattenBinder(
    const sp<IBinder>& binder, sp<IBinder>* out) const
{
    int32_t stability;
    status_t status = readInt32(&stability);
    if (status != OK) return status;
​
    status = internal::Stability::setRepr(binder.get(), static_cast<int16_t>(stability),
                                          true /*log*/);
    if (status != OK) return status;
​
    *out = binder;
    return OK;
}

上一篇中提到ProcessState::self()->getStrongProxyForHandle(handle)相当于BpBinder::create(handle),readNullableStrongBinder通过flat->hdr.type来判断拿到的binder是否是当前进程的,分别获取BBinder和BpBinder对象返回。

interface_cast(binder)

拿到服务之后通过interface_cast来创建了一个BpMediaPlayerService,后续和MediaPlayerService的交互就通过BpMediaPlayerService来处理。interface_cast在上一篇也讲过就是通过asInterface来创建一个对象,实现就是通过模板方法。

#frameworks/av/media/libmedia/include/media/IMediaPlayerService.h
DECLARE_META_INTERFACE(MediaPlayerService);
#frameworks/av/media/libmedia/IMediaPlayerService.cpp
IMPLEMENT_META_INTERFACE(MediaPlayerService, "android.media.IMediaPlayerService");

在IMediaPlayerService.h中通过DECLARE_META_INTERFACE声明asInterface,在IMediaPlayerService.cpp中IMPLEMENT_META_INTERFACE来实现方法。

#define DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                        \
    const ::android::StaticString16 I##INTERFACE##_descriptor_static_str16(                     \
            __IINTF_CONCAT(u, NAME));                                                           \
    const ::android::String16 I##INTERFACE::descriptor(I##INTERFACE##_descriptor_static_str16); \
    DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE0(I##INTERFACE, I##INTERFACE, Bp##INTERFACE)
​
​
#define DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE0(ITYPE, INAME, BPTYPE)                     \
 
    ::android::sp<ITYPE> ITYPE::asInterface(const ::android::sp<::android::IBinder>& obj) {        \
        ::android::sp<ITYPE> intr;                                                                 \
        if (obj != nullptr) {                                                                      \
            intr = ::android::sp<ITYPE>::cast(obj->queryLocalInterface(ITYPE::descriptor));        \
            if (intr == nullptr) {                                                                 \
                intr = ::android::sp<BPTYPE>::make(obj);                                           \
            }                                                                                      \
        }                                                                                          \
        return intr;                                                                               \
    }                                                                                              \
​
//带入MediaPlayerService,"android.media.IMediaPlayerService"
DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE0(IMediaPlayerService, IMediaPlayerService, BpMediaPlayerService)
​
::android::sp<IMediaPlayerService> IMediaPlayerService::asInterface(const ::android::sp<::android::IBinder>& obj) {        
        ::android::sp<IMediaPlayerService> intr;                                                                 
        if (obj != nullptr) {                                                                      
            intr = ::android::sp<IMediaPlayerService>::cast(obj->queryLocalInterface(IMediaPlayerService::descriptor));        
            if (intr == nullptr) {                                                                 
                intr = ::android::sp<BPMediaPlayerService>::make(obj);                                           
            }                                                                                      
        }                                                                                          
        return intr;                                                                               
    }       
  

通过模板方法拿到BPMediaPlayerService一个service的获取就结束了。

参考:http://gityuan.com/2015/11/15/binder-get-service/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值