WindowManagerService一个解决界面闪屏的例子

WindowManagerService一个解决界面闪屏的例子


问题描述:手机插入USB后点击切换USB连接模式,出现闪屏。

首先分析WMS的问题,手机是默认没有开启相关Log的,需要开启相关Log来进行调试,开启方法:
1.adb shell命令动态打开,不需要build codebase
adb shell dumpsys window -d enable a
PS:不需要用adb shell stop/start重启adb,重启手机或者重启adb后都需要重新开启

2.修改WindowManagerService.java中相关的code
将windowManagerService.java中的所有带DEBUG标志的flag(比如DEBUG,DEBUG_XX)都修改为true,然后重新build frameworks/base/services/core 模块

首先在Settings->Developer Options->Window animation AppTransition animation Animation scale 这3个item,都调为off,关闭动画再做测试,发现问题依然存在,排除动画切换方面的因素。

然后我们怀疑dim layer的z-order值发生了变化,但是按上叙方法打印的Log中dim layer的layer值没有打印出来,需要在DimLayer.java中添加log如下:

void setLayer(int layer) {
   Slog.d(TAG,"setLayer: new layer = "+layer+“,mLayer=”+mLayer);// add log
   if (mLayer != layer) {
       mLayer = layer;
       mDimSurface.setLayer(layer);
    }
 }

加了Log以后,从log从发现如下信息:
usbmode的activity从visible到invisible到过程中,dim layer的z-order值有发生异常变化,z-order被加了1000

01-01 12:40:08.464    AppWindowToken{8f2e46a token=Token{8931255 ActivityRecord{9b9205e u0 com.android.settings/.deviceinfo.UsbModeChooserActivity t28}}} Visible
01-01 12:40:08.457957 998 1030 D DimLayer-1-AnimBg: setLayer: new layer = 21059, mLayer = 21054
01-01 12:40:17.410351 998 1030 D DimLayer-1-AnimBg: setLayer: new layer = 21039, mLayer = 21059
01-01 12:40:17.632218 998 1030 D DimLayer-1-AnimBg: setLayer: new layer = 22039, mLayer = 21039 //在这一次发生跳变
01-01 12:40:17.722028 998 1030 D DimLayer-1-AnimBg: setLayer: new layer = 22039, mLayer = 22039
01-01 12:40:17.725    AppWindowToken{8f2e46a token=Token{8931255 ActivityRecord{9b9205e u0 com.android.settings/.deviceinfo.UsbModeChooserActivity t28}}} Invisible

这就算引起切换模式时闪烁的原因.找到地方后继续添加一些log,把调用信息也打印出来:

void setLayer(int layer) {
    Slog.d(TAG,"setLayer: new layer = "+layer+“,mLayer=”+mLayer,new Throwable("setLayer"));//add log
    if (mLayer != layer) {
       mLayer = layer;
       mDimSurface.setLayer(layer);
    }
 }

打印出完整的log:

