ServiceManager Initialization Flow
When the system boots, the init process parses init.rc to launch the servicemanager. The startup sequence invokes the main() functon in main.cpp, which performs four critical operations:
- Open the /dev/binder device node
- Map the binder device's memory space into the ServiceManager process address space
- Register ServiceManager as the context manager
- Enter the event loop to process incoming binder transactions
int main(int argc, char** argv) {
if (argc > 2) {
LOG(FATAL) << "usage: " << argv[0] << " [binder driver]";
}
const char* driver = argc == 2 ? argv[1] : "/dev/binder";
// Step 1: Open /dev/binder and map device memory into SM process
sp<ProcessState> ps = ProcessState::initWithDriver(driver);
ps->setThreadPoolMaxThreadCount(0);
ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);
// Step 2: Create ServiceManager and register it
sp<ServiceManager> manager = sp<ServiceManager>::make(std::make_unique<Access>());
if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
LOG(ERROR) << "Could not self register servicemanager";
}
// Step 3: Set ServiceManager as context manager
IPCThreadState::self()->setTheContextObject(manager);
ps->becomeContextManager();
// Step 4: Enter polling loop to handle transactions
sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);
BinderCallback::setupTo(looper);
ClientCallbackCallback::setupTo(looper, manager);
while(true) {
looper->pollAll(-1);
}
return EXIT_FAILURE;
}
Opening the Binder Device
The ProcessState constructor handles device opening and memory mapping:
ProcessState::ProcessState(const char *driver)
: mDriverName(String8(driver))
, mDriverFD(open_driver(driver))
, mCallRestriction(CallRestriction::NONE) {
if (mDriverFD >= 0) {
mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE,
mDriverFD, 0);
if (mVMStart == MAP_FAILED) {
ALOGE("Using %s failed: unable to mmap transaction memory.\n",
mDriverName.c_str());
close(mDriverFD);
mDriverFD = -1;
}
}
}
The open_driver() function opens the binder device node and queries driver capabilities via ioctl():
static int open_driver(const char *driver) {
int fd = open(driver, O_RDWR | O_CLOEXEC);
if (fd >= 0) {
int vers = 0;
status_t result = ioctl(fd, BINDER_VERSION, &vers);
if (result != 0) {
close(fd);
return -1;
}
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
if (result != 0) {
ALOGE("Binder driver does not support BINDER_SET_MAX_THREADS\n");
}
uint32_t enable = DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION;
result = ioctl(fd, BINDER_ENABLE_ONEWAY_SPAM_DETECTION, &enable);
} else {
ALOGW("Opening '%s' failed: %s\n", driver, strerror(errno));
}
return fd;
}
Memory Mapping from Kernel to User Space
The kernel-side binder_mmap() function handles the memory mapping request:
static int binder_mmap(struct file *filp, struct vm_area_struct *vma) {
int ret;
struct binder_proc *proc = filp->private_data;
if (proc->tsk != current->group_leader)
return -EINVAL;
// Enforce 4MB size limit
if ((vma->vm_end - vma->vm_start) > SZ_4M)
vma->vm_end = vma->vm_start + SZ_4M;
// Validate memory flags
if (vma->vm_flags & FORBIDDEN_MMAP_FLAGS) {
ret = -EPERM;
goto err_bad_arg;
}
vma->vm_flags |= VM_DONTCOPY | VM_MIXEDMAP;
vma->vm_flags &= ~VM_MAYWRITE;
vma->vm_ops = &binder_vm_ops;
vma->vm_private_data = proc;
ret = binder_alloc_mmap_handler(&proc->alloc, vma);
if (ret)
return ret;
return 0;
}
Registerring as Context Manager
ServiceManager registers itself with the binder driver as the context manager:
sp<ServiceManager> manager = sp<ServiceManager>::make(std::make_unique<Access>());
if (!manager->addService("manager", manager, false, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
LOG(ERROR) << "Could not self register servicemanager";
}
The ServiceManager stores registered services in an internal map:
Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder) {
mNameToService[name] = Service {
.binder = binder,
.allowIsolated = allowIsolated,
.dumpPriority = dumpPriority,
.debugPid = ctx.debugPid,
};
return Status::ok();
}
The becomeContextManager() function uses ioctl() with BINDER_SET_CONTEXT_MGR:
bool ProcessState::becomeContextManager() {
AutoMutex _l(mLock);
flat_binder_object obj {
.flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX,
};
int unused = 0;
result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &unused);
return result == 0;
}
Event Loop
ServiceManager enters a polling loop to process incoming transactions:
int main(int argc, char** argv) {
// ... initialization code ...
sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);
BinderCallback::setupTo(looper);
ClientCallbackCallback::setupTo(looper, manager);
while(true) {
looper->pollAll(-1);
}
return EXIT_FAILURE;
}