From 7a25791d53530b1236896b2c3d6275ee7556e8b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pisarski?= Date: Mon, 25 Mar 2024 21:53:23 +0100 Subject: [PATCH] feat(Mi Fitness): Add `Force English locale` and `Fix login` patch (#2734) Co-authored-by: oSumAtrIX --- api/revanced-patches.api | 12 ++++++ .../misc/locale/ForceEnglishLocalePatch.kt | 39 +++++++++++++++++++ .../SyncBluetoothLanguageFingerprint.kt | 12 ++++++ .../mifitness/misc/login/FixLoginPatch.kt | 35 +++++++++++++++++ ...omiAccountManagerConstructorFingerprint.kt | 14 +++++++ 5 files changed, 112 insertions(+) create mode 100644 src/main/kotlin/app/revanced/patches/mifitness/misc/locale/ForceEnglishLocalePatch.kt create mode 100644 src/main/kotlin/app/revanced/patches/mifitness/misc/locale/fingerprints/SyncBluetoothLanguageFingerprint.kt create mode 100644 src/main/kotlin/app/revanced/patches/mifitness/misc/login/FixLoginPatch.kt create mode 100644 src/main/kotlin/app/revanced/patches/mifitness/misc/login/fingerprints/XiaomiAccountManagerConstructorFingerprint.kt diff --git a/api/revanced-patches.api b/api/revanced-patches.api index 849737d42..f82f86e45 100644 --- a/api/revanced-patches.api +++ b/api/revanced-patches.api @@ -284,6 +284,18 @@ public final class app/revanced/patches/messenger/inputfield/patch/DisableTyping public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V } +public final class app/revanced/patches/mifitness/misc/locale/ForceEnglishLocalePatch : app/revanced/patcher/patch/BytecodePatch { + public static final field INSTANCE Lapp/revanced/patches/mifitness/misc/locale/ForceEnglishLocalePatch; + public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V + public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V +} + +public final class app/revanced/patches/mifitness/misc/login/FixLoginPatch : app/revanced/patcher/patch/BytecodePatch { + public static final field INSTANCE Lapp/revanced/patches/mifitness/misc/login/FixLoginPatch; + public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V + public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V +} + public final class app/revanced/patches/moneymanager/UnlockProPatch : app/revanced/patcher/patch/BytecodePatch { public static final field INSTANCE Lapp/revanced/patches/moneymanager/UnlockProPatch; public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V diff --git a/src/main/kotlin/app/revanced/patches/mifitness/misc/locale/ForceEnglishLocalePatch.kt b/src/main/kotlin/app/revanced/patches/mifitness/misc/locale/ForceEnglishLocalePatch.kt new file mode 100644 index 000000000..c71b0c626 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/mifitness/misc/locale/ForceEnglishLocalePatch.kt @@ -0,0 +1,39 @@ +package app.revanced.patches.mifitness.misc.locale + +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction +import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.annotation.CompatiblePackage +import app.revanced.patcher.patch.annotation.Patch +import app.revanced.patches.mifitness.misc.locale.fingerprints.SyncBluetoothLanguageFingerprint +import app.revanced.patches.mifitness.misc.login.FixLoginPatch +import app.revanced.util.exception +import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction + +@Patch( + name = "Force English locale", + description = "Forces wearable devices to use the English locale.", + compatiblePackages = [CompatiblePackage("com.xiaomi.wearable")], + dependencies = [FixLoginPatch::class], +) +@Suppress("unused") +object ForceEnglishLocalePatch : BytecodePatch( + setOf(SyncBluetoothLanguageFingerprint), +) { + override fun execute(context: BytecodeContext) { + SyncBluetoothLanguageFingerprint.result?.let { + val resolvePhoneLocaleInstruction = it.scanResult.patternScanResult!!.startIndex + + it.mutableMethod.apply { + val registerIndexToUpdate = + getInstruction(resolvePhoneLocaleInstruction).registerA + + replaceInstruction( + resolvePhoneLocaleInstruction, + "const-string v$registerIndexToUpdate, \"en_gb\"", + ) + } + } ?: throw SyncBluetoothLanguageFingerprint.exception + } +} diff --git a/src/main/kotlin/app/revanced/patches/mifitness/misc/locale/fingerprints/SyncBluetoothLanguageFingerprint.kt b/src/main/kotlin/app/revanced/patches/mifitness/misc/locale/fingerprints/SyncBluetoothLanguageFingerprint.kt new file mode 100644 index 000000000..95c9a43f0 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/mifitness/misc/locale/fingerprints/SyncBluetoothLanguageFingerprint.kt @@ -0,0 +1,12 @@ +package app.revanced.patches.mifitness.misc.locale.fingerprints + +import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.Opcode + +internal object SyncBluetoothLanguageFingerprint : MethodFingerprint( + customFingerprint = { methodDef, _ -> + methodDef.definingClass == "Lcom/xiaomi/fitness/devicesettings/DeviceSettingsSyncer;" && + methodDef.name == "syncBluetoothLanguage" + }, + opcodes = listOf(Opcode.MOVE_RESULT_OBJECT), +) diff --git a/src/main/kotlin/app/revanced/patches/mifitness/misc/login/FixLoginPatch.kt b/src/main/kotlin/app/revanced/patches/mifitness/misc/login/FixLoginPatch.kt new file mode 100644 index 000000000..cf67c893d --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/mifitness/misc/login/FixLoginPatch.kt @@ -0,0 +1,35 @@ +package app.revanced.patches.mifitness.misc.login + +import app.revanced.patcher.data.BytecodeContext +import app.revanced.patcher.extensions.InstructionExtensions.addInstruction +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction +import app.revanced.patcher.patch.BytecodePatch +import app.revanced.patcher.patch.annotation.CompatiblePackage +import app.revanced.patcher.patch.annotation.Patch +import app.revanced.patches.mifitness.misc.login.fingerprints.XiaomiAccountManagerConstructorFingerprint +import app.revanced.util.exception +import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction + +@Patch( + name = "Fix login", + description = "Fixes login for uncertified Mi Fitness app", + compatiblePackages = [CompatiblePackage("com.xiaomi.wearable")], +) +@Suppress("unused") +object FixLoginPatch : BytecodePatch( + setOf(XiaomiAccountManagerConstructorFingerprint), +) { + override fun execute(context: BytecodeContext) { + XiaomiAccountManagerConstructorFingerprint.result?.let { + it.mutableMethod.apply { + val isCertifiedIndex = it.scanResult.patternScanResult!!.startIndex + val isCertifiedRegister = getInstruction(isCertifiedIndex).registerA + + addInstruction( + isCertifiedIndex, + "const/4 p$isCertifiedRegister, 0x0", + ) + } + } ?: throw XiaomiAccountManagerConstructorFingerprint.exception + } +} diff --git a/src/main/kotlin/app/revanced/patches/mifitness/misc/login/fingerprints/XiaomiAccountManagerConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/mifitness/misc/login/fingerprints/XiaomiAccountManagerConstructorFingerprint.kt new file mode 100644 index 000000000..e5d06acef --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/mifitness/misc/login/fingerprints/XiaomiAccountManagerConstructorFingerprint.kt @@ -0,0 +1,14 @@ +package app.revanced.patches.mifitness.misc.login.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode + +internal object XiaomiAccountManagerConstructorFingerprint : MethodFingerprint( + accessFlags = AccessFlags.PRIVATE or AccessFlags.CONSTRUCTOR, + customFingerprint = { methodDef, _ -> + methodDef.definingClass == "Lcom/xiaomi/passport/accountmanager/XiaomiAccountManager;" + }, + opcodes = listOf(Opcode.IF_NEZ), +)