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. MySQL分区技术 (一)

    4:MySQL 分区技术(是mysql 5.1以版本号后開始用->是甲骨文mysql技术团队维护人员以插件形式插入到mysql里面的技术) 眼下,针对海量数据的优化主要有2中方法: 1:大表拆成 ...

  2. VSTO 为Office已有右键菜单添加自己的菜单项(word,Excel)

    原文:VSTO 为Office已有右键菜单添加自己的菜单项(word,Excel) private void AddRightMenu()         {            Microsoft ...

  3. 第二篇Activity:2、任务和返回堆栈(Tasks and Back Stack)之基本介绍

    参考:http://developer.android.com/guide/components/tasks-and-back-stack.html 在Android中,一个应用程序里面,通常包含了多 ...

  4. php学习之道:php中soap的使用实例以及生成WSDL文件,提供自己主动生成WSDL文件的类库——SoapDiscovery.class.php类

    1. web service普及: Webservice soap wsdl差别之个人见解 Web Service实现业务诉求:  Web Service是真正"办事"的那个,提供 ...

  5. BASH Shell 简易进度条小函数

    不多说,直接上脚本. # processbar <current> <total> processbar() { local current=$1; local total=$ ...

  6. ConditonHelper

    在网上其实已经有很多类似这种拼接sql条件的类,但是没有看到一个让我感觉完全满意的这样的类.最近看到 http://www.cnblogs.com/xtdhb/p/3811956.html 这博客,觉 ...

  7. 对consistencygroup的一些研究和实践

    声明: 本博客欢迎转载,但请保留原作者信息! 作者:李人可 团队:华为杭州OpenStack团队 consistency group,直译是一致性组,是Juno版本号cinder新引进的一个概念.顾名 ...

  8. Mesos和kubernetes

    Mesos和kubernetes http://dockone.io/article/956我坚定地认为,下一年里,它们的使用增长会更快,因此是时候回顾总结,为2016年做好准备了.本文我想讨论Mes ...

  9. Javascript Base64编码与解码

    原文:[转]Javascript Base64编码与解码 <html> <head> <META HTTP-EQUIV="MSThemeCompatible&q ...

  10. 基于.net开发chrome核心浏览器【三】

    原文:基于.net开发chrome核心浏览器[三] 本篇我们讲解怎么用CefGlue开发一个最简单的浏览器 一: CefGlue是建立在Cef项目之上的,Cef项目是C/C++的项目:CefGlue只 ...