Android Binder通信原理(四):service获取

源码基于:Android R

0. 前言

上一篇博文中 已经得知如何通过 defaultServiceManager() 得来的 BpInterface 与 servciemanager 进行通信,并分析了addServcie() 的流程,这里再来看下service 的获取过程。

1. getService()

这个接口有两种方式,一个是通过 defaultServiceManager() 获取到 servicemanager 的 BpBinder,然后再通过该代理的 getService() 进行调用;另一个是 IServiceManager.h 中直接提供了全局的接口函数。

1.1 全局接口函数 getService()

frameworks/native/libs/binder/include/binder/IServiceManager.h

template<typename INTERFACE>
status_t getService(const String16& name, sp<INTERFACE>* outService)
{
    const sp<IServiceManager> sm = defaultServiceManager();
    if (sm != nullptr) {
        *outService = interface_cast<INTERFACE>(sm->getService(name));
        if ((*outService) != nullptr) return NO_ERROR;
    }
    return NAME_NOT_FOUND;
}

 这里封装了 defaultServiceManager(),然后再调用 getService()。

1.2 代理接口函数 getService()

frameworks/native/libs/binder/IServiceManager.cpp

sp<IBinder> ServiceManagerShim::getService(const String16& name) const
{
    static bool gSystemBootCompleted = false;

    sp<IBinder> svc = checkService(name);
    if (svc != nullptr) return svc;

    const bool isVendorService =
        strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder") == 0;
    const long timeout = 5000;
    int64_t startTime = uptimeMillis();
    // Vendor code can't access system properties
    if (!gSystemBootCompleted && !isVendorService) {
#ifdef __ANDROID__
        char bootCompleted[PROPERTY_VALUE_MAX];
        property_get("sys.boot_completed", bootCompleted, "0");
        gSystemBootCompleted = strcmp(bootCompleted, "1") == 0 ? true : false;
#else
        gSystemBootCompleted = true;
#endif
    }
    // retry interval in millisecond; note that vendor services stay at 100ms
    const long sleepTime = gSystemBootCompleted ? 1000 : 100;

    int n = 0;
    while (uptimeMillis() - startTime < timeout) {
        n++;
        ALOGI("Waiting for service '%s' on '%s'...", String8(name).string(),
            ProcessState::self()->getDriverName().c_str());
        usleep(1000*sleepTime);

        sp<IBinder> svc = checkService(name);
        if (svc != nullptr) return svc;
    }
    ALOGW("Service %s didn't start. Returning NULL", String8(name).string());
    return nullptr;
}

代码逻辑比较简单,通过checkServcie() 确认servcie 是否存在,如果没有会有 5s 的retry,如果还是没有 checkService() 成功,则返回nullptr。

2. checkService()

frameworks/native/libs/binder/IServiceManager.cpp

sp<IBinder> ServiceManagerShim::checkService(const String16& name) const
{
    sp<IBinder> ret;
    if (!mTheRealServiceManager->checkService(String8(name).c_str(), &ret).isOk()) {
        return nullptr;
    }
    return ret;
}

上一篇博文 已经分析过 BpBinder 到 BBinder 的通信流程,对于BpServcieManager,其handle 比较特殊,值为0,其实无论特殊与否,最终都会调用到 BBinder 的 transact()

frameworks/native/libs/binder/Binder.cpp

status_t BBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    data.setDataPosition(0);

    status_t err = NO_ERROR;
    switch (code) {
        case PING_TRANSACTION:
            err = pingBinder();
            break;
        case EXTENSION_TRANSACTION:
            err = reply->writeStrongBinder(getExtension());
            break;
        case DEBUG_PID_TRANSACTION:
            err = reply->writeInt32(getDebugPid());
            break;
        default:
            err = onTransact(code, data, reply, flags);
            break;
    }

    // In case this is being transacted on in the same process.
    if (reply != nullptr) {
        reply->setDataPosition(0);
    }

    return err;
}

除了特殊的code,其他的都会继续调用onTransact,而BBinder 的onTransact 会被Bn端覆盖掉。

2.1 BpServiceManager::checkService()

out/soong/.intermediates/frameworks/native/libs/binder/libbinder/.../gen/aidl/frameworks/native/libs/binder/aidl/android/os/IServiceManager.cpp

::android::binder::Status BpServiceManager::checkService(const ::std::string& name, ::android::sp<::android::IBinder>* _aidl_return) {
  ::android::Parcel _aidl_data;
  ::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);
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  _aidl_ret_status = remote()->transact(::android::IBinder::FIRST_CALL_TRANSACTION + 1 /* checkService */, _aidl_data, &_aidl_reply);
  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);
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  _aidl_error:
  _aidl_status.setFromStatusT(_aidl_ret_status);
  return _aidl_status;
}

这里主要是将code 为 ::android::IBinder::FIRST_CALL_TRANSACTION + 1 传到server 端, 携带的参数有两个,一个是 name 会写到 _aidl_data 传到server 端,另外一个是 _aidl_return,需要在 transact 返回后从 _aidl_reply 中读出来。

注意这里的 _aidl_replay.readNullableStrongBinder(),后面统一分析。

2.2 BnServiceManager::onTransact()

