Skip to content

Hwservice Contexts

从 HIDL hwservice_contexts 构建和 label lookup,追踪到 hwservicemanager 的 add/find/list、hwbinder 权限、HAL 属性宏与失败路径。

基于android-17.0.0_r1
AndroidSELinuxhwservice_contextshwservicemanagerHIDLhwbinder源码阅读

Hwservice Contexts ​

本文面向已经读过 安全上下文、TE规则语法、Service Contexts 和 Binder 基础文章的读者。上一主题讨论 /dev/binder 上的 system ServiceManager;本篇改看历史 HIDL HAL 使用的 /dev/hwbinder、hwservicemanager 和 hwservice_contexts。

hwservice_contexts 只解决“接口名对应哪个 hwservice_manager target type”。注册者能否 add、消费者能否 find、客户端是否能打开 hwbinder、拿到引用后能否对 HAL 进程发起 Binder call,分别由不同源码和 policy 消费。AIDL HAL 若注册到系统 ServiceManager,使用的是 service_contexts,不应把两套名字空间混用。

本文基于 Android 17 android-17.0.0_r1,覆盖 HIDL 仍存在时的真实路径:HIDL proxy 的 registerAsService()、libhidl transport、hwservicemanager AccessControl、add_hwservice/hal_attribute_hwservice 宏、hwservice_manager neverallow、VINTF manifest 约束以及 lshal/VTS 验证。读完后,读者应能解释“HAL 注册失败”“Framework 找不到 HIDL HAL”“查找成功但 hwbinder call 被拒绝”分别停在哪一层。

1. 两套名字空间 ​

1.1 HIDL路径 ​

HIDL 服务名通常由 package、interface 和 instance 组成,例如 android.hardware.audio::IDevicesFactory/default。HIDL transport 把接口的 fully-qualified name 交给 hwservicemanager,target Context 从 hwservice_contexts lookup。

源码文件:system/sepolicy/private/hwservice_contexts

text
android.hardware.audio::IDevicesFactory                         u:object_r:hal_audio_hwservice:s0
android.hardware.camera.provider::ICameraProvider               u:object_r:hal_camera_hwservice:s0
android.hardware.power::IPower                                  u:object_r:hal_power_hwservice:s0
*                                                               u:object_r:default_android_hwservice:s0

1.2 AIDL对照 ​

AIDL HAL 使用 /dev/binder 和 system ServiceManager,条目位于 service_contexts,格式通常是 android.hardware.foo.IFoo/default。迁移时必须同步替换 manager、设备节点、object class、target type 和 policy 宏。

维度HIDLAIDL HAL
managerhwservicemanagerservicemanager
驱动/dev/hwbinder/dev/binder
contextshwservice_contextsservice_contexts
classhwservice_managerservice_manager
注册宏add_hwserviceadd_service
服务名package::IInterface + instancepackage.Interface/instance

1.3 权限层级 ​

hwservice_manager add/find/list 只控制 hwservicemanager 的名字表。HAL 进程之间的 Binder transaction 仍由 hwbinder_use 和目标 domain 的 Binder policy 控制;打开 /dev/hwbinder 还受字符设备权限约束。

2. 规则格式 ​

2.1 实际条目 ​

Android 17 platform 文件仍包含音频、相机、传感器、健康、电源等 HIDL 接口。版本号不写进 Context key;instance 由 HIDL transport 在注册/查找时另行处理。

源码文件:system/sepolicy/private/hwservice_contexts

text
android.frameworks.sensorservice::ISensorManager                 u:object_r:fwk_sensor_hwservice:s0
android.hardware.audio.effect::IEffectsFactory                   u:object_r:hal_audio_hwservice:s0
android.hardware.graphics.composer::IComposer                    u:object_r:hal_graphics_composer_hwservice:s0
android.hardware.health::IHealth                                  u:object_r:hal_health_hwservice:s0
android.hardware.sensors::ISensors                                u:object_r:hal_sensors_hwservice:s0
android.system.suspend::ISystemSuspend                            u:object_r:system_suspend_hwservice:s0

2.2 默认标签 ​

默认 default_android_hwservice 只用于 backend fallback,policy 明确禁止对它执行 add,避免新 HAL 忘记声明专用 type 却仍能注册。

源码文件:system/sepolicy/private/domain.te

text
neverallow * default_android_hwservice:hwservice_manager *;

