一个关于android WindowManangerService layer 异常的bug

          一个关于android WindowManangerService layer 异常的bug

最近在工作中,解决的一个android 原生的问题,分享给大家:


手机在MTBF 测试的时候,有一个简单的case:那就是在信息文件夹视图下,点击左上角列表框,没有弹出含“发件箱”、“草稿箱”等选项的列表,然后选择草稿箱,再退出。

结果在多次测试中,极偶现在信息文件夹视图下,点击左上角列表框,没有弹出含“发件箱”、“草稿箱”等选项的列表。


刚开始这个问题也是没有思路,只能够确认发生问题的时候,窗口的焦点是正常的切换的,但是却没有显示出来。

刚开始怀疑graphic的问题,于是在android framework 里面添加log 复测。


在log中发现这样的现象:
从Input focus has changed to popupwindow 到 Input focus has changed to BoxMsgListActivity持续了近一分钟。
在这一分钟时间段内应该是popupwindow的显示时间段。

11-29 23:07:06.048   565 19274 D WindowManager: Input focus has changed to Window{41dd3170 u0 PopupWindow:41fc51d8}

11-29 23:08:00.701   565   879 D WindowManager: Input focus has changed to Window{41ec9e58 u0 com.android.mms/com.sprd.mms.folderview.BoxMsgListActivity}


但是在SurfaceFlinger这边加log发现:
popupwindow在layer list里面只是持续了从11-29 23:07:06.158到11-29 23:07:06.358的200ms内, 
在接下来的时间段内popupwindow便从layer list中消失了。


下面是事发现场的surfaceflinger中的信息:

