前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >google 分屏 popup无法显示故障分析

google 分屏 popup无法显示故障分析

作者头像
用户1263308
发布2018-02-02 10:18:49
1.6K0
发布2018-02-02 10:18:49
举报
文章被收录于专栏:代码GG之家代码GG之家

问题描述 [Message][Input method]Display is wrong when message at split mode. 分屏模式下短信界面显示不正确

操作步骤 1.打开message然后退出 2.打开一个app如Call,然后长按recent键进入分屏模式 3.让message在分屏模式中处于底部,然后在message中编辑一些字符 4.长按这些字符串,不能显示出"CUT COPY SHARE"这3项 --KO

环境描述 android7.0.1 屏幕分辨率 720*1280 手机:eng版本

首先

按照bug描述,此时无法弹出pop框(cut copy...),我们第一步方向,去跟踪代码,追到此框弹出路径。(根据log分析, 使用调试工具Eclipse打断,跟踪流程),得到一条调用栈信息:

Editor.java

--->startSelectionActionModeInternal

--->mTextView.startActionMode

DecorView.java

--->startActionModeForChild

--->startActionMode

--->createFloatingActionMode

--->FloatingActionMode

FloatingActionMode.java

--->repositionToolbar

--->updateViewLocationInWindow

--->repositionToolbar

结论

确定位置FloatingActionMode.java 的 repositionToolbar方法上,此处 if (isContentRectWithinBounds()) 判断上:

分析

前面的结论,写的非常粗糙,只是给出了大致结果,没有给出如何处理此问题的,如下我们慢慢展开。

01

使用hierarchyviewer 工具,我们全屏下操作出来copy 对话框,去看它的视图信息。

展看后我们看到了:

看下cut copy这个框中的元素,发现最终类为:FloatingActionMode.java,因此直接定位在了这个类。

大致去阅读下这个类,同时工程下搜索下这个类,很快可以看到一条轨迹。在轨迹路途加入断点,快速定位流程,搜索内容如下:

我们可以排除StatusBarWindowView.java(因为我们不属于这里),我们忽略本身的FloatingActionMode.java ,来到了DecorView.java位置,(一看代码,有戏)

于是我们上断点,定位出来流程。

02

通过跟踪,对比全屏和分屏下出错的流程,发现问题点在于updateToolbarVisibility 函数的调用上,全屏下会调用这个show,而出错的在分屏下的底部时,没有调用。

于是我们继续定位,去找谁调用了这个函数。再次筛选,我们需要调用到show方法上。寻着这个路径,我们看到了本文件里面的调用关系:mMovingOff调用了updateToolbarVisibility方法

继续找mMovingOff的调用位置,可以得到如下

两个条件,最终确定是第一个条件出现问题,出现点为:

这里代码的意思为:

mContentRectOnScreen 弹出框在全屏的显示区域

mScreenRect 全屏区域 (错误点在这里)

mViewRectOnScreen view在全屏的显示区域

此段代码做了校验,判断popup框是否在屏幕外,如果在,就不要画了(画了你也看不见)

错误是因为:此段代码判断结论为,popup不在可见范围,不用画。(我擦,有没搞错,我在编辑框上选个内容,需要复制,粘贴,怎么会不在可见范围,哭晕..)

然而错误的原因你会泪奔的,原因是

mContext.getResources().getDisplayMetrics().heightPixels 的值为558,而popup的位置是579(系统判断579>558 ,所以在屏幕外?OMG,我觉得是在开玩笑),郁闷的是我们手机屏幕是720*1280的,(579<1280,应该要画的)。于是我们愤怒转移到了getDisplayMetrics().heightPixels方法,此方法取出来的不是屏幕高,是不是有些崩溃,那么为什么不是呢?

03

让我们停止怀疑人生,继续来追踪

mContext.getResources().getDisplayMetrics().heightPixels 为什么会给错呢?

最终

我们发现:

系统getDisplayMetrics().heightPixels此方法给出的是当前task的高度值,并非屏幕的高度值。