2.3 条件条目 ​

hwservice contexts 在 M4 阶段接受 release flags。条件未启用时,接口条目不会进入安装产物,运行时 lookup 也不会“看见源码中的行”。

3. 分区构建 ​

3.1 Module定义 ​

Soong 为 platform、system_ext、product、vendor 和 odm 分别生成 hwservice contexts。vendor module 合并 platform vendor、vendor 和 reqd_mask 输入;Recovery 变体使用相同 stem。

源码文件:system/sepolicy/contexts/Android.bp

make
hwservice_contexts {
    name: "plat_hwservice_contexts",
    defaults: ["contexts_flags_defaults"],
    srcs: [":hwservice_contexts_files{.plat_private}"],
}

hwservice_contexts {
    name: "vendor_hwservice_contexts",
    defaults: ["contexts_flags_defaults"],
    srcs: [
        ":hwservice_contexts_files{.plat_vendor}",
        ":hwservice_contexts_files{.vendor}",
        ":hwservice_contexts_files{.reqd_mask}",
    ],
    soc_specific: true,
}

hwservice_contexts {
    name: "odm_hwservice_contexts",
    defaults: ["contexts_flags_defaults"],
    srcs: [":hwservice_contexts_files{.odm}"],
    device_specific: true,
}

3.2 通用命令 ​

hwservice contexts 使用通用 M4/去注释流程,但不使用 file contexts 的 fc_sort。输出仍保持输入顺序,真正的服务查找由 Android libselinux service backend 完成。

源码文件:system/sepolicy/build/soong/selinux_contexts.go

go
func (m *selinuxContextsModule) buildServiceContexts(
        ctx android.ModuleContext, inputs android.Paths) android.Path {
    if m.properties.Remove_comment == nil {
        m.properties.Remove_comment = proptools.BoolPtr(true)
    }
    return m.buildGeneralContexts(ctx, inputs)
}

func hwServiceFactory() android.Module {
    m := newModule()
    m.build = m.buildServiceContexts
    return m
}

3.3 静态检查 ​

hwservice_contexts_test 使用 checkfc -e -l:-l 选择 hwbinder service backend,-e 允许某些分区 contexts 为空。测试同时读取 compiled policy,检查 target type 属于 hwservice_manager_type。

源码文件:system/sepolicy/build/soong/selinux_contexts.go

go
case HwServiceContext:
    flags = []string{
        "-e" /* allow empty */, "-l" /* hwbinder services */,
    }

4. AccessControl ​

4.1 Handle初始化 ​

hwservicemanager 的 AccessControl 构造函数立即获取 selinux_android_hw_service_context_handle(),读取自身 Context,打开 SELinux status,并注册 audit/log callback。handle 获取失败是进程级 fatal,而不是一次请求返回 null。

源码文件:system/hwservicemanager/AccessControl.cpp

cpp
AccessControl::AccessControl() {
    mSeHandle = selinux_android_hw_service_context_handle();
    LOG_ALWAYS_FATAL_IF(mSeHandle == nullptr,
                        "Failed to acquire SELinux handle.");

    if (getcon(&mSeContext) != 0) {
        LOG_ALWAYS_FATAL("Failed to acquire hwservicemanager context.");
    }

    selinux_status_open(true);
    mSeCallbacks.func_audit = AccessControl::auditCallback;
    selinux_set_callback(SELINUX_CB_AUDIT, mSeCallbacks);
    mSeCallbacks.func_log = selinux_log_callback;
    selinux_set_callback(SELINUX_CB_LOG, mSeCallbacks);
}

4.2 FQName规范化 ​

canAdd()/canGet() 接收 HIDL fully-qualified name,但 lookup key 是 package::Interface,不含 instance。先用 FQName::parse() 校验,再把 package 和 interface 拼成 checkName。

源码文件:system/hwservicemanager/AccessControl.cpp

cpp
bool AccessControl::canAdd(const std::string& fqName,
                           const CallingContext& callingContext) {
    FQName fqIface;
    if (!FQName::parse(fqName, &fqIface)) return false;

    const std::string checkName =
            fqIface.package() + "::" + fqIface.name();
    return checkPermission(callingContext, "add", checkName.c_str());
}

bool AccessControl::canGet(const std::string& fqName,
                           const CallingContext& callingContext) {
    FQName fqIface;
    if (!FQName::parse(fqName, &fqIface)) return false;

    const std::string checkName =
            fqIface.package() + "::" + fqIface.name();
    return checkPermission(callingContext, "find", checkName.c_str());
}

