You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 13:25:54