反编译实战之给锤子ROM加上显示GPU过度绘制
什么叫“顯示GPU過度繪制”呢?
? ? ? ?當使用GPU繪圖時,在屏幕上繪制不同的顏色來表明過度繪制的情況。過度繪制情況的好壞通過顏色來表示,從藍色、綠色、淡紅色到紅色 ,分別代表從好到壞的漸變(1x過度繪制、2x過度繪制、3x過度繪制和超過4x過度繪制)。界面上存在少量的淡紅色可以接受,但如果存在較多的大紅色就代表過度繪制有點嚴重了。
? ? ? ?通俗的來講我們可以這樣理解,過度繪制可以理解為屏幕上像素被繪制的次數(shù)。1x表示1次,2x表示2次,以此類推。也就是說當我們看到的具體圖片(或者文字)時,有可能該圖片的后面還存在別的圖片(或者文字),只是被遮擋住了我們無法看見,如果層次較多就會導(dǎo)致過度繪制。通過分析應(yīng)用的過度繪制情況,有利于我們優(yōu)化應(yīng)用,給用戶更好的體驗。開啟“顯示GPU過度繪制”的方法是,在系統(tǒng)設(shè)置中開發(fā)者選項里面打開。
? ? ? ?之前一直想把玩下羅老師的錘子ROM,雖然看了發(fā)布會,但畢竟沒有上手過,所以不知道具體情況。終于有機會將最新版的錘子ROM刷到了Find 5上試試,不試不要緊,一試嚇一跳,怎么這么卡頓(如果幀數(shù)<60fps/s就會感覺卡頓)。作為開發(fā)人員遂打算看看是否有過度繪制的情況,可找遍了設(shè)置,愣是沒有看到“顯示GPU過度繪制”的選項(小米也沒有,AOSP以及CM可是默認就帶有的哦),難道給屏蔽了??有必要嗎??(心中頓時一萬頭草泥馬奔涌而過)
? ? ? ?難道不給看就完了嗎?于是乎便有了此文……
問題:
? ? ? ?設(shè)置界面上無“顯示GPU過度繪制”選項
分析:
? ? ? ?將選項屏蔽了。屏蔽的方法其實很容易想到,在配置文件里移除“顯示GPU過度繪制”,并在代碼中刪掉(或注釋掉)對應(yīng)的初始化以及處理代碼。
解決方案:
? ? ? ?既然分析出了屏蔽的方法,那么自然解決方案就有了:
1. 重新加入該選項
? ? ? ?畢竟原生系統(tǒng)默認是帶有該功能的,既然屏蔽了那自然加上就可以了(后文采用該方法)。這種方法需要對smali代碼較為熟悉,難度較大,但修改完成后不會影響原設(shè)置的功能。
2. 替換相關(guān)選項
? ? ? ?在沒有源碼的情況下,我們能修改的就只有smali代碼了,如果對于smali代碼不是很熟悉,就很容易出錯。那么我們可以采用替換的方法來添加“顯示GPU過度繪制”的選項,也就是“偷梁換柱”法。修改配置文件里相應(yīng)的配置項,在初始化代碼中將設(shè)置里面已有的某一項替換成“顯示GPU過度繪制”,這樣就可以使用該方法了。這種方法是最簡單粗暴的,但也是最快捷的一種。
步驟:
? ? ? ?經(jīng)過了上面的分析和思考,我們應(yīng)該動手了。這里采用的是第一種解決方案,雖然要難一點但可以在不破壞原設(shè)置的情況下加入我們的東西,我個人比較喜歡這種。當然如果會使用第一種解決方案了,第二種自然也就信手拈來,好了廢話不多說,“翠花,上干貨……”
1. 準備反編譯資源
? ? ? ?這里我們需要獲取錘子Find5刷機包,并提取其中的/system/app/Settings.apk和/system/framework/framework-res.apk
2. 準備反編譯工具
? ? ? ?工欲善其事必先利其器,所以我們需要準備好順手的反編譯工具,這里我使用的是APKTOOL和Dex2Jar以及JD-GUI。
3. 反解Settings.apk
在終端中執(zhí)行
apktool if framework-res.apk
安裝資源文件,然后再執(zhí)行
apktool d Settings.apk
將APK文件解包為smali文件
同時將Settings.apk中的classes.dex文件解壓出來,使用dex2jar工具將dex文件轉(zhuǎn)換為jar包,使用JD-GUI進行查看。
4. 定位問題
? ? ? ?打開Eclipse并使用Hierarchy View工具(這里并不是一定需要Eclipse,通過抓取跳轉(zhuǎn)Log同樣可以定位到對應(yīng)的顯示頁面)進行查看,可以得到當前頁面對應(yīng)的文件是com.android.settings.DevelopmentSettingsActivity。
然后再在使用apktool反解后的文件夾中搜索關(guān)鍵字——"過度繪制",可以知道其在string.xml中對應(yīng)的字符串ID,這里搜索到的結(jié)果是:
<string name="show_hw_overdraw">顯示 GPU 過度繪制</string>? ? ? ?通過前面的分析我們知道,屏蔽的方法只是修改配置文件和初始化代碼,因此資源文件多數(shù)情況下是不會去修改的。雖然我們搜索到了,但如果繼續(xù)試用該ID進行搜索可能會無法找打相關(guān)內(nèi)容,畢竟初始化代碼和配置文件已經(jīng)修改了。因此這里我們采用迂回戰(zhàn)術(shù),什么叫迂回戰(zhàn)術(shù)呢?我們知道在設(shè)置里面除了“顯示GPU過度繪制”選項意外還有“顯示布局邊界”,我們在string.xml中搜索“顯示布局邊界”可以得到:
<string name="debug_layout">顯示布局邊界</string>? ? ? ?那么我們以debug_layout為關(guān)鍵字繼續(xù)搜索,可以在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中的,這里我們是反編譯,因此再打包回去時肯定不會再編譯一次,因此相應(yīng)的資源ID(R.java中的16進制代碼)就無法生成,所以我們需要手動修改以下文件:
/res/values/ids.xml
? ? ? ?因為我們剛在使用的是@id/switch_show_hw_overdraw注意這里不是@+id,所以需要在id.xml中增加對應(yīng)的代碼,參考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之后,資源文件對應(yīng)的資源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" />? ? ? ?如果放錯了位置,會導(dǎo)致回編譯的時候報錯。 在做完以上錯做之后,基本上就完成了1/2的工作了,這個時候可以先回編譯試試看
apktool b Settings
? ? ? ?在Settings/dist文件夾中找到編譯好的Settings.apk,將其中的resource.arsc拖到原Settings.apk中,使用adb push指令將修改后的Settings.apk push到/system/app,重新運行設(shè)置,進入開發(fā)者選項里面我們就可以找到“顯示GPU過度繪制”了,但這時候會發(fā)現(xiàn)我們點擊之后沒有效果,那是因為我們還沒有加上初始化和響應(yīng)代碼。
? ? ? ?因為初始化和響應(yīng)代碼就是基本流程了,直接照搬switch_debug_layout的就可以了,所以這里就不贅述了,以下是修改前后的對比圖,一目了然:
變量初始化
onCreate初始化
onResume顯示
onCheckedChanged處理
? ? ? ?經(jīng)過以上修改之后,我們再次打包并push到系統(tǒng)中進行測試,我們可以看到對比圖:
左側(cè)為錘子ROM原生設(shè)置界面 右側(cè)為修改后的設(shè)置界面
左側(cè)為未開啟狀態(tài) 右側(cè)為開啟狀態(tài)
總結(jié):
? ? ? ?一開始只是想看看“GPU過度繪制”,可沒成想人家不給看,那就只能自己動手了。以后遇到這種問題還是先分析,避免走彎道。
如果想深入了解GPU過度繪制以及APP優(yōu)化的童鞋可以參考以下鏈接(需要翻墻):
http://www.curious-creature.org/2012/12/01/android-performance-case-study/
國內(nèi)有大牛翻譯了,鏈接如下:
http://blog.chengyunfeng.com/?p=458#
優(yōu)化效果可以參看:
http://www.cnblogs.com/myzh/
下載:
我將修改前后的APK都打包上傳,有想動手試試的童鞋可以看看,下載地址在這里。
總結(jié)
以上是生活随笔為你收集整理的反编译实战之给锤子ROM加上显示GPU过度绘制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 最小操作数,木块砌墙问题
- 下一篇: cisco 产品销售手册