So my question: does a native service work correctly if it will be started before coldboot
done?
Sometimes it may work correct but in general case it may fail. If native service doesn't interact with any device it doesn't require the /dev/
file system. But binderized services communicate via Binder IPC which is require opening the binder driver (for interact between kernel and userspace layers):
frameworks/native/include/binder/BinderService.h:
template<typename SERVICE>
class BinderService
{
public:
...
static void instantiate() { publish(); }
...
static status_t publish(bool allowIsolated = false) {
sp<IServiceManager> sm(defaultServiceManager());
return sm->addService(
String16(SERVICE::getServiceName()),
new SERVICE(), allowIsolated);
}
frameworks/native/libs/binder/IServiceManager.cpp:
sp<IServiceManager> defaultServiceManager()
{
...
ProcessState::self()->getContextObject(NULL));
frameworks/native/libs/binder/ProcessState.cpp:
sp<ProcessState> ProcessState::self()
{
...
gProcess = new ProcessState("/dev/binder");
return gProcess;
}
ProcessState::ProcessState(const char *driver)
: mDriverName(String8(driver))
, mDriverFD(open_driver(driver))
...
{
if (mDriverFD >= 0) {
// mmap the binder, providing a chunk of virtual address space to receive transactions.
mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart == MAP_FAILED) {
// *sigh*
...
ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened. Terminating.");
}
static int open_driver(const char *driver)
{
int fd = open(driver, O_RDWR | O_CLOEXEC);
if (fd >= 0) {
...
} else {
ALOGW("Opening '%s' failed: %s\n", driver, strerror(errno));
}
return fd;
}
But the Binder driver /der/binder
(as well as /dev/hwbinder
and /dev/vndbinder
) is created at the coldboot
stage by the ueventd
according to ueventd.rc
.
system/core/rootdir/ueventd.rc:
...
/dev/binder 0666 root root
/dev/hwbinder 0666 root root
/dev/vndbinder 0666 root root
...
So if a native service was be started before coldboot
done it wouldn't open the /dev/binder
!
Also at before coldboot
done the cgrops
and SELinux
(not sure) are not initialized:
system/core/rootdir/init.rc:
on init
...
# Mount cgroup mount point for cpu accounting
mount cgroup none /acct cpuacct
mkdir /acct/uid
P.S. But if a service communicates in passthrough mode?