1、每个窗体的ViewRootImpl都有一个mWindowAttributes窗体属性,该属性在WindowManagerGlobal.updateViewLayout()->ViewRootImpl.setView()和WindowManagerGlobal.updateViewLayout->ViewRootImpl.setLayoutParams()中赋值。同一时候ViewRootImpl.mWindowAttributesChanged也会设为true表示窗体属性已更改。当窗体属性更改时。surfaceChanged也会设置为true

 if (mWindowAttributesChanged) {
mWindowAttributesChanged = false;
surfaceChanged = true;
params = lp;
}

当surfaceChanged设置为true时,以下这段代码会调用

if (surfaceChanged) {
mSurfaceHolderCallback.surfaceChanged(mSurfaceHolder,
lp.format, mWidth, mHeight);
SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
if (callbacks != null) {
for (SurfaceHolder.Callback c : callbacks) {
c.surfaceChanged(mSurfaceHolder, lp.format,
mWidth, mHeight);
}
}
}

调用回调函数,表明当前窗体Surface有更新。

2、在WMS中Stackbox、TaskStack、Task、AppWindowToken之间的关系:

3、relayoutWindow()函数中对于可见的壁纸、输入法、activity等窗体会作下面处理:

            if (viewVisibility == View.VISIBLE &&
(win.mAppToken == null || !win.mAppToken.clientHidden)) {
toBeDisplayed = !win.isVisibleLw();
if (win.mExiting) {
winAnimator.cancelExitAnimationForNextAnimationLocked();
win.mExiting = false;
}
if (win.mDestroying) {
win.mDestroying = false;
mDestroySurface.remove(win);
}
if (oldVisibility == View.GONE) {
winAnimator.mEnterAnimationPending = true;
}
if (toBeDisplayed) {
if (win.isDrawnLw() && okToDisplay()) {
winAnimator.applyEnterAnimationLocked();
}
if ((win.mAttrs.flags
& WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
if (DEBUG_VISIBILITY) Slog.v(TAG,
"Relayout window turning screen on: " + win);
win.mTurnOnScreen = true;
}
if (win.isConfigChanged()) {
if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + win
+ " visible with new config: " + mCurConfiguration);
outConfig.setTo(mCurConfiguration);
}
}
if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) {
// To change the format, we need to re-build the surface.
winAnimator.destroySurfaceLocked();
toBeDisplayed = true;
surfaceChanged = true;
}
try {
if (!win.mHasSurface) {
surfaceChanged = true;
}
SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();
if (surfaceControl != null) {
outSurface.copyFrom(surfaceControl);
if (SHOW_TRANSACTIONS) Slog.i(TAG,
" OUT SURFACE " + outSurface + ": copied");
} else {
// For some reason there isn't a surface. Clear the
// caller's object so they see the same state.
outSurface.release();
}
} catch (Exception e) {
mInputMonitor.updateInputWindowsLw(true /*force*/); Slog.w(TAG, "Exception thrown when creating surface for client "
+ client + " (" + win.mAttrs.getTitle() + ")",
e);
Binder.restoreCallingIdentity(origId);
return 0;
}
if (toBeDisplayed) {
focusMayChange = isDefaultDisplay;
}
if (win.mAttrs.type == TYPE_INPUT_METHOD
&& mInputMethodWindow == null) {
mInputMethodWindow = win;
imMayMove = true;
}
if (win.mAttrs.type == TYPE_BASE_APPLICATION
&& win.mAppToken != null
&& win.mAppToken.startingWindow != null) {
// Special handling of starting window over the base
// window of the app: propagate lock screen flags to it,
// to provide the correct semantics while starting.
final int mask =
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
| WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
WindowManager.LayoutParams sa = win.mAppToken.startingWindow.mAttrs;
sa.flags = (sa.flags&~mask) | (win.mAttrs.flags&mask);
}
}

