Android 15 ServiceManager与Binder服务注册深度解析

引言

在上一篇文章中,我们深入分析了Binder驱动的内核机制。但是有一个核心问题还没有回答:Client如何知道Server的Binder句柄?

想象一下,你想打电话给朋友,但你不知道他的电话号码。这时你需要查电话簿(Yellow Pages)。在Android系统中,ServiceManager就是这本"电话簿"------它维护了系统中所有服务的注册表,提供服务的注册和查询功能。

没有ServiceManager,Binder IPC就无法工作。所有的系统服务(如ActivityManagerService、WindowManagerService)都需要先向ServiceManager注册,客户端才能通过ServiceManager查询到它们的Binder句柄,进而进行跨进程调用。

本文将深入Android 15源码,剖析ServiceManager的工作机制:

你将学到:

  • ServiceManager的启动流程与特殊性
  • 服务注册(addService)的完整实现
  • 服务查询(getService)的查找机制
  • 死亡通知(DeathRecipient)的工作原理
  • VINTF声明验证与安全机制
  • Android 15的新特性与优化

ServiceManager的特殊性

在深入代码前,我们先理解ServiceManager的几个特殊之处。

1. Handle 0:ServiceManager的唯一标识

在Binder系统中,ServiceManager有一个硬编码的句柄值:0

cpp 复制代码
// ProcessState.cpp
enum {
    CONTEXT_MGR_HANDLE = 0  // ServiceManager的句柄固定为0
};

这是一个"先有鸡还是先有蛋"的问题:

  • 所有服务都需要向ServiceManager注册
  • 但客户端如何获取ServiceManager的句柄?

解决方案 :将ServiceManager的句柄硬编码为0。这样,所有进程都知道,要与ServiceManager通信,只需要使用handle=0。

💡 设计巧思: Handle 0是Binder协议的特殊约定,在Binder驱动初始化时就预留了这个位置给ServiceManager。这是一个优雅的引导机制(Bootstrap)。

2. Context Manager:成为Binder上下文管理者

ServiceManager不仅仅是一个普通服务,它还是Binder上下文管理者(Context Manager)

cpp 复制代码
// main.cpp (Android 15)
int main(int argc, char** argv) {
    const char* driver = argc == 2 ? argv[1] : "/dev/binder";

    sp<ProcessState> ps = ProcessState::initWithDriver(driver);

    sp<ServiceManager> manager = sp<ServiceManager>::make(std::make_unique<Access>());

    // 关键步骤1:将自己设置为Context Object
    IPCThreadState::self()->setTheContextObject(manager);

    // 关键步骤2:向驱动注册为Context Manager
    if (!ps->becomeContextManager()) {
        LOG(FATAL) << "Could not become context manager";
    }

    // 进入消息循环
    sp<Looper> looper = Looper::prepare(false);
    while(true) {
        looper->pollAll(-1);
    }
}

becomeContextManager做了什么?

cpp 复制代码
// ProcessState.cpp
bool ProcessState::becomeContextManager() {
    // 通过ioctl告诉驱动:"我是ServiceManager"
    flat_binder_object obj{
        .flags = FLAT_BINDER_FLAG_ACCEPTS_FDS,
    };

    binder_write_read bwr{};
    binder_transaction_data tr{};
    tr.target.handle = 0;
    tr.code = BINDER_SET_CONTEXT_MGR;

    // 驱动会将handle 0绑定到当前进程
    int result = ioctl(mDriverFD, BINDER_WRITE_READ, &bwr);
    return result == 0;
}

驱动收到BINDER_SET_CONTEXT_MGR命令后,会:

  1. 检查调用进程是否有权限(需要root或system权限)
  2. 将handle 0永久绑定到ServiceManager进程
  3. 确保只有一个进程能成为Context Manager

3. 单例且唯一

整个Android系统中,只能有一个ServiceManager实例。它由init进程在系统启动早期启动,并一直运行直到系统关闭。

bash 复制代码
# init.rc中的ServiceManager启动配置
service servicemanager /system/bin/servicemanager
    class core animation
    user system
    group system readproc
    critical
    onrestart restart apexd
    onrestart restart audioserver
    # ...重启时需要重启依赖的服务

critical标志:ServiceManager被标记为关键服务,如果它崩溃,系统会自动重启进入恢复模式。

ServiceManager架构概览

