Treble 架构之 HwServiceManager

HAL ServiceManager main


int main() {
    // 配置 binder驱动线程池数量
    // 实现在 libhwbinder/ProcessState.cpp 中
    // 配置线程池数量为 1, 简单的说,就是 不允许binder驱动在创建线程了  
    // size_t kernelMaxThreads = maxThreads - 1;
    configureRpcThreadpool(1, true /* callerWillJoin */);


    sp<ServiceManager> manager = new ServiceManager();
    setRequestingSid(manager, true);

    if (!manager->add(serviceName, manager)) {
        ALOGE("Failed to register hwservicemanager with itself.");
    }

    TokenManager *tokenManager = new TokenManager();

    if (!manager->add(serviceName, tokenManager)) {
        ALOGE("Failed to register ITokenManager with hwservicemanager.");
    }

    // 创建 Looper
    sp<Looper> looper(Looper::prepare(0 /* opts */));

    int binder_fd = -1;
    // 获取binder fd 并往binder驱动 写入 BC_ENTER_LOOPER
    IPCThreadState::self()->setupPolling(&binder_fd);
    if (binder_fd < 0) {
        ALOGE("Failed to aquire binder FD. Aborting...");
        return -1;
    }
    // Flush after setupPolling(), to make sure the binder driver
    // knows about this thread handling commands.
    IPCThreadState::self()->flushCommands();

    // 当有数据到达时,就会回调 BinderCallback处理数据
    sp<BinderCallback> cb(new BinderCallback);
    if (looper->addFd(binder_fd, Looper::POLL_CALLBACK, Looper::EVENT_INPUT, cb,
            nullptr) != 1) {
        ALOGE("Failed to add hwbinder FD to Looper. Aborting...");
        return -1;
    }

    // Tell IPCThreadState we're the service manager
    sp<BnHwServiceManager> service = new BnHwServiceManager(manager);
    IPCThreadState::self()->setTheContextObject(service);
    // Then tell binder kernel
    flat_binder_object obj {
        .flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX,
    };

    status_t result = ioctl(binder_fd, BINDER_SET_CONTEXT_MGR_EXT, &obj);

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

        result = ioctl(binder_fd, BINDER_SET_CONTEXT_MGR, 0);
    }

    // Only enable FIFO inheritance for hwbinder
    // FIXME: remove define when in the kernel
#define BINDER_SET_INHERIT_FIFO_PRIO    _IO('b', 10)

    int rc = ioctl(binder_fd, BINDER_SET_INHERIT_FIFO_PRIO);
    if (rc) {
        ALOGE("BINDER_SET_INHERIT_FIFO_PRIO failed with error %d\n", rc);
    }

    // Hw ServicveMananger 启动就绪
    rc = property_set("hwservicemanager.ready", "true");
    if (rc) {
        ALOGE("Failed to set \"hwservicemanager.ready\" (error %d). "\
              "HAL services will not start!\n", rc);
    }

    // 进入循环。
    while (true) {
        looper->pollAll(-1 /* timeoutMillis */);
    }

    return 0;
}

  1. 打开binder驱动

    configureRpcThreadpool(1, true /* callerWillJoin */);
    

    就这简单的一句,做了如下工作:

    • 限制了当前进程的线程数量。binder驱动不能再通过BR_SPAWN_LOOPER创建子线程了,简单的说就是整个ServiceManager进程只有一个主线程。没有其他线程了。

    • 打开bidner驱动。

      static int open_driver()
      {
          int fd = open("/dev/hwbinder", O_RDWR | O_CLOEXEC);
      	size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;			// 0
      	result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
          return fd;
      }
      
  2. 创建ServiceManager对象

    创建过程也很简单,关于ServiceManger是如何管理注册过来的服务的,见ServiceManager的解析,这里不表。

  3. 创建TokenManager对象

    作用我还不清楚。

  4. 创建Looper对象

    这个是Java Looper的底层实现吧,MessageQueue的核心。通过epoll实现,通过addFd方法将文件描述符注册到Looper后,当有读写等事件到来时,就会调用回调函数(对应这里的BinderCallback)。

  5. 创建BnHwServiceManager,并设置为Context Object。

    虽然创建了BnHwServiceManager对象,但是并没有将其传递到驱动中去生成binder_node。由于设置成为了conetext,驱动根据binder_proc->context就能直接找到该进程。然后将发送给BpHwBinder::mHandler == 0的请求都交由我们的Service Manager进程处理。

  6. 设置就绪属性,并进入循环

    设置属性的作用是defaultServiceManager需要等待ServiceManager就绪。

    
    static const char* kHwServicemanagerReadyProperty = "hwservicemanager.ready";
    // ProcessState::self()->getContextObject(NULL) 前调用
    void waitForHwServiceManager() {
        using std::literals::chrono_literals::operator""s;
    
        while (!WaitForProperty(kHwServicemanagerReadyProperty, "true", 1s)) {
            LOG(WARNING) << "Waited for hwservicemanager.ready for a second, waiting another...";
        }
    }
    

