前面一节学习了ServiceManager这个特殊service的工作过程,这一节来看看普通service的工作过程。
就用media.extractor这个service来当例子!
1、服务的注册及启动
media.extractor这个service的注册及启动在 frameworks/av/services/mediaextractor/main_extractorservice.cpp
int main(int argc __unused, char** argv) { #if __has_feature(hwaddress_sanitizer) ALOGI("disable media.extractor memory limits (hwasan enabled)"); #else ALOGI("enable media.extractor memory limits"); limitProcessMemory( "ro.media.maxmem", /* property that defines limit */ SIZE_MAX, /* upper limit in bytes */ 20 /* upper limit as percentage of physical RAM */); #endif signal(SIGPIPE, SIG_IGN); //b/62255959: this forces libutis.so to dlopen vendor version of libutils.so //before minijail is on. This is dirty but required since some syscalls such //as pread64 are used by linker but aren't allowed in the minijail. By //calling the function before entering minijail, we can force dlopen. android::report_sysprop_change(); SetUpMinijail(kSystemSeccompPolicyPath, kVendorSeccompPolicyPath); strcpy(argv[0], "media.extractor"); // 1、打开binder driver sp<ProcessState> proc(ProcessState::self()); // 2、获取ServiceManager sp<IServiceManager> sm = defaultServiceManager(); // 3、实例化MediaExtractorService,并注册到ServiceManager当中 MediaExtractorService::instantiate(); // 4、 ProcessState::self()->startThreadPool(); // 5、 IPCThreadState::self()->joinThreadPool(); }
前面两个步骤已经很熟悉了,就直接来看看后面三步在干什么:
a. 实例化MediaExtractorService,并注册到ServiceManager当中
MediaExtractorService继承与BinderService,instantiate声明在 frameworks/native/libs/binder/include/binder/BinderService.h 中,同样被包含在libbinder中
template<typename SERVICE> class BinderService { public: static status_t publish(bool allowIsolated = false, int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT) { sp<IServiceManager> sm(defaultServiceManager()); return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated, dumpFlags); } static void publishAndJoinThreadPool( bool allowIsolated = false, int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT) { publish(allowIsolated, dumpFlags); joinThreadPool(); } static void instantiate() { publish(); } static status_t shutdown() { return NO_ERROR; } private: static void joinThreadPool() { sp<ProcessState> ps(ProcessState::self()); ps->startThreadPool(); ps->giveThreadPoolName(); IPCThreadState::self()->joinThreadPool(); } };
服务的注册过程前面一节已经看过了,ServiceManager中的map会记录下传进来的这个BBinder对象。
b. ProcessState::self()->startThreadPool()
void ProcessState::startThreadPool() { AutoMutex _l(mLock); if (!mThreadPoolStarted) { mThreadPoolStarted = true; spawnPooledThread(true); } } void ProcessState::spawnPooledThread(bool isMain) { if (mThreadPoolStarted) { String8 name = makeBinderThreadName(); ALOGV("Spawning new pooled thread, name=%s\n", name.string()); sp<Thread> t = sp<PoolThread>::make(isMain); t->run(name.string()); } } class PoolThread : public Thread { public: explicit PoolThread(bool isMain) : mIsMain(isMain) { } protected: virtual bool threadLoop() { IPCThreadState::self()->joinThreadPool(mIsMain); return false; } const bool mIsMain; };
在ProcessState中开了一个PoolThread线程来执行 IPCThreadState::self()->joinThreadPool,但是看看main函数执行的最后一句代码也是 IPCThreadState::self()->joinThreadPool,做了同样的事情,接下来看看:
void IPCThreadState::joinThreadPool(bool isMain) { LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid()); mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER); mIsLooper = true; status_t result; do { processPendingDerefs(); // now get the next command to be processed, waiting if necessary result = getAndExecuteCommand(); if (result < NO_ERROR && result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) { LOG_ALWAYS_FATAL("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting", mProcess->mDriverFD, result); } // Let this thread exit the thread pool if it is no longer // needed and it is not the main process thread. if(result == TIMED_OUT && !isMain) { break; } } while (result != -ECONNREFUSED && result != -EBADF); LOG_THREADPOOL("**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err=%d\n", (void*)pthread_self(), getpid(), result); mOut.writeInt32(BC_EXIT_LOOPER); mIsLooper = false; talkWithDriver(false); }
这里有个do while循环用来检查是否client端有信息发过来并且处理信息,同时不让server进程结束。至于为什么调用了两次 IPCThreadState::joinThreadPool,这可能是和server端的多线程处理有关,这边后续再研究。
2、服务的获取
注册并启动服务之后我们要使用服务,首先要用ServiceManager来获取服务
这里摘一段MediaExtractorFactory中的代码:
sp<IBinder> binder = defaultServiceManager()->getService(String16("media.extractor")); sp<IMediaExtractorService> mediaExService(interface_cast<IMediaExtractorService>(binder)); sp<IMediaExtractor> ex; mediaExService->makeExtractor( CreateIDataSourceFromDataSource(source), mime ? std::optional<std::string>(mime) : std::nullopt, &ex);
先来看看getService
sp<IBinder> ServiceManagerShim::getService(const String16& name) const { static bool gSystemBootCompleted = false; sp<IBinder> svc = checkService(name); if (svc != nullptr) return svc; const bool isVendorService = strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder") == 0; constexpr int64_t timeout = 5000; int64_t startTime = uptimeMillis(); // Vendor code can't access system properties if (!gSystemBootCompleted && !isVendorService) { #ifdef __ANDROID__ char bootCompleted[PROPERTY_VALUE_MAX]; property_get("sys.boot_completed", bootCompleted, "0"); gSystemBootCompleted = strcmp(bootCompleted, "1") == 0 ? true : false; #else gSystemBootCompleted = true; #endif } // retry interval in millisecond; note that vendor services stay at 100ms const useconds_t sleepTime = gSystemBootCompleted ? 1000 : 100; ALOGI("Waiting for service '%s' on '%s'...", String8(name).string(), ProcessState::self()->getDriverName().c_str()); int n = 0; while (uptimeMillis() - startTime < timeout) { n++; usleep(1000*sleepTime); sp<IBinder> svc = checkService(name); if (svc != nullptr) { ALOGI("Waiting for service '%s' on '%s' successful after waiting %" PRIi64 "ms", String8(name).string(), ProcessState::self()->getDriverName().c_str(), uptimeMillis() - startTime); return svc; } } ALOGW("Service %s didn't start. Returning NULL", String8(name).string()); return nullptr; }
核心方法就是checkService
sp<IBinder> ServiceManagerShim::checkService(const String16& name) const { sp<IBinder> ret; if (!mTheRealServiceManager->checkService(String8(name).c_str(), &ret).isOk()) { return nullptr; } return ret; }
调用的就是BpServiceManager的checkService方法,对外的接口参数是String16,而BpServiceManager接口参数为String8。经过Binder驱动的处理最终调用到server端的checkService
Status ServiceManager::checkService(const std::string& name, sp<IBinder>* outBinder) { *outBinder = tryGetService(name, false); // returns ok regardless of result for legacy reasons return Status::ok(); }
sp<IBinder> ServiceManager::tryGetService(const std::string& name, bool startIfNotFound) { auto ctx = mAccess->getCallingContext(); sp<IBinder> out; Service* service = nullptr; if (auto it = mNameToService.find(name); it != mNameToService.end()) { service = &(it->second); if (!service->allowIsolated) { uid_t appid = multiuser_get_app_id(ctx.uid); bool isIsolated = appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END; if (isIsolated) { return nullptr; } } out = service->binder; } if (!mAccess->canFind(ctx, name)) { return nullptr; } if (!out && startIfNotFound) { tryStartService(name); } if (out) { // Setting this guarantee each time we hand out a binder ensures that the client-checking // loop knows about the event even if the client immediately drops the service service->guaranteeClient = true; } return out; }
注意到在addService时,保存到map中的IBinder实际是一个BnBinder对象,那Server端getSevice获得的也是一个BnBinder对象,返回给调用进程的就是这个BnBinder对象吗?其实不是的。
来看看BpServiceManager的checkService代码:
::android::binder::Status BpServiceManager::checkService(const ::std::string& name, ::android::sp<::android::IBinder>* _aidl_return) { ::android::Parcel _aidl_data; _aidl_data.markForBinder(remoteStrong()); ::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(BnServiceManager::TRANSACTION_checkService, _aidl_data, &_aidl_reply, 0); if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && IServiceManager::getDefaultImpl())) { return IServiceManager::getDefaultImpl()->checkService(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.readNullableStrongBinder(_aidl_return); if (((_aidl_ret_status) != (::android::OK))) { goto _aidl_error; } _aidl_error: _aidl_status.setFromStatusT(_aidl_ret_status); return _aidl_status; }
获得RPC调用结果aidl_reply之后,最后面还有一句Parcel.readNullableStrongBinder,目的就是获取代理
status_t Parcel::readNullableStrongBinder(sp<IBinder>* val) const { return unflattenBinder(val); } status_t Parcel::unflattenBinder(sp<IBinder>* out) const { if (isForRpc()) { LOG_ALWAYS_FATAL_IF(mSession == nullptr, "RpcSession required to read from remote parcel"); int32_t isNull; status_t status = readInt32(&isNull); if (status != OK) return status; sp<IBinder> binder; if (isNull & 1) { auto addr = RpcAddress::zero(); status_t status = addr.readFromParcel(*this); if (status != OK) return status; binder = mSession->state()->onBinderEntering(mSession, addr); } return finishUnflattenBinder(binder, out); } // 这里可以拿到一个Handle const flat_binder_object* flat = readObject(false); if (flat) { switch (flat->hdr.type) { case BINDER_TYPE_BINDER: { sp<IBinder> binder = sp<IBinder>::fromExisting(reinterpret_cast<IBinder*>(flat->cookie)); return finishUnflattenBinder(binder, out); } case BINDER_TYPE_HANDLE: { // 创建一个BpBinder(handle) sp<IBinder> binder = ProcessState::self()->getStrongProxyForHandle(flat->handle); return finishUnflattenBinder(binder, out); } } } return BAD_TYPE; }
后面调用interface_cast 获取一个 BpMediaExtractorService,这和之前SeviceManager是相同的。
template<typename INTERFACE> inline sp<IMediaExtractorService> interface_cast(const sp<IBinder>& obj) { return IMediaExtractorService::asInterface(obj); } ::android::sp<IMediaExtractorService> IMediaExtractorService::asInterface( const ::android::sp<::android::IBinder>& obj) { ::android::sp<IMediaExtractorService> intr; if (obj != nullptr) { intr = ::android::sp<IMediaExtractorService>::cast( obj->queryLocalInterface(IMediaExtractorService::descriptor)); if (intr == nullptr) { intr = ::android::sp<BpMediaExtractorService>::make(obj); } } return intr; } template<typename INTERFACE> inline sp<IInterface> BnInterface<IMediaExtractorService>::queryLocalInterface( const String16& _descriptor) { if (_descriptor == IMediaExtractorService::descriptor) return sp<IInterface>::fromExisting(this); return nullptr; }
3、服务的使用
client使用就不再看了,看到server端时想到一个问题,IPCThreadState监听消息,但是没有指定由谁来执行。之前ServiceManager调用了setTheContextObject指定执行对象,但是media.extractor没有执行这一句,但是仔细看代码,似乎是从client发送的数据中可以找到target
binder_transaction_data_secctx tr_secctx; binder_transaction_data& tr = tr_secctx.transaction_data; // ...... if (cmd == (int) BR_TRANSACTION_SEC_CTX) { result = mIn.read(&tr_secctx, sizeof(tr_secctx)); } else { result = mIn.read(&tr, sizeof(tr)); tr_secctx.secctx = 0; } // ...... 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<BBinder*>(tr.cookie)->transact(tr.code, buffer, &reply, tr.flags); reinterpret_cast<BBinder*>(tr.cookie)->decStrong(this); } else { error = UNKNOWN_TRANSACTION; } } else { error = the_context_object->transact(tr.code, buffer, &reply, tr.flags); }
到这里binder service框架大致就了解了,之后看到相关内容也更加从容,binder驱动之后有空再学习。