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. Xcode 4.6.2 运行次数为偶数程序崩溃问题

    如果你的MAC 系统升级到10.8.4  Xcode升级到4.6.2,在工程运行第二次.第四次.第六次 ... 的时候程序就会崩溃 无论是新建的模板工程也会这样,这个属于系统BUG,在stackove ...

  2. Extjs 3.4 和 web SSH(Ajaxterm)-howge-ChinaUnix博客

    Extjs 3.4 和 web SSH(Ajaxterm)-howge-ChinaUnix博客   Extjs 3.4 和 web SSH(Ajaxterm) 2013-04-07 15:20:17 ...

  3. 从零开始,使用python快速开发web站点(1)

    环境:ubuntu 12.04 python版本:  2.73 ok,首先,既然是从零开始,我们需要的是一台可以运行的python的计算机环境,并且假设你已经安装好了python, (ubuntu 或 ...

  4. Python基础 - 关键字

    前言 与C一样,python也有自己的关键字,关键字有特殊的意义,不能作为普通的变量名类名等用途 关键字列表 以python2.7.5为例,有如下关键字: and del from not while ...

  5. Flume传输数据事务分析

    Flume传输数据事务分析 本文基于ThriftSource,MemoryChannel,HdfsSink三个组件,对Flume传输数据的事务进行分析.假设使用的是其它组件.Flume事务详细的处理方 ...

  6. JavaFX的扩展控件库ControlsFX介绍

    声明:   本博客文章原创类别的均为个人原创,版权所有.转载请注明出处: http://blog.csdn.net/ml3947,另外本人的个人博客:http://www.wjfxgame.com. ...

  7. IE浏览器审查密码的清除

    上周去188工业区,总装厂的喷油部的电脑上被谁设置了IE的审查密码,后来通过电话沟通,运维岗给出了具体的解决方法: 进入注册表HKEY_LOCAL_MACHINE\Software\Microsoft ...

  8. Linux进程间通信(九)---综合实验之有名管道通信实验

    实验目的 通过编写有名管道多路通信实验,进一步掌握管道的创建.读写等操作,同时复习使用select()函数实现管道的通信. 实验内容 这里采用管道函数创建有名管道(不是在控制台下输入命令mknod), ...

  9. adt-bundle-windows-x86_32-20140702

    adt-bundle-windows-x86_32-20140702 Windows > Preference,在Android里没有NDK选项 法一:help->install new ...

  10. Linux如何查找大文件或目录总结及在全部目录中查找

    在Windows系统中,我们可以使用TreeSize工具查找一些大文件或文件夹,非常的方便高效,在Linux系统中,如何去搜索一些比较大的文件呢?下面我整理了一下在Linux系统中如何查找大文件或文件 ...