Android WindowManagerService解析(1)

来源:互联网 发布:js a标签的href不跳转 编辑:程序博客网 时间:2024/05/24 02:39

ContextImpl.java

服务的注册函数

private static void registerService(String serviceName, ServiceFetcher fetcher) {    if (!(fetcher instanceof StaticServiceFetcher)) {        fetcher.mContextCacheIndex = sNextPerContextServiceCacheIndex++;    }    SYSTEM_SERVICE_MAP.put(serviceName, fetcher);}

服务的远程代理对象的获取函数

@Overridepublic Object getSystemService(String name) {    ServiceFetcher fetcher = SYSTEM_SERVICE_MAP.get(name);    return fetcher == null ? null : fetcher.getService(this);}

WindowService的注册过程

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;            }            return new WindowManagerImpl(display);        }});

可以看到,我们通过的使用getSystemService(Context.WINDOW_SERVICE)获取得到的是一个WindowManagerImpl对象,并且它并不是一个真正的WindowManagerService的远程代理对象,而是一个对DisplayManagerService远程代理对象的封装。

WindowManagerImpl

public final class WindowManagerImpl implements WindowManager {    private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();    private final Display mDisplay;    private final Window mParentWindow;    public WindowManagerImpl(Display display) {        this(display, null);    }    private WindowManagerImpl(Display display, Window parentWindow) {        mDisplay = display;        mParentWindow = parentWindow;    }    public WindowManagerImpl createLocalWindowManager(Window parentWindow) {        return new WindowManagerImpl(mDisplay, parentWindow);    }    public WindowManagerImpl createPresentationWindowManager(Display display) {        return new WindowManagerImpl(display, mParentWindow);    }    @Override    public void addView(View view, ViewGroup.LayoutParams params) {        mGlobal.addView(view, params, mDisplay, mParentWindow);    }    @Override    public void updateViewLayout(View view, ViewGroup.LayoutParams params) {        mGlobal.updateViewLayout(view, params);    }    @Override    public void removeView(View view) {        mGlobal.removeView(view, false);    }    @Override    public void removeViewImmediate(View view) {        mGlobal.removeView(view, true);    }    @Override    public Display getDefaultDisplay() {        return mDisplay;    }}

WindowManagerImpl实现了WindowManager接口,一般我们得到WindowManager之后,我们会调用addView、removeView等方法,下面我们来看看对addView方法的调用。

WindowManagerGlobal类是一个单例类,是WindowManagerImpl里面方法的具体操作类,下面来看看它的addView方法

WindowManagerGlobal

public void addView(View view, ViewGroup.LayoutParams params,        Display display, Window parentWindow) {    ViewRootImpl root;    View panelParentView = null;    root = new ViewRootImpl(view.getContext(), display);    view.setLayoutParams(wparams);    mViews.add(view);    mRoots.add(root);    mParams.add(wparams);    root.setView(view, wparams, panelParentView);    }}

我们直接看上面的核心代码,最终调用的是ViewRootImpl的setView方法。首先我们看看ViewRootImpl的构造函数。

ViewRootImpl

final IWindowSession mWindowSession;public ViewRootImpl(Context context, Display display) {    mWindowSession = WindowManagerGlobal.getWindowSession();}

mWindowSession对象是通过WindowManagerGlobal.getWindowSession()得到的,我们来看看这个函数的实现。

WindowManagerGlobal

public static IWindowSession getWindowSession() {    synchronized (WindowManagerGlobal.class) {        if (sWindowSession == null) {            try {                InputMethodManager imm = InputMethodManager.getInstance();                // 1、得到WindowManagerService的远程代理对象                IWindowManager windowManager = getWindowManagerService();                // 2、从远程获取sWindowSession对象                sWindowSession = windowManager.openSession(                        imm.getClient(), imm.getInputContext());                float animatorScale = windowManager.getAnimationScale(2);                ValueAnimator.setDurationScale(animatorScale);            } catch (RemoteException e) {                Log.e(TAG, "Failed to open window session", e);            }        }        return sWindowSession;    }}

可以看到真正的获取WindowManagerService的远程代理对象是在这个地方得到的。

具体我们来看看getWindowManagerService方法。

public static IWindowManager getWindowManagerService() {    synchronized (WindowManagerGlobal.class) {        if (sWindowManagerService == null) {            sWindowManagerService = IWindowManager.Stub.asInterface(                    ServiceManager.getService("window"));        }        return sWindowManagerService;    }}

然后看看它的setView方法。

ViewRootImpl

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {    mOrigWindowType = mWindowAttributes.type;    mAttachInfo.mRecomputeGlobalAttributes = true;    collectViewAttributes();    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,            getHostVisibility(), mDisplay.getDisplayId(),            mAttachInfo.mContentInsets, mInputChannel);         }

上面是核心代码。从前面的分析可以知道,mWindowSession是WindowManagerService中的一个远程对象。上面就是通过mWindowSession来调用WindowManagerService远程服务。

另外,在addToDisplay函数中还传入了一个mWindow对象,我们具体来看看这个对象。

 public ViewRootImpl(Context context, Display display) {    mWindowSession = WindowManagerGlobal.getWindowSession();    mWindow = new W(this);}
static class W extends IWindow.Stub {    private final WeakReference<ViewRootImpl> mViewAncestor;    private final IWindowSession mWindowSession;    W(ViewRootImpl viewAncestor) {        mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor);        mWindowSession = viewAncestor.mWindowSession;    }    @Override    public void resized(Rect frame, Rect overscanInsets, Rect contentInsets,            Rect visibleInsets, boolean reportDraw, Configuration newConfig) {        final ViewRootImpl viewAncestor = mViewAncestor.get();        if (viewAncestor != null) {            viewAncestor.dispatchResized(frame, overscanInsets, contentInsets,                    visibleInsets, reportDraw, newConfig);        }    }    // 省略下面代码}

从上面我们可以总结到,WindowSession是应用跟远程WindowManagerService服务通信的枢纽,W是远程WindowManagerService服务跟应用的通信的枢纽。

另外,我们可以看到,其实我们使用WindowManagerService远程服务,不是单一的使用WindowManagerService远程服务,而是将其和DisplayManagerService搭配起来一块来使用。

阅读全文
0 0