Skip to content

VINTF-ServiceManager

追踪 ServiceManager 的 VINTF 声明解析、稳定性校验、accessor 路由、权限联动与条件编译边界。

基于android-17.0.0_r1
AndroidBinderServiceManagerVINTF源码阅读

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__

cpp
#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来源 ​

cpp
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 声明查询 ​

cpp
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()

cpp
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 可以直接通过这一门槛。

cpp
#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()

cpp
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 查询变体 ​

cpp
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权限 ​

cpp
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 可执行阅读 ​

bash
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 中是否出现逻辑名称。