在深入启动流程前,先看看ServiceManager的整体架构:

图1: ServiceManager架构 - SystemServer注册服务,Client查询服务,ServiceManager维护服务注册表

ServiceManager启动流程

让我们跟踪ServiceManager从启动到就绪的完整流程。

1. main函数:初始化与准备

cpp 复制代码
// main.cpp (Android 15)
int main(int argc, char** argv) {
    // 1. 初始化日志
    android::base::InitLogging(argv, android::base::KernelLogger);

    const char* driver = argc == 2 ? argv[1] : "/dev/binder";

    #if !defined(VENDORSERVICEMANAGER)
    android::register_perfetto_te_categories();  // Perfetto追踪
    #endif

    LOG(INFO) << "Starting sm instance on " << driver;

    // 2. 初始化ProcessState
    sp<ProcessState> ps = ProcessState::initWithDriver(driver);
    ps->setThreadPoolMaxThreadCount(0);  // 不使用线程池,单线程处理
    ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);

    // 3. 禁用后台调度,确保高优先级
    IPCThreadState::self()->disableBackgroundScheduling(true);

    // 4. 创建ServiceManager实例
    sp<ServiceManager> manager = sp<ServiceManager>::make(std::make_unique<Access>());

    // 5. 自己也要注册为服务(服务的服务)
    if (!manager->addService("manager", manager,
                            false /*allowIsolated*/,
                            IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
        LOG(ERROR) << "Could not self register servicemanager";
    }

    // 6. 成为Context Manager
    IPCThreadState::self()->setTheContextObject(manager);
    if (!ps->becomeContextManager()) {
        LOG(FATAL) << "Could not become context manager";
    }

    // 7. 设置事件循环
    sp<Looper> looper = Looper::prepare(false);

    sp<BinderCallback> binderCallback = BinderCallback::setupTo(looper);
    ClientCallbackCallback::setupTo(looper, manager, binderCallback);

    // 8. 设置ready属性,通知其他进程可以使用了
    #ifndef VENDORSERVICEMANAGER
    if (!SetProperty("servicemanager.ready", "true")) {
        LOG(ERROR) << "Failed to set servicemanager ready property";
    }
    #endif

    // 9. 进入消息循环,永不退出
    while(true) {
        looper->pollAll(-1);  // 阻塞等待Binder事务
    }

    return EXIT_FAILURE;  // 不应该到达这里
}

关键点解析:

  1. 单线程模式 :setThreadPoolMaxThreadCount(0)表示不使用Binder线程池,只用主线程处理,简化并发控制
  2. 只接受单向调用 :FATAL_IF_NOT_ONEWAY确保所有对ServiceManager的调用都是异步的,防止死锁
  3. 高优先级 :disableBackgroundScheduling(true)确保ServiceManager不会被降优先级
  4. 自我注册:ServiceManager也将自己注册为名为"manager"的服务,供特殊情况使用
  5. Ready属性:通过系统属性通知其他等待的进程

2. Looper事件循环

ServiceManager使用Looper而不是传统的Binder线程池:

cpp 复制代码
// BinderCallback:处理Binder事件
class BinderCallback : public LooperCallback {
public:
    static sp<BinderCallback> setupTo(const sp<Looper>& looper) {
        sp<BinderCallback> cb = sp<BinderCallback>::make();
        cb->mLooper = looper;

        // 将Binder驱动的文件描述符加入Looper监听
        IPCThreadState::self()->setupPolling(&cb->mBinderFd);

        int ret = looper->addFd(cb->mBinderFd,
                               Looper::POLL_CALLBACK,
                               Looper::EVENT_INPUT,
                               cb, nullptr);
        LOG_ALWAYS_FATAL_IF(ret != 1, "Failed to add binder FD to Looper");

        return cb;
    }

    // 当Binder驱动有数据时,此函数被调用
    int handleEvent(int fd, int events, void* data) override {
        IPCThreadState::self()->handlePolledCommands();
        return 1;  // 继续接收回调
    }

private:
    sp<Looper> mLooper;
    int mBinderFd = -1;
};

为什么用Looper而不是线程池?

  • 简单:单线程模型,无需考虑并发同步
  • 可控:ServiceManager需要精确控制事务处理顺序
  • 高效:避免线程切换开销
  • 可扩展:可以同时监听其他事件(如定时器)

服务注册:addService详解

