反编译实战之给锤子ROM加上显示GPU过度绘制
什么叫“顯示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都打包上傳,有想動手試試的童鞋可以看看,下載地址在這里。
總結
以上是生活随笔為你收集整理的反编译实战之给锤子ROM加上显示GPU过度绘制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 最小操作数,木块砌墙问题
- 下一篇: cisco 产品销售手册