假设当前窗体在退出(win.mExiting==true),就调用cancelExitAnimationForNextAnimationLocked()取消退出动画。假设窗体正在销毁(win.mDestroying)。就将该窗体从mDestroySurface中移除,mDestroySurface中保存的都是要销毁surface的窗体。假设该窗体上一个状态是不可见的,即由不可见进入可见状态,winAnimator.mEnterAnimationPending = true;表示等待进入动画;

    void applyEnterAnimationLocked() {
final int transit;
if (mEnterAnimationPending) {
mEnterAnimationPending = false;
transit = WindowManagerPolicy.TRANSIT_ENTER;
} else {
transit = WindowManagerPolicy.TRANSIT_SHOW;
}
applyAnimationLocked(transit, true);
//TODO (multidisplay): Magnification is supported only for the default display.
if (mService.mDisplayMagnifier != null
&& mWin.getDisplayId() == Display.DEFAULT_DISPLAY) {
mService.mDisplayMagnifier.onWindowTransitionLocked(mWin, transit);
}
}

mEnterAnimationPending =true时。调用applyAnimationLocked()函数传进去的參数就为 WindowManagerPolicy.TRANSIT_ENTER表示窗体进入动画。

    boolean applyAnimationLocked(int transit, boolean isEntrance) {
if (mLocalAnimating && mAnimationIsEntrance == isEntrance) {
// If we are trying to apply an animation, but already running
// an animation of the same type, then just leave that one alone.
return true;
} // Only apply an animation if the display isn't frozen. If it is
// frozen, there is no reason to animate and it can cause strange
// artifacts when we unfreeze the display if some different animation
// is running.
if (mService.okToDisplay()) {
int anim = mPolicy.selectAnimationLw(mWin, transit);
int attr = -1;
Animation a = null;
if (anim != 0) {
a = anim != -1 ? AnimationUtils.loadAnimation(mContext, anim) : null;
} else {
switch (transit) {
case WindowManagerPolicy.TRANSIT_ENTER:
attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation;
break;
case WindowManagerPolicy.TRANSIT_EXIT:
attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation;
break;
case WindowManagerPolicy.TRANSIT_SHOW:
attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation;
break;
case WindowManagerPolicy.TRANSIT_HIDE:
attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation;
break;
}
if (attr >= 0) {
a = mService.mAppTransition.loadAnimation(mWin.mAttrs, attr);
}
}
if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
"applyAnimation: win=" + this
+ " anim=" + anim + " attr=0x" + Integer.toHexString(attr)
+ " a=" + a
+ " transit=" + transit
+ " isEntrance=" + isEntrance + " Callers " + Debug.getCallers(3));
if (a != null) {
if (WindowManagerService.DEBUG_ANIM) {
RuntimeException e = null;
if (!WindowManagerService.HIDE_STACK_CRAWLS) {
e = new RuntimeException();
e.fillInStackTrace();
}
Slog.v(TAG, "Loaded animation " + a + " for " + this, e);
}
setAnimation(a);
mAnimationIsEntrance = isEntrance;
}
} else {
clearAnimation();
} return mAnimation != null;
}

applyAnimationLocked()函数中,对于状态栏、导航栏(三个虚拟按键)selectAnimationLw()返回相应的动画资源id,对于一般窗体返回0。对于一般应用窗体,有“窗体进入”动画、“窗体退出”动画、“窗体显示”动画、“窗体隐藏”动画。找到相应的窗体动画资源。然后调用mService.mAppTransition.loadAnimation(mWin.mAttrs, attr)进行载入动画。

载入成功后再调用setAnimation(a)来设置当前窗体动画。mAppTransition是一个AppTransition类对象,AppTransition是一个转场动画状态管理类,该类中有一个mAppTransitionState变量。该变量就是专门用来保存当前转场动画状态的;AppTransition类中有两个创建动画的函数,一个是创建放大动画createScaleUpAnimationLocked,一个是创建缩小动画createThumbnailAnimationLocked().

    Animation loadAnimation(WindowManager.LayoutParams lp, int animAttr) {
int anim = 0;
Context context = mContext;
if (animAttr >= 0) {
AttributeCache.Entry ent = getCachedAnimations(lp);
if (ent != null) {
context = ent.context;
anim = ent.array.getResourceId(animAttr, 0);
}
}
if (anim != 0) {
return AnimationUtils.loadAnimation(context, anim);
}
return null;
}

