zoukankan      html  css  js  c++  java
  • 如何在Root的手机上开启ViewServer,使得HierachyViewer能够连接(转)

    前期准备:
    关于什么是Hierarchy Viewer,请查看官方文档:http://developer.android.com/tools/debugging/debugging-ui.html。个人理解:Hierarchy Viewer能获得当前手机实时的UI信息,给界面设计人员和自动化测试人员带来极大的便利。
     
    在Android的官方文档中提到:
    To preserve security, Hierarchy Viewer can only connect to devices running a developer version of the Android system.
    即:出于安全考虑,Hierarchy Viewer只能连接Android开发版手机或是模拟器(准确地说,只有ro.secure参数等于0且ro.debuggable等于1的android系统)。Hierarchy Viewer在连接手机时,手机上必须启动一个叫View Server的客户端与其进行socket通信。而在商业手机上,是无法开启View Server的,故Hierarchy Viewer是无法连接到普通的商业手机。
     
    Android源码实现这一限制的地方在:
    ANDROID源码根目录frameworksaseservicesjavacomandroidserverwmWindowManageService.java
    中的一段:
    =====================================================================================
    public boolean startViewServer(int port) {
        if (isSystemSecure()) {
            return false;
        }

        if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
            return false;
        }
    ....
    =====================================================================================
     
    检验一台手机是否开启了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_ROOTsystemframework文件夹 (本文出现的ANDROID_SDK_ROOT指你安装Android SDK的根目录
    接着在cmd中跳转至ANDROID_SDK_ROOTplatform-tools文件夹下,输入以下代码进行备份:
    adb pull /system/framework  ANDROID_SDK_ROOTsystemframework
     
    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文件的。
    下载地址:
    假设我将这两个jar都下载到了ANDROID SDK根目录下。
     
    5.运行baksmali反编译systemframework下的services.odex文件:
    java -jar ANDROID_SDK_ROOTaksmali-1.4.2.jar -a 17 -x ANDROID_SDK_ROOTsystemframeworkservices.odex -d ANDROID_SDK_ROOTsystemframework
    想特别说明的是“-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打开outcomandroidserverwmWindowManagerService.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工具:
    假设,我也把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文件
    我们也将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 ./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树吧。
  • 相关阅读:
    小波变换的引入,通俗易懂
    Leetcode 437. Path Sum III
    Leetcode 113. Path Sum II
    Leetcode 112 Path Sum
    Leetcode 520 Detect Capital
    Leetcode 443 String Compression
    Leetcode 38 Count and Say
    python中的生成器(generator)总结
    python的random模块及加权随机算法的python实现
    leetcode 24. Swap Nodes in Pairs(链表)
  • 原文地址:https://www.cnblogs.com/qq78292959/p/4316220.html
Copyright © 2011-2022 走看看