zoukankan      html  css  js  c++  java
  • 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对象时。

  • 相关阅读:
    dbutils关于连接维护的问题Q
    触发器
    mysql的full join的实现
    mysql exists 和 in的效率比较
    浏览器禁用Cookie后的session处理
    自定义org.apache.commons.beanutils的类型转换器
    Java中形参个数可变的方法
    递归方法的重要规定——递归一定要向己知方向递归
    抽象工厂模式——肯德基消费
    异常链
  • 原文地址:https://www.cnblogs.com/naray/p/15227430.html
Copyright © 2011-2022 走看看