最近在工作中,解决的一个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();
}
......
}
代码如下:
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;
}
......
}