新人阿彡的Android多媒体学习之路
🚄🚄🚄 第一章 Android Binder通信机制学习之Binder基本原理
🚄🚄🚄 第二章 Android Binder通信机制学习之Binder基本架构
🚄🚄🚄 第三章 Android Binder通信机制学习之ServiceManager流程分析
🚄🚄🚄 第四章 Android Binder通信机制学习之addService服务注册流程
本章目录
0、前言
主要参考:https://www.cnblogs.com/rongmiao/p/16067971.html
作为一名新步入Android领域的职场老鸟,奈何最近环境不好,整体越来越卷的大背景下,本老鸟又新进入Android开发这个领域,后续工作基本应该是主攻Android Framework层的开发,辅助Android Applicatios层的开发,在这里记录一下个人的学习之旅,一方面方便自己学习总结,另一方面也方便后续的查漏补缺。整体学习基于Android 12 版本的代码。
1、ServiceManager启动流程
ServiceManager 是 Binder 进程间通信机制的核⼼组件之⼀, 它扮演着Binder进程间通信机制上下⽂管理者的⾓⾊, 同时负责管理系统中的Service组件, 并且向Client组件提供获取Service代理对象的服务。ServiceManager (下⽂都称 SM) 运⾏在⼀个独⽴的进程中, 因此, Service 组件和 Client 组件也需要通过进程间通信机制来和它进⾏交互, ⽽采⽤的进程间通信机制正好也是 Binder 机制。这样看来 SM 除了是 Binder 进程间通信机制的上下⽂管理者外, 还是⼀个特殊的 Service 组件。
先来看一下完整的ServiceManager启动流程:
下面展示关键函数代码以及相应注释
代码路劲:native/cmds/servicemanager/main.cpp
/******************************1、main()**********************************/
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";
// 打开binder驱动,open,mmap
sp<ProcessState> ps = ProcessState::initWithDriver(driver);
// 在初始化ProcessState的时候,mThreadPoolStarted被初始化为false了,所以setThreadPoolMaxThreadCount函数里面不会设置线程池最大线程数
ps->setThreadPoolMaxThreadCount(0);
// oneway限制,sm发起的binder调用必须是单向,否则打印堆栈日志提示
ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);
// 实例化ServiceManager,传入Access类用于鉴权
sp<ServiceManager> manager = sp<ServiceManager>::make(std::make_unique<Access>());
// 将自身注册到ServiceManager当中
if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
LOG(ERROR) << "Could not self register servicemanager";
}
// 将ServiceManager设置给 IPCThreadState 的全局变量
IPCThreadState::self()->setTheContextObject(manager);
// 注册到驱动,成为binder管理员,handle是0
ps->becomeContextManager();
// 准备Looper
sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);
// 通知驱动BC_ENTER_LOOPER,监听驱动fd,有消息时回调到handleEvent处理binder调用
BinderCallback::setupTo(looper);
ClientCallbackCallback::setupTo(looper, manager);
// 循环等待消息
while(true) {
looper->pollAll(-1);
}
// should not be reached
return EXIT_FAILURE;
}
1.1、ProcessState初始化
/****************4、sp<ProcessState>::make(driver)********************/
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),
mStarvationStartTimeMs(0),
mForked(false),
mThreadPoolStarted(false),
mThreadPoolSeq(1),
mCallRestriction(CallRestriction::NONE) {
base::Result<int> opened = open_driver(driver); // 1、调用 open_driver 打开 binder 驱动设备
if (opened.ok()) {
// 2、执行内存映射操作
// 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();
}
}
1.2、open_driver打开binder驱动
/****************5、open_driver(const char* driver)********************/
static base::Result<int> open_driver(const char* driver) {
int fd = open(driver, O_RDWR | O_CLOEXEC); // 1.通过open系统调用打开了/dev/binder设备
if (fd < 0) {
return base::ErrnoError() << "Opening '" << driver << "' failed";
}
int vers = 0;
// 2.通过ioctl获取Binder实现的版本号,并检查是否匹配
status_t result = ioctl(fd, BINDER_VERSION, &vers);
if (result == -1) {
close(fd);
return base::ErrnoError() << "Binder ioctl to obtain version failed";
}
if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
close(fd);
return base::Error() << "Binder driver protocol(" << vers
<< ") does not match user space protocol("
<< BINDER_CURRENT_PROTOCOL_VERSION
<< ")! ioctl() return value: " << result;
}
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
// 3.通过ioctl设置进程支持的最大Binder线程数
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
if (result == -1) {
ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
}
uint32_t enable = DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION;
result = ioctl(fd, BINDER_ENABLE_ONEWAY_SPAM_DETECTION, &enable);
if (result == -1) {
ALOGE_IF(ProcessState::isDriverFeatureEnabled(
ProcessState::DriverFeature::ONEWAY_SPAM_DETECTION),
"Binder ioctl to enable oneway spam detection failed: %s", strerror(errno));
}
return fd;
}
1.3、addService注册实例到ServiceManager中
/****************15、addService(const char* driver)********************/
Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) {
auto ctx = mAccess->getCallingContext();
// uid鉴权
if (multiuser_get_app_id(ctx.uid) >= AID_APP) {
return Status::fromExceptionCode(Status::EX_SECURITY, "App UIDs cannot add services");
}
// selinux鉴权
if (!mAccess->canAdd(ctx, name)) {
return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denial");
}
if (binder == nullptr) {
return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Null binder");
}
// 检查名字是否有效
if (!isValidServiceName(name)) {
LOG(ERROR) << "Invalid service name: " << name;
return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Invalid service name");
}
#ifndef VENDORSERVICEMANAGER
if (!meetsDeclarationRequirements(binder, name)) {
// already logged
return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "VINTF declaration error");
}
#endif // !VENDORSERVICEMANAGER
// implicitly unlinked when the binder is removed
// remoteBinder返回不为空,说明是代理对象,则注册死亡通知并检查注册结果
if (binder->remoteBinder() != nullptr &&
binder->linkToDeath(sp<ServiceManager>::fromExisting(this)) != OK) {
LOG(ERROR) << "Could not linkToDeath when adding " << name;
return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "linkToDeath failure");
}
// Overwrite the old service if it exists
// 将binder保存到map容器当中
mNameToService[name] = Service {
.binder = binder,
.allowIsolated = allowIsolated,
.dumpPriority = dumpPriority,
.debugPid = ctx.debugPid,
};
auto it = mNameToRegistrationCallback.find(name);
if (it != mNameToRegistrationCallback.end()) {
for (const sp<IServiceCallback>& cb : it->second) {
mNameToService[name].guaranteeClient = true;
// permission checked in registerForNotifications
cb->onRegistration(name, binder);
}
}
return Status::ok();
}
1.4、becomeContextManager注册实例到Binder驱动中,并设置为管理员
/************************17、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;
// 传入命令 BINDER_SET_CONTEXT_MGR 将自己注册成为SM
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;
}
2、ServiceManager对象如何获取
启动ServiceManager之后我们要如何获取到ServiceManager并且使用它的方法呢?这时候就要到libbinder中的IServiceManager了,我们平时使用会直接调用defaultServiceManager来获取ServiceManager。
[[clang::no_destroy]] static std::once_flag gSmOnce;
[[clang::no_destroy]] static sp<IServiceManager> gDefaultServiceManager;
sp<IServiceManager> defaultServiceManager()
{
std::call_once(gSmOnce, []() {
sp<AidlServiceManager> sm = nullptr;
while (sm == nullptr) {
// 先创建ProcessState对象,然后调用其getContextObject函数创建一个Binder对象,然后调用
// 模板函数 interface_cast<IServiceManager> 将其封装为一个ServiceManager的代理对象
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);
}
}
// 实例化 ServiceManagerShim,他的真是面目是 BpServiceManager(BpBinder(0))
gDefaultServiceManager = sp<ServiceManagerShim>::make(sm);
});
return gDefaultServiceManager;
}
先调用ProcessState::self 打开binder驱动(一般情况下调用进程和ServiceManager服务端不在同一个进程,这时候会重新打开binder驱动),然后调用getContextObject获取服务端的ServiceManager(handle为0默认为ServiceManager),然后调用getStrongProxyForHandle函数来实现获取Binder代理对象。
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
/* struct handle_entry {
IBinder* binder;
RefBase::weakref_type* refs;
};
每一个 Binder 代理对象都使用一个 handle_entry 的结构体来描述. handle_entry 的两个成员变量 binder 与 refs
分别指向一个 Binder 代理对象以及它内部的一个弱引用计数对象.
*/
handle_entry* e = lookupHandleLocked(handle);
if (e != nullptr) {
IBinder* b = e->binder;
/* 判断 handlle_entry 结构体的成员变量 binder 值是否为 NULL, 如果为 NULL, 说明尚未为
句柄值 handle 创建过 Binder 代理对象. 那么就会下面创建 Binder 代理对象. 如果不为 NULL,
说明它已经指向了一个 Binder 代理对象, 则需要调用 attemptIncWeak 函数检查这个代理对象是否还存活着 */
if (b == nullptr || !e->refs->attemptIncWeak(this)) {
// handle == 0 创建ServiceManager
if (handle == 0) {
IPCThreadState* ipc = IPCThreadState::self();
CallRestriction originalCallRestriction = ipc->getCallRestriction();
ipc->setCallRestriction(CallRestriction::NONE);
Parcel data;
// 通过 PING_TRANSACTION 命令测试 Binder 是否准备就绪
status_t status = ipc->transact(
0, IBinder::PING_TRANSACTION, data, nullptr, 0);
ipc->setCallRestriction(originalCallRestriction);
if (status == DEAD_OBJECT)
return nullptr;
}
// 根据句柄值 handle 创建 Binder 代理对象, 并将其保存在 handle_entry 结构体 e 的成员变量 binder 中
sp<BpBinder> b = BpBinder::PrivateAccessor::create(handle);
e->binder = b.get();
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
// 进程中已经有一个 Binder 代理对象与句柄值 handle 相对应, 并且这个 Binder 代理对象是有效的. 直接返回给调用者
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
interface_cast是一个模板函数,之前的章节Android Binder通信机制学习(二)有提到,这里再看一下interface_cast的定义
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
// asInterface 函数定义在宏 DECLARE_META_INTERFACE
return INTERFACE::asInterface(obj);
}
其内部所调用的函数asInterface是在宏IMPLEMENT_META_INTERFACE里面定义的,之前的章节Android Binder通信机制学习(二)也有提到
::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) {
/* 以 ServiceManager 为例子,这里创建的是BpServiceManager */ \
intr = ::android::sp<BPTYPE>::make(obj); \
} \
} \
return intr; \
}
其内部调用的queryLocalInterface函数,具体实现是在IInterface.h中定义的模板函数BnInterface< INTERFACE >::queryLocalInterface,这里的INTERFACE 模板类也就是ServiceManager。
template<typename INTERFACE>
inline sp<IInterface> BnInterface<INTERFACE>::queryLocalInterface(
const String16& _descriptor)
{
if (_descriptor == INTERFACE::descriptor) return sp<IInterface>::fromExisting(this);
return nullptr;
}
先获取当前进程的Bn对象,如果返回null,那么就通过intr = ::android::sp<BPTYPE>::make(obj)
语句创建一个Bp对象,即BpServiceManager。
最后看一下完整的流程图:
本章主要学习了ServiceManager是如何启动以及启动后怎么获取ServiceManager对象,后面章节会在此基础上继续学习Server端是如何向ServiceManager注册服务,以及Client又是如何向ServerManager获取服务的。
3、参考资料
1、Android 12(S) Binder(一)
2、Android12系统源码分析NativeBinder代码变迁
3、梳理Binder原理之ServiceManager的注册流程(启动流程)AndroidP
4、Android之ServiceManager服务