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进程启动过程 的相关文章

  • 使用 SMJobBless() 编写特权帮助工具

    尽管该 API 自 Mac OS X Leopard 以来就已开放 但令人惊讶且不幸的是 关于如何正确使用的文档却很少SMJobBless 用于创建特权帮助工具 即使直接从 Apple 的示例项目复制代码 也存在很多问题 幸运的是 我找到了
  • Binder机制知识点

    引言 在Android领域 Binder作为进程间通信的核心机制 是每位Android技术人员都应该深入了解的重要知识点 本文将从面试官的角度出发 围绕Android Binder展开一系列高级疑难问题 通过问题分析与问题简答 旨在帮助大家
  • 为什么 ITelephony.aidl 有效?

    我看到一些 SO 帖子讨论了如何以编程方式结束电话 例如 this one https stackoverflow com questions 18065144 end call in android programatically 是的
  • 使用 vbscript 进行进程间通信

    我需要将数据从一个进程发送到另一个进程 限制条件 发送方进程是非常昂贵的调用 需要使用 vbscipt 来完成 对于Sender进程来说 这个数据传输是一项额外的工作 它应该不会受到这个特性的太大影响 4 5 分钟内 发送方进程中大约有 1
  • 如何从一个Windows控制台应用程序向另一个应用程序发送消息?

    我有一个启动子进程的 Windows 控制台应用程序 如何向子进程发送消息 我发现类似的功能PostMessage PeekMessage http msdn microsoft com en us library windows desk
  • 一次使用共享内存的多个实例

    为了在记录程序和显示程序 不能相同 之间传输视频流 我使用共享内存 为了同步访问 我组合了一个类 它包装了一个shared memory object 一个mapped region和一个interprocess sharable mute
  • 从另一个进程访问 mmap 内存

    我开始玩 mmap 了 我正在尝试创建一个示例工作区 然后将其扩展到实际案例 这就是我想要实现的目标 流程1 mmap一个文件 实际上是一个设备 但是用文本文件生成一个例子是可以的 进程2 不是从进程1复制而来 只是一个独立的进程 读取进程
  • 通过 aidl 从另一个服务在绑定服务中执行 httprequest 时出现 Networkonmainthread 异常

    我有一个通过aidl 绑定另一个服务的服务 当通过aidl 从callign 服务调用该方法时 绑定的服务执行httprequest 并返回响应 我在执行此操作时遇到 Networkonmainthread 异常 使用 Asynctask
  • PHP - 访问用 C++ 创建的共享内存

    几天以来 我一直在努力让以下事情发挥作用 我有一个微型 C 程序 它从串行端口连续读取一些数据 该数据存储在共享内存中 如下所示 HANDLE hMapFile hMapFile CreateFileMapping INVALID HAND
  • 如何监控 FIFO?

    我想通过设置该流量的只读终端窗口来调试两个进程之间的问题 我可以简单地使用现有的标准 Linux 实用程序来实现这一点吗 FIFO 位于 run myfifo并在其中一个进程中创建 Create a FIFO if one doesn t
  • IPC::Run - 检测早产儿退出和关闭管道

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

    我正在为游戏编写一个机器人 它具有 C API 接口 即 当事件发生时 游戏会调用 Cpp dll 中的方法 该 dll 可以回调游戏中的方法来触发操作 我真的不想用 C 编写我的机器人 我是一个相当有经验的 C 程序员 但我根本没有 C
  • 如何用IPC::Open2过滤大量数据?

    我的任务是使用外部实用程序 addr2line 从 perl 脚本中过滤一些数据 数据量相当大 我需要打印大量数据stdin程序并读回大量数据 来自stdout程序到我的脚本中 现在我这样做IPC Open2 但我不混合阅读和写作 这合法吗
  • 将管道/连接作为上下文参数传递给多处理 Pool.apply_async()

    我想使用管道与池中的流程实例进行通信 但出现错误 让 p 成为 Pool 的一个实例 master pipe worker pipe Pipe self p apply async worker task handler info cont
  • 通过 mmap 文件进行 IPC:应该使用原子和/或易失性吗?

    我使用 mmap 文件在进程之间共享数据 代码是这样的 struct Shared int Data int file open file dat O RDWR Shared shared static cast
  • Java中如何通知特定线程

    如何在线程间通信中调用特定线程 在下面的程序中我有两个线程t1 and t2 当我打电话时t1 notify 它提出 Exception in thread Thread 1 java lang IllegalMonitorStateExc
  • 尝试使用 POSIX 消息队列创建消息队列时权限被拒绝

    我正在使用以下代码片段创建一个消息队列Linux 编程接口 http man7 org tlpi if mq open my message queue O CREAT O RDWR NULL 1 perror mq creation fa
  • 使用 WM_COPYDATA 在进程之间发送数据

    我希望在进程之间发送文本 我发现了很多这样的例子 但没有一个我可以工作 这是我到目前为止所拥有的 对于发送部分 COPYDATASTRUCT CDS CDS dwData 1 CDS cbData 8 CDS lpData NULL Sen
  • Linux 消息队列 - 多个接收者

    我最近一直在研究和研究 Linux 消息队列 并遇到了一些我不太明白为什么会发生的事情 如果我们运行两个程序 它们都在无限 for 循环中使用 msgrcv 来检查消息 然后发送两条消息 那么第一个运行的程序将收到第一条消息 第二个程序将收
  • 登录方式使用GINA定制

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

随机推荐

  • 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进程