因此 hwservice_contexts 的 key 不需要 /default instance;instance 只用于 VINTF transport 和 hwservicemanager 的服务表。

4.3 Target查询 ​

lookup 失败直接记录 interface 名并返回 false;成功后使用 hwservice_manager class 调用 selinux_check_access()。

源码文件:system/hwservicemanager/AccessControl.cpp

cpp
bool AccessControl::checkPermission(const CallingContext& source,
                                    const char* perm,
                                    const char* interface) {
    char* targetContext = nullptr;
    if (selabel_lookup(mSeHandle, &targetContext,
                       interface, 0) != 0) {
        ALOGE("No match for interface %s in hwservice_contexts",
              interface);
        return false;
    }

    bool allowed = checkPermission(source, targetContext,
                                   perm, interface);
    freecon(targetContext);
    return allowed;
}

4.4 Source查询 ​

Binder 调用的 source PID/SID 来自 hwbinder IPCThreadState;如果调用 SID 不可用且 PID 不是自身,ServiceManager 再通过 getpidcon() 查询。

源码文件:system/hwservicemanager/ServiceManager.cpp

cpp
AccessControl::CallingContext getBinderCallingContext() {
    const auto& self = IPCThreadState::self();
    pid_t pid = self->getCallingPid();
    const char* sid = self->getCallingSid();

    if (sid == nullptr) {
        if (pid != getpid()) {
            android_errorWriteLog(0x534e4554, "121035042");
        }
        return AccessControl::getCallingContext(pid);
    }
    return { true, sid, pid };
}

4.5 Audit字段 ​

audit callback 输出 interface、source SID 和 pid。它不会输出 instance,因为 canAdd/canGet 的 policy key 已在 FQName 规范化阶段去掉 instance。

源码文件:system/hwservicemanager/AccessControl.cpp

cpp
int AccessControl::auditCallback(void* data,
                                 security_class_t /*cls*/,
                                 char* buf, size_t len) {
    struct audit_data* ad = (struct audit_data*)data;
    if (!ad || !ad->interfaceName) {
        ALOGE("No valid hwservicemanager audit data");
        return 0;
    }
    const char* sid = ad->sid ? ad->sid : "N/A";
    snprintf(buf, len, "interface=%s sid=%s pid=%d",
             ad->interfaceName, sid, ad->pid);
    return 0;
}

5. HIDL注册 ​

5.1 注册入口 ​

libhidl 的 registerAsServiceInternal() 先获得默认 HIDL ServiceManager,再查询 descriptor/name 的 VINTF transport;不是 HWBINDER 时直接失败。通过后读取 interface chain,调用 addWithChain()。

源码文件:system/libhidl/transport/ServiceManagement.cpp

cpp
status_t registerAsServiceInternal(const sp<IBase>& service,
                                   const std::string& name) {
    if (service == nullptr) return UNEXPECTED_NULL;

    sp<IServiceManager1_2> sm = defaultServiceManager1_2();
    if (sm == nullptr) return INVALID_OPERATION;

    const std::string descriptor = getDescriptor(service.get());
    if (!isTrebleTestingOverride()) {
        Return<IServiceManager1_0::Transport> transport =
                sm->getTransport(descriptor, name);
        if (!transport.isOk()) return UNKNOWN_ERROR;
        if (transport != IServiceManager1_0::Transport::HWBINDER) {
            LOG(ERROR) << "Service " << descriptor << "/" << name
                       << " must be in VINTF manifest";
            return UNKNOWN_ERROR;
        }
    }

    bool registered = false;
    Return<void> ret = service->interfaceChain([&](const auto& chain) {
        registered = sm->addWithChain(name.c_str(), service, chain)
                .withDefault(false);
    });
    if (!ret.isOk()) return UNKNOWN_ERROR;
    if (registered) onRegistrationImpl(descriptor, name);
    return registered ? OK : UNKNOWN_ERROR;
}

5.2 add入口 ​

hwservicemanager 的 add() 先拒绝空 binder,再对 IBase::descriptor 检查 add;随后通过 interfaceChain() 把叶接口和所有父接口交给 addImpl()。

源码文件:system/hwservicemanager/ServiceManager.cpp

