Android servicemanager进程启动过程

2023-11-16

在分析ServiceManager实例化注册流程前,先放张ServiceManager在Binder体系中的UML图。
在这里插入图片描述

一、ServiceManager启动流程

查看system/core/rootdir/init.rc脚本可知,init进程在 on init阶段启动 servicemanager进程。

# system/core/rootdir/init.rc
on init
    # Start essential services.
     start servicemanager
     start hwservicemanager
     start vndservicemanager

servicemanager服务在framework/native/cmds/servicemanager/模块中定义:

# framework/native/cmds/servicemanager/servicemanager.rc
service servicemanager /system/bin/servicemanager
    class core animation
    user system
    group system readproc
    critical
    onrestart restart apexd
    onrestart restart audioserver
    onrestart restart gatekeeperd
    onrestart class_restart --only-enabled main
    onrestart class_restart --only-enabled hal
    onrestart class_restart --only-enabled early_hal
    task_profiles ServiceCapacityLow
    shutdown critical

模块中main.cpp的main方法执行主要启动逻辑。

//framework/native/cmds/servicemanager/main.cpp
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";

  //1. 初始化 ProcessState对象,打开/dev/binder节点,mmap()共享内存
    sp<ProcessState> ps = ProcessState::initWithDriver(driver);
    ps->setThreadPoolMaxThreadCount(0);
    ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);

  //2. 实例化 ServiceManager对象,new ServiceManager(std::make_unique<Access>())
    sp<ServiceManager> manager = sp<ServiceManager>::make(std::make_unique<Access>());
  //3. 注册serviceManager
    if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
        LOG(ERROR) << "Could not self register servicemanager";
    }

  //4. 初始化 IPCThreadState对象,mIn,mOut。
    IPCThreadState::self()->setTheContextObject(manager);
  //5. becomeContextManager,BpBinder->handler=0
    ps->becomeContextManager();

  //6. 启动循环,监听消息
    sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);

    BinderCallback::setupTo(looper);
    ClientCallbackCallback::setupTo(looper, manager);

    while(true) {
        looper->pollAll(-1);
    }

    // should not be reached
    return EXIT_FAILURE;
}

1.1、初始化 ProcessState对象

ProcessState使用了单例设计模式,一个进程中只会有一个ProcessState实例。

initWithDriver参数中传入了binder节点路径"/dev/binder",最终调用到ProcessState的构造方法:

//ProcessState.cpp
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),
        mCurrentThreads(0),
        mKernelStartedThreads(0),
        mStarvationStartTimeMs(0),
        mForked(false),
        mThreadPoolStarted(false),
        mThreadPoolSeq(1),
        mCallRestriction(CallRestriction::NONE) {
    base::Result<int> opened = open_driver(driver);

    if (opened.ok()) {
        // 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();
    }
}

Open_driver(driver)方法“int fd = open(driver, O_RDWR | O_CLOEXEC)”打开 /dev/binder 节点,binder节点在kernel仓库的binder.c文件中创建,其中定义了一系列文件操作,open,mmap等:

// binder.c
static const struct file_operations binder_fops = {
	.owner = THIS_MODULE,
	.poll = binder_poll,
	.unlocked_ioctl = binder_ioctl,
	.compat_ioctl = binder_ioctl,
	.mmap = binder_mmap,
	.open = binder_open,
	.flush = binder_flush,
	.release = binder_release,
};

binder节点打开成功后,open()方法返回int类型的文件描述符作为参数,mmap将其内存映射到进程的地址空间,mmap实现了跨进程的内存访问,对比传统IO其只有一次数据拷贝,读写效率更高。

最后将打开的binder节点文件描述符赋值给变量 mDriverFD。

1.2、实例化 ServiceManager对象

ServiceManager处于binder通信的服务端,继承BnServiceManager,BnServiceManager又继承自BnInterface,BnInterface继承BBinder。

class ServiceManager : public os::BnServiceManager, public IBinder::DeathRecipient {}

值得一提的是,源码中并没有定义BnServiceManager类的文件,如BnServiceManager.cpp,BnServiceManager.h,而是由libbinder模块中的IServiceManager.aidl生成。

// frameworks/native/libs/binder/aidl/android/os/IServiceManager.aidl
package android.os;