Line 8085: 07-03 19:54:26.980 981 3846 D ActivityManager: ACT-AM_FINISH_ACTIVITY ActivityRecord{d5725e7 u0 com.android.settings/.deviceinfo.UsbModeChooserActivity t19 f} task:TaskRecord{593a7a6 #19 I=com.android.settings/.deviceinfo.UsbModeChooserActivity U=0 StackId=1 sz=1} app-request
    Line 8132: 07-03 19:54:26.996 981 3846 D ActivityManager:     at com.android.server.am.ActivityStack.finishActivityLocked(ActivityStack.java:3793)

07-03 19:54:27.267 981 5365 V WindowManager: **** GOOD TO GO, Callers=com.android.server.wm.WindowSurfacePlacer.performSurfacePlacementInner:341 com.android.server.wm.WindowSurfacePlacer.performSurfacePlacementLoop:239 com.android.server.wm.WindowSurfacePlacer.performSurfacePlacement:187 com.android.server.wm.WindowManagerService.executeAppTransition:4442 com.android.server.am.ActivityStackSupervisor.reportResumedActivityLocked:3020 com.android.server.am.ActivityStack.completeResumeLocked:1547 
    
07-03 19:54:27.270 981 5365 V WindowManager: applyAnimation: anim=android.view.animation.AnimationSet@20a299c animAttr=0xb transit=TRANSIT_TASK_CLOSE isEntrance=false Callers=com.android.server.wm.WindowManagerService.applyAnimationLocked:3508 com.android.server.wm.WindowManagerService.setTokenVisibilityLocked:4716 com.android.server.wm.WindowSurfacePlacer.handleClosingApps:1338 
07-03 19:54:27.271 981 5365 I WindowManager: Loaded animation android.view.animation.AnimationSet@20a299c for AppWindowToken{a663983 token=Token{7429832 ActivityRecord{d5725e7 u0 com.android.settings/.deviceinfo.UsbModeChooserActivity t19}}}
07-03 19:54:27.271 981 5365 I WindowManager: java.lang.RuntimeException
07-03 19:54:27.271 981 5365 I WindowManager:     at com.android.server.wm.WindowManagerService.logWithStack(WindowManagerService.java:2866)
07-03 19:54:27.271 981 5365 I WindowManager:     at com.android.server.wm.WindowManagerService.applyAnimationLocked(WindowManagerService.java:3512)
07-03 19:54:27.271 981 5365 I WindowManager:     at com.android.server.wm.WindowManagerService.setTokenVisibilityLocked(WindowManagerService.java:4716)
07-03 19:54:27.271 981 5365 I WindowManager:     at com.android.server.wm.WindowSurfacePlacer.handleClosingApps(WindowSurfacePlacer.java:1338)
07-03 19:54:27.271 981 5365 I WindowManager:     at com.android.server.wm.WindowSurfacePlacer.handleAppTransitionReadyLocked(WindowSurfacePlacer.java:1215)
07-03 19:54:27.271 981 5365 I WindowManager:     at com.android.server.wm.WindowSurfacePlacer.performSurfacePlacementInner(WindowSurfacePlacer.java:341)
07-03 19:54:27.271 981 5365 I WindowManager:     at com.android.server.wm.WindowSurfacePlacer.performSurfacePlacementLoop(WindowSurfacePlacer.java:239)
07-03 19:54:27.271 981 5365 I WindowManager:     at com.android.server.wm.WindowSurfacePlacer.performSurfacePlacement(WindowSurfacePlacer.java:187)
07-03 19:54:27.271 981 5365 I WindowManager:     at com.android.server.wm.WindowManagerService.executeAppTransition(WindowManagerService.java:4442)
07-03 19:54:27.271 981 5365 I WindowManager:     at com.android.server.am.ActivityStackSupervisor.reportResumedActivityLocked(ActivityStackSupervisor.java:3020)
07-03 19:54:27.271 981 5365 I WindowManager:     at com.android.server.am.ActivityStack.completeResumeLocked(ActivityStack.java:1547)
07-03 19:54:27.271 981 5365 I WindowManager:     at com.android.server.am.ActivityStack.resumeTopActivityInnerLocked(ActivityStack.java:2787)
07-03 19:54:27.271 981 5365 I WindowManager:     at com.android.server.am.ActivityStack.resumeTopActivityUncheckedLocked(ActivityStack.java:2251)
07-03 19:54:27.271 981 5365 I WindowManager:     at com.android.server.am.ActivityStackSupervisor.resumeFocusedStackTopActivityLocked(ActivityStackSupervisor.java:1870)
07-03 19:54:27.271 981 5365 I WindowManager:     at com.android.server.am.ActivityStack.completePauseLocked(ActivityStack.java:1450)
07-03 19:54:27.271 981 5365 I WindowManager:     at com.android.server.am.ActivityStack.activityPausedLocked(ActivityStack.java:1276)
07-03 19:54:27.271 981 5365 I WindowManager:     at com.android.server.am.ActivityManagerService.activityPaused(ActivityManagerService.java:7502)
07-03 19:54:27.271 981 5365 I WindowManager:     at android.app.ActivityManagerNative.onTransact(ActivityManagerNative.java:573)
07-03 19:54:27.271 981 5365 I WindowManager:     at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2949)
07-03 19:54:27.271 981 5365 I WindowManager:     at android.os.Binder.execTransact(Binder.java:570)
07-03 19:54:27.271 981 5365 V WindowManager: Setting animation in AppWindowToken{a663983 token=Token{7429832 ActivityRecord{d5725e7 u0 com.android.settings/.deviceinfo.UsbModeChooserActivity t19}}}: android.view.animation.AnimationSet@20a299c wxh=1440x2272 isVisible=true
07-03 19:54:27.271 981 5365 V WindowManager: Updating layer Window{7538942 u0 com.android.settings/com.android.settings.deviceinfo.UsbModeChooserActivity}: 22005

Line 9656: 07-03 19:54:27.277 981 5365 V WindowManager: Assign layer Window{7538942 u0 com.android.settings/com.android.settings.deviceinfo.UsbModeChooserActivity}: mBase=21000 mLayer=21005 mAppLayer=1000 =mAnimLayer=22005
    
Line 9854: 07-03 19:54:27.308 981 1306 I WindowManager: SURFACE 7538942: controller=Surface b0888f9 com.android.settings/com.android.settings.deviceinfo.UsbModeChooserActivity (0): shown=true layer=21005 alpha=1.0 528.0,3539.0 384x384 crop=[0,0][384,384] opaque=false (1.0,0.0,0.0,1.0)alpha=0.0 layer=22005 matrix=[1.0*1.0,0.0*1.0][0.0*1.0,1.0*1.0] / com.android.settings/com.android.settings.deviceinfo.UsbModeChooserActivity
   