cpp
Return<bool> ServiceManager::add(const hidl_string& name,
                                 const sp<IBase>& service) {
    if (service == nullptr) return false;

    auto pidcon = getBinderCallingContext();
    if (!mAcl.canAdd(IBase::descriptor, pidcon)) {
        LOG(ERROR) << "Missing permissions to add IBase";
        return false;
    }

    bool addSuccess = false;
    auto ret = service->interfaceChain([&](const auto& interfaceChain) {
        addSuccess = addImpl(name, service, interfaceChain, pidcon);
    });
    if (!ret.isOk()) {
        LOG(ERROR) << "Failed to retrieve interface chain: "
                   << ret.description();
        return false;
    }
    return addSuccess;
}

5.3 Chain权限 ​

addImpl() 对 interface chain 中每一个 FQName 调用 canAdd()。因此只为叶接口添加 target mapping 或 add 规则并不足够,父接口也必须满足权限检查。

源码文件:system/hwservicemanager/ServiceManager.cpp

cpp
if (interfaceChain.size() == 0) {
    LOG(WARNING) << "Empty interface chain for " << name;
    return false;
}

for (size_t i = 0; i < interfaceChain.size(); i++) {
    const std::string fqName = interfaceChain[i];
    if (!mAcl.canAdd(fqName, callingContext)) {
        return false;
    }
}

5.4 HidlService表 ​

通过权限后,ServiceManager 将服务挂入 mServiceMap[fqName].instanceMap。同一 binder 的父接口会建立关联;子类注册到已存在的父类 instance 时,旧 superclass entry 可能被移除以保持 castFrom/getService 语义一致。

源码文件:system/hwservicemanager/ServiceManager.cpp

cpp
const std::string childFqName = interfaceChain[0];
HidlService* hidlService = lookup(childFqName, name);
if (hidlService != nullptr) {
    const sp<IBase> remove = hidlService->getService();
    if (remove != nullptr) {
        const std::string instanceName = name;
        removeService(remove, &instanceName);
    }
}

6. HIDL查找 ​

6.1 get服务 ​

get(fqName, instance) 先执行 canGet(),再 lookup HidlService。服务缺失或 binder 为空时调用 tryStartService() 设置 ctl.interface_start=<fqName>/<instance>,并立即返回 null。

源码文件:system/hwservicemanager/ServiceManager.cpp

cpp
Return<sp<IBase>> ServiceManager::get(
        const hidl_string& hidlFqName,
        const hidl_string& hidlName) {
    const std::string fqName = hidlFqName;
    const std::string name = hidlName;

    if (!mAcl.canGet(fqName, getBinderCallingContext())) {
        return nullptr;
    }

    HidlService* hidlService = lookup(fqName, name);
    if (hidlService == nullptr || hidlService->getService() == nullptr) {
        tryStartService(fqName, name);
        return nullptr;
    }

    sp<IBase> service = hidlService->getService();
    hidlService->guaranteeClient();
    return service;
}

6.2 Lazy启动 ​

lazy HIDL 启动使用 ctl.interface_start,value 是完整 fqName/instance,与 AIDL servicemanager 使用的 aidl/<name> 格式不同。

源码文件:system/hwservicemanager/ServiceManager.cpp

cpp
std::thread([=] {
    if (!SetProperty("ctl.interface_start", fqName + "/" + name)) {
        LOG(INFO) << "Tried to start " << fqName << "/" << name
                  << " as a lazy service, but was unable to.";
    }
}).detach();

6.3 list权限 ​

list() 检查的是 hwservicemanager 自身 target Context 上的 list。listByInterface() 则先对指定 FQName 执行 canGet(),再返回该 interface 下已有 instance。

源码文件:system/hwservicemanager/ServiceManager.cpp

cpp
Return<void> ServiceManager::list(list_cb _hidl_cb) {
    if (!mAcl.canList(getBinderCallingContext())) {
        _hidl_cb({});
        return Void();
    }

    hidl_vec<hidl_string> list;
    list.resize(countExistingService());
    size_t idx = 0;
    forEachExistingService([&](const HidlService* service) {
        list[idx++] = service->string();
        return true;
    });
    _hidl_cb(list);
    return Void();
}

6.4 Death清理 ​

HidlService 对 binder death 使用 cookie 区分 service、package listener、service listener 和 client callback。死亡后 removeService() 将对应 HidlService 的 binder 置空,但保留 instance 条目,使后续 lazy/notification 仍能定位它。

