在Root的手機上開啓ViewServer,使得HierachyViewer可以鏈接

前期準備:html

關於什麼是Hierarchy Viewer,請查看官方文檔:http://developer.android.com/tools/debugging/debugging-ui.html。我的理解:Hierarchy Viewer能得到當前手機實時的UI信息,給界面設計人員和自動化測試人員帶來極大的便利。java

在Android的官方文檔中提到:android

To preserve security, Hierarchy Viewer can only connect to devices running a developer version of the Android system.shell

即:出於安全考慮,Hierarchy Viewer只能鏈接Android開發版手機或是模擬器(準確地說,只有ro.secure參數等於0且ro.debuggable等於1的android系統)。Hierarchy Viewer在鏈接手機時,手機上必須啓動一個叫View Server的客戶端與其進行socket通訊。而在商業手機上,是沒法開啓View Server的,故Hierarchy Viewer是沒法鏈接到普通的商業手機。apache


Android源碼實現這一限制的地方在:windows

ANDROID源碼根目錄\frameworks\base\services\java\com\android\server\wm\WindowManageService.java安全

中的一段:app

=====================================================================================socket

public boolean startViewServer(int port{
    if (isSystemSecure()) {
        return false;
    }

    if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
        return false;
    }
ide

....


檢驗一臺手機是否開啓了View Server的辦法爲:

adb shell service call window 3

若返回值是:Result: Parcel(00000000 00000000 '........')" 說明View Server處於關閉狀態

若返回值是:Result: Parcel(00000000 00000001 '........')" 說明View Server處於開啓狀態


如果一臺能夠打開View Server的手機(Android開發版手機 、模擬器or 按照本帖步驟給系統打補丁的手機),咱們可使用如下命令打開View Server:

adb shell service call window 1 i32 4939

使用如下命令關閉View Server:

adb shell service call window 2 i32 4939

實現步驟:

通過一番調查和實踐,我發現其實只要是root,而且裝有busybox的手機,經過修改手機上/system/framework中的某些文件,就能夠開啓。本文參考了http://blog.apkudo.com/tag/viewserver/如下是具體步驟(本人基於Windows,若你是Linux的操做系統,直接看原帖吧):

前提是:你的手機已經得到ROOT權限,且有BUSYBOX

另外:請仔細閱讀本帖的評論,或許你會有新的收穫。


1.將商業手機經過USB鏈接PC,確保adb服務運行正常


2.備份手機上/system/framework/中的文件至PC。備份的時候請確保PC上保存備份文件的文件夾結構與手機中的/system/framework相同

例如:新建 ANDROID_SDK_ROOT\system\framework文件夾 (本文出現的ANDROID_SDK_ROOT指你安裝Android SDK的根目錄

接着在cmd中跳轉至ANDROID_SDK_ROOT\platform-tools文件夾下,輸入如下代碼進行備份:

adb pull /system/framework  ANDROID_SDK_ROOT\system\framework


3.進入adb shell,輸出BOOTCLASSPATH:

推薦的作法:

1. 在adb shell中echo $BOOTCLASSPATH > /sdcard/bootclasspath.txt

2. 退回到windows cmd中,輸入adb pull /sdcard/bootclasspath.txt

3. bootclasspath.txt將會保存在C:\Users\你的用戶名 文件夾下

在第十五步中將會用到這個txt中的內容。

4.下載baksmali 和smali工具。這兩個工具是用來反編譯和編譯odex文件的。

下載地址:

https://dl.dropboxusercontent.com/u/5055823/baksmali-1.4.2.jar

https://dl.dropboxusercontent.com/u/5055823/smali-1.4.2.jar

假設我將這兩個jar都下載到了ANDROID SDK根目錄下。


5.運行baksmali反編譯\system\framework下的services.odex文件:

java -jar ANDROID_SDK_ROOT\baksmali-1.4.2.jar -a 17 -x ANDROID_SDK_ROOT\system\framework\services.odex -d ANDROID_SDK_ROOT\system\framework

參數解釋:https://code.google.com/p/smali/wiki/DeodexInstructions

想特別說明的是「-a」後跟的數字,表示你係統的API Level(與你的系統版本有關)。系統版本和API Level的對照關係以下:


(另外,你不會連java -jar都不能運行吧?快去裝jdk!)

此步成功的話,在同文件夾下(對於我,就是ANDROID_SDK_ROOT),會有個out文件夾生成


這裏順便解釋一下odex文件和dex文件。

dex文件Dex是Dalvik VM executes的全稱,即Android Dalvik執行程序,並不是Java的字節碼而是Dalvik字節碼,16進制機器指令。

odex文件:將dex文件依據具體機型而優化,造成的optimized dex文件,提升軟件運行速度,減小軟件運行時對RAM的佔用。

smali文件:將dex文件變爲可讀易懂的代碼形式,反編譯出文件的通常格式。


6.用Eclipse打開out\com\android\server\wm\WindowManagerService.smali文件

查找.method private isSystemSecure()Z這個函數

================================================================

.method private isSystemSecure()Z

    .registers 4

    .prologue

    .line 5965

    const-string v0, "1"

    const-string v1, "ro.secure"

    const-string v2, "1"

    invoke-static {v1, v2}, Landroid/os/SystemProperties;->get(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;

    move-result-object v1

    invoke-virtual {v0, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

    move-result v0

    if-eqz v0, :cond_22

    const-string v0, "0"

    const-string v1, "ro.debuggable"

    const-string v2, "0"

    invoke-static {v1, v2}, Landroid/os/SystemProperties;->get(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;

    move-result-object v1

    invoke-virtual {v0, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

    move-result v0

    if-eqz v0, :cond_22

    const/4 v0, 0x1

    :goto_21

    return v0

    :cond_22

    const/4 v0, 0x0

    goto :goto_21

.end method

================================================================

在這段代碼的倒數7,8行「:goto_21」和「return v0」之間加入"const/4 v0, 0x0"一行.這樣,就使得v0返回的值永遠爲0x0,即false,這樣就跳過了WindowManagerService.java裏對isSystemSecure的判斷。

.method private isSystemSecure()Z函數最後變爲:

================================================================

.method private isSystemSecure()Z

    .registers 4

    .prologue

    .line 6276

    const-string v0, "1"

    const-string v1, "ro.secure"

    const-string v2, "1"

    invoke-static {v1, v2}, Landroid/os/SystemProperties;->get(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;

    move-result-object v1

    invoke-virtual {v0, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

    move-result v0

    if-eqz v0, :cond_22

    const-string v0, "0"

    const-string v1, "ro.debuggable"

    const-string v2, "0"

    invoke-static {v1, v2}, Landroid/os/SystemProperties;->get(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;

    move-result-object v1

    invoke-virtual {v0, v1}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z

    move-result v0

    if-eqz v0, :cond_22

    const/4 v0, 0x1

    :goto_21

    const/4 v0, 0x0

    return v0

    :cond_22

    const/4 v0, 0x0

    goto :goto_21

.end method

=====================================================================================

7. 如今運行smali,從新編譯:

java -jar smali-1.4.2.jar -o classes.dex

這時候,應該在ANDROID_SDK_ROOT文件夾中出現了classes.dex文件


8. 下載windows下的zip工具:

https://dl.dropboxusercontent.com/u/5055823/zip.exe

假設,我也把zip.exe放進了ANDROID_SDK_ROOT文件夾

9.確認當前cmd命令行運行目錄爲ANDROID_SDK_ROOT,運行:

zip.exe services_hacked.jar ./classes.dex

這時候在ANDROID_SDK_ROOT文件夾下,出現了打包好的services_hacked.jar

10.進入adb shell,輸入su得到ROOT權限

11.從新掛載/system,並更改/system權限

參考步驟(僅供參考,請確保使用相適應於本身手機的正確方法。請參考下面的"galfordq的blog"用戶的回覆):

  a. 輸入mount,查看哪一個分區掛載了/system,例如個人是:

  b. 輸入如下命令從新掛載/system,並更改/system權限(請將「/dev/block/mmcblk0p25」替換成你的/system掛載分區):

   mount -o rw,remount -t yaffs2 /dev/block/mmcblk0p25

   chmod -R 777 /system 使得/system 能夠被咱們任意修改

這一步的做用,主要是爲了第17步可以將/system/framework裏的services.odex替換掉。這一步若不成功,在第17步的時候可能出現權限不夠,沒法替換的錯誤(Read-Only File System)

12.下載dexopt-wrapper文件

https://dl.dropboxusercontent.com/u/5055823/dexopt-wrapper

咱們也將dexopt-wrapper文件放在ANDROID_SDK_ROOT文件夾中


13.將services_hacked.jar和dexopt-wrapper複製到手機的/data/local/tmp文件夾中

adb push ANDROID_SDK_ROOT/services_hacked.jar /data/local/tmp

adb push ANDROID_SDK_ROOT/dexopt-wrapper /data/local/tmp

14.進入adb shell,輸入su後,將dexopt-wrapper的權限改成777

chmod 777 /data/local/tmp/dexopt-wrapper

15.在adb shell中cd到/data/local/tmp文件夾下,運行:

./dexopt-wrapper ./services_hacked.jar ./services_hacked.odex <本帖第三步存的地址,可是要刪除其中的":/system/framework/services.jar">

這一步就是將第七部生成dex文件最終優化成了odex文件。[若是失敗,dexopt-wrapper文件拷貝到/system/bin目錄下]

===================================================================================================

例如個人命令是:./dexopt-wrapper ./services_hacked.jar ./services_hacked.odex /system/framework/core.jar:/system/framework/core-junit.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/

framework.jar:/system/framework/framework2.jar:/system/framework/android.policy.jar:/system/

framework/apache-xml.jar:/system/framework/HTCDev.jar:/system/framework/HTCExtension.jar:/system/

framework/filterfw.jar:/system/framework/com.htc.android.bluetooth.jar:/system/framework/wimax.jar:

/system/framework/usbnet.jar:/system/framework/com.orange.authentication.simcard.jar

===================================================================================================

這樣,便在/data/local/tmp文件夾中生成了咱們本身的odex:services_hacked.odex

16.給咱們本身生成的services_hacked.odex簽名:

busybox dd if=/system/framework/services.odex of=/data/local/tmp/services_hacked.odex bs=1 count=20 skip=52 seek=52 conv=notrunc

參數解釋:

if = input file

of = output file

bs = block size (1 byte)

count = number of blocks

skip = input file offset

seek = output file offset

conv=notrunc – don’t truncate the output file.

17.將/system/framework裏的services.odex替換成咱們本身製做的services_hacked.odex吧!

dd if=/data/local/tmp/services_hacked.odex of=/system/framework/services.odex

這一步運行後,過一小會兒(1分鐘之內)手機就自動重啓了!稍等片刻吧!


18.成功重啓後,用如下命令打開View Server:

adb shell service call window 1 i32 4939

用如下命令查看View Server是否打開:

adb shell service call window 3

返回的值如果Result: Parcel(00000000 00000001   '........'),那麼你就起了!

(若某一步失敗,須要恢復系統,請參考http://blog.apkudo.com/tag/viewserver/中的Step 16或聯繫個人郵箱進一步討論:czxttkl@gmail.com


接下來,就在Eclipse下編譯運行HierarchyViewer來查看手機實時的UI樹吧。

請參考:http://maider.blog.sohu.com/255485243.html

相關文章
相關標籤/搜索