现在的位置: 首页 > 综合 > 正文

反编译实战之给锤子ROM加上”显示GPU过度绘制”

2013年12月01日 ⁄ 综合 ⁄ 共 4325字 ⁄ 字号 评论关闭

什么叫“显示GPU过度绘制”呢?

       当使用GPU绘图时,在屏幕上绘制不同的颜色来表明过度绘制的情况。过度绘制情况的好坏通过颜色来表示,从蓝色、绿色、淡红色到红色 ,分别代表从好到坏的渐变(1x过度绘制、2x过度绘制、3x过度绘制和超过4x过度绘制)。界面上存在少量的淡红色可以接受,但如果存在较多的大红色就代表过度绘制有点严重了。

       通俗的来讲我们可以这样理解,过度绘制可以理解为屏幕上像素被绘制的次数。1x表示1次,2x表示2次,以此类推。也就是说当我们看到的具体图片(或者文字)时,有可能该图片的后面还存在别的图片(或者文字),只是被遮挡住了我们无法看见,如果层次较多就会导致过度绘制。通过分析应用的过度绘制情况,有利于我们优化应用,给用户更好的体验。开启“显示GPU过度绘制”的方法是,在系统设置中开发者选项里面打开。

       之前一直想把玩下罗老师的锤子ROM,虽然看了发布会,但毕竟没有上手过,所以不知道具体情况。终于有机会将最新版的锤子ROM刷到了Find 5上试试,不试不要紧,一试吓一跳,怎么这么卡顿(如果帧数<60fps/s就会感觉卡顿)。作为开发人员遂打算看看是否有过度绘制的情况,可找遍了设置,愣是没有看到“显示GPU过度绘制”的选项(小米也没有,AOSP以及CM可是默认就带有的哦),难道给屏蔽了??有必要吗??(心中顿时一万头草泥马奔涌而过)

       难道不给看就完了吗?于是乎便有了此文……

问题:

       设置界面上无“显示GPU过度绘制”选项

分析:

       将选项屏蔽了。屏蔽的方法其实很容易想到,在配置文件里移除“显示GPU过度绘制”,并在代码中删掉(或注释掉)对应的初始化以及处理代码。

解决方案:

       既然分析出了屏蔽的方法,那么自然解决方案就有了:

1. 重新加入该选项

       毕竟原生系统默认是带有该功能的,既然屏蔽了那自然加上就可以了(后文采用该方法)。这种方法需要对smali代码较为熟悉,难度较大,但修改完成后不会影响原设置的功能。

2. 替换相关选项

       在没有源码的情况下,我们能修改的就只有smali代码了,如果对于smali代码不是很熟悉,就很容易出错。那么我们可以采用替换的方法来添加“显示GPU过度绘制”的选项,也就是“偷梁换柱”法。修改配置文件里相应的配置项,在初始化代码中将设置里面已有的某一项替换成“显示GPU过度绘制”,这样就可以使用该方法了。这种方法是最简单粗暴的,但也是最快捷的一种。

步骤:

       经过了上面的分析和思考,我们应该动手了。这里采用的是第一种解决方案,虽然要难一点但可以在不破坏原设置的情况下加入我们的东西,我个人比较喜欢这种。当然如果会使用第一种解决方案了,第二种自然也就信手拈来,好了废话不多说,“翠花,上干货……”

1. 准备反编译资源

       这里我们需要获取锤子Find5刷机包,并提取其中的/system/app/Settings.apk和/system/framework/framework-res.apk

2. 准备反编译工具

       工欲善其事必先利其器,所以我们需要准备好顺手的反编译工具,这里我使用的是APKTOOL和Dex2Jar以及JD-GUI。

3. 反解Settings.apk

在终端中执行

apktool if framework-res.apk

安装资源文件,然后再执行

apktool d Settings.apk

将APK文件解包为smali文件

同时将Settings.apk中的classes.dex文件解压出来,使用dex2jar工具将dex文件转换为jar包,使用JD-GUI进行查看。

4. 定位问题

       打开Eclipse并使用Hierarchy View工具(这里并不是一定需要Eclipse,通过抓取跳转Log同样可以定位到对应的显示页面)进行查看,可以得到当前页面对应的文件是com.android.settings.DevelopmentSettingsActivity。

然后再在使用apktool反解后的文件夹中搜索关键字——"过度绘制",可以知道其在string.xml中对应的字符串ID,这里搜索到的结果是:

<string name="show_hw_overdraw">显示 GPU 过度绘制</string>

       通过前面的分析我们知道,屏蔽的方法只是修改配置文件和初始化代码,因此资源文件多数情况下是不会去修改的。虽然我们搜索到了,但如果继续试用该ID进行搜索可能会无法找打相关内容,毕竟初始化代码和配置文件已经修改了。因此这里我们采用迂回战术,什么叫迂回战术呢?我们知道在设置里面除了“显示GPU过度绘制”选项意外还有“显示布局边界”,我们在string.xml中搜索“显示布局边界”可以得到:

<string name="debug_layout">显示布局边界</string>

       那么我们以debug_layout为关键字继续搜索,可以在apktool解包文件/res/layout/development_settings_layout.xml中找到以下代码:

<com.android.settings.SettingItemSwitch android:id="@id/switch_debug_layout" android:background="@drawable/selector_setting_sub_item_bg_top" android:layout_width="fill_parent" android:layout_height="wrap_content" setting:title="@string/debug_layout" setting:isEnable="false" />

       这里我们可以看到,在锤子ROM中,这种checkbox被重写了,也就是这里的SettingItemSwitch,我们不需要去管它具体做了什么,因为我们的目的是加上“显示GPU过度绘制”。通过查看development_settings_layout.xml文件,我们可以知道,这就是配置文件,既然被删掉了那么我们就仿造前面的“显示布局边界”自己定义一个并稍作改动,如下:

<com.android.settings.SettingItemSwitch android:id="@id/switch_show_hw_overdraw" android:background="@drawable/selector_setting_sub_item_bg_middle" android:layout_width="fill_parent" android:layout_height="wrap_content" setting:title="@string/show_hw_overdraw" setting:isEnable="false" />

       id取名叫做switch_show_hw_overdraw。我们知道这些ID都是在我们编译的时候会自动生成在R.java中的,这里我们是反编译,因此再打包回去时肯定不会再编译一次,因此相应的资源ID(R.java中的16进制代码)就无法生成,所以我们需要手动修改以下文件:

/res/values/ids.xml

       因为我们刚在使用的是@id/switch_show_hw_overdraw注意这里不是@+id,所以需要在id.xml中增加对应的代码,参考switch_debug_layout:

<item type="id" name="switch_debug_layout">false</item>
<item type="id" name="switch_show_hw_overdraw">false</item>

/res/values/public.xml

       这里的public.xml并不是framework中的那个public.xml,我们反解APK之后,资源文件对应的资源ID写入了public.xml中。所以这里我们也需要手动添加,这里一定要注意,因为我们添加的是switch_show_hw_overdraw的资源ID,不能放到public.xml最后,需要紧接着前面的id写,如下:

<public type="id" name="wifi_wps" id="0x7f0a03a9" />
<public type="id" name="switch_show_hw_overdraw" id="0x7f0a03aa" />
<public type="color" name="black" id="0x7f0b0000" />

       如果放错了位置,会导致回编译的时候报错。在做完以上错做之后,基本上就完成了1/2的工作了,这个时候可以先回编译试试看

apktool b Settings

       在Settings/dist文件夹中找到编译好的Settings.apk,将其中的resource.arsc拖到原Settings.apk中,使用adb push指令将修改后的Settings.apk push到/system/app,重新运行设置,进入开发者选项里面我们就可以找到“显示GPU过度绘制”了,但这时候会发现我们点击之后没有效果,那是因为我们还没有加上初始化和响应代码。

       因为初始化和响应代码就是基本流程了,直接照搬switch_debug_layout的就可以了,所以这里就不赘述了,以下是修改前后的对比图,一目了然:

变量初始化

onCreate初始化

onResume显示

onCheckedChanged处理

       经过以上修改之后,我们再次打包并push到系统中进行测试,我们可以看到对比图:

左侧为锤子ROM原生设置界面 右侧为修改后的设置界面

左侧为未开启状态 右侧为开启状态

总结:

       一开始只是想看看“GPU过度绘制”,可没成想人家不给看,那就只能自己动手了。以后遇到这种问题还是先分析,避免走弯道。

如果想深入了解GPU过度绘制以及APP优化的童鞋可以参考以下链接(需要翻墙):

http://www.curious-creature.org/2012/12/01/android-performance-case-study/

国内有大牛翻译了,链接如下:

http://blog.chengyunfeng.com/?p=458#

优化效果可以参看:

http://www.cnblogs.com/myzh/

下载:

我将修改前后的APK都打包上传,有想动手试试的童鞋可以看看,下载地址在这里。

抱歉!评论已关闭.