import android.os.IClientCallback;
import android.os.IServiceCallback;
/**
 * Basic interface for finding and publishing system services.
 *
 * You likely want to use android.os.ServiceManager in Java or
 * android::IServiceManager in C++ in order to use this interface.
 *
 * @hide
 */
interface IServiceManager {
    //...
}

可以使用SDK中的aidl工具生成对应的cpp文件:

Android/Sdk/build-tools/30.0.3/aidl --lang=cpp -IF:./ /home/lin/tmp/aidl/android/os/IServiceManager.aidl -o ./out/cpp/ --header_out ./header_out/

生成cpp代码类IServiceManager,BnSeeyaManager,BpSeeyaManager。

// IServiceManager.h
namespace android {
namespace os {
class IServiceManager : public ::android::IInterface {
    //...
};
}
}

// BnServiceManager.h
namespace android {
namespace os {
class BnServiceManager : public ::android::BnInterface<IServiceManager> {
public:
  explicit BnServiceManager();
  ::android::status_t onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) override;
};  // class BnServiceManager
}
}

// BpServiceManager.h
namespace android {
namespace os {
class BpServiceManager : public ::android::BpInterface<IServiceManager> {
    //...
};
}
}

也可以使用SDK中的aidl工具生成对应的java文件:

Android/Sdk/build-tools/30.0.3/aidl --lang=java -IF:./ /home/lin/tmp/aidl/android/os/IServiceManager.aidl -o ./out/java/

1.3、注册ServiceManager

将服务名称与服务的对应关系添加到变量mNameToService管理。

 //framework/native/cmds/servicemanager/ServiceManager.cpp
		mNameToService[name] = Service {
        .binder = binder,
        .allowIsolated = allowIsolated,
        .dumpPriority = dumpPriority,
        .debugPid = ctx.debugPid,
    };

1.4、初始化IPCThreadState对象

ProcessState是进程单例对象,IPCThreadState是线程单例对象。

IPCThreadState::selft()是一个静态方法,

//IPCThreadState.cpp
IPCThreadState* IPCThreadState::self()
{
    if (gHaveTLS.load(std::memory_order_acquire)) {
restart:
        const pthread_key_t k = gTLS;
        IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
        if (st) return st;
        return new IPCThreadState;
    }

    // Racey, heuristic test for simultaneous shutdown.
    if (gShutdown.load(std::memory_order_relaxed)) {
        ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n");
        return nullptr;
    }

    pthread_mutex_lock(&gTLSMutex);
    if (!gHaveTLS.load(std::memory_order_relaxed)) {
        int key_create_value = pthread_key_create(&gTLS, threadDestructor);
        if (key_create_value != 0) {
            pthread_mutex_unlock(&gTLSMutex);
            ALOGW("IPCThreadState::self() unable to create TLS key, expect a crash: %s\n",
                    strerror(key_create_value));
            return nullptr;
        }
        gHaveTLS.store(true, std::memory_order_release);
    }
    pthread_mutex_unlock(&gTLSMutex);
    goto restart;
}

pthread_getspecific(),pthread_setspecific()是存储线程私有数据的方法,相当于Java中的ThreadLocal,IPCThreadState类的线程单例就是这么实现的,key值为gTLS,如果当前线程存在IPCThreadState对象则直接返回,否则重新实例化一个:

IPCThreadState::IPCThreadState()
      : mProcess(ProcessState::self()),
        mServingStackPointer(nullptr),
        mServingStackPointerGuard(nullptr),
        mWorkSource(kUnsetWorkSource),
        mPropagateWorkSource(false),
        mIsLooper(false),
        mIsFlushing(false),
        mStrictModePolicy(0),
        mLastTransactionBinderFlags(0),
        mCallRestriction(mProcess->mCallRestriction) {
    pthread_setspecific(gTLS, this);
    clearCaller();
    mHasExplicitIdentity = false;
    mIn.setDataCapacity(256);
    mOut.setDataCapacity(256);
}

构造方法中将对象通过pthread_setspecific(gTLS, this)保存到当前线程中,初始化mProcess,mIn、mOut是Parcel对象。

1.5、becomeContextManager

servicemanager进程需要通知内核binder我才是servicemanager进程,