当系统服务(如AMS)想要注册时,会调用addService。让我们看完整流程。

1. 客户端调用

cpp 复制代码
// SystemServer.java (Java层)
ServiceManager.addService(Context.ACTIVITY_SERVICE, activityManager);

// 最终调用到Native层
// IServiceManager.aidl
interface IServiceManager {
    void addService(String name, IBinder service,
                   boolean allowIsolated, int dumpPriority);
}

2. ServiceManager实现

cpp 复制代码
// ServiceManager.cpp (Android 15)
Status ServiceManager::addService(const std::string& name,
                                  const sp<IBinder>& binder,
                                  bool allowIsolated,
                                  int32_t dumpPriority) {
    SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_PROTO_FIELDS(
            PERFETTO_TE_PROTO_FIELD_CSTR(kProtoServiceName, name.c_str())));

    // 1. 获取调用者上下文(UID/PID/SID)
    auto ctx = mAccess->getCallingContext();

    // 2. 权限检查:App UID不能注册服务
    if (multiuser_get_app_id(ctx.uid) >= AID_APP) {
        return Status::fromExceptionCode(Status::EX_SECURITY,
                                        "App UIDs cannot add services.");
    }

    // 3. 检查是否有权限注册此服务
    std::optional<std::string> accessorName;
    if (auto status = canAddService(ctx, name, &accessorName); !status.isOk()) {
        return status;
    }

    // 4. 基本参数检查
    if (binder == nullptr) {
        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Null binder.");
    }

    if (!isValidServiceName(name)) {
        ALOGE("%s Invalid service name: %s", ctx.toDebugString().c_str(), name.c_str());
        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT,
                                        "Invalid service name.");
    }

    // 5. VINTF声明检查(Android 15重要机制)
    #ifndef VENDORSERVICEMANAGER
    if (!meetsDeclarationRequirements(ctx, binder, name)) {
        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT,
                                        "VINTF declaration error.");
    }
    #endif

    // 6. 检查dump优先级标志
    if ((dumpPriority & DUMP_FLAG_PRIORITY_ALL) == 0) {
        ALOGW("%s Dump flag priority is not set when adding %s",
              ctx.toDebugString().c_str(), name.c_str());
    }

    // 7. 注册死亡通知(关键机制!)
    if (binder->remoteBinder() != nullptr &&
        binder->linkToDeath(sp<ServiceManager>::fromExisting(this)) != OK) {
        ALOGE("%s Could not linkToDeath when adding %s",
              ctx.toDebugString().c_str(), name.c_str());
        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE,
                                        "Couldn't linkToDeath.");
    }

    // 8. 检查是否已存在同名服务
    auto it = mNameToService.find(name);
    bool prevClients = false;
    if (it != mNameToService.end()) {
        const Service& existing = it->second;
        prevClients = existing.hasClients;

        // 警告:不同UID/SID注册相同服务名
        if (existing.ctx.uid != ctx.uid) {
            ALOGW("Service '%s' originally registered from UID %u "
                  "but now from UID %u. Multiple instances?",
                  name.c_str(), existing.ctx.uid, ctx.uid);
        }

        if (existing.ctx.sid != ctx.sid) {
            ALOGW("Service '%s' originally registered from SID %s "
                  "but now from SID %s. Multiple instances?",
                  name.c_str(), existing.ctx.sid.c_str(), ctx.sid.c_str());
        }
    }

    // 9. 添加/更新服务到注册表
    mNameToService[name] = Service{
        .binder = binder,
        .allowIsolated = allowIsolated,
        .dumpPriority = dumpPriority,
        .hasClients = prevClients,
        .guaranteeClient = false,
        .ctx = ctx,
    };

    // 10. 通知等待此服务的客户端
    if (auto it = mNameToRegistrationCallback.find(name);
        it != mNameToRegistrationCallback.end()) {

        mNameToService[name].guaranteeClient = true;
        CHECK(handleServiceClientCallback(2, name, false));

        for (const sp<IServiceCallback>& cb : it->second) {
            cb->onRegistration(name, binder);  // 回调通知
        }
    }

    return Status::ok();
}

核心数据结构:

