三星项目中,横屏下相机分屏切换到小窗口,点击预览界面跳动问题分析解决

本文分析了一款应用在横屏模式下,相机分屏切换到小窗口时出现的预览界面跳动问题。问题源于T架构升级后,ViewRootImpl类中relayoutWindow方法对transformHint属性的计算方式改变。最终定位到DisplayRotation获取不一致导致异常,并提出了解决方案。

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

1、问题描述:

横屏下相机分屏切换到小窗口,点击预览界面跳动。

2、根本原因:

T 架构 升级导致。

T上表现

在 FWK 中 ,ViewRootImpl 类中,有一个 relayoutWindow 方法,T 上 是 通过rotation的角度进行计算(如上图),然后赋给 transformHint 属性,后面流程跑的时候拿的就是计算之后的值,而在 S 及之前版本 上都是直接通过 JNI 获取到的该值(如下图)

S 上表现

3、问题分析:

1、先把 代码运行的流程搞清楚

	在此问题情景下,小窗的时候,点击预览界面,除了 AF/AE 触发的流程的之外,设置windowMode,以及剩下的比较相关的WindowConfiguration 的设置—— ScreenBrightness(window.setAttributes(layoutParams))

2、log 分析

	在发生异常的时候,我们可以看到 点击之后,首先进行了AF/AE 的操作,然后 不知道为什么触发了 surfaceChanged 动作。

log分析

3、具体分析:

T 上 新增问题。本身流程导致?版本升级导致?

首先 AF/AE 的流程 并不会涉及到 Surface 显示相关,可以排除 这个方向,暂时放弃windowMode的设置流程,因为竖屏的时候 是不会的。先排查WindowConfiguration 信息改变引起的 window 重构。

先查一查 Window 类的 setAttributes 方法

在这里插入图片描述
在这里插入图片描述

在这个方法中,把window信息进行了分发,而 window 中的 mCallback 接口,实际在Activity 类中进行了实现,因此此 window 信息的改变 就传递到了 activity 中,然后再经过 WindowManager,最终又传递到了 ViewRootImpl 类中,按我的理解是 ViewRootImpl 是处理 视图树以及事件的 大管家,所以要传递回去进行处理。

最终 走到了 ViewRootImpl 类中的 setLayoutParams 方法。在这个方法中,针对此问题的话,它是标记了 window 信息的改变,然后 发出绘制请求。

在这里插入图片描述

省略掉与此问题 不相关的 流程绘制显示的流程,有兴趣的话,可以自行研究研究,最终会 走到 ViewRootImpl 类中的 performTraversals 方法

在这里插入图片描述

在performTraversals方法中,我们看到触发了 relayoutWindow 的操作,此处也与log 中 对应了起来。先是触发了relayoutWindow 方法,然后 又触发了 updateSurafce 方法。

在relayoutWindow 方法中,经过版本比对,hint字段通过 rotation 值进行计算更新,而在 Android 32及之前的 版本中,都是通过 JNI 获取,并不会计算更新,会不会是因为这个呢?先画上问号。

然后 咋们 再反着推,log中既然显示触发了 SurfaceView 的 surfaceChanged 回调,那么肯定是 走到了SurfaceView 类中的 updateSurface 方法,而且 还要至少一个条件为 true,从 log 中 我们可以看到 hint 字段是 true,其他字段都是 false,所以 我们的 关注点 就转移到了 hint 字段上。

再结合 上面的 mark 点,因此 得出结论,hint计算更新出错,而出错是和DisplayRotation挂钩的,而 DisplayRotation 是 activity 中Resource 资源获取,通过添加log 发现:

在这里插入图片描述

确实如此,activity 的displayRotation与父级Context得到的DisplayRotation不一致。

为什么不一致呢?

因为 CameraActivity 类中 复写了 Context 类的 getResource 方法,导致与 父类得到的 是不一样的 实例对象。所以当前activity无论怎么旋转,得到的 displayRotation 的值 永远 为 0.

故而 竖屏没有问题,在横屏状态下hint 计算出错,导致异常发生。

4、解决方法

通过 反射,强制 设置 DisplayRotation为 super 类的值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值