zoukankan      html  css  js  c++  java
  • ViewRootImpl和WindowManagerService笔记

    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配置信息。

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

  • 相关阅读:
    第五章 Internet协议
    第四章 地址解析协议
    Learn the shell
    Linux学习前的准备
    第三章 链路层
    第二章 Internet 地址结构
    后台数据导出为Excel
    C#开发客户端、JAVA和tomcat开发服务端
    Java基础
    C++学习笔记--(1)
  • 原文地址:https://www.cnblogs.com/yxwkf/p/4624494.html
Copyright © 2011-2022 走看看