cpp 复制代码
// ServiceManager.h
struct Service {
    sp<IBinder> binder;           // 服务的Binder对象
    bool allowIsolated;           // 是否允许隔离进程访问
    int32_t dumpPriority;         // dump优先级
    bool hasClients;              // 是否有客户端
    bool guaranteeClient;         // 保证有客户端
    Access::CallingContext ctx;   // 注册者的上下文信息
};

// 服务注册表:服务名 -> Service
std::map<std::string, Service> mNameToService;

// 注册回调表:服务名 -> 回调列表
std::map<std::string, std::vector<sp<IServiceCallback>>> mNameToRegistrationCallback;

3. VINTF声明验证(Android 15安全机制)

Android 15强化了VINTF(Vendor Interface)声明验证:

cpp 复制代码
static bool meetsDeclarationRequirements(const Access::CallingContext& ctx,
                                        const sp<IBinder>& binder,
                                        const std::string& name) {
    // 检查Binder是否要求VINTF声明
    if (!Stability::requiresVintfDeclaration(binder)) {
        return true;  // 不需要声明,通过
    }

    // 检查是否在VINTF manifest中声明
    return isVintfDeclared(ctx, name);
}

static bool isVintfDeclared(const Access::CallingContext& ctx,
                           const std::string& name) {
    // 解析服务名(如 android.hardware.foo.IFoo/default)
    AidlName aname;
    if (!AidlName::fill(name, &aname, true)) return false;

    // 遍历所有manifest(device/framework)
    bool found = forEachManifest([&](const ManifestWithDescription& mwd) {
        if (mwd.manifest->hasAidlInstance(aname.package,
                                         aname.iface,
                                         aname.instance)) {
            ALOGI("%s Found %s in %s VINTF manifest.",
                  ctx.toDebugString().c_str(),
                  name.c_str(),
                  mwd.description);
            return true;
        }
        return false;
    });

    if (!found) {
        ALOGI("%s Could not find %s in the VINTF manifest.",
              ctx.toDebugString().c_str(), name.c_str());
    }

    return found;
}

VINTF的作用:

  • 明确声明HAL服务的接口版本
  • 防止未声明的服务注册(提高安全性)
  • 支持跨版本兼容性检查
  • 便于系统升级时的兼容性管理

服务查询:getService详解

客户端如何查询已注册的服务?

1. 客户端调用

cpp 复制代码
// Java层
IBinder binder = ServiceManager.getService(Context.ACTIVITY_SERVICE);

// Native层
sp<IBinder> binder = defaultServiceManager()->getService(String16("activity"));

2. ServiceManager实现

cpp 复制代码
// ServiceManager.cpp (Android 15)
Status ServiceManager::getService(const std::string& name, sp<IBinder>* outBinder) {
    SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_PROTO_FIELDS(
            PERFETTO_TE_PROTO_FIELD_CSTR(kProtoServiceName, name.c_str())));

    *outBinder = tryGetBinder(name, true);
    // 为了向后兼容,总是返回OK(即使服务不存在)
    return Status::ok();
}

sp<IBinder> ServiceManager::tryGetBinder(const std::string& name,
                                         bool startIfNotFound) {
    auto ctx = mAccess->getCallingContext();

    // 1. 权限检查:调用者是否有权限访问此服务
    if (!mAccess->canFind(ctx, name)) {
        ALOGE("%s Cannot find %s", ctx.toDebugString().c_str(), name.c_str());
        return nullptr;
    }

    // 2. 查询服务注册表
    auto it = mNameToService.find(name);
    if (it == mNameToService.end()) {
        ALOGI("%s Service %s not found", ctx.toDebugString().c_str(), name.c_str());
        return nullptr;
    }

    const Service& service = it->second;

    // 3. 检查隔离进程访问权限
    if (!service.allowIsolated && is_multiuser_uid_isolated(ctx.uid)) {
        ALOGW("%s Isolated process cannot access %s",
              ctx.toDebugString().c_str(), name.c_str());
        return nullptr;
    }

    // 4. 记录客户端信息
    if (!service.guaranteeClient) {
        mNameToService[name].guaranteeClient = true;
        mNameToService[name].hasClients = true;
    }

    // 5. 返回服务的Binder对象
    return service.binder;
}

checkService vs getService:

cpp 复制代码
// checkService:仅检查服务是否存在,不启动
Status ServiceManager::checkService(const std::string& name,
                                   os::Service* outService) {
    *outService = tryGetService(name, false);  // startIfNotFound = false
    return Status::ok();
}