由于之前我们没有分屏机制,所以task就是全屏的,这两个值一致,没有问题。当分屏产生时,此值大小则不是屏幕的高度了。这个属于分屏开发暴露的问题。

至于为什么分屏在上面时候,pop能弹出来,留个疑问给大家。

我们现在来查询heightPixels从何处来。此过程太过漫长,喝杯茶,容我慢慢道来。

mContext.getResources() 找到这个方法实现的地方,通过断点,找到此处的mContext在ContextImpl.java里面

getResources() 返回mResources ,于是我们要去找mResources的赋值地方,发现在ContextImpl的构造里面:

于是在ContextImpl的构造函数设置断点,发现确实此处传递的overrideConfiguration参数中有我们需要的错误值。

因此可以断定,此处之前已经有问题啦。

通过栈信息,我们可以看到,此时传递的路径为WindowManagerService.java的 handle里面的ADD_STARTING case里面,调用了addStartingWindow 方法

于是乎,我们看到了wtoken.mTask.mOverrideConfig 这个值决定了此处的overrideConfig。

如何去找哪里触发的这个case,我们搜索ADD_STARTING

在调用地方设置断点,如此可以找到调用路径。

于是我们发现setAppStartingWindow 里面调用了,我们向上去找,发现了此处的wtoken里面的值已经出错(此处为279,densityDpi值为2,和之前的558对应上了),于是我们的方向便是去找这个值从哪里来的。

通过栈信息,我们找到了ActivityStarter.java 里面的 startActivityUnchecked方法,看到了此处的mStartActivity.task值已经出错,于是我们需要在此处确认此值的来源。

于是我们向上跟踪,发现修改地方在setTaskFromReuseOrCreateNewTask函数里面,继续跟进去看:

结论已经出现:

由于我们的task的isResizeable()返回true,使得方法进入task.updateOverrideConfiguration(mBounds);此处task处在分屏时候,此时task的大小需要使用activity的边界值做覆盖,覆盖之后,使得我们最终调用mContext.getResources().getDisplayMetrics().heightPixels拿到的是task的高,并非屏幕的高。

等等,我们好像发现了什么?

这里我们再去细分析,发现此处逻辑没有问题,当前task如果是isResizeable的,那么我们是需要覆盖这个值的,因此这里值没有问题,此处逻辑追踪的只是想确定错误值的来源。通过看完,发现此值本身没有疑问,是task的大小,没有问题。

我们错了?why??

那我们再返回到我们定位的起点,此处判断错误,引起没有去显示popup框

mContentRectOnScreen 弹出框在全屏的显示区域

mScreenRect 全屏区域 (错误点在这里)

mViewRectOnScreen view在全屏的显示区域

mScreenRect 系统期望拿到的是屏幕大小,(task默认不分屏下是等于屏幕大小)而此处因为分屏了,task的大小不等于屏幕大小了。

而此段代码认为mContext.getResources().getDisplayMetrics().heightPixels拿到还是系统屏幕大小,导致出错的。

结论 mContext.getResources().getDisplayMetrics().heightPixels 真正意义上是task的大小,在不分屏下,和屏幕大小相等(当然这里屏幕大小不是真正物理屏幕大小,因为还有状态栏和虚拟按键不在task的范围内,具体就不扩展了)

于是我们的修改思路便是,需要找到此处可以拿到屏幕大小的方法,解决此问题。

修复 FloatingActionMode.java 里面,修改isContentRectWithinBounds的方法实现,具体修改为:

修改前:

修改后:

编译版本,验证OK。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-02-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 代码GG之家 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
短信
腾讯云短信(Short Message Service,SMS)可为广大企业级用户提供稳定可靠,安全合规的短信触达服务。用户可快速接入,调用 API / SDK 或者通过控制台即可发送,支持发送验证码、通知类短信和营销短信。国内验证短信秒级触达,99%到达率;国际/港澳台短信覆盖全球200+国家/地区,全球多服务站点,稳定可靠。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档