Line 9854: 07-03 19:54:27.308 981 1306 I WindowManager: SURFACE 7538942: controller=Surface b0888f9 com.android.settings/com.android.settings.deviceinfo.UsbModeChooserActivity (0): shown=true layer=21005 alpha=1.0 528.0,3539.0 384x384 crop=[0,0][384,384] opaque=false (1.0,0.0,0.0,1.0)alpha=0.0 layer=22005 matrix=[1.0*1.0,0.0*1.0][0.0*1.0,1.0*1.0] / com.android.settings/com.android.settings.deviceinfo.UsbModeChooserActivity
Line 9856: 07-03 19:54:27.309 981 1306 V WindowManager: setLayer(22005): OLD:Surface b0888f9 com.android.settings/com.android.settings.deviceinfo.UsbModeChooserActivity (0): shown=true layer=21005 alpha=0.0 528.0,3539.0 384x384 crop=[0,0][384,384] opaque=false (1.0,0.0,0.0,1.0). Called by com.android.server.wm.WindowSurfaceController.prepareToShowInTransaction:320 com.android.server.wm.WindowStateAnimator.prepareSurfaceLocked:1691 com.android.server.wm.WindowAnimator.animateLocked:774 
//finish过程中明显看到有layer调整比之前高了。    
Line 8665: 07-03 19:54:27.125 981 1306 V WindowManager: destroy: Surface 794f78e com.android.settings/com.android.settings.deviceinfo.UsbModeChooserActivity (0): shown=false layer=21015 alpha=0.0 -92.0,303.0 1624x1857 crop=[92,0][1532,1857] opaque=false (1.0,0.0,0.0,1.0). Called by com.android.server.wm.WindowSurfaceController.destroyInTransaction:161 com.android.server.wm.WindowStateAnimator.destroySurface:2154 com.android.server.wm.WindowStateAnimator.destroySurfaceLocked:947 

Line 10401: 07-03 19:54:27.416 981 5365 V WindowManager: destroy: Surface b0888f9 com.android.settings/com.android.settings.deviceinfo.UsbModeChooserActivity (0): shown=false layer=22005 alpha=0.0 528.0,1040.0 384x384 crop=[0,0][384,384] opaque=false (1.0,0.0,0.0,1.0). Called by com.android.server.wm.WindowSurfaceController.destroyInTransaction:161 com.android.server.wm.WindowStateAnimator.destroySurface:2154 com.android.server.wm.WindowStateAnimator.destroySurfaceLocked:947

可以看出导致闪屏的原因是因为finish该UsbModeChooserActivity的时候,由于其是半透明的,并且它有两个不同layer 的window,WMS会将其中一个window的Layer调整比之前高,进而做窗口切换时导致的闪屏。

解法:在window做退出动画前,提前将animLayerAdjustment 提高避免闪屏。

 /frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

import static com.android.server.wm.AppTransition.TRANSIT_TASK_CLOSE; // add this
import static com.android.server.wm.AppTransition.TRANSIT_TASK_OPEN;
import static com.android.server.wm.AppTransition.TRANSIT_TASK_OPEN_BEHIND;
import static com.android.server.wm.AppTransition.TRANSIT_TASK_TO_BACK;
import static com.android.server.wm.AppTransition.TRANSIT_TASK_TO_FRONT;


@Override
public void setAppVisibility(IBinder token, boolean visible) {
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
"setAppVisibility()")) {
throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
}

AppWindowToken wtoken;

synchronized(mWindowMap) {
wtoken = findAppWindowToken(token);
if (wtoken == null) {
Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: " + token);
return;
}

if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION || !IS_USER_BUILD)
Slog.v(TAG_WM, "setAppVisibility(" +
token + ", visible=" + visible + "): " + mAppTransition +
" hidden=" + wtoken.hidden + " hiddenRequested=" +
wtoken.hiddenRequested + " Callers=" + Debug.getCallers(6));
//add begin
if(wtoken!=null&&visible==false&&mAppTransition.getAppTransition()==TRANSIT_TASK_CLOSE 
&&wtoken.hidden==false){
Slog.v(TAG_WM,wtoken +"going to do exist animation so adjust animLayerAdjustment to 1000");
wtoken.mAppAnimator.animLayerAdjustment =1000;
} //add end

mOpeningApps.remove(wtoken);
mClosingApps.remove(wtoken);

编译版本后问题不再复现。本文是基于Android M的一个例子。后面的Android版本代码可能有变动,但是基本思路不变。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值