// getService:如果服务支持懒启动,会尝试启动它
Status ServiceManager::getService(const std::string& name,
                                 sp<IBinder>* outBinder) {
    *outBinder = tryGetBinder(name, true);  // startIfNotFound = true
    return Status::ok();
}

3. 权限控制:Access类

cpp 复制代码
// Access.cpp
bool Access::canFind(const CallingContext& ctx, const std::string& name) {
    // 1. 检查SELinux上下文
    if (!checkSelinuxAccess(ctx, name, "find")) {
        return false;
    }

    // 2. 检查特殊服务的访问控制列表
    if (isRestrictedService(name)) {
        return isAllowedUser(ctx.uid, name);
    }

    return true;
}

bool Access::canAdd(const CallingContext& ctx, const std::string& name) {
    // 只有system/root用户可以注册服务
    if (ctx.uid != AID_SYSTEM && ctx.uid != AID_ROOT) {
        return false;
    }

    // 检查SELinux
    return checkSelinuxAccess(ctx, name, "add");
}

CallingContext结构:

cpp 复制代码
struct CallingContext {
    pid_t pid;          // 进程ID
    uid_t uid;          // 用户ID
    std::string sid;    // SELinux SID
    int debugPid;       // 调试用PID

    // 从IPCThreadState获取
    static CallingContext fromBinder() {
        IPCThreadState* ipc = IPCThreadState::self();
        return CallingContext{
            .pid = ipc->getCallingPid(),
            .uid = ipc->getCallingUid(),
            .sid = getSeContext(ipc->getCallingPid()),
            .debugPid = ipc->getCallingPid(),
        };
    }
};

死亡通知:DeathRecipient机制

当服务进程异常退出时,ServiceManager如何感知并清理?

1. linkToDeath:注册死亡监听

addService时,ServiceManager会注册死亡通知:

cpp 复制代码
// addService中
if (binder->linkToDeath(sp<ServiceManager>::fromExisting(this)) != OK) {
    ALOGE("Could not linkToDeath when adding %s", name.c_str());
    return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE,
                                    "Couldn't linkToDeath.");
}

2. binderDied:处理死亡通知

cpp 复制代码
// ServiceManager.cpp
void ServiceManager::binderDied(const wp<IBinder>& who) {
    // 遍历所有服务,找到死亡的那个
    for (auto it = mNameToService.begin(); it != mNameToService.end(); ) {
        if (it->second.binder == who.promote()) {
            ALOGI("Service '%s' died (binder %p)",
                  it->first.c_str(), who.unsafe_get());

            // 通知等待的客户端
            if (auto cbIt = mNameToRegistrationCallback.find(it->first);
                cbIt != mNameToRegistrationCallback.end()) {
                for (const sp<IServiceCallback>& cb : cbIt->second) {
                    // 通知服务已死亡
                    cb->onRegistration(it->first, nullptr);
                }
            }

            // 从注册表移除
            it = mNameToService.erase(it);
        } else {
            ++it;
        }
    }
}

Binder驱动的死亡通知机制:

3. 客户端注册回调

客户端也可以监听服务的注册/死亡:

cpp 复制代码
// IServiceManager.aidl
interface IServiceManager {
    void registerForNotifications(String name, IServiceCallback callback);
}

// 客户端使用
serviceManager->registerForNotifications("activity", new ServiceCallback() {
    @Override
    public void onRegistration(String name, IBinder service) {
        if (service == null) {
            // 服务死亡
            Log.w(TAG, "Service " + name + " died!");
        } else {
            // 服务注册/重启
            Log.i(TAG, "Service " + name + " registered!");
        }
    }
});

服务列表与dump

ServiceManager还提供了服务列表和dump功能。

1. listServices:列出所有服务

cpp 复制代码
Status ServiceManager::listServices(int32_t dumpPriority,
                                   std::vector<std::string>* outList) {
    // 权限检查
    if (!mAccess->canList(mAccess->getCallingContext())) {
        return Status::fromExceptionCode(Status::EX_SECURITY,
                                        "Cannot list services.");
    }

    // 按dump优先级过滤
    for (const auto& [name, service] : mNameToService) {
        if (dumpPriority == IServiceManager::DUMP_FLAG_PRIORITY_ALL ||
            (service.dumpPriority & dumpPriority) != 0) {
            outList->push_back(name);
        }
    }

    return Status::ok();
}

2. dump:导出服务信息

bash 复制代码
# 通过dumpsys查看ServiceManager状态
adb shell dumpsys servicemanager

# 输出示例
Registered services:
  activity: [android.app.IActivityManager]
    UID: 1000 (system)
    PID: 1234
    Clients: 15
    DumpPriority: CRITICAL|HIGH|NORMAL

  window: [android.view.IWindowManager]
    UID: 1000 (system)
    PID: 1234
    Clients: 8
    DumpPriority: CRITICAL|HIGH

Total services: 87
Active clients: 156

Android 15的新特性

1. Perfetto追踪集成

Android 15深度集成了Perfetto追踪:

cpp 复制代码
// 每个关键函数都有追踪宏
Status ServiceManager::addService(const std::string& name, ...) {
    SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_PROTO_FIELDS(
            PERFETTO_TE_PROTO_FIELD_CSTR(kProtoServiceName, name.c_str())));

    // ... 函数实现
}

使用Perfetto可以精确追踪ServiceManager的性能:

bash 复制代码
# 抓取ServiceManager的trace
perfetto -c trace_config.pb -o trace.pb

# 在UI中查看service注册/查询的耗时

2. VINTF强制验证

Android 15强制HAL服务必须在VINTF manifest中声明:

xml 复制代码
<!-- device/vendor/manifest.xml -->
<hal format="aidl">
    <name>android.hardware.power</name>
    <interface>
        <name>IPower</name>
        <instance>default</instance>
    </interface>
    <fqname>@1.0::IPower/default</fqname>
</hal>

未声明的服务将无法注册:

cpp 复制代码
if (!meetsDeclarationRequirements(ctx, binder, name)) {
    return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT,
                                    "VINTF declaration error.");
}

3. Updatable APEX支持

支持通过APEX更新HAL服务:

cpp 复制代码
static std::optional<std::string> getVintfUpdatableApex(const std::string& name) {
    // 查询服务是否可以通过APEX更新
    forEachManifest([&](const ManifestWithDescription& mwd) {
        // 检查manifest中的updatableViaApex字段
        if (manifestInstance.updatableViaApex().has_value()) {
            return manifestInstance.updatableViaApex().value();
        }
    });
}

4. 客户端回调优化

Android 15优化了客户端回调机制,使用定时器定期检查:

cpp 复制代码
class ClientCallbackCallback : public LooperCallback {
public:
    static sp<ClientCallbackCallback> setupTo(...) {
        // 创建定时器,每5秒触发一次
        int fdTimer = timerfd_create(CLOCK_MONOTONIC, 0);

        itimerspec timespec {
            .it_interval = { .tv_sec = 5, .tv_nsec = 0 },
            .it_value = { .tv_sec = 5, .tv_nsec = 0 },
        };

        timerfd_settime(fdTimer, 0, &timespec, nullptr);
        looper->addFd(fdTimer, Looper::POLL_CALLBACK, Looper::EVENT_INPUT, cb, nullptr);

        return cb;
    }

    int handleEvent(int fd, int events, void* data) override {
        // 定期处理客户端回调
        mManager->handleClientCallbacks();
        mBinderCallback->repoll();  // b/316829336修复
        return 1;
    }
};

常见问题

Q1: 为什么ServiceManager的handle必须是0?

A: 这是一个引导问题(Bootstrap Problem)。要获取任何服务,都需要先查询ServiceManager,但要查询ServiceManager,又需要知道它的handle。通过硬编码handle=0,所有进程都知道如何找到ServiceManager,从而启动整个服务发现链条。

Q2: 如果ServiceManager崩溃会怎样?

A : ServiceManager被标记为critical服务:

  • init会立即重启ServiceManager
  • 所有依赖的服务(如audioserver、mediaserver)也会重启
  • 如果重启失败,系统进入恢复模式
bash 复制代码
# init.rc
service servicemanager /system/bin/servicemanager
    critical  # 崩溃导致系统重启
    onrestart restart audioserver
    onrestart restart mediaserver
    # ...

Q3: App为什么不能注册系统服务?

A: 安全考虑:

cpp 复制代码
// App UID检查
if (multiuser_get_app_id(ctx.uid) >= AID_APP) {
    return Status::fromExceptionCode(Status::EX_SECURITY,
                                    "App UIDs cannot add services.");
}

