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;
}
-
打开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; }
-
-
创建
ServiceManager
对象创建过程也很简单,关于
ServiceManger
是如何管理注册过来的服务的,见ServiceManager
的解析,这里不表。 -
创建
TokenManager
对象作用我还不清楚。
-
创建
Looper
对象这个是Java
Looper
的底层实现吧,MessageQueue
的核心。通过epoll
实现,通过addFd
方法将文件描述符注册到Looper
后,当有读写等事件到来时,就会调用回调函数(对应这里的BinderCallback
)。 -
创建
BnHwServiceManager
,并设置为Context Object。虽然创建了
BnHwServiceManager
对象,但是并没有将其传递到驱动中去生成binder_node
。由于设置成为了conetext
,驱动根据binder_proc->context
就能直接找到该进程。然后将发送给BpHwBinder::mHandler == 0
的请求都交由我们的Service Manager
进程处理。 -
设置就绪属性,并进入循环
设置属性的作用是
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,不然,更加一脸懵逼。。。。