Android之ServiceManager服务

一、ServiceManager的作用是什么

  ServiceManager从字面意思是管理服务的。

  ServiceManager是用于查询服务和获取服务的。

二、ServiceManager启动过程

  源码:frameworks/native/cmds/servicemanager

  ServiceManager是系统服务,与zygote、surfaceflinger一样,由系统进程init启动,init进程通过init.rc配置文件读取需要启动的配置,ServiceManager启动命名:

  源码:frameworks/native/cmds/servicemanager/servicemanager.rc

service servicemanager /system/bin/servicemanager
    class core animation
    user system
    group system readproc
    critical
    onrestart restart apexd
    onrestart restart audioserver
    onrestart restart gatekeeperd
    onrestart class_restart main
    onrestart class_restart hal
    onrestart class_restart early_hal
    writepid /dev/cpuset/system-background/tasks
    shutdown critical

  ServiceManager进程启动后,执行ServiceManager的main.cpp里main()函数:

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 = sp<ServiceManager>::make(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();

    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启动流程:

  1. 启动Binder线程池。

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

  2. 启动ServiceManager服务并获取ServiceManager服务Binder代理对象。

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

  3. 将ServiceManager服务的Binder代理对象注册到ServiceManager服务中。

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

  4. 将ServiceMager服务自己注册为上下文管理者。

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

  5. 启动Binder线程池Looper并接收处理消息。

sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);
BinderCallback::setupTo(looper);
ClientCallbackCallback::setupTo(looper, manager);
while(true) {
    looper->pollAll(-1);
}

 三、怎么获取ServiceManager

  源码:frameworks/base/core/java/android/os/ServiceManager.java

  1. 其它服务如何获取ServiceManager服务

  下面以渲染服务surfaceflinger服务为例,在surfaceflinger服务是怎么获取到ServiceManager服务的Binder代理对象。

  源码:frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp

int main(int, char**) {
    ……

    // publish surface flinger
    sp<IServiceManager> sm(defaultServiceManager());
   
    ……
}

  通过函数defaultServiceManager()函数获取ServiceManager服务的Binder代理对象。

  IServiceManager.h在binder源码里。

四、ServiceManager如何添加服务

  下面以渲染服务surfaceflinger服务为例:

sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
                   IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);

  通过获取到的ServiceManager的Binder代理对象,调用addService(...)函数注册服务。

/**
 * Place a new @a service called @a name into the service
 * manager.
 *
 * @param name the name of the new service
 * @param service the service object
 * @param allowIsolated set to true to allow isolated sandboxed processes
 * to access this service
 * @hide
 */
@UnsupportedAppUsage
public static void addService(String name, IBinder service, boolean allowIsolated) {
    addService(name, service, allowIsolated, IServiceManager.DUMP_FLAG_PRIORITY_DEFAULT);
}

/**
 * Place a new @a service called @a name into the service
 * manager.
 *
 * @param name the name of the new service
 * @param service the service object
 * @param allowIsolated set to true to allow isolated sandboxed processes
 * @param dumpPriority supported dump priority levels as a bitmask
 * to access this service
 * @hide
 */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static void addService(String name, IBinder service, boolean allowIsolated,
        int dumpPriority) {
    try {
        getIServiceManager().addService(name, service, allowIsolated, dumpPriority);
    } catch (RemoteException e) {
        Log.e(TAG, "error in addService", e);
    }
}

  在

五、ServiceManager如何获取服务

   通过ServiceManager的Binder代理对象,调用getService(String name)获取指定名称服务。

/**
    * Returns a reference to a service with the given name.
    *
    * @param name the name of the service to get
    * @return a reference to the service, or <code>null</code> if the service doesn't exist
    * @hide
    */
@UnsupportedAppUsage
public static IBinder getService(String name) {
    try {
        IBinder service = sCache.get(name);
        if (service != null) {
            return service;
        } else {
            return Binder.allowBlocking(rawGetService(name));
        }
    } catch (RemoteException e) {
        Log.e(TAG, "error in getService", e);
    }
    return null;
}

  在通过addService()函数注册服务时,ServiceManager会将服务存储在ServiceManager.sCache数据结构中,sCache是Map。key是服务名称。

六、Java层,应用启动时,服务是如何注册到应用的ServiceManager里

/**
 * This is only intended to be called when the process is first being brought
 * up and bound by the activity manager. There is only one thread in the process
 * at that time, so no locking is done.
 *
 * @param cache the cache of service references
 * @hide
 */
public static void initServiceCache(Map<String, IBinder> cache) {
    if (sCache.size() != 0) {
        throw new IllegalStateException("setServiceCache may only be called once");
    }
    sCache.putAll(cache);
}
  这个方法只会被调用一个,在服务

  在应用进程启动后,通知AMS,AMS再通知应用创建Application时,会将系统中注册的Services一起发送给就算的ServiceManager,存储在Java层的ServiceManager.sCache数据结构中。sCache是一个Map数据结构。

  

private class ApplicationThread extends IApplicationThread.Stub {
    ……

    public final void bindApplication(String processName, ApplicationInfo appInfo,
            ProviderInfoList providerList, ComponentName instrumentationName,
            ProfilerInfo profilerInfo, Bundle instrumentationArgs,
            IInstrumentationWatcher instrumentationWatcher,
            IUiAutomationConnection instrumentationUiConnection, int debugMode,
            boolean enableBinderTracking, boolean trackAllocation,
            boolean isRestrictedBackupMode, boolean persistent, Configuration config,
            CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
            String buildSerial, AutofillOptions autofillOptions,
            ContentCaptureOptions contentCaptureOptions, long[] disabledCompatChanges) {
        if (services != null) {
            if (false) {
                // Test code to make sure the app could see the passed-in services.
                for (Object oname : services.keySet()) {
                    if (services.get(oname) == null) {
                        continue; // AM just passed in a null service.
                    }
                    String name = (String) oname;

                    // See b/79378449 about the following exemption.
                    switch (name) {
                        case "package":
                        case Context.WINDOW_SERVICE:
                            continue;
                    }

                    if (ServiceManager.getService(name) == null) {
                        Log.wtf(TAG, "Service " + name + " should be accessible by this app");
                    }
                }
            }

            // Setup the service cache in the ServiceManager
            ServiceManager.initServiceCache(services);
        }
    }

    ……
}

  ServiceManager.initServiceCache()函数在应用启动调用,并且仅调用一次。就是在AMS通知应用创建Application对象时。

上一篇:Informer:改进Transformer的长序列时序预测模型


下一篇:如何高效掌控K8s资源变化?K8s Informer实现机制浅析