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