当前位置: 首页 > java >正文

Android12 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 servicesif (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 VENDORSERVICEMANAGERif (!meetsDeclarationRequirements(binder, name)) {// already loggedreturn Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);}
#endif  // !VENDORSERVICEMANAGER// implicitly unlinked when the binder is removedif (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 existsmNameToService[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 registerForNotificationscb->onRegistration(name, binder);}}return Status::ok();
}

解读

一、函数入口与权限校验​

​​调用方身份验证​​

auto ctx = mAccess->getCallingContext();
if (multiuser_get_app_id(ctx.uid) >= AID_APP) {return Status::fromExceptionCode(Status::EX_SECURITY);
}

​​作用​​:禁止普通应用进程(UID >= AID_APP)注册系统服务。
​​底层逻辑​​:multiuser_get_app_id 提取调用方 UID 的类别,若属于应用范畴则直接拒绝,防止权限越界。
​​服务添加权限校验​​

if (!mAccess->canAdd(ctx, name)) {return Status::fromExceptionCode(Status::EX_SECURITY);
}

​​SELinux 策略​​:mAccess->canAdd 检查调用方是否拥有 add_service SELinux 权限标签(如 servicemanager.te 中定义)。
​​动态权限控制​​:例如,ActivityManagerService 需声明 MANAGE_SERVICES 权限方可注册服务。

二、参数合法性校验​​

​​服务名有效性检查​​

if (!isValidServiceName(name)) {LOG(ERROR) << "Invalid service name: " << name;return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
}

​​规则​​:服务名需满足以下条件:
非空且长度 ≤ 127 字符;
符合命名规范(如不允许特殊字符);
非系统保留名称(如 android.* 前缀可能仅限系统进程使用)。
​​服务接口声明验证​​

#ifndef VENDORSERVICEMANAGER
if (!meetsDeclarationRequirements(binder, name)) {return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
}
#endif

​​目的​​:确保服务实现了声明的 AIDL 接口(如通过 BnInterface 或 BpInterface 继承链验证)。
​​厂商定制​​:VENDORSERVICEMANAGER 宏用于区分标准 ServiceManager 与厂商定制版本,后者可能放宽接口限制。

三、服务生命周期管理​​

​​Binder 死亡回调绑定​​

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 触发 ServiceManager 清理失效服务。
​​实现细节​​:remoteBinder 判断服务是否为远程对象(跨进程),仅远程服务需要绑定死亡通知。

四、服务注册与存储​​

​​服务存储结构​​

mNameToService[name] = Service {.binder = binder,.allowIsolated = allowIsolated,.dumpPriority = dumpPriority,.debugPid = ctx.debugPid,
};

​​数据结构​​:mNameToService 是 std::map<std::string, Service>,键为服务名,值为 Service 结构体。
​​字段含义​​:
allowIsolated:是否允许隔离环境(如沙盒应用)访问该服务;
dumpPriority:服务在 dumpsys 命令中的输出优先级;
debugPid:服务所属进程的 PID,用于调试。
​​覆盖式更新策略​​
直接覆盖同名服务的旧条目,无需显式删除,避免服务重启时的状态不一致问题。

五、回调通知机制​​

auto it = mNameToRegistrationCallback.find(name);
if (it != mNameToRegistrationCallback.end()) {for (const sp<IServiceCallback>& cb : it->second) {mNameToService[name].guaranteeClient = true;cb->onRegistration(name, binder);}
}

​​功能​​:触发注册回调,通知监听该服务名的组件(如 IServiceCallback 实现类)服务已可用。
​​应用场景​​:系统监控工具可借此实现服务状态实时追踪。

http://www.xdnf.cn/news/212.html

相关文章:

  • js reduce累加器
  • #去除知乎中“盐选”付费故事
  • @JsonView + 单一 DTO:如何实现多场景 JSON 字段动态渲染
  • 大语言模型智能体:安全挑战与应对之道
  • echarts饼图中心呈现一张图片,并且能动态旋转的效果react组件
  • 天梯赛数据结构合集
  • 51单片机实验三:数码管动态显示
  • Oracle 19c新特性:OCP认证考试与职业跃迁的关键?
  • 如何选择适合您的过程控制器?
  • VSCODE插值表达式失效问题
  • 4.18学习总结
  • CNN与VGG16的关系:从基础到经典模型的通俗解析
  • 【前沿】成像“跨界”测量——扫焦光场成像
  • 【AI部署】腾讯云GPU -—SadTalker的AI数字人访问web服务—未来之窗超算中心
  • 2025mathorcup妈妈杯数学建模挑战赛C题:汽车风阻预测,详细思路,模型,代码更新中
  • 专精特新政策推动,B端UI设计如何赋能中小企业创新发展?
  • 使用VHDL语言实现TXT文件的读写操作
  • 【LeetCode】大厂面试算法真题回忆(61)--组装新的数组
  • 7.Rust+Axum:打造高效 RESTful API 的最佳实践
  • FastGPT安装前,系统环境准备工作?
  • AI Agent系列(十) -Data Agent(数据分析智能体)开源资源汇总
  • Qt QTimer 详解与使用指南
  • PHP最新好看UI个人引导页网页源码
  • Flash存储器(二):SPI NAND Flash与SPI NOR Flash
  • 基于linux 设置无线网卡Monitor模式 sniffer抓包
  • 经济指标学习(二)
  • 神经网络优化 - 小批量梯度下降之批量大小的选择
  • ChatGPT-o3辅助学术写作的关键词和引言效果如何?
  • 鸿蒙NEXT开发键值型数据工具类(ArkTs)
  • PyTorch快速入门