前面提到,当数据到来时,Looper会回调BinderCallback处理数据,看一下其实现:

class BinderCallback : public LooperCallback {
public:
    BinderCallback() {}
    ~BinderCallback() override {}

    int handleEvent(int /* fd */, int /* events */, void* /* data */) override {
        IPCThreadState::self()->handlePolledCommands();
        return 1;  // Continue receiving callbacks.
    }
};

// libhwhandle
status_t IPCThreadState::handlePolledCommands()
{
    status_t result;

    do {
        result = getAndExecuteCommand();
    } while (mIn.dataPosition() < mIn.dataSize());

    processPendingDerefs();
    flushCommands();
    return result;
}

嗯,了解libbinder的都知道接下来的处理流程了:

处理 BR_TRANSACTION命令字:

case BR_TRANSACTION:
{
	binder_transaction_data& tr = tr_secctx.transaction_data;
	result = mIn.read(&tr, sizeof(tr));
	Parcel buffer;
	buffer.ipcSetDataReference(
                reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
                tr.data_size,
                reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
                tr.offsets_size/sizeof(binder_size_t), freeBuffer, this);

	if (tr.target.ptr) {
		// We only have a weak reference on the target object, so we must first try to
		// safely acquire a strong reference before doing anything else with it.
		if (reinterpret_cast<RefBase::weakref_type*>(
				tr.target.ptr)->attemptIncStrong(this)) {
                error = reinterpret_cast<BHwBinder*>(tr.cookie)->transact(tr.code, buffer,
					&reply, tr.flags, reply_callback);
				reinterpret_cast<BHwBinder*>(tr.cookie)->decStrong(this);
		} else {
		error = UNKNOWN_TRANSACTION;
		}

	} else {
        error = mContextObject->transact(tr.code, buffer, &reply, tr.flags, reply_callback);
	}
	...
}

重点来了,前面我们执行了IPCThreadState::self()->setTheContextObject(BnHwServiceManager);,所以这里的mContextObject就是BnHwServiceManager

当驱动知道数据的目的地是Context时,tr.target.ptr 就会被设置为nullptr。所以,最终数据最终都会交由BnHwServiceManager::onTransaction处理。

BnHwServiceManager有hild-gen自动生成,其内部会生成IServiceManager.hal中定义的函数的通用实现。所谓通用实现就是无关具体的业务逻辑,只处理binder通信过程中,函数参数的打包和解包等操作。具体的实现还是由我们来实现。

回过头看BnHwServiceManager的创建:

// Tell IPCThreadState we're the service manager
sp<BnHwServiceManager> service = new BnHwServiceManager(manager);

其需要传入我们实现的ServiceManager对象manager,所以可以大胆猜测,在其BnHwServiceManager::onTransaction中,最终还是会调用到manager的具体实现的。

到这里,ServiceManager的启动就分析完了,还有很多细节忽略了。有时间再补充。。。。

和 Framework ServiceManager的区别

Framework Service Manager 简称 FSM吧, 那HAl Service Manager就简称为 HSM吧。

FSM 用C语言实现的,没有用到libbinder库,自身简单的对binder数据进行解析。

HSM使用C++实现,用到libhwbinder库,和binder的数据交换过程完全屏蔽了,代码看上去清晰了很多,不过前提是了解libhwbinder或者 libbinder,不然,更加一脸懵逼。。。。

上一篇:Android Framework 架构介绍,Binder理解


下一篇:用.net开发PDMS插件的方法