所有的client和servicemanager通信,都是通过创建一个BpBinder(0)对象找到servicemanager,其中0就是BpBinder类的Handle属性,

binder驱动通过判断handle是否为0区分servicemanager进程。

回到ps->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;
        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;
}

通过ioctl,使binder驱动程序调用binder_ioctl()方法处理BINDER_SET_CONTEXT_MGR_EXT信息,将binder_context_mgr_uid赋值为当前uid,binder_context_mgr_node关联到当前进程。

  • binder_context_mgr_node

  • binder_context_mgr_uid

查看binder驱动的binder_transaction()方法,此后只需要判断tr->target.handle是否为0,如果为0,target_node就被赋值为binder_context_mgr_node,将消息交给servicemanager处理。

//binder.c
static void binder_transaction(struct binder_proc *proc,
			       struct binder_thread *thread,
			       struct binder_transaction_data *tr, int reply)
{
  if (reply) {
    
  } else {
    if (tr->target.handle) {
        struct binder_ref *ref;
        ref = binder_get_ref(proc, tr->target.handle);
        if (ref == NULL) {
          binder_user_error("%d:%d got transaction to invalid handle\n",
            proc->pid, thread->pid);
          return_error = BR_FAILED_REPLY;
          goto err_invalid_target_handle;
        }
        target_node = ref->node;
      } else {
        target_node = binder_context_mgr_node;				//servicemanager
        if (target_node == NULL) {
          return_error = BR_DEAD_REPLY;
          goto err_no_context_mgr_node;
        }
      }
  }
}

1.6、启动循环,监听消息

//framework/native/cmds/servicemanager/main.cpp
class BinderCallback : public LooperCallback {
public:
    static sp<BinderCallback> setupTo(const sp<Looper>& looper) {
        sp<BinderCallback> cb = sp<BinderCallback>::make();

        int binder_fd = -1;
      //1. 通知binder驱动进入looper
        IPCThreadState::self()->setupPolling(&binder_fd);
        LOG_ALWAYS_FATAL_IF(binder_fd < 0, "Failed to setupPolling: %d", binder_fd);

      //2. Looper添加/dev/binder文件描述符
        int ret = looper->addFd(binder_fd,
                                Looper::POLL_CALLBACK,
                                Looper::EVENT_INPUT,
                                cb,
                                nullptr /*data*/);
        LOG_ALWAYS_FATAL_IF(ret != 1, "Failed to add binder FD to Looper");

        return cb;
    }

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

int main(int argc, char** argv)
		sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);

    BinderCallback::setupTo(looper);
    ClientCallbackCallback::setupTo(looper, manager);
    while(true) {
        looper->pollAll(-1);
    }
return EXIT_FAILURE;
}

获取Looper对象绑定BinderCallback,通过ioctl通知binder驱动进入looper状态,将mProcess->mDriverFD文件描述符“/dev/binder”传给looper对象,pollAll()方法通过epoll监听消息,收到消息后,回调IPCThreadState的handlePolledCommands()处理parcel对象mIn,mOut中的消息。

二、defaultServiceManager()

经常看到通过defaultServiceManager()方法获取servicemanager对象,看看defaultServiceManager方法是如何实现的。

// IServiceManager.cpp
using AidlServiceManager = android::os::IServiceManager;

sp<IServiceManager> defaultServiceManager()
{
    std::call_once(gSmOnce, []() {
#if defined(__BIONIC__) && !defined(__ANDROID_VNDK__)
        /* wait for service manager */ {
            using std::literals::chrono_literals::operator""s;
            using android::base::WaitForProperty;
            while (!WaitForProperty("servicemanager.ready", "true", 1s)) {
                ALOGE("Waited for servicemanager.ready for a second, waiting another...");
            }
        }
#endif

        sp<AidlServiceManager> sm = nullptr;
        while (sm == nullptr) {
            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);
            }
        }

        gDefaultServiceManager = sp<ServiceManagerShim>::make(sm);
    });

    return gDefaultServiceManager;
}

std::call_once是C++11引入的新特性,如需使用,只需要#include <mutex>即可,简单来说std:call_once的作用,确保函数或代码片段在多线程环境下,只需要执行一次。AidlServiceManager是android::os::IServiceManager的别名,这里的using关键字相当于typedef。关键的代码就是将ProcessState::self()->getContextObject(nullptr)的返回对象强转为AidlServiceManager类型,接下来详细看看它返回的是什么。