该函数调用动画工具类AnimationUtils.loadAnimation()函数。參数anim是动画资源id,AnimationUtils.loadAnimation()中调用了createAnimationFromXml(context, parser);静态函数,parser是一个XmlResourceParser对象,动画资源id保存在该对象中。createAnimationFromXml()从名字能够看出就是从xml文件里解析出一个Animation出来

    private static Animation createAnimationFromXml(Context c, XmlPullParser parser,
AnimationSet parent, AttributeSet attrs) throws XmlPullParserException, IOException { Animation anim = null; // Make sure we are on a start tag.
int type;
int depth = parser.getDepth(); while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
&& type != XmlPullParser.END_DOCUMENT) { if (type != XmlPullParser.START_TAG) {
continue;
} String name = parser.getName(); if (name.equals("set")) {
anim = new AnimationSet(c, attrs);
createAnimationFromXml(c, parser, (AnimationSet)anim, attrs);
} else if (name.equals("alpha")) {
anim = new AlphaAnimation(c, attrs);
} else if (name.equals("scale")) {
anim = new ScaleAnimation(c, attrs);
} else if (name.equals("rotate")) {
anim = new RotateAnimation(c, attrs);
} else if (name.equals("translate")) {
anim = new TranslateAnimation(c, attrs);
} else {
throw new RuntimeException("Unknown animation name: " + parser.getName());
} if (parent != null) {
parent.addAnimation(anim);
}
} return anim; }

while循环依照一定的格式(动画格式)解析xml,依据不同的动画创建相应的Animation对象,然后返回。

对于AnimationSet动画(动画组合机制)。递归调用createAnimationFromXml()函数,将一个个动画按队列的方式保存,最后返回第一个动画。由源码看出android提供了组合动画、渐变动画、缩放动画、旋转动画、转场动画(移动的动画效果。图片浏览滑动效果)。

回到applyAnimationLocked()函数中。从xml文件里解析出一个相应的Animation后,再调用setAnimation(a)

public void setAnimation(Animation anim) {

        if (localLOGV) Slog.v(TAG, "Setting animation in " + this + ": " + anim);
mAnimating = false;
mLocalAnimating = false;
mAnimation = anim;
mAnimation.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION);
mAnimation.scaleCurrentDuration(mService.mWindowAnimationScale);
// Start out animation gone if window is gone, or visible if window is visible.
mTransformation.clear();
mTransformation.setAlpha(mLastHidden ? 0 : 1);
mHasLocalTransformation = true;
}

该函数非常easy,设置mAnimating、mLocalAnimating为false,将上一步得到的Animation对象保存到WindowStateAnimator.mAnimation中。

3、WindowManagerService中 Configuration类对象mCurConfiguration中保存着当前配置信息。setNewConfiguration()负责更新这个对象。setNewConfiguration()被ActivityManagerService.updateConfigurationLocked()调用。AMS调用WMS的updateConfigurationLocked()函数时传入的configuration对象是AMS中的mConfiguration,那AMS与WMS保持相同configuration配置信息。

版权声明:本文博客原创文章,博客,未经同意,不得转载。

