播完关机动画会闪现一下动画前的界面的问题分析

在播放完关机动画后,设备会短暂显示关机前的界面,如锁屏或应用界面。问题与移植的圆角功能有关,具体表现为即使关闭圆角开关,问题依然存在。通过代码分析,发现在SurfaceFlinger::captureScreenImplLocked()方法中,与截屏宏TINNO_CUSTOM_FEATURE_SCREEN_CAPTURE_EXCLUDE_SCREEN_CORNER有关。在调用过程中,参数被错误地更新,导致问题发生。解决方法需在updateDimensionsLocked()调用前对reqWidth和reqHeight进行判断。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题点

在播放完关机动画的时候会出现一个动画之前的界面,比如我在锁屏界面长按power键关机,等关机动画播放完后会闪现一下刚才的锁屏界面,如果是在home界面或是某个应用界面关机,等播完动画之后也会闪现一下之前的home界面或那个应用界面,而且问题必现。

 

分析:

该问题在之前负责开关机模块的同事那里已经分析过,后经排查发现和移植的圆角功能有关,而圆角功能是我这边移植的,所以问题转到我这了。

圆角的整个feature是有开关控制的,一个是上层的prop开关persist.tcf.screen.corner,一个是native层的宏开关TINNO_CUSTOM_FEATURE_SCREEN_CAPTURE_EXCLUDE_SCREEN_CORNER,拿到问题之后我做了个初步验证:

1.   通过adb命令将persist.tcf.screen.corner设置为0,也就是关掉开关。重启手机后圆角的效果没有了,但是问题依旧存在。

2.   将TINNO_CUSTOM_FEATURE_SCREEN_CAPTURE_EXCLUDE_SCREEN_CORNER宏去掉,编译验证,问题消失。

由此可以得出结论是由于TINNO_CUSTOM_FEATURE_SCREEN_CAPTURE_EXCLUDE_SCREEN_CORNER这个宏定义导致的问题。而这个宏的作用是什么呢?其实就是处理截屏的。就是说在截屏的时候我们需要将圆角去掉,否则截出来的图片会有明显的四个圆角,不好看。


代码分析:

再看下对应的代码:

android/frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:

#ifdef TINNO_CUSTOM_FEATURE_SCREEN_CAPTURE_EXCLUDE_SCREEN_CORNER

    {

        // this value fromandroid.view.WindowManager.LayoutParams.TYPE_SCREEN_CORNER -FIRST_SYSTEM_WINDOW * 10000   

        // some other app also needcaptureScreen for some Animation

        //ALOGE("captureScreenImplLockedreqWidth=%d reqHeight=%d maxLayerZ=%d ", reqWidth, reqHeight, maxLayerZ);

        if(reqWidth != 0 && reqHeight !=0 &&maxLayerZ > 390000) {

            ALOGE("captureScreenImplLockedfix for 18:9 device XY (%d X %d)  Z (%d -%d(->%d)) ", reqWidth, reqHeight, minLayerZ, maxLayerZ,390000);

            maxLayerZ = 390000;

        }

    }

#endif

这段代码是在SurfaceFlinger::captureScreenImplLocked()中,当时看到这的时候还比较纳闷,看这方法名不是应该在触发了截屏动作才会走到的么?按理说关机流程中应该不会跑到这来,接下来就需要追下这个方法的调用流程了。

通过在搜索该方法的调用及加入的log确认发现从Java层到native层的调用关系如下:

SurfaceControl.screenshot()

 ->android_view_SurfaceControl.nativeScreenshot()

 -> ScreenshotClient::capture()

 -> SurfaceFlinger::captureScreen()

-> SurfaceFlinger::captureScreenImplLocked()

接着我又在SurfaceControl.java的screenshot()方法中加入log,让其主动跑异常,这样就可以继续往上看到这个方法的调用关系了,打印出来的日志如下:

 

 

01-0302:27:28.486 741 886 D SurfaceControl: call stack 
01-03 02:27:28.486 741 886 D SurfaceControl: java.lang.RuntimeException: calledby 
01-03 02:27:28.486 741 886D SurfaceControl: atandroid.view.SurfaceControl.screenshot(SurfaceControl.java:925) 
01-03 02:27:28.486 741 886 D SurfaceControl: atandroid.view.SurfaceControl.screenshot(SurfaceControl.java:843) 
01-03 02:27:28.486 741 886 D SurfaceControl: at com.android.server.display.ColorFade.captureScreenshotTextureAndSetViewport(ColorFade.java:483) 
01-03 02:27:28.486 741 886 D SurfaceControl: atcom.android.server.display.ColorFade.prepare(ColorFade.java:153) 
01-03 02:27:28.486 741 886 D SurfaceControl: at com.android.server.display.DisplayPowerState.prepareColorFade(DisplayPowerState.java:179) 
01-03 02:27:28.486 741 886 D SurfaceControl: atcom.android.server.display.DisplayPowerController.animateScreenStateChange(DisplayPowerController.java:1269)
 
