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
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:s01.2 AIDL对照
AIDL HAL 使用 /dev/binder 和 system ServiceManager,条目位于 service_contexts,格式通常是 android.hardware.foo.IFoo/default。迁移时必须同步替换 manager、设备节点、object class、target type 和 policy 宏。
| 维度 | HIDL | AIDL HAL |
|---|---|---|
| manager | hwservicemanager | servicemanager |
| 驱动 | /dev/hwbinder | /dev/binder |
| contexts | hwservice_contexts | service_contexts |
| class | hwservice_manager | service_manager |
| 注册宏 | add_hwservice | add_service |
| 服务名 | package::IInterface + instance | package.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
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:s02.2 默认标签
默认 default_android_hwservice 只用于 backend fallback,policy 明确禁止对它执行 add,避免新 HAL 忘记声明专用 type 却仍能注册。
源码文件:system/sepolicy/private/domain.te
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 静态产物
# 查看设备上实际加载的 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_contexts10.2 服务表
# 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 interface | FQName、flag、分区文件 | add/find 已授权 |
Missing permissions to add IBase | server 的 hwbinder_use 与 IBase add | 叶接口已注册 |
canAdd false | target type、add_hwservice、neverallow | 服务表损坏 |
must be in VINTF manifest | HAL manifest transport | SELinux deny |
get() 返回 null | canGet、instance 表、lazy rc | 接口调用权限 |
| transaction denied | hwbinder call/目标 domain policy | service_contexts 错误 |
11. 测试与验证
11.1 Checkfc测试
# 选择产品并构建平台、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测试
# 构建 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测试
# 构建 libhidl transport 相关测试(产品配置可能裁剪目标)。
m libhidl_test
atest libhidl_test11.4 设备断言
以 android.hardware.power::IPower/default 为例:
hwservice_contexts中应命中hal_power_hwservice。- HAL server domain 应拥有该 target 的
hwservice_manager add,并可 addhidl_base_hwservice。 - Framework client domain 应拥有
find,且有hwbinder_use。 lshal --neat应看到该 instance,VINTF transport 应为 HWBINDER。- 拿到 binder 后若调用失败,再检查目标 HAL domain 的 Binder call 和接口权限。
12. 源码导航
| 问题 | 首选源码 | 关键符号 |
|---|---|---|
| 接口名映射 | system/sepolicy/private/hwservice_contexts | package::Interface 条目、默认项 |
| 分区构建 | system/sepolicy/contexts/Android.bp | plat/vendor/odm_hwservice_contexts |
| M4与测试选择 | system/sepolicy/build/soong/selinux_contexts.go | hwServiceFactory、-l |
| target type | system/sepolicy/public/hwservice.te | hwservice_manager_type、protected_hwservice |
| server/client规则 | system/sepolicy/public/te_macros | add_hwservice、hal_attribute_hwservice、hwbinder_use |
| manager自身策略 | system/sepolicy/private/hwservicemanager.te | set_context_mgr、contexts file read |
| lookup与MAC | system/hwservicemanager/AccessControl.cpp | canAdd、canGet、checkPermission |
| add/get/list状态 | system/hwservicemanager/ServiceManager.cpp | addImpl、get、list、removeService |
| manager启动 | system/hwservicemanager/service.cpp | transport、ready、polling |
| HIDL注册入口 | system/libhidl/transport/ServiceManagement.cpp | registerAsServiceInternal |
| HIDL辅助注册 | system/libhidl/transport/LegacySupport.cpp | registerPassthroughServiceImplementation |
复述一个 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 生命周期和真实调用”连成一条可验证主线。
