没有addService的C ++ Binder()

时间:2014-03-17 16:37:50

标签: android-ndk android-binder

是否可以使用C ++ Binder API在两个非特权进程之间进行通信?

我找到的所有示例(例如https://github.com/mcr/Android-HelloWorldService)都依赖于通过ServiceManager->addService()注册服务,这会在非根电话上执行时抛出以下错误:

E/ServiceManager﹕ add_service('my.test.service',0x48) uid=2000 - PERMISSION DENIED

1 个答案:

答案 0 :(得分:2)

在文件框架/ native / cmds / servicemanager / service_manager.c中的AOSP(Android开源项目)内部 你可以找到以下方法:

int svc_can_register(uid_t uid, const uint16_t *name)
{
    size_t n;

    if ((uid == 0) || (uid == AID_SYSTEM))
        return 1;

    for (n = 0; n < sizeof(allowed) / sizeof(allowed[0]); n++)
        if ((uid == allowed[n].uid) && str16eq(name, allowed[n].name))
            return 1;

    return 0;
}

以上一点:

/* TODO:
 * These should come from a config file or perhaps be
 * based on some namespace rules of some sort (media
 * uid can register media.*, etc)
 */
static struct {
    uid_t uid;
    const char *name;
} allowed[] = {
    { AID_MEDIA, "media.audio_flinger" },
    { AID_MEDIA, "media.log" },
    { AID_MEDIA, "media.player" },
    { AID_MEDIA, "media.camera" },
    { AID_MEDIA, "media.audio_policy" },
    { AID_DRM,   "drm.drmManager" },
    { AID_NFC,   "nfc" },
    { AID_BLUETOOTH, "bluetooth" },
    { AID_RADIO, "radio.phone" },
    { AID_RADIO, "radio.sms" },
    { AID_RADIO, "radio.phonesubinfo" },
    { AID_RADIO, "radio.simphonebook" },
/* TODO: remove after phone services are updated: */
    { AID_RADIO, "phone" },
    { AID_RADIO, "sip" },
    { AID_RADIO, "isms" },
    { AID_RADIO, "iphonesubinfo" },
    { AID_RADIO, "simphonebook" },
    { AID_MEDIA, "common_time.clock" },
    { AID_MEDIA, "common_time.config" },
    { AID_KEYSTORE, "android.security.keystore" },
};

并进一步向下:

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

结论:/ system / bin / servicemanager中的系统二进制文件不允许它。 (出于安全原因) 可能的解决方案:

  • 杀死并重用PID和列出的服务名称
  • 重新编译您自己的servicemanager二进制文件并使用此文件
  • 将您的代码注入此二进制文件,以允许所有人
  • 更改PID servicemanager读取(更改ioctl响应servicemanager获取binder.h(同一目录))
  • 或者只是在具有root权限的二进制文件中启动服务器。客户端可以在没有root的情况下连接,但服务器需要它。