android4.0 WindowManagerService的分析

对于Activity,在ActivityThread.javahandleLaunchActivity会调用performLaunchActivity,而performLaunchActivity则调用Activity中的attach函数,实现创建window(实际是PhoneWindow)

Activity.java

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) {

//创建window

mWindow = PolicyManager.makeNewWindow(this);

    mWindow.setCallback(this);

    mWindow.getLayoutInflater().setPrivateFactory(this);

    if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {

         mWindow.setSoftInputMode(info.softInputMode);

    }

    if (info.uiOptions != 0) {

        mWindow.setUiOptions(info.uiOptions);

    }

//获取WindowManager

 mWindow.setWindowManager(null, mToken, mComponent.flattenToString(),

                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);

mWindowManager = mWindow.getWindowManager();

}

PolicyManager.java

public static Window makeNewWindow(Context context) {

//使用sPolicy来创建window

        return sPolicy.makeNewWindow(context);

}

这里的sPolicy定义是:private static final IPolicy sPolicy;

那么,如何初始化?

private static final String POLICY_IMPL_CLASS_NAME =

        “com.android.internal.policy.impl.Policy”;

static {

        // 获取Policy这个class并实例化

        try {

            Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME);

            sPolicy = (IPolicy)policyClass.newInstance();

        }

}

再往下:

Policy.java

public class Policy implements IPolicy {

public Window makeNewWindow(Context context) {

/*可见,activity.attach中的PolicyManager.makeNewWindow(this)是新建一个PhoneWindow

*context则是Activity中实现的ContextImpl实例

*PhoneWindowwindow的子类,故而可以赋给window

*/

        return new PhoneWindow(context);

}

……

}

Policy的定义可知,Policy implement IPolicy,并且实现了它定义的接口。

/*至此,实现了创建一个PhoneWindow*/

接着Activity.attach往下:

//设置windowCallbackActivity是实现了Window.Callback的接口的

mWindow.setCallback(this);

mWindow.getLayoutInflater().setPrivateFactory(this);

//设置soft input mode

if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {

       mWindow.setSoftInputMode(info.softInputMode);

}

if (info.uiOptions != 0) {

   mWindow.setUiOptions(info.uiOptions);

}

我们回到最初,我们说过,在ActivityThread中会在performLaunchActivity之后判断是否成功,并真正调用handleResumeActivity();

ActivityThread.java

final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {

ActivityClientRecord r = performResumeActivity(token, clearHide);

//这个layoutParams是在ActivityClientRecord 这里的。

WindowManager.LayoutParams l = r.window.getAttributes();

……

/*

*rActivityClientRecord,在performResumeActivity之前并没有将window加入到r

*那么,activity如何创建并且是如何加入到这个activityClientRecord中的呢?

*/

if (r.window == null && !a.mFinished && willBeVisible) {

               //activityattach函数中创建的activitywindow赋给r.window

       r.window = r.activity.getWindow();

   //我们知道attach创建的是PhoneWindow,那PhoneWindowDecorView如何创建的?

       View decor = r.window.getDecorView();

       decor.setVisibility(View.INVISIBLE);

   //WindowManagerViewManager的子类

       ViewManager wm = a.getWindowManager();

       WindowManager.LayoutParams l = r.window.getAttributes();

   //decor赋给ActivitymDecor

       a.mDecor = decor;

   //type的数值是1

       l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;

       l.softInputMode |= forwardBit;

       if (a.mVisibleFromClient) {

             a.mWindowAdded = true;

 //将主View(decorView)添加到WindowManager

             wm.addView(decor, l);

       }

}

}

我们在Context的分析中已经分析过,WindowManager实际上初始化的是WindowManagerImpl,通过它来进行各种操作,我们转到WindowManagerImpl.java分析addView

PhoneWindow.java

是这样获取DecorView

public final View getDecorView() {

        if (mDecor == null) {

            installDecor();

        }

        return mDecor;

}

private void installDecor() {

if (mDecor == null) {

//创建DecorView,接着往下去看如何创建DecorViewDecorView是个什么?

    mDecor = generateDecor();

    mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);

    mDecor.setIsRootNamespace(true);

}

if (mContentParent == null) {

//这个mContentParent是干什么的?

    mContentParent = generateLayout(mDecor);

}

}

private final class DecorView extends FrameLayout implements RootViewSurfaceTaker 

{

public DecorView(Context context, int featureId) {

      super(context);

      mFeatureId = featureId;

}

/*

*DecorView中还实现了派发key eventkey快捷方式等方法

*/

public boolean dispatchKeyEvent(KeyEvent event) {

……

}

public boolean dispatchKeyShortcutEvent(KeyEvent ev) {

……

}

}

DecorView定义我们可以知道,DecorView是一个扩张的FrameLayout,它是所有当前的ActivityView的主View

WindowManagerImpl.java

public void addView(View view, ViewGroup.LayoutParams params, CompatibilityInfoHolder cih)  {

     addView(view, params, cih, false);

}