2.1 ProcessState::self()

从类的方法名可以猜到应该是获取ProcessState对象。

// ProcessState.cpp
const char* kDefaultDriver = "/dev/binder";

sp<ProcessState> ProcessState::self()
{
    return init(kDefaultDriver, false /*requireDefault*/);
}

kDefaultDriver值为"/dev/binder"。

sp<ProcessState> ProcessState::init(const char* driver, bool requireDefault) {
    std::call_once(gProcessOnce, [&](){
        int ret = pthread_atfork(ProcessState::onFork, ProcessState::parentPostFork,
                                 ProcessState::childPostFork);
        gProcess = sp<ProcessState>::make(driver);
    }
    verifyNotForked(gProcess->mForked);
    return gProcess;
}

pthread_atfork()为pthread库中提供的函数,在fork()创建子进程时被调用。"/dev/binder"作为构造参数实例化ProcessState对象。verifyNotForked在检测到当前进程gProcess->mForked为true时抛出异常crash,因为 Binder 的架构设计并不支持 Fork,原因之一在 Binder 核心的内存映射实现无法避免子进程与原进程的写入冲突,相关虚拟地址的内存映射不会被子进程所继承。最后返回实例化的gProcess对象。

查看ProcessState构造函数:

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),
        mCurrentThreads(0),
        mKernelStartedThreads(0),
        mStarvationStartTimeMs(0),
        mForked(false),
        mThreadPoolStarted(false),
        mThreadPoolSeq(1),
        mCallRestriction(CallRestriction::NONE) {
    		base::Result<int> opened = open_driver(driver);
            if (opened.ok()) {
                mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE,
                        opened.value(), 0);
            }
            if (opened.ok()) {
                mDriverFD = opened.value();
            }
        }

driver参数为传递过来的"/dev/binder"。open_driver(driver)通过open方法获取文件描述符fd,接着通过ioctl设置BINDER_VERSION,BINDER_SET_MAX_THREADS,BINDER_ENABLE_ONEWAY_SPAM_DETECTION等参数,最后将fd返回赋值给opened变量。mmap()使用户空间和内核空间共享内存。

ProcessState::self()方法初始化ProcessState对象,打开了"/dev/binder"节点,构建了进程间通信环境,接下来看看getContextObject(nullptr)做了什么。

2.2 ProcessState::getContextObject(nullptr)

// ProcessState.cpp
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
    sp<IBinder> context = getStrongProxyForHandle(0);
    return context;
}

返回一个IBinder对象。

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    handle_entry* e = lookupHandleLocked(handle);
    
    if (handle == 0) {
        IPCThreadState* ipc = IPCThreadState::self();

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

        Parcel data;
        status_t status = ipc->transact(
                0, IBinder::PING_TRANSACTION, data, nullptr, 0);

        ipc->setCallRestriction(originalCallRestriction);

        if (status == DEAD_OBJECT)
           return nullptr;
    }
    
    sp<BpBinder> b = BpBinder::PrivateAccessor::create(handle);
    e->binder = b.get();
    if (b) e->refs = b->getWeakRefs();
    result = b;
    
    return result;
}

lookupHandleLocked方法在数组中查找对象是否已经存在,这里handle参数为0,返回一个handle_entry对象。

当handler==0时,还需要做些特殊化处理,先进行一次跨进程通信保证servicemanager被注册。

实例化BpBinder对象,handle参数为0,返回BpBinder(0)。

回到defaultServiceManager()方法:AidlServiceManager sm = interface_cast<AidlServiceManager>(ProcessState::self()->getContextObject(nullptr));,ProcessState::self()为进程间通信做好了准备,getContextObject(nullptr)返回一个BpBinder(0)对象,代码转换一下相当于:

AidlServiceManager sm = interface_cast<AidlServiceManager>(new BpBinder(0));,BpBinder对象是如何转换成AidlServiceManager对象呢?接着看interface_cast方法。

2.3 interface_cast

// IInterface.h
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
    return INTERFACE::asInterface(obj);
}

DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE0(I##INTERFACE, I##INTERFACE, Bp##INTERFACE)

#define DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE0(ITYPE, INAME, BPTYPE)  
    ::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) {                                                                 
                intr = ::android::sp<BPTYPE>::make(obj);                                           
            }                                                                                      
        }                                                                                          
        return intr;                                                                               
    }     

interface_cast方法定义在IInterface.h文件,参数obj为传递过来的BpBinder(0),调用INTERFACE::asInterface(obj)方法,asInterface在宏函数DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE0中实现,转换过来参数ITYPE:IServiceManager,INAME:IServiceManager,BPTYPE:BpServiceManager。

queryLocalInterface查询是否存在本地BBinder对象,否则实例化BpServiceManager(BpBinder(0))对象返回,BpServiceManager类由IServiceManager.aidl编译期间自动生成文件定义,路径:out/soong/.intermediates/frameworks/native/libs/binder/libbinder/android_arm64_armv8-a_cortex-a55_shared/gen/aidl/android/os/BpServiceManager.h。

好了,总结一下,interface_cast方法执行后,defaultServiceManager()方法相当于:

AidlServiceManager sm = new BpServiceManager(new BpBinder(0)); 

AidlServiceManager为android::os::IServiceManager的别名,BpServiceManager继承自IServiceManager。

得到BpServiceManager对象后,就可以和BnServiceManager通信了,BnServiceManager在上文1.2小节实例化 ServiceManager对象中被创建。

三、进程间通信

有了BpServiceManager和BnServiceManager对象,接下来看看它们是如何通信的,具体分析IServiceManager::isDeclared(const String16& name)方法实现。

因为BpServiceManager和BnServiceManager类都是通过aidl文件自动生成的,BpServiceManager::isDeclared方法实现在文件:

out/soong/.intermediates/frameworks/native/libs/binder/libbinder/android_arm64_armv8-a_cortex-a55_shared_asan/gen/aidl/frameworks/native/libs/binder/aidl/android/os/IServiceManager.cpp

// IServiceManager.cpp
::android::binder::Status BpServiceManager::isDeclared(const ::std::string& name, bool* _aidl_return) {
  ::android::Parcel _aidl_data;
  ::android::Parcel _aidl_reply;
  ::android::status_t _aidl_ret_status = ::android::OK;
  ::android::binder::Status _aidl_status;
  _aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  _aidl_ret_status = _aidl_data.writeUtf8AsUtf16(name);
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  _aidl_ret_status = remote()->transact(::android::IBinder::FIRST_CALL_TRANSACTION + 6 /* isDeclared */, _aidl_data, &_aidl_reply);
  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && IServiceManager::getDefaultImpl())) {
     return IServiceManager::getDefaultImpl()->isDeclared(name, _aidl_return);
  }
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  _aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  if (!_aidl_status.isOk()) {
    return _aidl_status;
  }
  _aidl_ret_status = _aidl_reply.readBool(_aidl_return);
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  _aidl_error:
  _aidl_status.setFromStatusT(_aidl_ret_status);
  return _aidl_status;
}

isDeclared方法检查service是否在servicemanager中被声明。参数name为service注册名,_aidl_return为返回值,true表示已被声明。

remote()方法返回BpBinder(0)对象,调用其transact方法。

// BpBinder.cpp
status_t BpBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    status_t status = IPCThreadState::self()->transact(binderHandle(), code, data, reply, flags);
    return status;
}

调用IPCThreadState的transact方法,binderHandle()返回int32_t handle=0的BinderHandle对象。

IPCThreadState的transact方法将数据内容写入到mOut, mIn对象中,通过ioctl和binder节点交互,实现和BnServiceManager进程间通信。

ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr);

bwr是struce binder_write_read解构体类型,保存了mOut和mIn数据。

进程间通信的另一端BnServiceManger,1.6小节中启动循环,监听binder节点事件,消息到来时调用IPCThreadState::handlePolledCommands()方法。

最终会调用到BnServiceManger端的isDeclared方法:

// ServiceManager.cpp
Status ServiceManager::isDeclared(const std::string& name, bool* outReturn) {
    auto ctx = mAccess->getCallingContext();

    if (!mAccess->canFind(ctx, name)) {
        return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
    }

    *outReturn = false;

#ifndef VENDORSERVICEMANAGER
    *outReturn = isVintfDeclared(name);
#endif
    return Status::ok();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android servicemanager进程启动过程 的相关文章

  • 如何处理 C 和 Python 之间的 IPC?

    我有一个具有两个进程的应用程序 一个在 C 中 一个在 Python 中 C 进程是完成所有繁重工作的地方 而 Python 进程则处理用户界面 C 程序每秒向大型缓冲区写入 4 次 Python 进程读取该数据 至此与Python进程的通
  • IPC::Run - 检测早产儿退出和关闭管道

    我想使用 IPC Run 通过孩子的 STDIN STDOUT 和 STDERR 开始 泵送 完成 与孩子进行通信 似乎有效 我想知道如何检测 儿童过早退出 例如由错误引起 水管被孩子关闭 The pump抛出一个die出现错误时 或将其消
  • C# 和 C++ 之间的进程间通信

    我正在为游戏编写一个机器人 它具有 C API 接口 即 当事件发生时 游戏会调用 Cpp dll 中的方法 该 dll 可以回调游戏中的方法来触发操作 我真的不想用 C 编写我的机器人 我是一个相当有经验的 C 程序员 但我根本没有 C
  • process.send 在 *nix/Windows 上是同步/异步吗?

    我有一个 Node js 进程 不是服务器 它分叉 N 个子进程 在某个时候 CP 可能会超过 50 个 所以我开始思考 如果 process send IPC 确实是阻塞的 那么这可能是每个 CP 经历的一个很大的惩罚 因为我的程序中发生
  • .NET 中 32 位进程如何与 64 位进程通信?

    Windows 不允许 32 位进程加载 64 位 dll 因此我尝试使用远程处理来允许 32 位进程与 64 位进程交互 问题是 虽然两个应用程序位于同一台计算机上 但一个是 32 位 另一个是 64 位 而且它们必须是这样的 同时使用
  • 使用 setjmp / longjmp 的通信协议和本地环回

    我使用共享内存和共享互斥体编写了一些相对简单的通信协议 但后来我想扩展支持以在使用不同运行时的两个 dll 之间进行通信 很明显 如果你有一些std vector lt int64 gt 和两个 dll 一个 vs2010 一个 vs201
  • msgrcv - SA_RESTART 标志不起作用

    我的使用 IPC 队列在线程之间通信的代码有问题 我需要安全地处理 SIGINT 让程序在关闭之前出现 SIGINT 时完成所有活动线程 不过 我在寻找解决方案方面遇到了严重的问题 因为即使使用带有标志 SA RESTART 的 SIGIN
  • 将参数发送到驻留在另一个进程中的应用程序实例

    我有一个单实例应用程序 c WPF net3 51 检查应用程序是否已实例化是通过互斥体完成的 如果应用程序已在运行 我会从已打开的应用程序实例中打开一个新窗口 到目前为止效果很好 但是 由于应用程序扩展 我现在必须将 e Args 或至少
  • 将一个对象传递给默认 AppDomain,以从进程内创建的子 AppDomain 接收回调

    地点 我正在从我的进程创建一个子应用程序域来加载程序集 我能够调用此 AppDomain 我想将一个对象从我的默认进程 AppDomain 传递到这个新创建的 AppDomain 以接收从新 AppDomain 中加载的程序集到我的默认 A
  • 与修改后的 python 解释器进行进程间通信

    TL DR 当 stdin stdout 不可用时 如何生成不同的 python 解释器 从 python 内部 并在父级和子级之间创建通信通道 我希望我的 python 脚本执行修改后的Python解释器并通过某种IPC 例如multip
  • 在Python中与子进程多次通信

    这个问题不是重复的 与一个进程进行多次通信而不破坏管道 https stackoverflow com questions 3065060 communicate multiple times with a process without
  • 如何从单独的进程监控应用程序崩溃

    我有一个特定的 net 应用程序 偶尔会因以下 Windows 错误之一而崩溃 application name has encountered a problem and needs to close We are sorry for t
  • Android中AIDL的实时示例和使用?

    我想知道aidl 的实时示例及其使用 我研究了有关此主题的android 开发人员博客 我无法在实时世界中实现这一点 谁能举个例子告诉我 AIDL用于以某种格式共享数据 primitive and parcelable 与其他应用程序 现实
  • 从一个 Nodejs 应用程序调用另一个 Nodejs 应用程序中的 API 的方法

    我们的应用程序将有一个网站和一个移动应用程序 两者都与同一个 API 后端进行通信 我有一个仅提供 API 服务的 Nodejs 应用程序 还有一个为网站提供 html 页面服务的 Nodejs 应用程序 我正在为这两个应用程序使用 Exp
  • 无法在 Linux 中阻止从命名管道 (FIFO) 读取

    很奇怪 我似乎无法完成这项工作 这是我的架构 我有一个命名管道 它将在永远运行 root读取器进程和多个应用程序编写器进程 读者进程必须是blocking当作家们在nonblocking 因此 这就是我在阅读器进程中所做的 该进程将运行ro
  • 登录方式使用GINA定制

    我知道在 GINA 中找到大师并不容易 但我的问题最接近进程间通信 IPC 我用非托管 c 编写了我的自定义 GINA 我在其中包含了一个方法来检查用户尝试的指纹的有效性为了登录 该函数将调用正在运行的系统Windows服务中用C 编写的一
  • 等待进程直到所有子进程完成? [复制]

    这个问题在这里已经有答案了 我有一个创建两个或更多子进程的主进程 我希望主进程等待所有子进程完成其操作并退出 main script py p1 subprocess Popen python script1 py p2 subproces
  • 向父进程发出信号,表明子进程已完全初始化

    我正在启动一个公开 WCF 端点的子进程 如何从子进程向父进程发出信号 表明子进程已完全初始化并且现在可以访问端点 我曾考虑过使用信号量来实现此目的 但不太清楚如何实现所需的信号 string pipeUri net pipe localh
  • 使用 EOF 在未命名管道上发出信号

    我有一个测试程序 它使用使用 pipeline 创建的无名管道在 Linux 系统上使用 fork 创建的父进程和子进程之间进行通信 通常 当发送进程关闭管道的 write fd 时 接收进程从 read 返回值为 0 表示 EOF 然而
  • 通过子进程捕获输出,无需使用通信

    我正在使用 subprocess 在 Python 脚本中调用外部程序 外部程序产生大量输出 我需要捕获该程序的输出 当前的代码是这样的 process subprocess Popen cmd exe shell False stdin

随机推荐

  • sql server 提取汉字、数字和字母的sql server方法

    sql server 提取汉字 数字 字母的方法 提取数字 if object id dbo get number2 is not null drop function dbo get number2 go create function
  • QT学习(五)——从子窗口传来多个信号(带参数的自定义信号)

    同样是两个窗口 主窗口与副窗口 给副窗口自定义两个重载的信号 传给主窗口处理 void mySignals 信号可以重载 void mySignals int QString 由被关联的按钮发送消息 并送出两条消息给主窗口 emit myS
  • 常用C语言文件操作

    1 fopen 使用fopen需要引用头文件stdio h 函数声明如下 FILE fopen const char pathname const char mode 这里要多多关心的是第二个参数mode 关系到我们对文件操作的权限 这里做
  • 提升KNN的运行效率

    20221005 引言 KNN算法是一种 懒惰 算法 在模型训练过程 仅仅是将数据存储到快速查询的数据结构中 在测试阶段会通过进行距离计算来输出结果 那么当数据集比较大的时候 一方面内存要求会提升 另一方面在计算的时间也会增大 之前的时候
  • vue实现文字水印效果

    vue文件代码
  • Java自学路线(超全超详细)—初学者零基础版Ⅰ

    Java 对于第一次见到它的人来说 不知道它是什么东西 可能看起来是个单词 可是通过网络翻译却没办法给它一个中文定义 但是 在计算机领域中 它是一门面向对象的编程语言 那么问题来了 有人对于 面向对象的编程语言 这个词组并不理解 在此 作出
  • 出现'MySQL Daemon failed to start‘解决方法

    方法千万条 备份第一条 运行 service mysqld start 重启数据库总是会出现如下提示 MySQL Daemon failed to start Starting mysqld FAILED 的提示 如果直接输入 mysql
  • Ubuntu/linux c开发(6)内存泄露

    写好个服务程序 短期测试没啥问题 准备跑长时间的 结果 前两天正常 第三天突然涨了100多M 这感觉 爽飞了 这里说下Ubuntu中内存泄露检测工具 Valgrind 安装和使用连接如下 链接 Valgrind安装使用 这里大概说下统计结果
  • 神经网络量化

    前言 神经网络在图像 语音识别等领域使用越来越广泛 大部分实时性要求不高的服务都可以部署在云上 然而还是有不少模型需要在计算能力有限的可移动设备上快速运行 如人脸解锁 拍照视频的实时处理等 一般训练的模型采用的都是32位浮点数 考虑到大部分
  • 第四讲 赋予网页样式

    文科编程系列课程 Web开发 第四讲 赋予网页样式 目录 引言 1 大小 1 1 长度单位 1 1 1 px 像素 1 1 2 百分比 1 2 宽高 1 1 1 宽度 1 1 2 高度 1 1 3 边框 2 颜色 2 1 颜色的三种表示形式
  • 毕业设计:自主开发的害虫识别系统--文档附源码

    基于yolov5多目标检测算法的农业害虫识别查询系统 设计文档 目标问题与意义价值 研究意义 本项目能够及时准确地识别农业害虫的种类 是害虫准确测报和合理防治的前提 传统的害虫识别方法主要依赖个人的专业经验进行辨别 或参考书本 网络上的文字
  • Qt5(一)编写Qt多窗口程序

    本文作者 小嗷 微信公众号 aoxiaoji 吹比QQ群 736854977 链接 https f600lt github io archives 摘要 这篇开始将从基础知识点开始一步一步QT到QT项目 原因就是读者说 QT类很多看不懂 这
  • 如何抵御ddos攻击-免费防御方法分享

    网站遭受DDOS攻击不要怕 今天来跟大家聊聊防御ddos攻击 顺便分享一些防御ddos攻击比较使用的方法 如果你是学生也不要紧 这里可以给你分享免费的防御方法 针对ddos攻击 我们升级服务器带宽配置是不起作用的 因为大部分攻击都是来自海外
  • 文心千帆为你而来

    1 前言 3月16号百度率先发布了国内第一个人工智能大语言模型 文心一言 文心一言的发布在业界引起了不小的震动 而文心一言的企业服务则由文心千帆大模型平台提供 文心千帆大模型平台是百度智能云打造出来的一站式大模型开发与应用平台 提供包括文心
  • 【面试题】说一下promise的理解

    一 什么是Promise ES6 异步编程的一种解决方案 比传统的方案 回调函数和事件 更加的合理和强大 大家都知道传统解决异步编程用的是回调函数套回调函数 简称回调地域 以前用JQuery的朋友应该是相当熟悉了 维护起来很难搞 回调地域
  • 七种Linux设备驱动模型之——Device

    前言 Linux将所有的设备统一抽象为struct device结构 同时将所有的驱动统一抽象为struct device driver结构 这样设计之后就方便驱动开发工程师编写驱动 只需要将具体的设备包含struct device结构 具
  • std::string用法总结

    在平常工作中经常用到了string类 本人记忆了不好用到了的时候经常要去查询 在网上摘抄一下总结一下 为以后的查询方便 string类的构造函数 string const char s 用c字符串s初始化string int n char
  • Windows10下Nginx初步配置

    1 nginx启动与关闭 nginx启动命令 一闪而过为正常启动 且看不到nginx进程 D server nginx nginx 1 16 0 gt start nginx nginx关闭命令 快速停止 nginx s stop 完整有序
  • 宝塔面板ip:端口,访问不进去;提示:请使用正确的入口登录面板 解决办法

    请使用正确的入口登录面板 错误原因 当前新安装的已经开启了安全入口登录 新装机器都会随机一个8位字符的安全入口名称 亦可以在面板设置处修改 如您没记录或不记得了 可以使用以下方式解决 解决方法 在SSH终端输入以下一种命令来解决 1 查看面
  • Android servicemanager进程启动过程

    在分析ServiceManager实例化注册流程前 先放张ServiceManager在Binder体系中的UML图 一 ServiceManager启动流程 查看system core rootdir init rc脚本可知 init进程