out/soong/.intermediates/frameworks/native/libs/binder/libbinder/.../gen/aidl/frameworks/native/libs/binder/aidl/android/os/IServiceManager.cpp

  case ::android::IBinder::FIRST_CALL_TRANSACTION + 1 /* 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;

首先是将参数 in_name 读出来,并将参数 _aidl_return 一并带入到真正实现 BnServiceManager 的地方。调用完成后会将 _aidl_return 存入到 _aidl_reply 中。

这里注意下Parcel 的 writeStrongBinder(),后面与BpServiceManager 中的readNullableStrongBinder() 统一分析。

接下来看下 ServiceManager  中实现的地方:

2.3 ServiceManager::checkService()

frameworks/native/cmds/servicemanager/ServiceManager.cpp

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()) {
        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;
}

这里不多分析,主要是将 mNameToService 中 add 进去的service 再次取出来,上一篇博文 提到了service 的 BBinder 经过驱动后会转成 remote 方式,checkService() 返回后会将 IBinder 存放到Parcel,通过接口 writeStrongBinder():

frameworks/native/libs/binder/Parcel.cpp

status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
    return flattenBinder(val);
}

status_t Parcel::flattenBinder(const sp<IBinder>& binder)
{
    flat_binder_object obj;

    if (IPCThreadState::self()->backgroundSchedulingDisabled()) {
        /* minimum priority for all nodes is nice 0 */
        obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS;
    } else {
        /* minimum priority for all nodes is MAX_NICE(19) */
        obj.flags = 0x13 | FLAT_BINDER_FLAG_ACCEPTS_FDS;
    }

    if (binder != nullptr) {
        BBinder *local = binder->localBinder();
        if (!local) {
            BpBinder *proxy = binder->remoteBinder();
            if (proxy == nullptr) {
                ALOGE("null proxy");
            }
            const int32_t handle = proxy ? proxy->handle() : 0;
            obj.hdr.type = BINDER_TYPE_HANDLE;
            obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
            obj.handle = handle;
            obj.cookie = 0;
        } else {
            if (local->isRequestingSid()) {
                obj.flags |= FLAT_BINDER_FLAG_TXN_SECURITY_CTX;
            }
            obj.hdr.type = BINDER_TYPE_BINDER;
            obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
            obj.cookie = reinterpret_cast<uintptr_t>(local);
        }
    } else {
        obj.hdr.type = BINDER_TYPE_BINDER;
        obj.binder = 0;
        obj.cookie = 0;
    }

    return finishFlattenBinder(binder, obj);
}

IBinder 不再是BBbinder 了,localBinder 为nullptr,配置好 hdr.type 为 HANDLE 方式,在Bp 端会通过 readNullableStrongBinder() 进行 unflattenBinder():

_aidl_ret_status = _aidl_reply.readNullableStrongBinder(_aidl_return);
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
{
    const flat_binder_object* flat = readObject(false);

    if (flat) {
        switch (flat->hdr.type) {
            case BINDER_TYPE_BINDER: {
                sp<IBinder> binder = reinterpret_cast<IBinder*>(flat->cookie);
                return finishUnflattenBinder(binder, out);
            }
            case BINDER_TYPE_HANDLE: {
                sp<IBinder> binder =
                    ProcessState::self()->getStrongProxyForHandle(flat->handle);
                return finishUnflattenBinder(binder, out);
            }
        }
    }
    return BAD_TYPE;
}

在writeStrongBinder() 的时候hdr.type 设置的是HANDLE,所以,这里通过getStrongProxyForHandle() 接口:

frameworks/native/libs/binder/ProcessState.cpp

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    sp<IBinder> result;

    AutoMutex _l(mLock);

    handle_entry* e = lookupHandleLocked(handle);

    if (e != nullptr) {

        if (b == nullptr || !e->refs->attemptIncWeak(this)) {
            if (handle == 0) {
                Parcel data;
                status_t status = IPCThreadState::self()->transact(
                        0, IBinder::PING_TRANSACTION, data, nullptr, 0);
                if (status == DEAD_OBJECT)
                   return nullptr;
            }

            b = BpBinder::create(handle);
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {
            // This little bit of nastyness is to allow us to add a primary
            // reference to the remote proxy when this team doesn't have one
            // but another team is sending the handle to us.
            result.force_set(b);
            e->refs->decWeak(this);
        }
    }

    return result;
}

通过接口 lookupHandleLocked() 查询进程中的 handle ,如果存在了就直接返回,如果没有则通过BpBinder::create() 新建一个。

至此,service 的获取流程已经分析完毕,总结下流程:

  • 通过 defaultServiceManager() 获取到 servciemanager 的代理 BpServiceManager;
  • 通过代理 BpBinder 调用 getService(),而service 的Binder 通过checkServcie() 获取;
  • 调用BpBinder->transact() 将code 、data、reply 传入,IPCThreadState->transact() 会talkWithDriver() 调用;
  • servciemanager 中 IPCThreadState 收到 BR_TRANSACTION 后会调用 BBinder->transact(),进而调用 BBinder->onTransact();
  • ServiceManager 中会将之前 addService() 存放到 mNameToService 中的servcie IBinder 取出,并通过 writeStrongBinder() 写入reply 中;
  • BBinder->onTransact() 返回后 sendReply(),client 端会收到 BR_REPLY,并将 data read 到reply;
  • Bp端对 _aidl_reply 进行 unfattenBinder(),得到 sercie 的BpBinder;

猜你喜欢

转载自blog.csdn.net/jingerppp/article/details/131410743