01-03 02:27:28.486 741 886D SurfaceControl: atcom.android.server.display.DisplayPowerController.updatePowerState(DisplayPowerController.java:728) 
01-03 02:27:28.486 741 886 D SurfaceControl: atcom.android.server.display.DisplayPowerController.-wrap6(Unknown Source:0)
01-03 02:27:28.486 741 886 D SurfaceControl: atcom.android.server.display.DisplayPowerController$DisplayControllerHandler.handleMessage(DisplayPowerController.java:1566)
01-03 02:27:28.486 741 886 D SurfaceControl: atandroid.os.Handler.dispatchMessage(Handler.java:106) 
01-03 02:27:28.486 741 886 D SurfaceControl: atandroid.os.Looper.loop(Looper.java:164) 
01-03 02:27:28.486 741 886 D SurfaceControl: atandroid.os.HandlerThread.run(HandlerThread.java:65) 
01-03 02:27:28.486 741 886 D SurfaceControl: at com.android.server.ServiceThread.run(ServiceThread.java:46)

到这里,起初我是比较怀疑这个流程是不是不对,然后想起之前N版本上面我们也有移植该功能,但是没有这个问题,所以拿N版本的机器也打了下log对比,发现也有这个调用流程,所以确定我怀疑的这个方向错了,问题不是出在这里。再次对比log,又发现一个可疑地方,在N版本上,只有真正触发了截屏的时候才会打印这行log:

SurfaceFlinger:captureScreenImplLocked reqWidth=720 reqHeight=1440 maxLayerZ=2147483647

但是我们的39O平台上面的项目在关机的时候也打出来了这行,结合上面的代码可以看到if( reqWidth != 0 && reqHeight !=0 && maxLayerZ >390000)这个条件已经形同虚设了。

 

 

山重水复疑无路,柳岸花明又一村:

经过上面的对比分析,总算是找到一点眉目了,基本可以确定是if()条件判断里面的参数问题。接着继续debug,给调用该方法的地方加log,看看上层传下来的参数都是啥。

01-03 02:27:28.485741 886 D SurfaceControl: screenshot2222222: width=0, height=0------wzl 

01-0112:25:44.483   775   900 E SurfaceComposerClient:ScreenshotClient: capture 111111111: reqWidth=0, reqHeight=0
01-01 12:25:44.486   340  877 E SurfaceFlinger: 1111111111 SurfaceFlinger::captureScreen reqWidth=0reqHeight=0 

01-01 12:25:44.486   340  877 E SurfaceFlinger: 4444444444 SurfaceFlinger::captureScreen reqWidth=720reqHeight=1440

从这里的log就可以很清晰的看出来了,上面传的参数是0,但是最终到了SurfaceFlinger::captureScreen()这里值就变了,好,接下来重点看SurfaceFlinger::captureScreen()方法。

然后在这个方法中发现了这个:

updateDimensionsLocked(displayDevice,rotationFlags, &reqWidth, &reqHeight);

再看其实现:

……

    if (*requestedWidth == 0) {

        *requestedWidth = displayWidth;

    }

    if (*requestedHeight == 0) {

        *requestedHeight =displayHeight;

}

……

果然,这里有重新赋值,导致下面captureScreenImplLocked()方法传入的参数变了。我又对比了下N版本surfaceflinger部分的代码,改动还是比较大的,而且没有updateDimensionsLocked()方法,由于不清楚这部分的改动,也不确定是不是mtk在新版本上做的修改,也不敢随意删除。后面咨询了下mtk工程师,他们答复这部分的代码他们也是follow google的,应该是增加了容错处理,这样的话就不能直接删了,还是要保持原始代码,要解决我们现在这个问题只能是在updateDimensionsLocked()方法调用之前来进行reqWidth和reqHeight的判断。

小结:

这个问题确实也是埋的比较深的一个坑,因为这套圆角的方案在N版本上面还是比较成熟了,移植到O1上面也一直没有报过相关的问题,而且大部分项目都没有加关机动画,并且报出问题来了之后很难想到会和这个圆角的功能有关,确实也是辛苦了开关机模块同事的分析和排查。

定位到了问题之后就是要找出具体原因了,需要追寻那个可疑点往各个方向排查。其实,先提出一些假设也是挺有必要的,通过假设,对比,验证来确定是否成立,追根溯源,找到root cause,然后解决问题。当然,有时候可能找到了root cause也不一定能有好的解决方案,但是要解决问题肯定还是要先找到原因。

 

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值