从dumpsys自定义服务来认识Android binder

  1. 问题的提出
    dumpsys是一个非常有用的命令,可以用来查看打印一些系统服务数据

    adb shell dumpsys display
    adb shell dumpsys battery

详细内容可以搜索dumpsys查看

在查看代码的时候,发现
publishBinderService(“battery”, new BinderService());

private final class BinderService extends Binder {
    @Override
    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
                != PackageManager.PERMISSION_GRANTED) {

            pw.println("Permission Denial: can't dump Battery service from from pid="
                    + Binder.getCallingPid()
                    + ", uid=" + Binder.getCallingUid());
            return;
        }

        dumpInternal(pw, args);
    }
}

猜测dumpsys 服务名
可以调用的服务是在这里设置的
publishBinderService(“battery”, new BinderService());

于是,照葫芦画瓢,写了一句
publishBinderService(“atest”, new BinderService());

预料adb shell dumpsys atest 会进行打印调用

结果呢?
编译后,手机不能开机了。
好在可以在DDMS里抓到log

01-01 00:00:57.841: E/AndroidRuntime(817): * FATAL EXCEPTION IN SYSTEM PROCESS: main
01-01 00:00:57.841: E/AndroidRuntime(817): java.lang.RuntimeException: Failed to start service com.android.server.BatteryService: onStart threw an exception
01-01 00:00:57.841: E/AndroidRuntime(817): at com.android.server.SystemServiceManager.startService(SystemServiceManager.java:119)
01-01 00:00:57.841: E/AndroidRuntime(817): at com.android.server.SystemServer.startCoreServices(SystemServer.java:621)
01-01 00:00:57.841: E/AndroidRuntime(817): at com.android.server.SystemServer.run(SystemServer.java:372)
01-01 00:00:57.841: E/AndroidRuntime(817): at com.android.server.SystemServer.main(SystemServer.java:258)
01-01 00:00:57.841: E/AndroidRuntime(817): at java.lang.reflect.Method.invoke(Native Method)
01-01 00:00:57.841: E/AndroidRuntime(817): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:849)
01-01 00:00:57.841: E/AndroidRuntime(817): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:739)
01-01 00:00:57.841: E/AndroidRuntime(817): Caused by: java.lang.SecurityException

一个字符串名称异常导致了系统不能开机,也就是说,一个字符就可以让系统不能开机,太可怕了

在publishBinderService(“atest”, new BinderService());
调用的时候进行try catch处理
结果还好,系统可以开机了
01-01 13:20:07.860: D/BatteryService(968): ================ atest ============
01-01 13:20:07.861: E/SELinux(325): avc: denied { add } for service=atest scontext=u:r:system_server:s0 tcontext=u:object_r:default_android_service:s0 tclass=service_manager
01-01 13:20:07.862: E/ServiceManager(325): add_service(‘atest’,28) uid=1000 - PERMISSION DENIED
01-01 13:20:07.862: D/BatteryService(968): ================ atest catch ============
01-01 13:20:07.862: W/System.err(968): java.lang.SecurityException
01-01 13:20:07.868: W/System.err(968): at android.os.BinderProxy.transactNative(Native Method)

还不错,打印出了具体信息,SELinux权限的问题

搜索
SELinux(325): avc: denied { add } for service
在stackoverflow上看到一种解决方案
To file:
android-dev\external\sepolicy\service.te
Add:
type mytest_service, system_api_service, system_server_service, service_manager_type;
To file:
android-dev\external\sepolicy\service_contexts
Add:
mytestservice u:object_r:mytest_service:s0
where mytestservice your name service

修改android/external/sepolicy 里的文件

修改后编译,还是抛异常

查找代码
find . -name *.c|xargs grep ’ PERMISSION DENIED’
./frameworks/native/cmds/servicemanager/service_manager.c: ALOGE(“add_service(‘%s’,%x) uid=%d - PERMISSION DENIED\n”,
./frameworks/native/cmds/servicemanager/service_manager.c: ALOGE(“list_service() uid=%d - PERMISSION DENIED\n”,

修改了te文件还是有异常,??
这个不清楚是不是编译的问题,现在决定跳过赋权,对服务调用进行测试
修改./frameworks/native/cmds/servicemanager/service_manager.c
int do_add_service(struct binder_state *bs,
const uint16_t *s, size_t len,
uint32_t handle, uid_t uid, int allow_isolated,
pid_t spid)
{
struct svcinfo *si;

//ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle,
//        allow_isolated ? "allow_isolated" : "!allow_isolated", uid);

if (!handle || (len == 0) || (len > 127))
    return -1;

if (!svc_can_register(s, len, spid)) {
    ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
         str8(s, len), handle, uid);

ALOGE(“=======test go =======”);
// return -1;
}

就可以调用自定义服务了
dumpsysatestdumpsysatestBinderService2dumpcalled====================


  1. ap调用测试
    adb shell dumpsys atest
    可以调用atest服务的dump方法

再写个ap进行测试
Binder aObject;
try {
aObject = (Binder)getSystemService(“atest”);
int id = aObject.getCallingPid();
System.out.println(“Pid = ” + id);
Log.d(“test614”, “Pid = ” + id);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}

Log
01-05 09:32:35.122: D/test614(801): Pid = 801

这样调用的都是binder里的接口方法,如果要自定义方法,aidl就出场了
详细使用可以查看这位达人的系列blog
http://www.cloudchou.com/android/post-447.html
写的非常好

  1. 总结
    这里通过添加一个自定义服务,了解了addService的一些信息。

binder是用来进行进程间通信的,和ICE通信机制类似。
采用一些数据传送方法,把client和server关联交互起来

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值