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對象時。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM