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

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值