Window 与 WindowManager 之间使用的是桥接模式,先来看看他们的 uml 图: 这里写图片描述 Window 类和 PhoneWindow 类为抽象部分,PhoneWindow 为 Window 类的唯一实现子类,在 Window 类中,持有了一个 WindowManager 类的引用,并且在 setWindowManager 方法中将其赋值为了 WindowManagerImpl 对象:
public void setWindowManager(WindowManager wm, IBinder appToken, String appName, boolean hardwareAccelerated) { ... mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);}
对应着的 WindowManager 接口和 WindowManagerImpl 类就组成了实现部分,所以说这四个类使用的就是典型的桥接模式,Window 中的 addView,removeView 等操作都桥接给了 WindowManagerImpl 去处理。但是实际上 WindowManagerImpl 中并没有去实现 addView 方法,在 WindowManagerImpl 类中持有了一个 WindowManagerGlobal 对象的引用,这个引用是通过单例模式获取的,而 addView 等方法就直接交给了 WindowManagerGlobal 类去处理:
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { applyDefaultToken(params); mGlobal.addView(view, params, mDisplay, mParentWindow);}
继续分析 WindowManagerGlobal 类的 addView 函数,在该函数中,最后调用到了 ViewRootImpl 类中的 setView 成员方法,ViewRootImpl 类中的 setView 方法最后会调用到 scheduleTraversals 方法,scheduleTraversals 方法:
void scheduleTraversals() { if (!mTraversalScheduled) { ... notifyRendererOfFramePending(); pokeDrawLockIfNeeded(); }}
我们继续看看 pokeDrawLockIfNeeded 函数:
void pokeDrawLockIfNeeded() { final int displayState = mAttachInfo.mDisplayState; if (mView != null && mAdded && mTraversalScheduled && (displayState == Display.STATE_DOZE || displayState == Display.STATE_DOZE_SUSPEND)) { try { mWindowSession.pokeDrawLock(mWindow); } catch (RemoteException ex) { // System server died, oh well. } }}
看到了 mWindowSession 对象,是不是很熟悉,mWindowSession 对象的创建:
mWindowSession = WindowManagerGlobal.getWindowSession();
嗯,又回到了 WindowManagerGlobal 类,去看看它的 getWindowSession 方法:
public static IWindowSession getWindowSession() { synchronized (WindowManagerGlobal.class) { if (sWindowSession == null) { try { InputMethodManager imm = InputMethodManager.getInstance(); IWindowManager windowManager = getWindowManagerService(); sWindowSession = windowManager.openSession( new IWindowSessionCallback.Stub() { @Override public void onAnimatorScaleChanged(float scale) { ValueAnimator.setDurationScale(scale); } }, imm.getClient(), imm.getInputContext()); } catch (RemoteException e) { Log.e(TAG, "Failed to open window session", e); } } return sWindowSession; }}
WindowSession 是通过 IWindowManager 创建的:
public static IWindowManager getWindowManagerService() { synchronized (WindowManagerGlobal.class) { if (sWindowManagerService == null) { sWindowManagerService = IWindowManager.Stub.asInterface( ServiceManager.getService("window")); try { sWindowManagerService = getWindowManagerService(); ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale()); } catch (RemoteException e) { Log.e(TAG, "Failed to get WindowManagerService, cannot set animator scale", e); } } return sWindowManagerService; }}
跨进程之间的通信,最终调用到的是 WindowManagerService 中。这里需要简单提到的一句是 WMS 和 AMS 一样都是由 SystemServer 启动的,是在另一个进程中的,这也是为什么需要跨进程之间的通信。