11-29 23:07:08.410   161   161 D SurfaceFlinger: + Layer 0xb805e618 (PopupWindow:41fc51d8)
11-29 23:07:08.410   161   161 D SurfaceFlinger:   Region transparentRegion (this=0xb805e77c, count=1)
11-29 23:07:08.410   161   161 D SurfaceFlinger:     [  0,   0,   0,   0]
11-29 23:07:08.410   161   161 D SurfaceFlinger:   Region visibleRegion (this=0xb805e620, count=1)
11-29 23:07:08.410   161   161 D SurfaceFlinger:     [  0,   0,   0,   0]
11-29 23:07:08.410   161   161 D SurfaceFlinger:       layerStack=   0, z=    21055, pos=(0,98), size=( 153, 315), crop=(   0,   0, 153, 315), isOpaque=0, invalidate=0, alpha=0xff, flags=0x00000000, tr=[1.00, 0.00][0.00, 1.00]
11-29 23:07:08.410   161   161 D SurfaceFlinger:       client=0xb803b350
11-29 23:07:08.410   161   161 D SurfaceFlinger:       format= 1, activeBuffer=[ 153x 315: 154,  1], queued-frames=0, mRefreshPending=0
11-29 23:07:08.410   161   161 D SurfaceFlinger:             mTexName=2 mCurrentTexture=2
11-29 23:07:08.410   161   161 D SurfaceFlinger:             mCurrentCrop=[0,0,0,0] mCurrentTransform=0
11-29 23:07:08.410   161   161 D SurfaceFlinger:             mAbandoned=0
11-29 23:07:08.410   161   161 D SurfaceFlinger:             -BufferQueue mMaxAcquiredBufferCount=1, mDequeueBufferCannotBlock=0, default-size=[153x315], default-format=1, transform-hint=00, FIFO(0)={}
11-29 23:07:08.410   161   161 D SurfaceFlinger:              [00:0xb8012d40] state=FREE    , 0xb8025d48 [ 153x 315: 154,  1]
11-29 23:07:08.410   161   161 D SurfaceFlinger:              [01:0xb8014c10] state=FREE    , 0xb8037440 [ 153x 315: 154,  1]
11-29 23:07:08.410   161   161 D SurfaceFlinger:             >[02:0xb8036220] state=ACQUIRED, 0xb80152b0 [ 153x 315: 154,  1]
11-29 23:07:08.410   161   161 D SurfaceFlinger:              [03:0xb805d140] stat
11-29 23:07:08.410   161   161 D SurfaceFlinger: + Layer 0xb805b738 (com.android.mms/com.sprd.mms.folderview.BoxMsgListActivity)
11-29 23:07:08.410   161   161 D SurfaceFlinger:   Region transparentRegion (this=0xb805b89c, count=1)
11-29 23:07:08.410   161   161 D SurfaceFlinger:     [  0,   0,   0,   0]
11-29 23:07:08.410   161   161 D SurfaceFlinger:   Region visibleRegion (this=0xb805b740, count=1)
11-29 23:07:08.410   161   161 D SurfaceFlinger:     [  0,  38, 480, 800]
11-29 23:07:08.410   161   161 D SurfaceFlinger:       layerStack=   0, z=    22050, pos=(0,0), size=( 480, 800), crop=(   0,  38, 480, 800), isOpaque=1, invalidate=0, alpha=0xff, flags=0x00000000, tr=[1.00, 0.00][0.00, 1.00]
11-29 23:07:08.410   161   161 D SurfaceFlinger:       client=0xb803b350
11-29 23:07:08.410   161   161 D SurfaceFlinger:       format= 1, activeBuffer=[ 480x 800: 480,  1], queued-frames=0, mRefreshPending=0
11-29 23:07:08.410   161   161 D SurfaceFlinger:             mTexName=10 mCurrentTexture=1
11-29 23:07:08.410   161   161 D SurfaceFlinger:             mCurrentCrop=[0,0,0,0] mCurrentTransform=0
11-29 23:07:08.410   161   161 D SurfaceFlinger:             mAbandoned=0
11-29 23:07:08.410   161   161 D SurfaceFlinger:             -BufferQueue mMaxAcquiredBufferCount=1, mDequeueBufferCannotBlock=0, default-size=[480x800], default-format=1, transform-hint=00, FIFO(0)={}
11-29 23:07:08.410   161   161 D SurfaceFlinger:              [00:0xb8018638] state=FREE    , 0xb804f748 [ 480x 800: 480,  1]
11-29 23:07:08.410   161   161 D SurfaceFlinger:             >[01:0xb8024c40] state=ACQUIRED, 0xb8030440 [ 480x 800: 480,  1]
11-29 23:07:08.410   161   161 D SurfaceFlinger:              [02:0xb80544d0] state=FREE    , 0xb8046a68 [ 480x 800: 480,
11-29 23:07:08.410   161   161 D SurfaceFlinger: + Layer 0xb801eea0 (StatusBar)
11-29 23:07:08.410   161   161 D SurfaceFlinger:   Region transparentRegion (this=0xb801f004, count=1)
11-29 23:07:08.410   161   161 D SurfaceFlinger:     [  0,   0,   0,   0]
11-29 23:07:08.410   161   161 D SurfaceFlinger:   Region visibleRegion (this=0xb801eea8, count=1)
11-29 23:07:08.410   161   161 D SurfaceFlinger:     [  0,   0, 480,  38]
11-29 23:07:08.410   161   161 D SurfaceFlinger:       layerStack=   0, z=   161000, pos=(0,0), size=( 480,  38), crop=(   0,   0, 480,  38), isOpaque=0, invalidate=0, alpha=0xff, flags=0x00000000, tr=[1.00, 0.00][0.00, 1.00]
11-29 23:07:08.410   161   161 D SurfaceFlinger:       client=0xb801ecd8
11-29 23:07:08.410   161   161 D SurfaceFlinger:       format= 1, activeBuffer=[ 480x  38: 480,  1], queued-frames=0, mRefreshPending=0
11-29 23:07:08.410   161   161 D SurfaceFlinger:             mTexName=6 mCurrentTexture=0
11-29 23:07:08.410   161   161 D SurfaceFlinger:             mCurrentCrop=[0,0,0,0] mCurrentTransform=0
11-29 23:07:08.410   161   161 D SurfaceFlinger:             mAbandoned=0
11-29 23:07:08.410   161   161 D SurfaceFlinger:             -BufferQueue mMaxAcquiredBufferCount=1, mDequeueBufferCannotBlock=0, default-size=[480x38], default-format=1, transform-hint=00, FIFO(0)={}
11-29 23:07:08.410   161   161 D SurfaceFlinger:             >[00:0xb802f200] state=ACQUIRED, 0xb80203f8 [ 480x  38: 480,  1]
11-29 23:07:08.410   161   161 D SurfaceFlinger:              [01:0xb8025b10] state=FREE    , 0xb80257c8 [ 480x  38: 480,  1]
11-29 23:07:08.410   161   161 D SurfaceFlinger:              [02:0xb8025dc0] state=FREE    , 0xb8024be8 [ 480x  38: 480,  1]
11-29 23:07:08.410   161   161 D SurfaceFlinger:              [03:0xb80260e0] state=FREE    , 0

作为对比我们又测试了正常情况下,popwindow的layer:

11-29 23:07:06.158   161   161 D SurfaceFlinger: + Layer 0xb805b738 (com.android.mms/com.sprd.mms.folderview.BoxMsgListActivity)
11-29 23:07:06.158   161   161 D SurfaceFlinger:   Region transparentRegion (this=0xb805b89c, count=1)
11-29 23:07:06.158   161   161 D SurfaceFlinger:     [  0,   0,   0,   0]
11-29 23:07:06.158   161   161 D SurfaceFlinger:   Region visibleRegion (this=0xb805b740, count=1)
11-29 23:07:06.158   161   161 D SurfaceFlinger:     [  0,  38, 480, 800]
11-29 23:07:06.158   161   161 D SurfaceFlinger:       layerStack=   0, z=    22050, pos=(0,0), size=( 480, 800), crop=(   0,  38, 480, 800), isOpaque=1, invalidate=0, alpha=0xff, flags=0x00000000, tr=[1.00, 0.00][0.00, 1.00]
11-29 23:07:06.158   161   161 D SurfaceFlinger:       client=0xb803b350
11-29 23:07:06.158   161   161 D SurfaceFlinger:       format= 1, activeBuffer=[ 480x 800: 480,  1], queued-frames=0, mRefreshPending=0
11-29 23:07:06.158   161   161 D SurfaceFlinger:             mTexName=10 mCurrentTexture=1
11-29 23:07:06.158   161   161 D SurfaceFlinger:             mCurrentCrop=[0,0,0,0] mCurrentTransform=0
11-29 23:07:06.158   161   161 D SurfaceFlinger:             mAbandoned=0
11-29 23:07:06.158   161   161 D SurfaceFlinger:             -BufferQueue mMaxAcquiredBufferCount=1, mDequeueBufferCannotBlock=0, default-size=[480x800], default-format=1, transform-hint=00, FIFO(0)={}
11-29 23:07:06.158   161   161 D SurfaceFlinger:              [00:0xb8018638] state=FREE    , 0xb804f748 [ 480x 800: 480,  1]
11-29 23:07:06.158   161   161 D SurfaceFlinger:             >[01:0xb8024c40] state=ACQUIRED, 0xb8030440 [ 480x 800: 480,  1]
11-29 23:07:06.158   161   161 D SurfaceFlinger:              [02:0xb80544d0] state=FREE    , 0xb8046a68 [ 480x 800: 480,
11-29 23:07:06.158   161   161 D SurfaceFlinger: + Layer 0xb805e618 (PopupWindow:41fc51d8)
11-29 23:07:06.158   161   161 D SurfaceFlinger:   Region transparentRegion (this=0xb805e77c, count=1)
11-29 23:07:06.158   161   161 D SurfaceFlinger:     [  0,   0,   0,   0]
11-29 23:07:06.158   161   161 D SurfaceFlinger:   Region visibleRegion (this=0xb805e620, count=1)
11-29 23:07:06.158   161   161 D SurfaceFlinger:     [  5,  98, 148, 392]
11-29 23:07:06.158   161   161 D SurfaceFlinger:       layerStack=   0, z=    22055, pos=(5.11716,98), size=( 153, 315), crop=(   0,   0, 153, 315), isOpaque=0, invalidate=0, alpha=0x4d, flags=0x00000000, tr=[0.93, 0.00][0.00, 0.93]
11-29 23:07:06.158   161   161 D SurfaceFlinger:       client=0xb803b350
11-29 23:07:06.158   161   161 D SurfaceFlinger:       format= 1, activeBuffer=[ 153x 315: 154,  1], queued-frames=0, mRefreshPending=0
11-29 23:07:06.158   161   161 D SurfaceFlinger:             mTexName=2 mCurrentTexture=1
11-29 23:07:06.158   161   161 D SurfaceFlinger:             mCurrentCrop=[0,0,0,0] mCurrentTransform=0
11-29 23:07:06.158   161   161 D SurfaceFlinger:             mAbandoned=0
11-29 23:07:06.158   161   161 D SurfaceFlinger:             -BufferQueue mMaxAcquiredBufferCount=1, mDequeueBufferCannotBlock=0, default-size=[153x315], default-format=1, transform-hint=00, FIFO(0)={}
11-29 23:07:06.158   161   161 D SurfaceFlinger:              [00:0xb8012d40] state=FREE    , 0xb8025d48 [ 153x 315: 154,  1]
11-29 23:07:06.158   161   161 D SurfaceFlinger:             >[01:0xb8014c10] state=ACQUIRED, 0xb8037440 [ 153x 315: 154,  1]
11-29 23:07:06.158   161   161 D SurfaceFlinger: + Layer 0xb801eea0 (StatusBar)
11-29 23:07:06.158   161   161 D SurfaceFlinger:   Region transparentRegion (this=0xb801f004, count=1)
11-29 23:07:06.158   161   161 D SurfaceFlinger:     [  0,   0,   0,   0]
11-29 23:07:06.158   161   161 D SurfaceFlinger:   Region visibleRegion (this=0xb801eea8, count=1)
11-29 23:07:06.158   161   161 D SurfaceFlinger:     [  0,   0, 480,  38]
11-29 23:07:06.158   161   161 D SurfaceFlinger:       layerStack=   0, z=   161000, pos=(0,0), size=( 480,  38), crop=(   0,   0, 480,  38), isOpaque=0, invalidate=0, alpha=0xff, flags=0x00000000, tr=[1.00, 0.00][0.00, 1.00]
11-29 23:07:06.158   161   161 D SurfaceFlinger:       client=0xb801ecd8
11-29 23:07:06.158   161   161 D SurfaceFlinger:       format= 1, activeBuffer=[ 480x  38: 480,  1], queued-frames=0, mRefreshPending=0
11-29 23:07:06.158   161   161 D SurfaceFlinger:             mTexName=6 mCurrentTexture=0
11-29 23:07:06.158   161   161 D SurfaceFlinger:             mCurrentCrop=[0,0,0,0] mCurrentTransform=0
11-29 23:07:06.158   161   161 D SurfaceFlinger:             mAbandoned=0
11-29 23:07:06.158   161   161 D SurfaceFlinger:             -BufferQueue mMaxAcquiredBufferCount=1, mDequeueBufferCannotBlock=0, default-size=[480x38], default-format=1, transform-hint=00, FIFO(0)={}
11-29 23:07:06.158   161   161 D SurfaceFlinger:             >[00:0xb802f200] state=ACQUIRED, 0xb80203f8 [ 480x  38: 480,  1]
11-29 23:07:06.158   161   161 D SurfaceFlinger:              [01:0xb8025b10] state=FREE    , 0xb80257c8 [ 480x  38: 480,  1]
11-29 23:07:06.158   161   161 D SurfaceFlinger:              [02:0xb8025dc0] state=FREE    , 0xb8024be8 [ 480x  38: 480,  1]
11-29 23:07:06.158   161   161 D SurfaceFlinger:              [03:0xb80260e0] state=FREE    , 0


这时对比异常和正常情况下的popwindow的layer值,发现:

根据底层添加的log信息,异常情况下popwin的Z轴值与正常情况有所区别:
正常的情况下,popupwindow 的 z 值比BoxMsgListActivity 要大,显示在上方
异常的时候,popupwindow 的 z 值比BoxMsgListActivity 要小,导致popupwindow在BoxMsgListActivity的下方,无法显示

因此需要添加响应的log以及打开相应的开关,开追踪window的z轴值的处理部分
在framework里面添加了一些log,主要是打开了一些wms以及ViewRootImpl的log信息,
来关注window的z轴位置的处理以及对surfaceflinger的layer设置等。
但是悲摧的时,添加log后一直没有复现这问题。


然后只能继续分析现有log 以及 code,

对比surfacelinger中正常情况和异常情况下,系统中各window的 z 值,
发现异常的情况下,PopupWindow 的Z值小了1000。

根据这个线索,猜测可能和下面的参数TYPE_LAYER_OFFSET(1000)的使用有关,
这个参数用来为每一种类型的窗口都预留一个足够大的值域来作为Z轴位置。

按照这个思路,发现在启动一个window的时候,会调整其过度动画的layer值,
public void setAnimation(Animation anim, int width, int height) {
        animation = anim;
        animating = false;
        if (!anim.isInitialized()) {
            anim.initialize(width, height, width, height);
        }
        anim.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION);
        anim.scaleCurrentDuration(mService.getTransitionAnimationScaleLocked());
        int zorder = anim.getZAdjustment();
        int adj = 0;
        if (zorder == Animation.ZORDER_TOP) {
            adj = WindowManagerService.TYPE_LAYER_OFFSET;
        } else if (zorder == Animation.ZORDER_BOTTOM) {
            adj = -WindowManagerService.TYPE_LAYER_OFFSET;
        }

        if (animLayerAdjustment != adj) {
            animLayerAdjustment = adj;
            updateLayers();
        }
				......
    }

在过度动画结束的时候,再将其layer的值调整回去;且调整值正好是TYPE_LAYER_OFFSET。因为整个系统中只有这一处调整layer值,基本可以确认,某种异常导致layer没有被调整为原来的值
为验证该推断,本地修改mms界面,动画结束后强制不重置layer值,100%必现这个问题。

代码如下:

 boolean stepAnimationLocked(long currentTime) {
	.......
	.......
	//动画执行结束
        if (!animating && animation == null) {
            return false;
        }

        mAnimator.setAppLayoutChanges(this, WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM,
                "AppWindowToken");

        clearAnimation();
        animating = false;
        //重置layer
        if (animLayerAdjustment != 0) {
            animLayerAdjustment = 0;
            updateLayers();
        }
	......
    }

由于一致没有复现,未找到root cause,启动activity的时候有设置window的layer值;在最后切换动画结束的时候,会重置layer值为原始值。但是中间执行过程较为发散

我的修改方案为:在切换动画结束结束的时候,检查layer值是否被设置回去,如果没有强制重置一下即可。

 boolean stepAnimationLocked(long currentTime) {
	.......
	.......
	//动画执行结束
	if (!animating && animation == null) {
	    //fix begin
	    if (animLayerAdjustment != 0) {	
	       animLayerAdjustment = 0;	
	       updateLayers();	
	    }	
	    //fix end
	    return false;
	}	
	......
    }


android平台本身没有考虑到这种异常的情况,虽然很偶现。



你可能感兴趣的:(移动开发)