VINTF-ServiceManager
VINTF 在 ServiceManager 中不是一张只读“HAL 名单”。它会影响稳定 Binder 服务能否注册、一个查询返回普通 Binder 还是 accessor、调用者需要通过哪些 SELinux 名称检查,以及 isDeclared()、APEX 更新来源和远端连接信息的结果。与此同时,这套逻辑受 VENDORSERVICEMANAGER 和 recovery 构建条件约束,不能外推为所有 ServiceManager 变体的共同实现。
本文承接 addService注册服务、getService查询服务 和 LazyServiceRegistrar。本文聚焦普通 AOSP servicemanager 如何消费 libvintf 数据;不把旧 HIDL hwservicemanager 当作同一进程,也不展开 VINTF XML 合并算法。
1. 构建边界
1.1 条件编译
源码文件:frameworks/native/cmds/servicemanager/ServiceManager.cpp
相关宏:VENDORSERVICEMANAGER、__ANDROID_RECOVERY__
#ifndef VENDORSERVICEMANAGER
#include <vintf/VintfObject.h>
#ifdef __ANDROID_RECOVERY__
#include <vintf/VintfObjectRecovery.h>
#endif
#include <vintf/constants.h>
#endif定义 VENDORSERVICEMANAGER 时,VINTF helper、声明校验、accessor 和连接信息路径都不编译。recovery 仍保留 VINTF 能力,但从 VintfObjectRecovery 读取 recovery manifest,而不是正常启动环境的 framework/device manifests。
1.2 Manifest来源
static std::vector<ManifestWithDescription>
GetManifestsWithDescription() {
#ifdef __ANDROID_RECOVERY__
auto vintfObject = VintfObjectRecovery::GetInstance();
return {{vintfObject->getRecoveryHalManifest(), "recovery"}};
#else
auto vintfObject = VintfObject::GetInstance();
return {
{vintfObject->getDeviceHalManifest(), "device"},
{vintfObject->getFrameworkHalManifest(), "framework"},
};
#endif
}普通系统查询 device 与 framework manifest;日志中的 description 也来自这里。ServiceManager 不拥有 XML 文件,它消费 libvintf 已解析的 HalManifest。
2. 名称解析
2.1 AIDL名称
源码文件:frameworks/native/cmds/servicemanager/ServiceManager.cpp
相关类型:AidlName
VINTF AIDL 名称形如 some.package.IFoo/default。解析器以最后一个点拆分 package/interface,以斜杠拆分 instance;缺少点、斜杠或实例时不构成有效 AIDL manifest 名称。native instance 则通过 NativeName 使用 package/instance 格式。
2.2 声明查询
static bool isVintfDeclared(
const Access::CallingContext& ctx,
const std::string& name) {
NativeName nname;
if (NativeName::fill(name, &nname)) {
return forEachManifest([&](const auto& mwd) {
return mwd.manifest->hasNativeInstance(
nname.package, nname.instance);
});
}
AidlName aname;
if (!AidlName::fill(name, &aname)) return false;
// scan AIDL manifest instances
...
}解析顺序先尝试 native 名称,再尝试 AIDL 名称。名称格式有效不代表已声明,最终仍要在实际 manifest instance 中匹配。
3. 注册校验
3.1 稳定性门槛
源码文件:frameworks/native/cmds/servicemanager/ServiceManager.cpp
相关函数:meetsDeclarationRequirements()、ServiceManager::addService()
static bool meetsDeclarationRequirements(
const Access::CallingContext& ctx,
const sp<IBinder>& binder,
const std::string& name) {
if (!Stability::requiresVintfDeclaration(binder)) {
return true;
}
return isVintfDeclared(ctx, name);
}不是所有 Binder 服务都必须出现在 VINTF。只有 Binder stability 要求 VINTF 声明时,注册名才必须匹配 manifest;普通 framework Binder 可以直接通过这一门槛。
#ifndef VENDORSERVICEMANAGER
if (!meetsDeclarationRequirements(ctx, binder, name)) {
return Status::fromExceptionCode(
Status::EX_ILLEGAL_ARGUMENT,
"VINTF declaration error.");
}
#endif校验发生在服务表写入和死亡通知建立之前。失败不会留下半注册表项。
4. Accessor路由
4.1 Accessor查找
源码文件:frameworks/native/cmds/servicemanager/ServiceManager.cpp
相关函数:getVintfAccessorName()
static std::optional<std::string> getVintfAccessorName(
const std::string& name) {
AidlName aname;
if (!AidlName::fill(name, &aname, false)) {
return std::nullopt;
}
std::optional<std::string> accessor;
forEachManifest([&](const auto& mwd) {
mwd.manifest->forEachInstance([&](const auto& instance) {
if (instance.format() != vintf::HalFormat::AIDL) return true;
if (instance.package() != aname.package) return true;
if (instance.interface() != aname.iface) return true;
if (instance.instance() != aname.instance) return true;
accessor = instance.accessor();
return false;
});
return false;
});
return accessor;
}只有 AIDL manifest instance 可以提供 accessor。匹配键由 package、interface、instance 三部分组成;找到 instance 但 accessor 为空时,仍走普通 Binder 路径。
4.2 查询变体
os::Service ServiceManager::tryGetService(
const std::string& name, bool startIfNotFound) {
std::optional<std::string> accessorName;
#ifndef VENDORSERVICEMANAGER
accessorName = getVintfAccessorName(name);
#endif
if (accessorName.has_value()) {
auto ctx = mAccess->getCallingContext();
if (!mAccess->canFind(ctx, name)) {
return os::Service::make<os::Service::Tag::accessor>(nullptr);
}
return os::Service::make<os::Service::Tag::accessor>(
tryGetBinder(*accessorName, startIfNotFound).service);
}
return os::Service::make<os::Service::Tag::serviceWithMetadata>(
tryGetBinder(name, startIfNotFound));
}返回 tag 区分 accessor 与普通 Binder metadata。调用者先对原始 VINTF 名称拥有 find 权限,随后 tryGetBinder(accessorName) 还会检查 accessor 名称自身的 find 权限。
4.3 Add权限
Status ServiceManager::canAddService(
const Access::CallingContext& ctx,
const std::string& name,
std::optional<std::string>* accessor) {
if (!mAccess->canAdd(ctx, name)) {
return Status::fromExceptionCode(Status::EX_SECURITY,
"SELinux denied for service.");
}
#ifndef VENDORSERVICEMANAGER
*accessor = getVintfAccessorName(name);
#endif
if (accessor->has_value() &&
!mAccess->canAdd(ctx, accessor->value())) {
return Status::fromExceptionCode(Status::EX_SECURITY,
"SELinux denied for the accessor of the service.");
}
return Status::ok();
}带 accessor 的服务注册需要同时通过逻辑服务名和 accessor 名的 add 权限。只配置其中一个 service_contexts 规则不足以完成注册。
5. VINTF接口
5.1 isDeclared
ServiceManager::isDeclared() 先执行 canFindService(),再在非 vendor 构建中调用 isVintfDeclared()。返回 true 只说明 manifest 声明存在,不说明服务当前已注册;当前运行状态应由 checkService() 判断。
5.2 实例枚举
源码文件:frameworks/native/cmds/servicemanager/ServiceManager.cpp
相关函数:getVintfInstances()、getDeclaredInstances()
native interface 名没有点时使用 getNativeInstances();AIDL interface 按最后一个点拆 package/interface,再调用 getAidlInstances()。ServiceManager 对每个实例调用 canFindService(),只返回调用者有权限看到的实例;全部被权限过滤而 manifest 非空时返回 security error。
5.3 APEX与连接
updatableViaApex()、getUpdatableNames() 和 getConnectionInfo() 都先进行 find 权限判断,再读取 manifest 中的 updatableViaApex 或 IP/port。它们返回的是声明 metadata,不代表对应服务进程正在运行或网络端点当前可达。
6. 测试边界
6.1 Cuttlefish输入
源码文件:frameworks/native/cmds/servicemanager/test_sm.cpp
VINTF 测试先检查设备是否为 Cuttlefish phone,否则 GTEST_SKIP()。Vintf.UpdatableViaApex 使用 camera provider 名称,断言返回指定 APEX;无实例后缀的非法名称断言 nullopt。GetUpdatableNames 反向输入 APEX 名,断言得到 camera provider 实例。
6.2 Native实例
Vintf.IsDeclared_native 输入 mapper/minigbm,断言 declared 为 true;GetDeclaredInstances_native 输入 mapper,断言返回 minigbm。这些断言依赖测试设备 manifest,不能外推成所有产品都声明相同实例。
6.3 可执行阅读
rg -n "isVintfDeclared|getVintfAccessorName|getVintfInstances|meetsDeclarationRequirements" \
frameworks/native/cmds/servicemanager/ServiceManager.cpp
rg -n "VENDORSERVICEMANAGER|VintfObjectRecovery|canAddService|canFindService" \
frameworks/native/cmds/servicemanager/ServiceManager.cpp
rg -n "TEST\(Vintf" \
frameworks/native/cmds/servicemanager/test_sm.cpp排查稳定 AIDL HAL 注册失败时,应依次确认 Binder stability 是否要求声明、名称能否解析、目标 manifest 是否含 instance、逻辑名和 accessor 名是否都有 SELinux add 权限。查询返回空时则分别检查声明、accessor 映射、两层 find 权限和 accessor 服务是否已注册,不能只查看 VINTF XML 中是否出现逻辑名称。
