Android Binder通信机制学习(三)

4 篇文章 1 订阅
4 篇文章 0 订阅

新人阿彡的Android多媒体学习之路

🚄🚄🚄 第一章 Android Binder通信机制学习之Binder基本原理
🚄🚄🚄 第二章 Android Binder通信机制学习之Binder基本架构
🚄🚄🚄 第三章 Android Binder通信机制学习之ServiceManager流程分析
🚄🚄🚄 第四章 Android Binder通信机制学习之addService服务注册流程

0、前言

主要参考:https://www.cnblogs.com/rongmiao/p/16067971.html

作为一名新步入Android领域的职场老鸟,奈何最近环境不好,整体越来越卷的大背景下,本老鸟又新进入Android开发这个领域,后续工作基本应该是主攻Android Framework层的开发,辅助Android Applicatios层的开发,在这里记录一下个人的学习之旅,一方面方便自己学习总结,另一方面也方便后续的查漏补缺。整体学习基于Android 12 版本的代码。

1、ServiceManager启动流程

ServiceManager 是 Binder 进程间通信机制的核⼼组件之⼀, 它扮演着Binder进程间通信机制上下⽂管理者的⾓⾊, 同时负责管理系统中的Service组件, 并且向Client组件提供获取Service代理对象的服务。ServiceManager (下⽂都称 SM) 运⾏在⼀个独⽴的进程中, 因此, Service 组件和 Client 组件也需要通过进程间通信机制来和它进⾏交互, ⽽采⽤的进程间通信机制正好也是 Binder 机制。这样看来 SM 除了是 Binder 进程间通信机制的上下⽂管理者外, 还是⼀个特殊的 Service 组件

先来看一下完整的ServiceManager启动流程
在这里插入图片描述

下面展示关键函数代码以及相应注释
代码路劲:native/cmds/servicemanager/main.cpp

/******************************1、main()**********************************/
int main(int argc, char** argv) {
#ifdef __ANDROID_RECOVERY__
    android::base::InitLogging(argv, android::base::KernelLogger);
#endif

    if (argc > 2) {
        LOG(FATAL) << "usage: " << argv[0] << " [binder driver]";
    }

    const char* driver = argc == 2 ? argv[1] : "/dev/binder";
    // 打开binder驱动,open,mmap
    sp<ProcessState> ps = ProcessState::initWithDriver(driver);
    // 在初始化ProcessState的时候,mThreadPoolStarted被初始化为false了,所以setThreadPoolMaxThreadCount函数里面不会设置线程池最大线程数
    ps->setThreadPoolMaxThreadCount(0);
    // oneway限制,sm发起的binder调用必须是单向,否则打印堆栈日志提示
    ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);
    // 实例化ServiceManager,传入Access类用于鉴权
    sp<ServiceManager> manager = sp<ServiceManager>::make(std::make_unique<Access>());
    // 将自身注册到ServiceManager当中
    if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
        LOG(ERROR) << "Could not self register servicemanager";
    }
    // 将ServiceManager设置给 IPCThreadState 的全局变量
    IPCThreadState::self()->setTheContextObject(manager);
    // 注册到驱动,成为binder管理员,handle是0
    ps->becomeContextManager();
    // 准备Looper
    sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);
    // 通知驱动BC_ENTER_LOOPER,监听驱动fd,有消息时回调到handleEvent处理binder调用
    BinderCallback::setupTo(looper);
    ClientCallbackCallback::setupTo(looper, manager);
    // 循环等待消息
    while(true) {
        looper->pollAll(-1);
    }

    // should not be reached
    return EXIT_FAILURE;
}

1.1、ProcessState初始化

/****************4、sp<ProcessState>::make(driver)********************/
ProcessState::ProcessState(const char* driver)
      : mDriverName(String8(driver)),
        mDriverFD(-1),
        mVMStart(MAP_FAILED),
        mThreadCountLock(PTHREAD_MUTEX_INITIALIZER),
        mThreadCountDecrement(PTHREAD_COND_INITIALIZER),
        mExecutingThreadsCount(0),
        mWaitingForThreads(0),
        mMaxThreads(DEFAULT_MAX_BINDER_THREADS),
        mStarvationStartTimeMs(0),
        mForked(false),
        mThreadPoolStarted(false),
        mThreadPoolSeq(1),
        mCallRestriction(CallRestriction::NONE) {
    base::Result<int> opened = open_driver(driver); // 1、调用 open_driver 打开 binder 驱动设备

    if (opened.ok()) {
        // 2、执行内存映射操作
        // mmap the binder, providing a chunk of virtual address space to receive transactions.
        mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE,
                        opened.value(), 0);
        if (mVMStart == MAP_FAILED) {
            close(opened.value());
            // *sigh*
            opened = base::Error()
                    << "Using " << driver << " failed: unable to mmap transaction memory.";
            mDriverName.clear();
        }
    }