ViewRootImpl和WindowManagerService笔记的更多相关文章

  1. Android开发之漫漫长途 Ⅴ——Activity的显示之ViewRootImpl的PreMeasure、WindowLayout、EndMeasure、Layout、Draw

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...

  2. 《深入理解Android 卷III》第七章 深入理解SystemUI

    <深入理解Android 卷III>即将公布,作者是张大伟.此书填补了深入理解Android Framework卷中的一个主要空白,即Android Framework中和UI相关的部分. ...

  3. Android 显示系统:SurfaceFlinger详解

    一.Android系统启动 Android设备从按下开机键到桌面显示画面,大致过程如下图流程: 开机显示桌面.从桌面点击 App 图标到 Activity显示在屏幕上的过程又是怎样的呢?下面介绍And ...

  4. Android全面解析之Window机制

    前言 你好! 我是一只修仙的猿,欢迎阅读我的文章. Window,读者可能更多的认识是windows系统的窗口.在windows系统上,我们可以多个窗口同时运行,每个窗口代表着一个应用程序.但在安卓上 ...

  5. 《android开发艺术探索》读书笔记(八)--WindowManager

    接上篇<android开发艺术探索>读书笔记(七)--动画 No1: Window是一个抽象类,它的具体实现是PhoneWindow.创建一个Window是很简单的事,只需要通过Windo ...

  6. Android笔记--View绘制流程源码分析(一)

    Android笔记--View绘制流程源码分析 View绘制之前框架流程分析 View绘制的分析始终是离不开Activity及其内部的Window的.在Activity的源码启动流程中,一并包含 着A ...

  7. 3.View绘制分析笔记之onLayout

    上一篇文章我们了解了View的onMeasure,那么今天我们继续来学习Android View绘制三部曲的第二步,onLayout,布局. ViewRootImpl#performLayout pr ...

  8. 4.View绘制分析笔记之onDraw

    上一篇文章我们了解了View的onLayout,那么今天我们来学习Android View绘制三部曲的最后一步,onDraw,绘制. ViewRootImpl#performDraw private ...

  9. 2.View绘制分析笔记之onMeasure

    今天主要学习记录一下Android View绘制三部曲的第一步,onMeasure,测量. 起源 在Activity中,所有的View都是DecorView的子View,然后DecorView又是被V ...

随机推荐

  1. OCA读书笔记(14) - 备份和恢复基本概念

    备份恢复概念 如何判断数据库的一致性 在mount状态下,oracle如何判断数据库的一致性 scn:system change number,它是数据库时钟 如何查询当前系统的scn: select ...

  2. Codeforce 57C Array

    C. Array time limit per test 2 seconds memory limit per test 256 megabytes input standard input outp ...

  3. Zigbee开发(1)

    只是研究zigbee的技术,也许后续的博客不会有很及时的更新,有时间 写一点东西能让大家有所收获吧. 环境搭建 Windows 64位的操作系统 IAR7.6 for 8051 ZStack CC25 ...

  4. HDU4876ZCC loves cards(多校题)

    ZCC loves cards Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Tot ...

  5. Flex中的DataGrid报错(二)

    1.错误描写叙述 此行的多个标记: -holeNum -1067: String 类型值的隐式强制指令的目标是非相关类型 mx.controls:Text. 2.错误原因  将字符串类型赋值给Text ...

  6. 低版本的 opencv库的 vs2010 打开 高版本opencv

    打开track.vcxproj文件, 注释掉跟版本有关的行就可. 本例子中,当用双击.sln用vs2010打开高版本的opencv项目时,会出现错误, 并且会有错误信息提示,双击该错误信息,就会打开该 ...

  7. Unity MVC框架 StrangeIoC

    StrangeIoC是一个超轻量级和高度可扩展的控制反转(IoC)框架,专门为C#和Unity编写. 项目地址:https://github.com/strangeioc/strangeioc 文档地 ...

  8. C++设计模式--观察员

    概要 在软件构建过程中.我们须要为某些对象建立一种"通知依赖关系" --一个对象(目标对象)的状态发生改变,全部的依赖对象(观察者对象)都将得到通知.假设这种依赖关系过于紧密,将使 ...

  9. properties editor for eclipse安装使用

    properties editor 是 Eclipse下编辑properties文件的插件,用来写国际化程序非常方便,自动保存为ASCII码,支持Unicode. 安装过程: 打开eclispe编辑器 ...

  10. 关于git的ssh-key:解决本地多个ssh-key的问题

    在设置github的时候,官方的说明文档要求备份当前的id_rsa.然后生成一份新的私钥用于github的登陆.假设真这样做,那么新的私钥是无法再继续登陆之前的机器的. 这样的方法有点暴力- 还好ss ...