简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!
优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀
人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
1.前言
本篇目的:理解ServiceManager成员函数addService是如何添加服务的。
2.ServiceManager::addService如何添加服务实现
Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) {
auto ctx = mAccess->getCallingContext();
// apps cannot add services
if (multiuser_get_app_id(ctx.uid) >= AID_APP) {
return Status::fromExceptionCode(Status::EX_SECURITY);
}
if (!mAccess->canAdd(ctx, name)) {
return Status::fromExceptionCode(Status::EX_SECURITY);
}
if (binder == nullptr) {
return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
}
if (!isValidServiceName(name)) {
LOG(ERROR) << "Invalid service name: " << name;
return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
}
#ifndef VENDORSERVICEMANAGER
if (!meetsDeclarationRequirements(binder, name)) {
// already logged
return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
}
#endif // !VENDORSERVICEMANAGER
// implicitly unlinked when the binder is removed
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);
}
// Overwrite the old service if it exists
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>.关键点
mNameToService[name] = Service {
.binder = binder,
.allowIsolated = allowIsolated,
.dumpPriority = dumpPriority,
.debugPid = ctx.debugPid,
};
<2>.注释
其中name表示服务名,binder表示每个服务的实例对象,将他们存放在mNameToService里面,那么mNameToService是什么类型呢?接着往下看
<3>.mNameToService定义
# ServiceManager.h
struct Service {
sp<IBinder> binder; // not null
bool allowIsolated;
int32_t dumpPriority;
bool hasClients = false; // notifications sent on true -> false.
bool guaranteeClient = false; // forces the client check to true
pid_t debugPid = 0; // the process in which this service runs
// the number of clients of the service, including servicemanager itself
ssize_t getNodeStrongRefCount();
};
using ServiceMap = std::map<std::string, Service>;
ServiceMap mNameToService;
由以上代码可以看到mNameToService的类型是ServiceMap,ServiceMap又是std::map<std::string, Service>的别名,它是一个C++的STL的map容器,第一个参数是key,第二个是value。
第一个参数的类型是string,第二个是Service类。
<4>.再看mNameToService[name]
mNameToService[name] = Service {
.binder = binder,
.allowIsolated = allowIsolated,
.dumpPriority = dumpPriority,
.debugPid = ctx.debugPid,
};
我们再看上边表达式初始化,将类Service的所有成员变量插入到map容器,对应的key就是name,Service的成员变量包括.binder(表示服务类对象),dumpPriority(表示优先级)。
3.addService应用实例
#include <cstdio>
#include <iostream>
#include <typeinfo>
#include <map>
using namespace std;
class Binder{
};
//struct Service {
class Service {
public:
Binder *binder;
bool allowIsolated;
int32_t dumpPriority;
bool hasClients = false;
bool guaranteeClient = false;
pid_t pid = 0;
ssize_t getNodeStrongRefCount();
};
//using设置别名:ServiceMap;容器map第一个参数是key,第二个是value;value为Service,Service又是一个类,包含变量和函数.
using ServiceMap = map<string, Service>;
ServiceMap mNameToService;
int main(){
Binder *binder1 = new Binder;
string name = "manager";
mNameToService[name] = Service {
.binder = binder1,
.allowIsolated = false,
.dumpPriority = 20,
.guaranteeClient = true,
.pid = 10,
};
string name_01 = "camera";
Binder *binder2 = new Binder;
mNameToService[name_01] = Service {
.binder = binder2,
.allowIsolated = false,
.dumpPriority = 24,
.guaranteeClient = false,
.pid = 11,
};
//first:表示key的值;second:表示value的值,即Service.
for(const auto& pair : mNameToService) {
printf("xxx-------->line = %d, first_name = %s, priority = %d, pid = %d\n",__LINE__,pair.first.c_str(), pair.second.dumpPriority,pair.second.pid);
}
}
打印:
xxx-------->line = 51, first_name = camera, priority = 24, pid = 11
xxx-------->line = 51, first_name = manager, priority = 20, pid = 10
4.总结
ServiceManager调用addService注册服务类,本质是将服务名+服务的对象插入到C++的map容器中,Client使用的时候,可以从map容器中获取就可以了。