Android WindowManagerService解析(1)

ContextImpl.java

服务的注册函数

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

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

@Override
public 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搭配起来一块来使用。

欢迎关注微信公众号:DroidMind
精品内容独家发布平台


呈现与博客不一样的技术干货

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值