参考:http://www.cnblogs.com/samchen2009/p/3364327.html
《图3》Choreographer处理Vsync流程图
《图5》
1)1号区域为OverscanScreen,包含了屏幕上的overscan区,相当于整个屏幕大小
2)2号区域为RestrictedOverscanScreen,包含overscan,不包含导航栏。因些上端到达屏幕的顶部,下端则只到导航栏的顶部
3)3号区域为RestrictedScreen,不包含屏幕上的overscan,不包含导航栏
4)4区域为UnrestrictedScreen,不包含Overscan,包含状态栏和导航栏
5)5区域为StableFullscreen,包含状态栏,不包含导航栏
6)6区域为Decor,不包含状态栏,不包含导航栏,包含输入法区域(System区域、Stable区域、Content区域同等)
7)7区域为Curren,不包含状态栏,不包含导航栏,不包含输入法区域
pf(ParentFrame):表示窗口的父窗的大小
df(DeviceFrame):设备的屏幕大小
of(OverScanFrame):设备的屏幕大小,和df的值一样
cf(ContentFrame):窗口内容区域的大小
vf(VisibleFrame):窗口可见区域的大小
dcf(DecorFrame):装饰区域的大小。除去状态栏条和导航条的区域
pf、df、of不包括导航栏;cf、vf不包含导航栏、状态栏、输入法;sf不包含导航栏、状态栏
1、addWindow()函数
//在mTokenMap中查找windowToken
WindowToken token = mTokenMap.get(attrs.token);
//子窗口,寻找父窗口
if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
attachedWindow = windowForClientLocked(null, attrs.token, false);
//创建WindowState对象
WindowState win = new WindowState(this, session, client, token,attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
//调整窗口参数
mPolicy.adjustWindowParamsLw(win.mAttrs);
//检查和设置窗口是否能够让其他的用户看见
win.setShowToOwnerOnlyLocked(mPolicy.checkShowToOwnerOnly(attrs));
//检查特殊类型的窗口是否能添加
res = mPolicy.prepareAddWindowLw(win, attrs);
//如果窗口接受输入,注册inputChannel
String name = win.makeInputChannelName();
InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
win.setInputChannel(inputChannels[0]);
inputChannels[1].transferTo(outInputChannel);
mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);
//加入WindowState对象到列表中。mWindowMap列表中保存了系统中所有顶层窗口的信息
win.attach();
mWindowMap.put(client.asBinder(), win);
//把WindowState按顺序加到mWindows。DisplayContent类的mWindows列表按Z序保存了每个窗口
addWindowToListInOrderLocked(win, true);
//计算Content区域大小
mPolicy.getInsetHintLw(win.mAttrs, mRotation, outContentInsets, outStableInsets,outOutsets);
//如果窗口能接受输入计算是否引起焦点变化
if (win.canReceiveKeys()) {
focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
false /*updateInputWindows*/);
if (focusChanged) {
imMayMove = false;
}
}
//重新计算z轴的位置
assignLayersLocked(displayContent.getWindowList());
//设置和更新Input焦点变化
if (focusChanged) {
mInputMonitor.setInputFocusLw(mCurrentFocus, false /*updateInputWindows*/);
}
mInputMonitor.updateInputWindowsLw(false /*force*/);
1.1、win.attach()函数
mSurfaceSession = new SurfaceSession();
mService.mSessions.add(this);
mNumWindow++;
2、invalidate
View.invalidate-> View.invalidateInternal-> ViewParent.invalidateChild
ViewRootImpl.invalidateChildInParent-> ViewRootImpl.scheduleTraversals
mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
3、performTraversals()函数
4、relayoutWindow()函数
//获取窗口WindowState
WindowState win = windowForClientLocked(session, client, false);
//如果请求窗口大小跟实际WindowState大小不一样,则以请求大小为标准
if (viewVisibility != View.GONE && (win.mRequestedWidth != requestedWidth
|| win.mRequestedHeight != requestedHeight)) {
win.mLayoutNeeded = true;
win.mRequestedWidth = requestedWidth;
win.mRequestedHeight = requestedHeight;
}
/**对于处于可见状态的窗口处理:
*1、如果窗口没有Surface,则为其创建一块Surface
*2、如果客户端改变了窗口的色彩格式(由LayoutParams.format指定)发生了变化则为其重新创建一块指定格式的Surface
*3、如果窗口尚未被显示,并且客串的客户端已经完成了绘制,则为其启动一个淡入动画
*/
if (viewVisibility == View.VISIBLE &&(win.mAppToken == null || !win.mAppToken.clientHidden)) {
winAnimator.mEnteringAnimation = true;
//执行进入动画
if (win.isDrawnLw() && okToDisplay()) {
winAnimator.applyEnterAnimationLocked();
}
//创建Surface
SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();
} else {
/*对于处于非可见状态下的窗口,主要的处理如下:
*1、标记WindowState的mExiting属性为true
*2、如果窗口目前正被显示,则为其启动一个淡出动画
*3、释放客户端所持有的Surface对象,自此之后,客户端无法再更新窗口的内容
*/
if (win.isWinVisibleLw() &&winAnimator.applyAnimationLocked(transit, false)) {
focusMayChange = isDefaultDisplay;
win.mExiting = true;
}
outSurface.release();
//更新焦点窗口
if (focusMayChange) {
if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
false /*updateInputWindows*/)) {
imMayMove = false;
}
}
//见<<深入理解Android 卷3>>分析,参考
《图5》
performLayoutAndPlaceSurfacesLocked();
//返回布局结果
outFrame.set(win.mCompatFrame);
outOverscanInsets.set(win.mOverscanInsets);
outContentInsets.set(win.mContentInsets);
outVisibleInsets.set(win.mVisibleInsets);
outStableInsets.set(win.mStableInsets);
outOutsets.set(win.mOutsets);