源码文件:system/hwservicemanager/ServiceManager.cpp

cpp
bool ServiceManager::removeService(
        const wp<IBase>& who,
        const std::string* restrictToInstanceName) {
    bool keepInstance = false;
    bool removed = false;
    for (auto& interfaceMapping : mServiceMap) {
        auto& instanceMap = interfaceMapping.second.getInstanceMap();
        for (auto& servicePair : instanceMap) {
            const std::string& instanceName = servicePair.first;
            const auto& service = servicePair.second;
            if (interfacesEqual(service->getService(), who.promote())) {
                if (restrictToInstanceName != nullptr &&
                    *restrictToInstanceName != instanceName) {
                    keepInstance = true;
                    continue;
                }
                service->setService(nullptr,
                    static_cast<pid_t>(IServiceManager::PidConstant::NO_PID));
                removed = true;
            }
        }
    }
    return !keepInstance && removed;
}

7. Policy配套 ​

7.1 类型声明 ​

public hwservice.te 为 target type 声明 hwservice_manager_type,多数 HAL type 还有 protected_hwservice。后者是面向 untrusted app 的额外保护属性,不是 lookup 格式的一部分。

源码文件:system/sepolicy/public/hwservice.te

text
type default_android_hwservice, hwservice_manager_type, protected_hwservice;
type hal_audio_hwservice, hwservice_manager_type, protected_hwservice;
type hal_camera_hwservice, hwservice_manager_type, protected_hwservice;
type hal_power_hwservice, hwservice_manager_type, protected_hwservice;
type hal_graphics_composer_hwservice, hwservice_manager_type, protected_hwservice;

type hal_graphics_mapper_hwservice, hwservice_manager_type, same_process_hwservice;
type hidl_base_hwservice, hwservice_manager_type;

7.2 add_hwservice ​

add_hwservice(server, target) 同时授予 server add/find、允许它 add hidl_base_hwservice,并生成仅该 server 可 add target 的 neverallow。

源码文件:system/sepolicy/public/te_macros

