【Android】一文总结Android系统服务大管家-ServiceManager

文章目录

本文涉及到的源码文件:

  • /frameworks/native/cmds/servicemanager/main.cpp
  • /frameworks/native/libs/binder/ProcessState.cpp
  • /frameworks/native/cmds/servicemanager/ServiceManager.cpp
  • /frameworks/native/libs/binder/IPCThreadState.cpp
  • /system/core/libutils/Looper.cpp

一、ServiceManager简介

本文基于Android 11

ServiceManager是一个由C/C++编写的系统服务,源码位于/framework/native/cmds/servicemanager中,存在如下文件结构:

从Android.bp可知,ServiceManager本质上会以程序的方式构建,源码入口位于main.cpp文件中:

main()函数内容如下:

c++ 复制代码
//framework/native/cmds/servicemanager/main.cpp

int main(int argc, char** argv) {
    if (argc > 2) {
        LOG(FATAL) << "usage: " << argv[0] << " [binder driver]";
    }

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

    sp<ProcessState> ps = ProcessState::initWithDriver(driver);
    ps->setThreadPoolMaxThreadCount(0);
    ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);

    sp<ServiceManager> manager = new ServiceManager(std::make_unique<Access>());
    if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
        LOG(ERROR) << "Could not self register servicemanager";
    }

    IPCThreadState::self()->setTheContextObject(manager);
    ps->becomeContextManager(nullptr, nullptr);

    sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);

    BinderCallback::setupTo(looper);
    ClientCallbackCallback::setupTo(looper, manager);

    while(true) {
        looper->pollAll(-1);
    }

    // should not be reached
    return EXIT_FAILURE;
}

从上述代码可以明确知道:ServiceManager程序一旦启动运行,则不会停止(系统不宕机的情况下),将会一直looper->pollAll(-1)。除此之外,还知道ServiceManager默认情况依托于/dev/binder这个设备节点,当然可以通过向ServiceManager传递参数指定设备节点。ServiceManager作为binder机制的核心组件之一,在实现进程间通信中占据着不可获取的地位。

从Android.bp可以知道,ServiceManager对应的程序名称是servicemanager。从Android.bp文件中,还存在一个名为vndservicemanager的程序,它们的源码都是一样的,只是rc文件存在出入,将传入/dev/vndbinder作为binder驱动。在Android启动启动过程中,vndservicemanagervndservicemanager都会被init拉起,他俩的区别总结如下:

1、对于servicemanager:

  • servicemanager是 Android 系统中的核心服务管理器,用于管理系统级的服务。
  • servicemanager管理的服务包括系统级服务(如ActivityManager、PackageManager、WindowManager等)和由应用程序注册的系统服务。
  • servicemanager的访问权限较高,一般只有系统级应用或者具有系统权限的应用程序才能够使用servicemanager进行服务的注册和查询。

2、对于vndservicemanager

  • vndservicemanager是 servicemanager的一个扩展,用于管理供应商特定的服务。
  • vndservicemanager管理的服务通常是供应商(vendor)特定的、定制化的服务,例如硬件厂商提供的驱动程序或服务。
  • vndservicemanager的访问权限一般较低,通常只有供应商特定的应用程序或系统组件才能够使用vndservicemanager进行服务的注册和查询。

二、ServiceManager的启动

第一小节简要介绍了ServiceManager,我们知道ServiceManager是一个具体程序,如果是个程序,那么该程序是如何启动的呢?又在什么时候触发运行的呢?

我们知道Android系统的第一个进程是init,这是由内核决定的。那么在init中将通过解析init.rc来启动系统的一些关键服务进程。其中ServiceManager就在这个时候启动运行。

在/framework/native/cmds/servicemanager/目录中存在一个servicemanager.rc,该文件是servicemanager的初始化配置文件,文件内容如下:

service servicemanager /system/bin/servicemanager
    class core animation
    user system
    group system readproc
    critical
    onrestart restart healthd
    onrestart restart zygote
    onrestart restart audioserver
    onrestart restart media
    onrestart restart surfaceflinger
    onrestart restart inputflinger
    onrestart restart drm
    onrestart restart cameraserver
    onrestart restart keystore
    onrestart restart gatekeeperd
    onrestart restart thermalservice
    writepid /dev/cpuset/system-background/tasks
    shutdown critical

三、ServiceManager详细剖析

本小节将从main函数分段展开描述。

(3-1)获取驱动的名称

如果在运行servicemanager时传入了驱动名称参数,则使用该参数作为驱动;否则使用/dev/binder作为驱动名称。vndservicemanager则以此方式运行!

(3-2)初始化进程状态ProcessState并设置重要参数

  • 初始化ProcessState,代码如下:
c++ 复制代码
sp<ProcessState> ps = ProcessState::initWithDriver(driver);

