如何通过AIDL正确连接用户应用与HAL C++服务?
问题:通过AIDL连接HAL C++服务与用户应用失败
已将SELinux设置为permissive模式,仍无法成功建立连接。
接口定义
基础AIDL接口代码:
package org.mwe.service; interface IDummy { String simple(); String complex(in byte[] from, out byte[] to, in String original, in int numeric); }
HAL服务配置与状态
参考Vibrator AIDL实现完成接口与默认实现开发,服务rc配置如下:
service mwe_dummy.service /vendor/bin/org.mwe.service.dummy-default myprefix class hal user root group root interface aidl org.mwe.service.IDummy/default
服务状态验证
执行命令确认服务已运行:
adb shell service check org.mwe.service.IDummy/default # 输出:Service org.mwe.service.IDummy/default: found
但直接调用方法无有效返回:
adb shell service call org.mwe.service.IDummy/default 1 # 输出:Result: Parcel(NULL)
应用连接尝试(两种方式均失败)
1. 通过Intent连接
简化后的Kotlin连接代码:
class MainActivity : AppCompatActivity() { private var service: IDummy? = null private var isServiceBound = false private val connection = object : ServiceConnection { override fun onServiceConnected(className: ComponentName, service: IBinder) { service = IDummy.Stub.asInterface(service) isServiceBound = true } override fun onServiceDisconnected(className: ComponentName) { service = null isServiceBound = false } } private fun initConnectionIntent() { if (isServiceBound) return Intent(IDummy::class.java.name).apply { setPackage(getPackageName()) }.let { bindService(it, connection, Context.BIND_AUTO_CREATE) Log.d(TAG, "binding") } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) initConnectionIntent() } }
尝试多种Intent构造方式:
Intent(IDummy::class.java.name).apply { setPackage(getPackageName()) } // 或 Intent(IDummy::class.java.name).apply { setPackage(getPackageName()) setAction("org.mwe.service") // 或 Intent().apply { component = ComponentName("org.mwe.service.IDummy", "default") }
日志均提示服务未找到:
ActivityManager: Unable to start service Intent { ... } U=0: not found
2. 直接连接(反射调用ServiceManager)
通过反射访问隐藏API的连接代码:
class MainActivity : AppCompatActivity() { private var service: IDummy? = null private fun initConnectionDirect() { val checkService = Class.forName("android.os.ServiceManager") .getMethod("checkService", String::class.java) val bdr = checkService.invoke(null, "org.mwe.service.IDummy/default")!! as IBinder service = IDummy.Stub.asInterface(bdr) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) initConnectionDirect() } }
能找到服务,但调用方法时崩溃,错误日志:
I org.mwe.app: type=1400 audit(0.0:579): avc: denied { call } for scontext=u:r:untrusted_app:s0:c117,c256,c512,c768 tcontext=u:r:mwe_dummy_default:s0 tclass=binder permissive=1 app=org.mwe.app E AndroidRuntime: FATAL EXCEPTION: main E AndroidRuntime: Process: org.mwe.app, PID: 3505 E AndroidRuntime: java.lang.IllegalArgumentException E AndroidRuntime: at android.os.BinderProxy.transactNative(Native Method) E AndroidRuntime: at android.os.BinderProxy.transact(BinderProxy.java:573) E AndroidRuntime: at org.mwe.service.IDummy$Stub$Proxy.simple(IDummy.java:123) ...(省略后续栈跟踪内容)
解决方案
一、Intent连接失败的核心原因
Intent绑定仅适用于Android应用层Service,你的HAL服务是注册到ServiceManager的系统级服务,完全不支持Intent连接方式,直接放弃该方案即可。
二、直接连接的问题修复
1. SELinux权限补充
尽管已设置permissive模式,但audit日志仍显示权限拒绝,需添加SELinux规则允许应用调用HAL服务:
- 在
/vendor/etc/selinux/目录下新增规则文件(如vendor_mwe_dummy.te):allow untrusted_app mwe_dummy_default:binder call; allow mwe_dummy_default untrusted_app:binder call; - 重新编译SELinux策略并推送至设备,测试阶段可临时执行
setenforce 0确保SELinux完全关闭。
2. HAL服务AIDL实现修复
service call返回Parcel(NULL)说明服务的onTransact方法存在问题:
- 检查C++服务中方法请求码的处理逻辑,确保对应
TRANSACTION_simple常量的分支正确写入返回值:status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override { switch(code) { case TRANSACTION_simple: { CHECK_INTERFACE(IDummy, data, reply); std::string result = simple(); reply->writeString16(String16(result.c_str())); return OK; } // 其他方法处理分支 default: return BnInterface<IDummy>::onTransact(code, data, reply, flags); } }
3. 应用层调用优化
反射ServiceManager的方式可行,但需优化调用逻辑:
- 在
AndroidManifest.xml中添加必要权限(若为系统应用可使用sharedUserId,第三方应用需依赖公开权限):<uses-permission android:name="android.permission.INTERNET" /> <!-- 示例,根据实际需求调整 --> - 调用方法时捕获异常避免崩溃:
try { service?.simple()?.let { Log.d(TAG, "调用结果: $it") } } catch (e: Exception) { Log.e(TAG, "调用失败", e) }
4. 服务RC配置修正
调整rc文件中的服务名称格式(避免带.service后缀):
service mwe_dummy /vendor/bin/org.mwe.service.dummy-default myprefix class hal user root group root interface aidl org.mwe.service.IDummy/default
重启服务生效:
adb shell stop mwe_dummy && adb shell start mwe_dummy
内容的提问来源于stack exchange,提问作者Sergey
相关产品推荐
相关产品推荐