只有system UID(1000)或root UID(0)才能注册服务,防止App伪造系统服务。

Q4: getService和checkService有什么区别?

A:

  • getService: 如果服务不存在但支持懒启动,会尝试启动服务,可能阻塞
  • checkService: 仅检查服务是否已注册,不会启动服务,不阻塞
cpp 复制代码
// 需要确保服务存在时使用getService
sp<IBinder> binder = sm->getService(String16("activity"));

// 仅检查状态时使用checkService(例如做UI展示)
sp<IBinder> binder = sm->checkService(String16("activity"));
if (binder == nullptr) {
    showServiceUnavailable();
}

Q5: 死亡通知是同步还是异步的?

A : 异步。当服务进程死亡时:

  1. Binder驱动检测到进程退出
  2. 驱动向ServiceManager发送BR_DEAD_BINDER命令
  3. ServiceManager在下次处理Binder命令时调用binderDied()
  4. 清理是异步的,有一定延迟

实战:追踪服务注册

1. 查看已注册的服务

bash 复制代码
# 列出所有服务
adb shell service list

# 输出示例
Found 87 services:
0    phone: [com.android.internal.telephony.ITelephony]
1    isms: [com.android.internal.telephony.ISms]
2    activity: [android.app.IActivityManager]
3    package: [android.content.pm.IPackageManager]
...

2. dumpsys查看服务详情

bash 复制代码
# 查看ServiceManager状态
adb shell dumpsys servicemanager

# 查看特定服务
adb shell dumpsys activity

# 查看服务的客户端连接
adb shell lsof | grep binder

3. 使用Systrace追踪

bash 复制代码
# 抓取包含ServiceManager的trace
systrace.py -t 10 binder sm -o trace.html

# 在Chrome中打开trace.html,搜索:
# - "ServiceManager::addService"
# - "ServiceManager::getService"

4. 监控服务注册

bash 复制代码
# 实时监控服务注册
adb logcat | grep "ServiceManager"

# 过滤特定服务
adb logcat | grep "addService.*activity"

总结

ServiceManager是Android Binder IPC的核心枢纽,承担着服务注册表的角色。

核心机制:

  • Handle 0:硬编码的唯一标识,解决引导问题
  • Context Manager:向驱动注册为Binder上下文管理者
  • 单例模式:全系统唯一实例,由init启动并标记为critical
  • 服务注册表:维护name→Service的映射
  • 权限控制:UID/SELinux多重检查
  • 死亡通知:自动清理已死亡的服务

工作流程:

  1. 启动: init→main→becomeContextManager→Looper
  2. 注册: addService→权限检查→VINTF验证→linkToDeath→添加到map
  3. 查询: getService→权限检查→查map→返回Binder
  4. 清理: binderDied→移除服务→通知客户端

Android 15增强:

  • Perfetto深度集成,性能追踪更精确
  • VINTF强制验证,安全性提升
  • APEX updatable支持,HAL可独立更新
  • 客户端回调优化,减少资源占用

理解ServiceManager,你就理解了Android服务架构的基石。在下一篇文章中,我们将深入AIDL和HIDL,看看如何定义和使用Binder服务接口。

系列文章


欢迎来我中的个人主页找到更多有用的知识和有趣的产品

相关推荐
2501_9160088912 小时前
深入解析iOS机审4.3原理与混淆实战方法
android·java·开发语言·ios·小程序·uni-app·iphone
千寻技术帮14 小时前
10327_基于SpringBoot的视频剪辑咨询网站
mysql·源码·springboot·代码·视频咨询
独行soc14 小时前
2026年渗透测试面试题总结-20(题目+回答)
android·网络·安全·web安全·渗透测试·安全狮
常利兵14 小时前
2026年,Android开发已死?不,它正迎来黄金时代!
android
Risehuxyc14 小时前
备份三个PHP程序
android·开发语言·php
侠客行031721 小时前
Mybatis连接池实现及池化模式
java·mybatis·源码阅读
Doro再努力1 天前
【Linux操作系统10】Makefile深度解析:从依赖推导到有效编译
android·linux·运维·服务器·编辑器·vim
Daniel李华1 天前
echarts使用案例
android·javascript·echarts
WangYaolove13141 天前
基于python的在线水果销售系统(源码+文档)
python·mysql·django·毕业设计·源码