使用xposed自动开启oppo usb调试(需root+xposed)

查看 470|回复 11
作者:LeadroyaL   
使用 xposed 自动开启 oppo usb 调试(需 root+xposed)
背景
上回(https://www.52pojie.cn/thread-1253114-1-1.html )我们说到如何干掉 adb install 时候的框,最近又被oppo的操作气到了,具体如下:
用 oppo 的开发者都知道,无论如何设置,插上 USB 后,
[color=]一定要主动点击 【传输文件】 这个按钮,否则 adb 连不上
。每次插 USB 都要点一下,非常让人恼火,于是写个 xposed 插件把这个东西给干掉。
目标:每次连接 USB 后,让 usb 调试可以自动开启。


IMG_20200901_153313.jpg (66.09 KB, 下载次数: 2)
下载附件
2020-9-1 15:51 上传

确认位置
使用 monitor dump ui,发现在 com.android.systemui 下。
直接用 apktool 解包时提醒缺少资源,需要用 apktool if 安装 framework 的资源,然后再解包。
adb pull /system/framework/oppo-framework-res.apk
adb pull /system/framework/framework-res.apk
apktool if oppo-framework-res.apk
apktool if framework-res.apk
apktool d SystemUI.apk
grep 字符串,确认到 UsbService 文件
➜  SystemUI grep "用于" * -R
res/values-zh-rCN/strings.xml:    USB 用于
➜  SystemUI grep "usb_usage_purpose" * -R
res/values/public.xml:   
res/values/strings.xml:    Use USB to
➜  SystemUI grep 0x7f1108b1 * -R
res/values/public.xml:   
smali_classes2/com/coloros/systemui/notification/usb/UsbService.smali:    const v2, 0x7f1108b1
分析代码
看到 showUsbDialog 方法有明显的绘制 GUI 的行为。
    private void showUsbDialog(boolean arg8) {
        ..........
        Builder v1 = new Builder(this, 0x7F1202B3).setDialogType(0).setTitle(0x7F1108B1);  // style:Theme.ColorSupport.Dialog.Alert.UsbType
        UsbTypeSelectAdapter v2 = this.mUsbTypeAdapter;
        com.coloros.systemui.notification.usb.UsbService.5 v3 = Utils.isOptionDisabled(this.mContext) ? null : new DialogInterface.OnClickListener() {
            @Override  // android.content.DialogInterface$OnClickListener
            public void onClick(DialogInterface arg2, int arg3) {
                UsbService.this.mUsbTypeAdapter.setChecked(arg3);
                UsbService.this.onUsbSelect(arg3);
                UsbService.this.delayDismiss();
                if(arg8) {
                    UsbStatistics.getInstance().collectUsbNotificationClickStatistic(UsbService.this.mContext, v0, arg3);
                    return;
                }
                UsbStatistics.getInstance().collectUsbInsertStatistic(UsbService.this.mContext, arg3);
            }
        };
        this.mUsbSelectDialog = v1.setSingleChoiceItems(v2, 0, v3).create();
        this.mUsbTypeAdapter.setRadioClickListener(new RadioButtonClickListener() {
            @Override  // com.coloros.systemui.notification.usb.UsbTypeSelectAdapter$RadioButtonClickListener
            public void onRadioButtonClick(int arg2) {
                UsbService.this.onUsbSelect(arg2);
                UsbService.this.delayDismiss();
            }
        });
        .......
    }
使用 xposed 进行 hook,打印一下栈回溯
java.lang.RuntimeException
        at de.robv.android.xposed.XC_MethodHook.callBeforeHookedMethod(XC_MethodHook.java:51)
        at EdHooker_.hook(Unknown Source:96)
        at com.coloros.systemui.notification.usb.UsbService.updateUsbNotification(UsbService.java:706)
        at com.coloros.systemui.notification.usb.UsbService.onUsbConnected(UsbService.java:595)
        at com.coloros.systemui.notification.usb.UsbService.access$1500(UsbService.java:71)
        at com.coloros.systemui.notification.usb.UsbService$4.run(UsbService.java:554)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:238)
        at android.app.ActivityThread.main(ActivityThread.java:7767)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1016)
发现插入 usb 的一瞬间触发的是 onUsbConnected。
观察代码,发现处理 com.oppo.test.only.charge 时会关掉 adb 调试,于是我们对这个 receiver 进行过滤。尝试后发现没有效果。
试一试将 onUsbConnected replace 为空实现。尝试后发现满足我们的要求,插上后就有adb了,但是通知栏的修改USB用途的Notification没有被显示。
    private void onUsbConnected(Context arg4) {
        if(SystemProperties.get("ro.oppo.factory_mode", "0").equals("1")) {
            return;
        }
        int v0 = 0;
        if(NotificationFeatureOption.isCtaSupport()) {
            v0 = 2;
        }
        Settings.System.putInt(this.mContext.getContentResolver(), "usb_remeber_selection", v0);
        this.updateAdbNotification(arg4);
        this.updateUsbNotification(arg4, v0);
        if((this.needReset()) && !this.mOpm.isClosedSuperFirewall()) {
            this.changeUsbConfig(arg4, v0);
        }
阅读代码发现,需要replace时调用 updateUsbNotification 来更新通知栏,传参给 1,表示正在传输文件。
尝试后完全满足我们的要求,框也不弹了,adb 也不断了,调试起来更有劲了,收工!
成品
public class Entry implements IXposedHookLoadPackage {
    @Override
    public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
        ClassLoader classLoader = lpparam.classLoader;
        if (lpparam.packageName.equals("com.android.systemui")) {
            XposedBridge.log("Patch oppo usb dialog START");
            XposedHelpers.findAndHookMethod("com.coloros.systemui.notification.usb.UsbService", classLoader, "onUsbConnected", Context.class, new XC_MethodReplacement() {
                @Override
                protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
                    Object thiz = param.thisObject;
                    thiz.getClass().getField("sNeedShowUsbDialog").set(null, false);
                    thiz.getClass().getMethod("updateUsbNotification", Context.class, int.class).invoke(thiz, (Context) param.args[0], 1);
                    return null;
                }
            });
            XposedBridge.log("Patch oppo usb dialog END");
        }
    }
}```

发现, 代码

LeadroyaL
OP
  


maza 发表于 2020-9-1 17:39
只能oppo吗

统一回复:只有 oppo 有这个毛病,其他品牌的手机都可以设置成  ”充电时允许 usb 调试”、“默认为 usb 调试“ 这种选项。所以其他手机没必要做这个事情。
忆清鸣   

还有个问题,ADB确实是切换出来了,但是文件传输模式没有调用出来,电脑上也不显示设备,添加调用 onUsbSelect(1) 方法,会发送切换文件传输模式的广播,然后电脑端就可以看到设备内置存储目录了
feng3593   

话说OPPO系统真令人恶心,打开开发者模式一直提示处在工程模式
chanbork   

天哪,太好了。非常需要这个。感谢分享!
夜步城   

vivo手机也很令人难受
tanghengvip   

这次和上次的都很实用!可否帮小白编译个插件出来
大手印   

使用 xposed 来外挂 QQ 和微信是否会比较容易封号呀
微笑掩盖忧伤   

支持,支持,有没有小米的
hualala   

谢谢分享
您需要登录后才可以回帖 登录 | 立即注册

返回顶部