我们先来看应用和WMS的通信
一、应用到WMS的通道
Activity对象中都有一个类型为Window的成员变量mWindow,定义如下:
- public class Activity {
- .......
- private Window mWindow;
- ....
- }
Window对象在应用进程中代表一个窗口。从WMS的角度,不关心各种View,只关心Window对象。Window是一个抽象类。
- final void attach(Context context, ActivityThread aThread,
- Instrumentation instr, IBinder token, int ident,
- Application application, Intent intent, ActivityInfo info,
- CharSequence title, Activity parent, String id,
- NonConfigurationInstances lastNonConfigurationInstances,
- Configuration config, String referrer, IVoiceInteractor voiceInteractor) {
- attachBaseContext(context);
- mFragments.attachActivity(this, mContainer, null);
- mWindow = PolicyManager.makeNewWindow(this);
再来看看Activity的attach方法,这个方法是Activity被创建的时候调用的。其初始化了mWindow对象。这里就不跟代码了,最后返回的是PhoneWindow对象。在Activity操作的Window,实际都是PhoneWindow。
在应用进程中WindowManager是和WMS进行通信的。
- private WindowManager mWindowManager;
WindowManager也是一个接口类:
- public interface WindowManager extends ViewManager {
再来看看attach方法:
- final void attach(Context context, ActivityThread aThread,.........) {
- ........
- mWindow.setWindowManager(
- (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
- mToken, mComponent.flattenToString(),
- (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
- if (mParent != null) {
- mWindow.setContainer(mParent.getWindow());
- }
- mWindowManager = mWindow.getWindowManager();
- ....
- public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
- boolean hardwareAccelerated) {
- mAppToken = appToken;
- mAppName = appName;
- mHardwareAccelerated = hardwareAccelerated
- || SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
- if (wm == null) {
- wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
- }
- mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
- }
- public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
- return new WindowManagerImpl(mDisplay, parentWindow);
- }
因此Activity中的mWindowManager实际上是一个WindowManagerImpl对象,看看其定义
- public final class WindowManagerImpl implements WindowManager {
- private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
- private final Display mDisplay;
- private final Window mParentWindow;
在WindowManagerImpl 中定义了一个mGlobal变量,是通过WindowManagerGlobal.getInstance得到:
- public static WindowManagerGlobal getInstance() {
- synchronized (WindowManagerGlobal.class) {
- if (sDefaultWindowManager == null) {
- sDefaultWindowManager = new WindowManagerGlobal();
- }
- return sDefaultWindowManager;
- }
- }
getInstance方法创建了一个全局唯一的WindowManagerGlobal对象,保存到静态变量sDefaultWindowManager
WindowManagerImpl类中各种方法的实现只是在转调WindowManagerGlobal类的方法,由此可见一个应用进程中所有Activity都是通过这个进程内唯一的WindowManagerGlobal对象和WMS通信。
- public final class WindowManagerGlobal {
- .....
- private final ArrayList<View> mViews = new ArrayList<View>();
- private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
- private final ArrayList<WindowManager.LayoutParams> mParams =
- new ArrayList<WindowManager.LayoutParams>();
- .....
- }
WindowManagerGlobal 保存了应用所有顶层view相关信息
mViews保存所有顶层View对象(DecorView)
mRoots保存和顶层View关联的ViewRootImpl
mParams保存的是创建顶层View的layout参数
ViewRootImpl类有很多成员变量,来看看和WMS相关的,
- public final class ViewRootImpl {
- .....
- final IWindowSession mWindowSession;
- .....
- final W mWindow;
- }
来看下ViewRootImpl的构造函数:
- public ViewRootImpl(Context context, Display display) {
- mContext = context;
- mWindowSession = WindowManagerGlobal.getWindowSession();
- ...
- mWindow = new W(this);
其中mWIndowSession变量是IWindowSession,它是WMS中某个Binder对象的引用对象。mWindowSession的值是通过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;
- }
- }
而getWindowManagerService就是获取WMS的客户端的Binder
- 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;
- }
- }
最后调用了WMS的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 = new Session(this, callback, client, inputContext);
- return session;
- }
openSession函数戒指创建了一个Session对象,是一个Binder服务对象。返回给用户进程的是Session的客户对象,这个客户对象就保存在WindowManagerGlobal的静态变量sWindowSession。调用函数getWindowSession方法返回的都是这个保存在sWindowSession中的IWindowSession对象。因此一个用户进程中所有ViewRootImpl对象中的mWIndowSession都是相同的。它就是建立了一条和WMS的通道。
二、WMS到应用的通道
Activity启动的时候会调用ActivityThread的handleResumeActivity方法,该方法调用了Activity的makeVisible方法:
- void makeVisible() {
- if (!mWindowAdded) {
- ViewManager wm = getWindowManager();
- wm.addView(mDecor, getWindow().getAttributes());
- mWindowAdded = true;
- }
- mDecor.setVisibility(View.VISIBLE);
- }
这个方法中又调用了WindowManager的addView方法,最后实际是调用WindowManagerGlobal的addView方法
- public void addView(View view, ViewGroup.LayoutParams params,
- Display display, Window parentWindow) {
- ........
- root = new ViewRootImpl(view.getContext(), display);//创建ViewRootImpl对象
- view.setLayoutParams(wparams);
- mViews.add(view);
- mRoots.add(root);
- mParams.add(wparams);
- }
- // do this last because it fires off messages to start doing things
- try {
- root.setView(view, wparams, panelParentView);
- }
- ......
- }
在WindowManagerGlobal的addView方法中创建了ViewRootImpl对象,通过其setView方法。把它和顶层的View对象关联在了一起:
- public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
- synchronized (this) {
- if (mView == null) {
- mView = view;
- ......
- try {
- mOrigWindowType = mWindowAttributes.type;
- mAttachInfo.mRecomputeGlobalAttributes = true;
- collectViewAttributes();
- res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
- getHostVisibility(), mDisplay.getDisplayId(),
- mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mInputChannel);
- } catch (RemoteException e) {
- .....
- }
方法中会检查mView的值,如果已经赋值了就不再赋了。因此ViewRootImpl对象和顶层的View之前的关联只会执行一次。在setView方法中会调用Session的addToDisplay方法,这个方法的第一个参数mWIndow,它是类W的实例对象。在ViewRootImpl构造函数中创建的。W是ViewRootImpl的嵌入类。
- static class W extends IWindow.Stub {
- private final WeakReference<ViewRootImpl> mViewAncestor;
- private final IWindowSession mWindowSession;
W是一个Binder服务类,通过addToDisplay方法将它的实例对象传到WMS。W在WMS中的客户对象的类型是IWindow,WMS保存了应用中每个顶层窗口的IWindow对象。
在WMS中,WindowState对象代表一个窗口。WindowState类定义了表示每个窗口的窗口信息
- final class WindowState implements WindowManagerPolicy.WindowState {
- static final String TAG = "WindowState";
- final WindowManagerService mService;
- final WindowManagerPolicy mPolicy;
- final Context mContext;
- final Session mSession;
- final IWindow mClient;
其中mClient是客户进程的Binder对象在WMS的引用,而mSession是WMS中和客户进程创建的Binder服务对象。
- final class Session extends IWindowSession.Stub
- @Override
- public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
- int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
- InputChannel outInputChannel) {
- return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
- outContentInsets, outStableInsets, outInputChannel);
- }
WMS的addWindows方法
- public int addWindow(Session session, IWindow client,...) {
- ......
- win = new WindowState(this, session, client, token,
- attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
- ......
- win.attach();
- mWindowMap.put(client.asBinder(), win);
- ......
- }
addWIndow函数较长,这里创建了WindowState对象,并把它加入mWindowMap列表中,这里面保存了系统所有的顶层窗口信息。
这样从应用到WMS,和从WMS到应用的通道都建立了。
应用 WMS
WindowManagerGlobal ---------IWindowSession--------> Session
Window <-----------IWindow-------------- WindowState
三、WMS的成员变量
- final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();
- final ArraySet<Session> mSessions = new ArraySet<Session>();
- final HashMap<IBinder, WindowState> mWindowMap = new HashMap<IBinder, WindowState>();
- final HashMap<IBinder, WindowToken> mTokenMap = new HashMap<IBinder, WindowToken>();
mSessions保存的是Session服务类的对象,每个应用在WMS都有一个对应的Session
mTokenMap保存的是所有窗口的WindowToken对象
mWindowMap保存的是所有窗口的WindowState对象
mPolicy是WMS的窗口策略类,目前只有一个PhoneWindowService。