在Android系统中,关于binder机制,ProcessState是一个重要的类,位于/frameworks/native/libs/binder/ProcessState.cpp中,用于管理每个应用进程中的binder操作。所以在servicemanager启动过程中,调用了initWithDriver()初始化ProcessState,该函数可以用来配置libbinder支持不同的binder节点。initWithDriver()实现代码如下:

c++ 复制代码
sp<ProcessState> ProcessState::initWithDriver(const char* driver)
{
    Mutex::Autolock _l(gProcessMutex);
    if (gProcess != nullptr) {
        // Allow for initWithDriver to be called repeatedly with the same
        // driver.
        if (!strcmp(gProcess->getDriverName().c_str(), driver)) {
            return gProcess;
        }
        LOG_ALWAYS_FATAL("ProcessState was already initialized.");
    }

    if (access(driver, R_OK) == -1) {
        ALOGE("Binder driver %s is unavailable. Using /dev/binder instead.", driver);
        driver = "/dev/binder";
    }

    gProcess = new ProcessState(driver);
    return gProcess;
}

在执行完initWithDriver()后,ProcessState实例对象就创建完成了,且调用open_driver()打开了对应的驱动程序。

随后设置线程池最大线程数为0。设置线程池调用限制为FATAL_IF_NOT_ONEWAY,表示中断阻塞调用的进程。(必须在线程池启动之前设置调用限制)。

(3-3)创建ServiceManager实例

接下来将创建ServiceManager实例manger,并将自己添加为Service。如下代码片段:

c++ 复制代码
sp<ServiceManager> manager = new ServiceManager(std::make_unique<Access>());
if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
    LOG(ERROR) << "Could not self register servicemanager";
}

(3-4)设置上下文对象

将创建好的ServiceManager实例manger设置为上下文对象,代码如下:

c 复制代码
IPCThreadState::self()->setTheContextObject(manager);
ps->becomeContextManager(nullptr, nullptr);

(3-5)创建looper,并执行pollAll

经过上文四个步骤的准备后,则进入servicemanager的核心操作:

c++ 复制代码
sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);

//将BinderCallback设置到looper
BinderCallback::setupTo(looper);

//将ClientCallbackCallback设置到looper和manager
ClientCallbackCallback::setupTo(looper, manager);

while(true) {
    looper->pollAll(-1);
}

首先调用Looper::prepare()静态成员函数,准备Looper,该函数实现如下:

c++ 复制代码
sp<Looper> Looper::prepare(int opts) {
    bool allowNonCallbacks = opts & PREPARE_ALLOW_NON_CALLBACKS;
    sp<Looper> looper = Looper::getForThread();
    if (looper == nullptr) {
        looper = new Looper(allowNonCallbacks);
        Looper::setForThread(looper);
    }
    if (looper->getAllowNonCallbacks() != allowNonCallbacks) {
        ALOGW("Looper already prepared for this thread with a different value for the "
                "LOOPER_PREPARE_ALLOW_NON_CALLBACKS option.");
    }
    return looper;
}

上述代码首先调用Looper::getForThread()从Thread中获取对应的looper,如果looper不存在则使用new创建,并调用Looper::setForThread(loope)将其设置到Thread。这两个函数本质上都是调用到线程库API实现,相关API有:

c++ 复制代码
void *pthread_getspecific(pthread_key_t key);
int pthread_setspecific(pthread_key_t key, const void *value);

int pthread_key_create(pthread_key_t *key, void (*destructor)(void*));

int pthread_once(pthread_once_t *once_control,void (*init_routine)(void));

总而言之,Looper::prepare()将准备一个与调用线程相关联的Looper,并返回该Looper。如果线程已经有Looper,则返回该Looper。否则将创建一个新的Looper,并与线程关联,然后返回。

回到servicemanager的核心操作过程中,接着会将BinderCallback设置到looper,将ClientCallbackCallback设置到loopermanagerBinderCallbackClientCallbackCallback都是继承自LooperCallback

最后在一个while(true){}中调用pollAll(-1)pollAll()用于执行所有挂起的回调,直到数据已被消耗或文件描述符可用且没有回调。该函数实现在/system/core/libutils/Looper.cpp中:

c++ 复制代码
int Looper::pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
    if (timeoutMillis <= 0) {
        int result;
        do {
            result = pollOnce(timeoutMillis, outFd, outEvents, outData);
        } while (result == POLL_CALLBACK);
        return result;
    } else {
        nsecs_t endTime = systemTime(SYSTEM_TIME_MONOTONIC)
                + milliseconds_to_nanoseconds(timeoutMillis);

        for (;;) {
            int result = pollOnce(timeoutMillis, outFd, outEvents, outData);
            if (result != POLL_CALLBACK) {
                return result;
            }

            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
            timeoutMillis = toMillisecondTimeoutDelay(now, endTime);
            if (timeoutMillis == 0) {
                return POLL_TIMEOUT;
            }
        }
    }
}

