##1、概述##
大家都知道我们平时在创建应用程序的Activity时,都需要通过WindowManagerService(后面简称WMS
)为启动的Activity创建对应的窗口,那今天我们就来简单的介绍一下WMS于应用程序的通信。
在介绍其通信之前我们先来了解一下WMS的一些类的关系。
##2、源码分析 ##
应用程序想要获取到WindowManager对象,就必须要通过Context.getSystemServer()方法获取,而Context的具体实现是ContextImpl类,如果大家对其不是很清楚,可以看一下我的另外一篇博客Android中的Context源码分析。
我们直接进入该类的getSystemServer方法。
public Object getSystemService(String name) {
ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);
return fetcher == null ? null : fetcher.getService(this);
}
可以看出在SYSTEM_SERVICE_MAP的HashMap中取出ServiceFetcher对象,然后调用该对象的getService方法。
在这里我们先看一下ServiceFetcher这个类。
static class ServiceFetcher {
int mContextCacheIndex = -1;
public Object getService(ContextImpl ctx) {
ArrayList<Object> cache = ctx.mServiceCache;
Object service;
synchronized (cache) {
//......
service = cache.get(mContextCacheIndex);
if (service != null) {
return service;
}
}
service = createService(ctx);
cache.set(mContextCacheIndex, service);
return service;
}
public Object createService(ContextImpl ctx) {
throw new RuntimeException("Not implemented");
}
}
可以发现该类有两个方法getService和createService方法,我们接下来只看WMS对应的代码逻辑。
//用于存储注册的服务
private static final HashMap<String, ServiceFetcher> SYSTEM_SERVICE_MAP = new HashMap<String, ServiceFetcher>();
//这里注册WMS服务
registerService(WINDOW_SERVICE, new ServiceFetcher() {
Display mDefaultDisplay;
public Object getService(ContextImpl ctx) {
Display display = ctx.mDisplay;
if (display == null) {
if (mDefaultDisplay == null) {
DisplayManager dm = (DisplayManager)ctx.getOuterContext().
getSystemService(Context.DISPLAY_SERVICE);
mDefaultDisplay = dm.getDisplay(Display.DEFAULT_DISPLAY);
}
display = mDefaultDisplay;
}
//重写getService方法返回WindowManagerImpl对象
return new WindowManagerImpl(display);
}});
//用于注册服务的方法,将结果存入SYSTEM_SERVICE_MAP的Map中
private static void registerService(String serviceName, ServiceFetcher fetcher) {
if (!(fetcher instanceof StaticServiceFetcher)) {
fetcher.mContextCacheIndex = sNextPerContextServiceCacheIndex++;
}
SYSTEM_SERVICE_MAP.put(serviceName, fetcher);
}
好啦,以上就是获取WindowManagerImpl代理对象的方法,我们接下来进入WindowManagerImpl的源码。
我们要知道,Window是一个抽象概念,每个Window都对应着一个View和ViewRootImpl,Window和View是通过ViewRootImpl建立联系,因此Window是以View的形式存在的。在实际中我们无法直接访问Window,对Window的访问必须通过WindowManager,为了分析Window,我们这里来了解操作Window的三个方法。
public interface ViewManager{
public void addView(View view, ViewGroup.LayoutParams params);
public void updateViewLayout(View view, ViewGroup.LayoutParams params);
public void removeView(View view);
}
这个类是WindowManager的父类,我们进入WindowManager类。
public interface WindowManager extends ViewManager {
//......
}
WindowManager没有直接重写ViewManager的三个抽象方法,而是留给其子类实现,我们进入其子类WindowManagerImpl。
public final class WindowManagerImpl implements WindowManager {
public WindowManagerImpl(Display display) {
this(display, null);
}
private WindowManagerImpl(Display display, Window parentWindow) {
mDisplay = display;
mParentWindow = parentWindow;
}
//获得WindowManagerGlobal对象
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
//调用mGlobal对象的addView方法
mGlobal.addView(view, params, mDisplay, mParentWindow);
}
public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
//调用mGlobal对象的updateViewLayout方法
mGlobal.updateViewLayout(view, params);
}
public void removeView(View view) {
//调用mGlobal对象的removeView方法
mGlobal.removeView(view, false);
}
@Override
public void removeViewImmediate(View view) {
mGlobal.removeView(view, true);
}
}
可以看到WindowManagerImpl对View的操作直接交给了WindowManagerGlobal对象了,另外我们说一下这里的removeView方法,这里的removeView方法有两个removeView和removeViewImmediate,它们分别表示异步删除和同步删除,平时我们主要使用的是异步删除,接下来我们进入WindowManagerGlobal类。
public static WindowManagerGlobal getInstance() {
synchronized (WindowManagerGlobal.class) {
if (sDefaultWindowManager == null) {
sDefaultWindowManager = new WindowManagerGlobal();
}
return sDefaultWindowManager;
}
}
首先通过getInstance获取到WindowManagerGlobal对象,这是一个单例模式,在这里我们就不详细的分析操作View的三个方法,我们会在后面的文章中详细阐述,这里我们主要就分析两处:
(1)获取WindowManagerService对象
public static IWindowManager getWindowManagerService() {
synchronized (WindowManagerGlobal.class) {
if (sWindowManagerService == null) {
//调用IWindowManager.Stub对象的asInterface方法
sWindowManagerService = IWindowManager.Stub.asInterface(
//从ServiceManager中获取WMS对象
ServiceManager.getService("window"));
sWindowManagerService = getWindowManagerService();
}
}
//返回IWindowManager对象
return sWindowManagerService;
}
从以上代码可以看出,首先我们获取WMS对象,通过ServiceManager.getService(“window”)获取,大家还记得我们之前文章分析SystemServer的启动流程吗?如果不是很清楚的可以去看一下SystemServer启动流程之Zygote启动(一),这里我也将代码贴一下。
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore);
//此处的Context.WINDOW_SERVICE值就是window
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
我们回到getWindowManagerService方法中,然后调用IWindowManager.Stub对象的asInterface方法并将WMS作为参数传递进去,我们进入asInterface方法源码。
public static android.view.IWindowManager asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
//这里分为两种情况
if (((iin!=null)&&(iin instanceof android.view.IWindowManager))) {
//直接返回
return ((android.view.IWindowManager)iin);
}
//这里创建IWindowManager.Stub的代理对象Proxy并返回
return new android.view.IWindowManager.Stub.Proxy(obj);
}
好啦,到此我们就可以通过getWindowManagerService方法获取到WMS对象或者其代理对象,接下来我们在分析如何获取WindowSession对象。
(2)获取WindowSession对象
public static IWindowSession getWindowSession() {
synchronized (WindowManagerGlobal.class) {
if (sWindowSession == null) {
try {
InputMethodManager imm = InputMethodManager.getInstance();
//通过getWindowManagerService获取得到WMS对象即其代理对象Proxy
IWindowManager windowManager = getWindowManagerService();
//调用WMS的Proxy对象的openSession方法
sWindowSession = windowManager.openSession(
new IWindowSessionCallback.Stub() {
//......
},
}
}
return sWindowSession;
}
}
这里我们主要分析调用WMS的Proxy对象的openSession方法,进入该方法的源码可以发现,其调用的是其子类WindowManagerService的openSession方法,我们进入该源码。
public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
IInputContext inputContext) {
if (client == null) throw new IllegalArgumentException("null client");
if (inputContext == null) throw new IllegalArgumentException("null inputContext");
//创建Session本地对象
Session session = new Session(this, callback, client, inputContext);
return session;
}
这里直接构造一个Session对象,并将该对象返回给应用程序进程,这样在应用程序这边就可以得到Session的代理对象IWindowSession.Proxy,并保存在ViewRootImpl对象的成员变量mWindowSession中。
下面我们用一张时序图来表示Session的获取方法。
以上就是ViewRootImpl通过getWindowSession来获取WindowSession的代理对象。
好啦,分析到这里相信大家对WMS的获取等都有一定的了解了吧,接下来我们我们用一张图来表示ViewRootImpl和WMS的关系。
到此本篇博客就分析完毕啦,关于Window和WindowManager之间的详细关系请参考另外一篇文章理解Window和WindowManager(一),大家不妨也去阅读一下吧。