WMS简介 (and5.1)

我们先来看应用和WMS的通信

一、应用到WMS的通道

Activity对象中都有一个类型为Window的成员变量mWindow,定义如下:

  1. public class Activity {  
  2. .......  
  3.     private Window mWindow;  
  4. ....  
  5. }     

Window对象在应用进程中代表一个窗口。从WMS的角度,不关心各种View,只关心Window对象。Window是一个抽象类。

  1. final void attach(Context context, ActivityThread aThread,  
  2.         Instrumentation instr, IBinder token, int ident,  
  3.         Application application, Intent intent, ActivityInfo info,  
  4.         CharSequence title, Activity parent, String id,  
  5.         NonConfigurationInstances lastNonConfigurationInstances,  
  6.         Configuration config, String referrer, IVoiceInteractor voiceInteractor) {  
  7.     attachBaseContext(context);  
  8.   
  9.     mFragments.attachActivity(this, mContainer, null);  
  10.   
  11.     mWindow = PolicyManager.makeNewWindow(this);  

再来看看Activity的attach方法,这个方法是Activity被创建的时候调用的。其初始化了mWindow对象。这里就不跟代码了,最后返回的是PhoneWindow对象。在Activity操作的Window,实际都是PhoneWindow。

在应用进程中WindowManager是和WMS进行通信的。

  1. private WindowManager mWindowManager;  

WindowManager也是一个接口类:

  1. public interface WindowManager extends ViewManager {  

再来看看attach方法:

  1.   final void attach(Context context, ActivityThread aThread,.........) {      
  2. ........  
  3. mWindow.setWindowManager(  
  4.               (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),  
  5.               mToken, mComponent.flattenToString(),  
  6.               (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);  
  7.       if (mParent != null) {  
  8.           mWindow.setContainer(mParent.getWindow());  
  9.       }  
  10.       mWindowManager = mWindow.getWindowManager();  
  11. ....  
  12.       
在attach方法中,对mWindowManager变量的赋值是调用mWIndow的getWindowManager,但是之前还调用了mWIndow的setWindowManager方法,这个方法不是在PhoneWindow中实现的,而是在基类中。

  1. public void setWindowManager(WindowManager wm, IBinder appToken, String appName,  
  2.         boolean hardwareAccelerated) {  
  3.     mAppToken = appToken;  
  4.     mAppName = appName;  
  5.     mHardwareAccelerated = hardwareAccelerated  
  6.             || SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);  
  7.     if (wm == null) {  
  8.         wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);  
  9.     }  
  10.     mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);  
  11. }  
在setWindowManager方法中调用了WindowManagerImpl类的createLocalWindowManager方法

  1. public WindowManagerImpl createLocalWindowManager(Window parentWindow) {  
  2.     return new WindowManagerImpl(mDisplay, parentWindow);  
  3. }  

因此Activity中的mWindowManager实际上是一个WindowManagerImpl对象,看看其定义

  1. public final class WindowManagerImpl implements WindowManager {  
  2.     private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();  
  3.     private final Display mDisplay;  
  4.     private final Window mParentWindow;  

在WindowManagerImpl 中定义了一个mGlobal变量,是通过WindowManagerGlobal.getInstance得到:

  1. public static WindowManagerGlobal getInstance() {  
  2.     synchronized (WindowManagerGlobal.class) {  
  3.         if (sDefaultWindowManager == null) {  
  4.             sDefaultWindowManager = new WindowManagerGlobal();  
  5.         }  
  6.         return sDefaultWindowManager;  
  7.     }  
  8. }  

getInstance方法创建了一个全局唯一的WindowManagerGlobal对象,保存到静态变量sDefaultWindowManager
WindowManagerImpl类中各种方法的实现只是在转调WindowManagerGlobal类的方法,由此可见一个应用进程中所有Activity都是通过这个进程内唯一的WindowManagerGlobal对象和WMS通信。

  1. public final class WindowManagerGlobal {  
  2.     .....  
  3.     private final ArrayList<View> mViews = new ArrayList<View>();  
  4.     private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();  
  5.     private final ArrayList<WindowManager.LayoutParams> mParams =  
  6.             new ArrayList<WindowManager.LayoutParams>();  
  7.     .....  
  8. }  

WindowManagerGlobal 保存了应用所有顶层view相关信息

mViews保存所有顶层View对象(DecorView)

mRoots保存和顶层View关联的ViewRootImpl

mParams保存的是创建顶层View的layout参数

ViewRootImpl类有很多成员变量,来看看和WMS相关的,

  1. public final class ViewRootImpl {  
  2.     .....  
  3.     final IWindowSession mWindowSession;  
  4.     .....  
  5.     final W mWindow;  
  6. }  

来看下ViewRootImpl的构造函数:

  1. public ViewRootImpl(Context context, Display display) {  
  2.     mContext = context;  
  3.     mWindowSession = WindowManagerGlobal.getWindowSession();  
  4. ...  
  5.     mWindow = new W(this);  

其中mWIndowSession变量是IWindowSession,它是WMS中某个Binder对象的引用对象。mWindowSession的值是通过WindowManagerGlobal的getWindowSession方法获得

  1. public static IWindowSession getWindowSession() {  
  2.     synchronized (WindowManagerGlobal.class) {  
  3.         if (sWindowSession == null) {  
  4.             try {  
  5.                 InputMethodManager imm = InputMethodManager.getInstance();  
  6.                 IWindowManager windowManager = getWindowManagerService();  
  7.                 sWindowSession = windowManager.openSession(  
  8.                         new IWindowSessionCallback.Stub() {  
  9.                             @Override  
  10.                             public void onAnimatorScaleChanged(float scale) {  
  11.                                 ValueAnimator.setDurationScale(scale);  
  12.                             }  
  13.                         },  
  14.                         imm.getClient(), imm.getInputContext());  
  15.             } catch (RemoteException e) {  
  16.                 Log.e(TAG, "Failed to open window session", e);  
  17.             }  
  18.         }  
  19.         return sWindowSession;  
  20.     }  
  21. }  

而getWindowManagerService就是获取WMS的客户端的Binder

  1. public static IWindowManager getWindowManagerService() {  
  2.     synchronized (WindowManagerGlobal.class) {  
  3.         if (sWindowManagerService == null) {  
  4.             sWindowManagerService = IWindowManager.Stub.asInterface(  
  5.                     ServiceManager.getService("window"));  
  6.             try {  
  7.                 sWindowManagerService = getWindowManagerService();  
  8.                 ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale());  
  9.             } catch (RemoteException e) {  
  10.                 Log.e(TAG, "Failed to get WindowManagerService, cannot set animator scale", e);  
  11.             }  
  12.         }  
  13.         return sWindowManagerService;  
  14.     }  
  15. }  

最后调用了WMS的openSession函数

  1. public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,  
  2.         IInputContext inputContext) {  
  3.     if (client == nullthrow new IllegalArgumentException("null client");  
  4.     if (inputContext == nullthrow new IllegalArgumentException("null inputContext");  
  5.     Session session = new Session(this, callback, client, inputContext);  
  6.     return session;  
  7. }  

openSession函数戒指创建了一个Session对象,是一个Binder服务对象。返回给用户进程的是Session的客户对象,这个客户对象就保存在WindowManagerGlobal的静态变量sWindowSession。调用函数getWindowSession方法返回的都是这个保存在sWindowSession中的IWindowSession对象。因此一个用户进程中所有ViewRootImpl对象中的mWIndowSession都是相同的。它就是建立了一条和WMS的通道。


二、WMS到应用的通道



Activity启动的时候会调用ActivityThread的handleResumeActivity方法,该方法调用了Activity的makeVisible方法:

  1. void makeVisible() {  
  2.     if (!mWindowAdded) {  
  3.         ViewManager wm = getWindowManager();  
  4.         wm.addView(mDecor, getWindow().getAttributes());  
  5.         mWindowAdded = true;  
  6.     }  
  7.     mDecor.setVisibility(View.VISIBLE);  
  8. }  

这个方法中又调用了WindowManager的addView方法,最后实际是调用WindowManagerGlobal的addView方法

  1.     public void addView(View view, ViewGroup.LayoutParams params,  
  2.             Display display, Window parentWindow) {  
  3.             ........  
  4.             root = new ViewRootImpl(view.getContext(), display);//创建ViewRootImpl对象  
  5.   
  6.             view.setLayoutParams(wparams);  
  7.   
  8.             mViews.add(view);  
  9.             mRoots.add(root);  
  10.             mParams.add(wparams);  
  11.         }  
  12.   
  13.         // do this last because it fires off messages to start doing things  
  14.         try {  
  15.             root.setView(view, wparams, panelParentView);  
  16.         }  
  17.     ......  
  18. }     

在WindowManagerGlobal的addView方法中创建了ViewRootImpl对象,通过其setView方法。把它和顶层的View对象关联在了一起:

  1.     public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {  
  2.         synchronized (this) {  
  3.             if (mView == null) {  
  4.                 mView = view;  
  5.         ......  
  6.         try {  
  7.                     mOrigWindowType = mWindowAttributes.type;  
  8.                     mAttachInfo.mRecomputeGlobalAttributes = true;  
  9.                     collectViewAttributes();  
  10.                     res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,  
  11.                             getHostVisibility(), mDisplay.getDisplayId(),  
  12.                             mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mInputChannel);  
  13.                 } catch (RemoteException e) {  
  14.                 .....  
  15. }                 

方法中会检查mView的值,如果已经赋值了就不再赋了。因此ViewRootImpl对象和顶层的View之前的关联只会执行一次。在setView方法中会调用Session的addToDisplay方法,这个方法的第一个参数mWIndow,它是类W的实例对象。在ViewRootImpl构造函数中创建的。W是ViewRootImpl的嵌入类。

  1. static class W extends IWindow.Stub {  
  2.     private final WeakReference<ViewRootImpl> mViewAncestor;  
  3.     private final IWindowSession mWindowSession;  

W是一个Binder服务类,通过addToDisplay方法将它的实例对象传到WMS。W在WMS中的客户对象的类型是IWindow,WMS保存了应用中每个顶层窗口的IWindow对象。

在WMS中,WindowState对象代表一个窗口。WindowState类定义了表示每个窗口的窗口信息

  1. final class WindowState implements WindowManagerPolicy.WindowState {  
  2.     static final String TAG = "WindowState";  
  3.   
  4.     final WindowManagerService mService;  
  5.     final WindowManagerPolicy mPolicy;  
  6.     final Context mContext;  
  7.     final Session mSession;  
  8.     final IWindow mClient;  

其中mClient是客户进程的Binder对象在WMS的引用,而mSession是WMS中和客户进程创建的Binder服务对象。

  1. final class Session extends IWindowSession.Stub  
Session类是从IWindowSession.Stub派生的。应用调用了Session的addToDisplay,最后调用了WMS的addWindow函数。

  1. @Override  
  2. public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,  
  3.         int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,  
  4.         InputChannel outInputChannel) {  
  5.     return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,  
  6.             outContentInsets, outStableInsets, outInputChannel);  
  7. }  

WMS的addWindows方法

  1. public int addWindow(Session session, IWindow client,...) {  
  2. ......  
  3.      win = new WindowState(this, session, client, token,  
  4.                     attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);  
  5. ......  
  6.     win.attach();  
  7.     mWindowMap.put(client.asBinder(), win);  
  8. ......    
  9. }  

addWIndow函数较长,这里创建了WindowState对象,并把它加入mWindowMap列表中,这里面保存了系统所有的顶层窗口信息。

这样从应用到WMS,和从WMS到应用的通道都建立了。


          应用                                                                              WMS

WindowManagerGlobal    ---------IWindowSession-------->   Session

Window                            <-----------IWindow--------------     WindowState



三、WMS的成员变量


  1. final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();    
  2. final ArraySet<Session> mSessions = new ArraySet<Session>();  
  3. final HashMap<IBinder, WindowState> mWindowMap = new HashMap<IBinder, WindowState>();  
  4. final HashMap<IBinder, WindowToken> mTokenMap = new HashMap<IBinder, WindowToken>();  

mSessions保存的是Session服务类的对象,每个应用在WMS都有一个对应的Session

mTokenMap保存的是所有窗口的WindowToken对象

mWindowMap保存的是所有窗口的WindowState对象

mPolicy是WMS的窗口策略类,目前只有一个PhoneWindowService。

猜你喜欢

转载自blog.csdn.net/u010144805/article/details/80050960
5.1