上述代码中,核心操作由pollOnce()完成,在该函数中继续调用pollInner()实现核心操作(函数内容较长),该函数中将实现以下操作:

  • (1)调用epoll_wait()等待由mEpollFd.get()获取到的文件描述符fd的相关事件是否发生。由于timeout为-1,所以将一直阻塞,直到对应I/O事件的发生。

  • (2)如果mEpollFd文件描述符fd的相关事件发生,则将被唤醒继续执行后续的代码,具体操作是:检测poll错误,检查pool是否有事件需要处理。

  • (3)处理所有事件。

  • (4)调用挂起的MessageEnvelopes回调:

    在该步骤中,将从MessageEnvelopes表中逐一取出MessageEnvelope,获取对应的MessageHandler,接着调用handleMessage()对应的回调函数处理消息,如下代码:

  • (5)调用所有Response的回调:

上述则是pollAll()的具体执行流程,也是servicemanager服务的具体功能实现。

四、ServiceManager的唤醒

ServiceManager 被唤醒的时机主要包括以下几种情况:

  1. 系统启动时: 在 Android 系统启动时,ServiceManager 会被初始化,并开始运行。它会加载系统中预定义的服务,并在 Binder 机制的支持下,为其他系统组件和应用程序提供服务的注册和查询。

  2. 服务注册和查询: 当有服务需要注册到 ServiceManager 或者其他组件需要查询某个服务时,ServiceManager 会被唤醒。注册服务时,ServiceManager 会将服务的信息保存起来,以供其他组件查询。查询服务时,其他组件会向 ServiceManager 发送请求,并等待其响应。

  3. 动态加载服务: 在运行时,某些服务可能会被动态加载或卸载,这时候 ServiceManager 也会被唤醒。动态加载服务时,ServiceManager 会更新其内部的服务列表;卸载服务时,ServiceManager 会将相应的服务从其列表中移除。

五、总结

在Android系统中,ServiceManager是一个重要的系统服务,它允许应用程序和系统组件通过Binder机制进行跨进程通信,从而访问和管理系统级的服务。ServiceManager的主要作用如下:

  1. 服务注册与查找: ServiceManager 允许系统中的服务在启动时向其注册,这些服务可以是系统级的服务,如电源管理、网络管理、传感器服务等,也可以是由应用程序提供的服务。注册后,其他应用程序或系统组件可以通过 ServiceManager 查询已注册的服务,并获取其引用,从而实现跨进程通信。

  2. 进程间通信(IPC): ServiceManager 提供了一种方便的机制,使得应用程序和系统组件可以通过 Binder 机制进行跨进程通信。通过 ServiceManager,客户端可以获取到服务的 Binder 对象,然后使用 Binder 机制与服务进行通信,包括调用服务提供的方法、传递数据等。

  3. 系统服务的启动和管理: ServiceManager 管理着 Android 系统中的许多核心服务,如 ActivityManager、PackageManager、WindowManager 等。这些服务通常是由系统启动时注册到 ServiceManager 中的,其他系统组件或应用程序可以通过 ServiceManager 获取这些系统服务的引用,并与之交互,从而实现系统功能的实现和控制。

  4. 提供系统服务的单例实例: ServiceManager 确保系统中的每个服务都是单例的,即同一个服务只有一个实例存在。当客户端通过 ServiceManager 获取服务的引用时,ServiceManager 会确保返回的是同一个实例对象,这样可以确保系统中的服务状态和数据的一致性。

总的来说,ServiceManager 在 Android 系统中起着非常重要的作用,它是实现系统服务和应用程序之间通信的关键组件之一,为 Android 系统的功能提供了丰富的扩展性和灵活性。

相关推荐
studyForMokey3 小时前
kotlin 函数类型接口lambda写法
android·开发语言·kotlin
梁同学与Android6 小时前
Android --- 新电脑安装Android Studio 使用 Android 内置模拟器电脑直接卡死,鼠标和键盘都操作不了
android·ide·android studio
山雨楼8 小时前
ExoPlayer架构详解与源码分析(14)——ProgressiveMediaPeriod
android·架构·音视频·源码·exoplayer·media3
IsaacBan10 小时前
XJBX-6-Android启动App进程
android
DoubleYellowIce10 小时前
Android Studio阅读frameworks源码的正确姿势
android·android studio
分享者花花10 小时前
最佳 iPhone 解锁软件工具,可免费下载用于电脑操作的
android·windows·macos·ios·pdf·word·iphone
小菜琳15 小时前
Android显式启动activity和隐式启动activity分别都是怎么启动?请举例说明二者使用时的注意事项。
android
许进进16 小时前
FlutterWeb渲染模式及提速
android·flutter·web
helson赵子健17 小时前
Rust 在 Android 中的应用
android·架构·rust
2401_8523867117 小时前
苹果ios安卓apk应用APP文件怎么修改手机APP显示的名称
android·智能手机