Activity和WMS关系梳理

来源:互联网 发布:有人招聘网络写手吗? 编辑:程序博客网 时间:2024/04/30 04:56

Activity启动完成,和WMS是有交互的。

这里分析一下Activity持有WMS服务的代理是什么,WMS持有的Activity这一侧代理是什么。


由于Activity和WMS交互都是RootViewImpl这个桥梁,所以分析Activity持有WMS代理也可以从

ViewRootImpl出发就好了。


1.Activity持有WMS代理是ViewRootImpl的一个成员变量

 final IWindowSession mWindowSession;

有了他,ViewRootImpl可以操作一些WMS服务方法,这样Activity也就可以操作了

跟踪怎么得到的


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());
                    ValueAnimator.setDurationScale(windowManager.getCurrentAnimatorScale());
                } catch (RemoteException e) {
                    Log.e(TAG, "Failed to open window session", e);
                }
            }
            return sWindowSession;
        }
    }


分析一下首先拿到IWindowManager代理。然后执行openSession()即可。

这里分享一个心得,遇到android里面aidl或者跨进程等Binder分析。尤其是java这种情况

一种很容易的思路如下。

接口   IWindowManager

接口实现   IWindowManager.Stub子类

客户端获取代理  IWindowManager wm=IWindowManager.Stub.asInterface(xxx)  xxx表示远程服务提供的binder


你看这样其实思路就会清晰一点,ViewRootImpl作为客户端,拿到IWindowManager这个接口代理,就是

拿一个binder,然后强制转成接口

如下:




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


这里的binder就是WMS

看一下WMS定义,真的是Binder,Stub是继承BBinder嘛。


WindowManagerService extends IWindowManager.Stub


------------------------------

分析完了IWindowManager,再看看IWindowSession吧,

其实还有很多接口在里面,像IWindow ,WindowManager,这些都是

接口,其实一般点进去还看不了。


他们其实都是一些aidl。怎么说呢。就是一个接口文件,定义方法。

服务端实现他。客户端想访问一般都是

IWindowManager.Stub.asInterface(Binder)

很暴力吧。


所以说谷歌这一套,分析到java这些层次遇到AMS,WMS,PMS这些很多概念。

每一个服务里面很多I开头的都是aidl接口,就看作一套协议好了,如果不好理解,

就当是抽象出一堆功能。服务端实现了,客户端拿来用。客户端怎么实现的,

找接口,Stub子类,比如IWindowManager.Stub,IWindow.Stub就好了。


-----------------------------------

openSession返回一个服务端代理所谓的Session,这样又可以操作WMS内容了。

客户端是看不到openSession原理的,想看只能去找Stub子类,也就是WMS



----------

WMS持有Activity代理,为什么这么做呢,比如WMS检测窗口发生变化,真以为Activity onSizeChanged能知道吗

WMS发给代理即可。

分析如下:

    final W mWindow;

还是刚刚的思路,看看继承关系

static class W extends IWindow.Stub 

发现又是实现类,也就是说定义一个接口aidl IWindow

这时候换做ViewRootImpl成员变量当作服务端了,实际上指的是Activty。

WMS'拿到这个代理,然后检测窗口变化通知一下代理,也就是调用代理方法。

这样Activity就知道窗口发生变化拉。

IWindow一些代码如下:

定义很多窗口变化的函数,想一下Activity横竖屏切换啊。获取焦点之类的。

这些ViewRootImpl可以拿到,最终又会传给Activity。


void executeCommand(String command, String parameters, in ParcelFileDescriptor descriptor);


    void resized(in Rect frame, in Rect overscanInsets, in Rect contentInsets,
            in Rect visibleInsets, in Rect stableInsets, boolean reportDraw,
            in Configuration newConfig);
    void moved(int newX, int newY);
    void dispatchAppVisibility(boolean visible);
    void dispatchGetNewSurface();


    /**
     * Tell the window that it is either gaining or losing focus.  Keep it up
     * to date on the current state showing navigational focus (touch mode) too.
     */
    void windowFocusChanged(boolean hasFocus, boolean inTouchMode);



总结:


Activity和WMS相互持有代理,可以调用代理方法。


不过他们不直接交互,他们雇了一个中介方便统一管理,叫ViewRootImpl


0 0
原创粉丝点击