private void addView(View view, ViewGroup.LayoutParams params,

            CompatibilityInfoHolder cih, boolean nest) {

//这说明将DecorView添加到WindowManager必须要满足下面这个条件,否则会报异常

if (!(params instanceof WindowManager.LayoutParams)) {

            throw new IllegalArgumentException(

                    “Params must be WindowManager.LayoutParams”);

}

final WindowManager.LayoutParams wparams

                = (WindowManager.LayoutParams)params;

ViewRootImpl root;

View panelParentView = null;

synchronized (this) {

//主要是查看要添加的View是否已经在mViews中了,若有就返回对应的index

int index = findViewLocked(view, false);

    if (index >= 0) {

         if (!nest) {

                    throw new IllegalStateException(“View ” + view

                            + ” has already been added to the window manager.”);

         }

 //为什么这样,因为若添加了viewmViews,那么mRoots也对应添加

         root = mRoots[index];

         root.mAddNesting++;

         // Update layout parameters.

         view.setLayoutParams(wparams);

         root.setLayoutParams(wparams, true);

         return;

    }

root = new ViewRootImpl(view.getContext());

//第一次添加viewmViewmViews是还没有分配空间的

if (mViews == null) {

         index = 1;

         mViews = new View[1];

         mRoots = new ViewRootImpl[1];

         mParams = new WindowManager.LayoutParams[1];

    } else {

//这里奇怪的是,为什么将mViewsmRoots中内容先保存然后再拷贝一遍呢?

         index = mViews.length + 1;

         Object[] old = mViews;

         mViews = new View[index];

         System.arraycopy(old, 0, mViews, 0, index-1);

         old = mRoots;

         mRoots = new ViewRootImpl[index];

         System.arraycopy(old, 0, mRoots, 0, index-1);

         old = mParams;

         mParams = new WindowManager.LayoutParams[index];

         System.arraycopy(old, 0, mParams, 0, index-1);

    }

            index–;

//这里就完成了添加ViewWindowManager

    mViews[index] = view;

    mRoots[index] = root;

    mParams[index] = wparams;

}

//这一步非常重要

root.setView(view, wparams, panelParentView);

}

ViewRootImpl.java

public ViewRootImpl(Context context) {

getWindowSession(context.getMainLooper());

//获取当前activity的线程

mThread = Thread.currentThread();

//IWindow的代理,在ViewRootImpl中创建

//这里强调一下,创建W时传入this,代指ViewRootImplContextImpl,而这个ContextImpl又是由

//WindowManagerImpl传入的ContextImpl,再之后就是当前的调用者的ContextImpl传递给//ContextImpl.java的获取Service时传入的。这样看来,在当前的上下文创建了一个实例,只要传入它的//Context,那么,都是可以通过Context找到这个当前调用者的

mWindow = new W(this);

}

public static IWindowSession getWindowSession(Looper mainLooper) {

        synchronized (mStaticInit) {

            if (!mInitialized) {

                try {

//先获取InputMethodManager,然后用它调用InputMethodManagerService

                    InputMethodManager imm = InputMethodManager.getInstance(mainLooper);

                    //获取WindowManagerService中的Session,同时我们看到这里用到了

//InputMethodManagerServicemClientControlledInputConnectionWrapper

sWindowSession = Display.getWindowManager().openSession(

                            imm.getClient(), imm.getInputContext());

                    

mInitialized = true;

                } catch (RemoteException e) {

                }

            }

//注意:sWindowSession是个全局变量

            return sWindowSession;

        }

}

WindowManagerService.java

这个sWindowSession是在WindowManagerService中实现的,是client调用WindowManagerService的接口。

每一个ViewRoot对应在WindowManagerService中有一个sWindowSession

同时我们注意,这里传入的clientInputMethodManager中的IInputMethodClient类型的mClient

public IWindowSession openSession(IInputMethodClient client,

            IInputContext inputContext) {

……

//创建一个Session并返回

//在这个Session的构造函数中有如下操作:

//mService.mInputMethodManager.addClient(client, inputContext, mUid, mPid);

//InputMethodManger中的mClient添加进去了                    

Session session = new Session(this, client, inputContext);

return session;

}

我们接着,WindowManagerImpl往下看,在setView的最后会调用ViewRoot.setView(),这个是连接client

WindowManagerService的关键地方:

public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {

……

try {

    mOrigWindowType = mWindowAttributes.type;

//这里调用

    res = sWindowSession.add(mWindow, mSeq, mWindowAttributes,

                getHostVisibility(), mAttachInfo.mContentInsets, mInputChannel);

    } catch (RemoteException e) {

……

}

}

Session.java

public int add(IWindow window, int seq, WindowManager.LayoutParams attrs,

            int viewVisibility, Rect outContentInsets, InputChannel outInputChannel) {

 //如此,将Client端提供给WindowManagerService的接口IWindow赋给WindowManagerService使用

     return mService.addWindow(this, window, seq, attrs, viewVisibility, outContentInsets,

                outInputChannel);

}

WindowManagerService.java

//主要是将PhoneWindow的回调函数IWindow传递给WindowManagerService

//outInputChannelinputChannel

public int addWindow(Session session, IWindow client, int seq,

            WindowManager.LayoutParams attrs, int viewVisibility,

            Rect outContentInsets, InputChannel outInputChannel) {

WindowState win = null;

win = new WindowState(this, session, client, token,

                    attachedWindow, seq, attrs, viewVisibility);

……

win.attach();

       if (outInputChannel != null && (attrs.inputFeatures

                    & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {

           String name = win.makeInputChannelName();

           InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);

           win.setInputChannel(inputChannels[0]);

           inputChannels[1].transferTo(outInputChannel);

                

           mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);

       }

}

windowState.java中调用attach

void attach() {

mSession.windowAddedLocked();

}

最后在Session.java中实现添加:

void windowAddedLocked() {

     if (mSurfaceSession == null) {

         mSurfaceSession = new SurfaceSession();

         mService.mSessions.add(this);

     }

     mNumWindow++;

}

至此,正式建立activityclientwindowManagerService之间的联系:

ViewRootImpl 通过IWindowSession 访问 WindowManagerService

WindowManagerService通过IWindow访问ViewRootImpl

    原文作者:kakaback
    原文地址: https://blog.csdn.net/kakaback/article/details/7747805
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