text
define(`add_hwservice', `
  allow $1 $2:hwservice_manager { add find };
  allow $1 hidl_base_hwservice:hwservice_manager add;
  neverallow { domain -$1 } $2:hwservice_manager add;
')

7.3 HAL属性宏 ​

hal_attribute_hwservice(hal_foo, foo_hwservice) 把 hal_foo_client 的 find 和 hal_foo_server 的 add/find 关联起来,并限制其他 domain find。它表达的是 HAL client/server 角色,不是 hwservice_contexts 的字符串映射。

源码文件:system/sepolicy/public/te_macros

text
define(`hal_attribute_hwservice', `
  allow $1_client $2:hwservice_manager find;
  add_hwservice($1_server, $2)
  build_test_only(`
    neverallow { domain -$1_client -$1_server } $2:hwservice_manager find;
  ')
')

7.4 hwbinder_use ​

服务注册者和消费者还需要能和 hwservicemanager 通信。hwbinder_use 授予对 hwservicemanager 的 binder call/transfer;它不授予具体 HAL target 的 hwservice_manager find。

源码文件:system/sepolicy/public/te_macros

text
define(`hwbinder_use', `
  allow $1 hwservicemanager:binder { call transfer };
  allow hwservicemanager $1:binder { call transfer };
')

7.5 Manager策略 ​

hwservicemanager 自己读取 hwservice_contexts,设置 hwbinder context manager,并调用 SELinux 检查接口。

源码文件:system/sepolicy/private/hwservicemanager.te

text
add_hwservice(hwservicemanager, hidl_manager_hwservice)
add_hwservice(hwservicemanager, hidl_token_hwservice)
allow hwservicemanager self:binder set_context_mgr;
allow hwservicemanager hwservice_contexts_file:file r_file_perms;
selinux_check_access(hwservicemanager)

8. Manager启动 ​

8.1 HIDL支持判断 ​

hwservicemanager 启动时先查询自身 HIDL manager descriptor 的 transport。没有 HIDL manifest transport 时设置 hwservicemanager.disabled=true 并等待 init 结束进程。

源码文件:system/hwservicemanager/service.cpp

cpp
auto transport = android::hardware::getTransport(
        ServiceManager::descriptor, serviceName);
if (transport == android::vintf::Transport::EMPTY) {
    ALOGI("HIDL is not supported on this device so hwservicemanager is not needed");
    int rc = property_set("hwservicemanager.disabled", "true");
    if (rc) LOG_ALWAYS_FATAL("Failed to set disabled");
    while (true) sleep(10);
}

8.2 ContextManager ​

服务 manager 创建后自注册、设置 requesting SID,再把 hwbinder 本地 binder 设置为 context object,最后调用 becomeContextManager()。

源码文件:system/hwservicemanager/service.cpp

cpp
sp<ServiceManager> manager = new ServiceManager();
setRequestingSid(manager, true);
if (!manager->add(serviceName, manager).withDefault(false)) {
    ALOGE("Failed to register hwservicemanager with itself.");
}

sp<IBinder> binder = toBinder<IServiceManager>(manager);
sp<BHwBinder> service = static_cast<BHwBinder*>(binder.get());
IPCThreadState::self()->setTheContextObject(service);
ProcessState::self()->becomeContextManager();

8.3 Ready状态 ​

hwservicemanager 设置 hwservicemanager.ready=true 后建立 Looper 和 hwbinder polling。HAL init rc 常以该 property 作为服务启动同步点。

源码文件:system/hwservicemanager/service.cpp

cpp
if (int rc = property_set("hwservicemanager.ready", "true"); rc != 0) {
    ALOGE("Failed to set hwservicemanager ready (error %d)", rc);
}

sp<Looper> looper = Looper::prepare(0 /* opts */);
(void)HwBinderCallback::setupTo(looper);
(void)ClientCallbackCallback::setupTo(looper, manager);

8.4 Hwbinder轮询 ​

setupTransportPolling() 将 hwbinder fd 加入 Looper;事件到达时调用 handleTransportPoll(fd),因此 service manager 的 RPC 消费发生在 Looper 回调而非独立 binder thread pool。

9. HIDL服务生命周期 ​

9.1 注册者入口 ​

典型 HIDL server 调用 registerAsService(instance),libhidl 通过 registerAsServiceInternal() 查询 VINTF transport、读取 interface chain 并提交 addWithChain()。

源码文件:system/libhidl/transport/ServiceManagement.cpp

cpp
const std::string descriptor = getDescriptor(service.get());
Return<IServiceManager1_0::Transport> transport =
        sm->getTransport(descriptor, name);
if (!transport.isOk() ||
    transport != IServiceManager1_0::Transport::HWBINDER) {
    LOG(ERROR) << "Service " << descriptor << "/" << name
               << " must be in VINTF manifest";
    return UNKNOWN_ERROR;
}

Return<void> ret = service->interfaceChain([&](const auto& chain) {
    registered = sm->addWithChain(name.c_str(), service, chain)
            .withDefault(false);
});

9.2 父接口检查 ​

hwservicemanager 对 interface chain 每一项执行 canAdd()。因此 android.hardware.audio::IDevicesFactory 的父接口 android.hidl.base::IBase 也需要对应策略;add_hwservice 宏显式包含 hidl_base_hwservice add 正是为了这一点。

9.3 查找者入口 ​

Framework 或另一个 HAL 调用 IFoo::getService(instance) 时,首先由 libhidl 查询 transport,再通过 hwservicemanager get()。canGet() 失败、服务表不存在、服务 binder 为空分别对应不同返回。

9.4 Passthrough边界 ​

当 transport 是 passthrough 而不是 HWBINDER 时,getRawServiceInternal() 可以从同进程实现获得 stub;但 registerAsServiceInternal() 在正常 Treble 路径会拒绝非 HWBINDER 注册。不要把 passthrough stub 的本地调用当成 hwservice_contexts lookup 成功。

10. 调试闭环 ​

10.1 静态产物 ​

bash
# 查看设备上实际加载的 HIDL Context 文本。
adb shell cat /system/etc/selinux/plat_hwservice_contexts
adb shell cat /vendor/etc/selinux/vendor_hwservice_contexts

# 查找接口是否有明确映射。
adb shell grep 'android.hardware.audio::IDevicesFactory' \
  /system/etc/selinux/plat_hwservice_contexts

10.2 服务表 ​

bash
# lshal 输出 HIDL manager 看到的实例和 transport。
adb shell lshal --neat | grep 'android.hardware.audio'

# 查看两个 manager 的进程 domain。
adb shell ps -AZ | grep -E 'hwservicemanager|servicemanager'

10.3 审计字段 ​

hwservicemanager 的 audit callback 使用 interface=<package::Interface> sid=<source> pid=<pid>。如果日志中没有 instance,先按 FQName 去掉 instance 后检查 hwservice_contexts key;不要直接把完整 /default 字符串加入文件。

10.4 失败分类 ​

现象先查不能据此推出
No match for interfaceFQName、flag、分区文件add/find 已授权
Missing permissions to add IBaseserver 的 hwbinder_use 与 IBase add叶接口已注册
canAdd falsetarget type、add_hwservice、neverallow服务表损坏
must be in VINTF manifestHAL manifest transportSELinux deny
get() 返回 nullcanGet、instance 表、lazy rc接口调用权限
transaction deniedhwbinder call/目标 domain policyservice_contexts 错误

11. 测试与验证 ​

11.1 Checkfc测试 ​

bash
# 选择产品并构建平台、vendor 的 HIDL contexts 检查。
source build/envsetup.sh
lunch PRODUCT-userdebug
m plat_hwservice_contexts plat_hwservice_contexts_test \
  vendor_hwservice_contexts vendor_hwservice_contexts_test

测试输入是 contexts 文本和 compiled policy;-l backend 加 hwservice_manager_type 断言能发现拼写错误、缺失 type 和错误 attribute,但不测试真实 HAL 注册。

11.2 Manager测试 ​

bash
# 构建 hwservicemanager 的 lazy/service manager device test。
m hwservicemanager_test
atest hwservicemanager_test

该测试目标来自 Android 17 system/hwservicemanager/Android.bp,主要覆盖服务表、lazy 行为和回调;它不自动替代设备上的 VINTF manifest 与 SELinux allow 组合。

11.3 Transport测试 ​

bash
# 构建 libhidl transport 相关测试(产品配置可能裁剪目标)。
m libhidl_test
atest libhidl_test

11.4 设备断言 ​

以 android.hardware.power::IPower/default 为例:

  1. hwservice_contexts 中应命中 hal_power_hwservice。
  2. HAL server domain 应拥有该 target 的 hwservice_manager add,并可 add hidl_base_hwservice。
  3. Framework client domain 应拥有 find,且有 hwbinder_use。
  4. lshal --neat 应看到该 instance,VINTF transport 应为 HWBINDER。
  5. 拿到 binder 后若调用失败,再检查目标 HAL domain 的 Binder call 和接口权限。

12. 源码导航 ​

问题首选源码关键符号
接口名映射system/sepolicy/private/hwservice_contextspackage::Interface 条目、默认项
分区构建system/sepolicy/contexts/Android.bpplat/vendor/odm_hwservice_contexts
M4与测试选择system/sepolicy/build/soong/selinux_contexts.gohwServiceFactory、-l
target typesystem/sepolicy/public/hwservice.tehwservice_manager_type、protected_hwservice
server/client规则system/sepolicy/public/te_macrosadd_hwservice、hal_attribute_hwservice、hwbinder_use
manager自身策略system/sepolicy/private/hwservicemanager.teset_context_mgr、contexts file read
lookup与MACsystem/hwservicemanager/AccessControl.cppcanAdd、canGet、checkPermission
add/get/list状态system/hwservicemanager/ServiceManager.cppaddImpl、get、list、removeService
manager启动system/hwservicemanager/service.cpptransport、ready、polling
HIDL注册入口system/libhidl/transport/ServiceManagement.cppregisterAsServiceInternal
HIDL辅助注册system/libhidl/transport/LegacySupport.cppregisterPassthroughServiceImplementation

复述一个 HIDL HAL 的完整路径时,应从 registerAsService(instance) 开始:libhidl 先用 descriptor/instance 查询 VINTF transport;确认 HWBINDER 后取得 interface chain,hwservicemanager 对每个 package::Interface 做 hwservice_contexts lookup 和 hwservice_manager:add,通过后写入 interface/instance 表并链接死亡通知。Framework getService() 先做同样的 FQName 到 target Context 的 find 检查,再查询 instance;未找到时可能设置 ctl.interface_start 启动 lazy HAL。引用返回后,hwbinder transaction 还要经过 hwbinder_use、目标 HAL domain 和接口业务权限。这样才能把“标签映射、名字服务、VINTF、lazy 生命周期和真实调用”连成一条可验证主线。