我们在应用端需要访问系统提供的服务时,经常会用到Context.getSystemService(Context.xxx)方法来取得对应服务的实例,但以前仅仅局限于用,并未仔细深究里面的实现过程,本文将以WindowManager为例来仔细推敲一下。
涉及代码路径:
frameworks/base/core/java/android/content/Context.java
frameworks/base/core/java/android/app/ContextImpl.java
frameworks/base/core/java/android/app/SystemServiceRegistry.java
frameworks/base/core/java/android/view/WindowManager.java
frameworks/base/services/java/com/android/server/SystemServer.java
1.我们知道,所有的系统服务在启动阶段都是被SystemServer进程启动的,其中在startOtherServices方法里会调用(WindowManager)context.getSystemService(Context.WINDOW_SERVICE)
Configuration config = wm.computeNewConfiguration();
DisplayMetrics metrics = new DisplayMetrics();
WindowManager w = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
w.getDefaultDisplay().getMetrics(metrics);
context.getResources().updateConfiguration(config, metrics);
2.Context是一个抽象类,其实现在ContextImpl类中,因此我们直接看ContextImpl中的getSystemService方法,其中直接调用了SystemServiceRegistry的静态方法
public abstract class Context {
class ContextImpl extends Context {
@Override
public Object getSystemService(String name) {
return SystemServiceRegistry.getSystemService(this, name);
}
3.SYSTEM_SERVICE_FETCHERS是一个哈希map,通过参数name,即Context.WINDOW_SERVICE,找到对应的ServiceFetcher,再由fetcher找到对应的service
public static Object getSystemService(ContextImpl ctx, String name) {
ServiceFetcher> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
return fetcher != null ? fetcher.getService(ctx) : null;
}
private static final HashMap, String> SYSTEM_SERVICE_NAMES =
new HashMap, String>();
private static final HashMap> SYSTEM_SERVICE_FETCHERS =
new HashMap>();
4.既然是哈希map,那么有get的操作必然就有put操作,果然在同文件中的方法registerService中,我们可以看到众多系统服务以及它们的名字在注册时放在了相应的哈希map中
private static void registerService(String serviceName, Class serviceClass,
ServiceFetcher serviceFetcher) {
SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
}
registerService(Context.WINDOW_SERVICE, WindowManager.class,
new CachedServiceFetcher() {
@Override
public WindowManager createService(ContextImpl ctx) {
return new WindowManagerImpl(ctx);
}});
5.由此我们可知,系统在启动时,将众多系统服务以及它们的名字注册到一个哈希表中,当应用端调用getSystemService时,根据指定的name参数,返回对应的服务实例。app即可通过此实例获得对应的服务