#ifdef __ANDROID__
    LOG_ALWAYS_FATAL_IF(!opened.ok(), "Binder driver '%s' could not be opened. Terminating: %s",
                        driver, opened.error().message().c_str());
#endif

    if (opened.ok()) {
        mDriverFD = opened.value();
    }
}

1.2、open_driver打开binder驱动

/****************5、open_driver(const char* driver)********************/
static base::Result<int> open_driver(const char* driver) {
    int fd = open(driver, O_RDWR | O_CLOEXEC); // 1.通过open系统调用打开了/dev/binder设备
    if (fd < 0) {
        return base::ErrnoError() << "Opening '" << driver << "' failed";
    }
    int vers = 0;
    // 2.通过ioctl获取Binder实现的版本号,并检查是否匹配
    status_t result = ioctl(fd, BINDER_VERSION, &vers);
    if (result == -1) {
        close(fd);
        return base::ErrnoError() << "Binder ioctl to obtain version failed";
    }
    if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
        close(fd);
        return base::Error() << "Binder driver protocol(" << vers
                             << ") does not match user space protocol("
                             << BINDER_CURRENT_PROTOCOL_VERSION
                             << ")! ioctl() return value: " << result;
    }
    size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
    // 3.通过ioctl设置进程支持的最大Binder线程数
    result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
    if (result == -1) {
        ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
    }
    uint32_t enable = DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION;
    result = ioctl(fd, BINDER_ENABLE_ONEWAY_SPAM_DETECTION, &enable);
    if (result == -1) {
        ALOGE_IF(ProcessState::isDriverFeatureEnabled(
                     ProcessState::DriverFeature::ONEWAY_SPAM_DETECTION),
                 "Binder ioctl to enable oneway spam detection failed: %s", strerror(errno));
    }
    return fd;
}

1.3、addService注册实例到ServiceManager中

/****************15、addService(const char* driver)********************/
Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) {
    auto ctx = mAccess->getCallingContext();
    // uid鉴权
    if (multiuser_get_app_id(ctx.uid) >= AID_APP) {
        return Status::fromExceptionCode(Status::EX_SECURITY, "App UIDs cannot add services");
    }
    // selinux鉴权
    if (!mAccess->canAdd(ctx, name)) {
        return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denial");
    }

    if (binder == nullptr) {
        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Null binder");
    }
    // 检查名字是否有效
    if (!isValidServiceName(name)) {
        LOG(ERROR) << "Invalid service name: " << name;
        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Invalid service name");
    }

#ifndef VENDORSERVICEMANAGER
    if (!meetsDeclarationRequirements(binder, name)) {
        // already logged
        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "VINTF declaration error");
    }
#endif  // !VENDORSERVICEMANAGER

    // implicitly unlinked when the binder is removed
    // remoteBinder返回不为空,说明是代理对象,则注册死亡通知并检查注册结果
    if (binder->remoteBinder() != nullptr &&
        binder->linkToDeath(sp<ServiceManager>::fromExisting(this)) != OK) {
        LOG(ERROR) << "Could not linkToDeath when adding " << name;
        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "linkToDeath failure");
    }

    // Overwrite the old service if it exists
    // 将binder保存到map容器当中
    mNameToService[name] = Service {
        .binder = binder,
        .allowIsolated = allowIsolated,
        .dumpPriority = dumpPriority,
        .debugPid = ctx.debugPid,
    };

    auto it = mNameToRegistrationCallback.find(name);
    if (it != mNameToRegistrationCallback.end()) {
        for (const sp<IServiceCallback>& cb : it->second) {
            mNameToService[name].guaranteeClient = true;
            // permission checked in registerForNotifications
            cb->onRegistration(name, binder);
        }
    }

    return Status::ok();
}

1.4、becomeContextManager注册实例到Binder驱动中,并设置为管理员

/************************17、becomeContextManager**************************/
bool ProcessState::becomeContextManager()
{
    AutoMutex _l(mLock);

    flat_binder_object obj {
        .flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX,
    };

    int result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR_EXT, &obj);

    // fallback to original method
    if (result != 0) {
        android_errorWriteLog(0x534e4554, "121035042");

        int unused = 0;
        // 传入命令 BINDER_SET_CONTEXT_MGR 将自己注册成为SM
        result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &unused);
    }

    if (result == -1) {
        ALOGE("Binder ioctl to become context manager failed: %s\n", strerror(errno));
    }

    return result == 0;
}

2、ServiceManager对象如何获取

启动ServiceManager之后我们要如何获取到ServiceManager并且使用它的方法呢?这时候就要到libbinder中的IServiceManager了,我们平时使用会直接调用defaultServiceManager来获取ServiceManager

[[clang::no_destroy]] static std::once_flag gSmOnce;
[[clang::no_destroy]] static sp<IServiceManager> gDefaultServiceManager;
sp<IServiceManager> defaultServiceManager()
{
    std::call_once(gSmOnce, []() {
        sp<AidlServiceManager> sm = nullptr;
        while (sm == nullptr) {
            // 先创建ProcessState对象,然后调用其getContextObject函数创建一个Binder对象,然后调用
            // 模板函数 interface_cast<IServiceManager> 将其封装为一个ServiceManager的代理对象
            sm = interface_cast<AidlServiceManager>(ProcessState::self()->getContextObject(nullptr));
            if (sm == nullptr) {
                ALOGE("Waiting 1s on context object on %s.", ProcessState::self()->getDriverName().c_str());
                sleep(1);
            }
        }
        // 实例化 ServiceManagerShim,他的真是面目是 BpServiceManager(BpBinder(0))
        gDefaultServiceManager = sp<ServiceManagerShim>::make(sm);
    });

    return gDefaultServiceManager;
}

先调用ProcessState::self 打开binder驱动(一般情况下调用进程和ServiceManager服务端不在同一个进程,这时候会重新打开binder驱动),然后调用getContextObject获取服务端的ServiceManager(handle为0默认为ServiceManager),然后调用getStrongProxyForHandle函数来实现获取Binder代理对象。

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

    AutoMutex _l(mLock);
    /* struct handle_entry {
           IBinder* binder;
           RefBase::weakref_type* refs;
       };
      每一个 Binder 代理对象都使用一个 handle_entry 的结构体来描述. handle_entry 的两个成员变量 binder 与 refs 
      分别指向一个 Binder 代理对象以及它内部的一个弱引用计数对象.
    */
    handle_entry* e = lookupHandleLocked(handle);

    if (e != nullptr) {
        IBinder* b = e->binder;
        /* 判断 handlle_entry 结构体的成员变量 binder 值是否为 NULL, 如果为 NULL, 说明尚未为
           句柄值 handle 创建过 Binder 代理对象. 那么就会下面创建 Binder 代理对象. 如果不为 NULL, 
           说明它已经指向了一个 Binder 代理对象, 则需要调用 attemptIncWeak 函数检查这个代理对象是否还存活着 */
        if (b == nullptr || !e->refs->attemptIncWeak(this)) {
            // handle == 0 创建ServiceManager
            if (handle == 0) {
                IPCThreadState* ipc = IPCThreadState::self();

                CallRestriction originalCallRestriction = ipc->getCallRestriction();
                ipc->setCallRestriction(CallRestriction::NONE);

                Parcel data;
                // 通过 PING_TRANSACTION 命令测试 Binder 是否准备就绪
                status_t status = ipc->transact(
                        0, IBinder::PING_TRANSACTION, data, nullptr, 0);

                ipc->setCallRestriction(originalCallRestriction);

                if (status == DEAD_OBJECT)
                   return nullptr;
            }
            // 根据句柄值 handle 创建 Binder 代理对象, 并将其保存在 handle_entry 结构体 e 的成员变量 binder 中
            sp<BpBinder> b = BpBinder::PrivateAccessor::create(handle);
            e->binder = b.get();
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {
            // 进程中已经有一个 Binder 代理对象与句柄值 handle 相对应, 并且这个 Binder 代理对象是有效的. 直接返回给调用者
            result.force_set(b);
            e->refs->decWeak(this);
        }
    }
    return result;
}

interface_cast是一个模板函数,之前的章节Android Binder通信机制学习(二)有提到,这里再看一下interface_cast的定义

template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
    // asInterface 函数定义在宏 DECLARE_META_INTERFACE 
    return INTERFACE::asInterface(obj);
}

其内部所调用的函数asInterface是在宏IMPLEMENT_META_INTERFACE里面定义的,之前的章节Android Binder通信机制学习(二)也有提到

::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) {
                /* 以 ServiceManager 为例子,这里创建的是BpServiceManager */                           \
                intr = ::android::sp<BPTYPE>::make(obj);                                           \
            }                                                                                      \
        }                                                                                          \
        return intr;                                                                               \
    } 

其内部调用的queryLocalInterface函数,具体实现是在IInterface.h中定义的模板函数BnInterface< INTERFACE >::queryLocalInterface,这里的INTERFACE 模板类也就是ServiceManager。

template<typename INTERFACE>
inline sp<IInterface> BnInterface<INTERFACE>::queryLocalInterface(
        const String16& _descriptor)
{
    if (_descriptor == INTERFACE::descriptor) return sp<IInterface>::fromExisting(this);
    return nullptr;
}

先获取当前进程的Bn对象,如果返回null,那么就通过intr = ::android::sp<BPTYPE>::make(obj)语句创建一个Bp对象,即BpServiceManager。

最后看一下完整的流程图:
在这里插入图片描述
本章主要学习了ServiceManager是如何启动以及启动后怎么获取ServiceManager对象,后面章节会在此基础上继续学习Server端是如何向ServiceManager注册服务,以及Client又是如何向ServerManager获取服务的。

3、参考资料

1、Android 12(S) Binder(一)
2、Android12系统源码分析NativeBinder代码变迁
3、梳理Binder原理之ServiceManager的注册流程(启动流程)AndroidP
4、Android之ServiceManager服务

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值