Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Mi Fitness): Add Force English locale and Fix login patch #2734

Merged
merged 11 commits into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions api/revanced-patches.api
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
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?.apply {
val resolvePhoneLocaleInstruction = scanResult.patternScanResult!!.startIndex

mutableMethod.apply {
val registerIndexToUpdate = getInstruction<OneRegisterInstruction>(resolvePhoneLocaleInstruction).registerA

replaceInstruction(
resolvePhoneLocaleInstruction,
"const-string v$registerIndexToUpdate, \"en_gb\"",
)
}
} ?: throw SyncBluetoothLanguageFingerprint.exception
}
}
Original file line number Diff line number Diff line change
@@ -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),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package app.revanced.patches.mifitness.misc.login

import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
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

@Patch(
name = "Fix login",
description = "Fixes login for uncertified Mi Fitness app",
oSumAtrIX marked this conversation as resolved.
Show resolved Hide resolved
compatiblePackages = [CompatiblePackage("com.xiaomi.wearable")],
)
@Suppress("unused")
object FixLoginPatch : BytecodePatch(
setOf(XiaomiAccountManagerConstructorFingerprint),
) {
override fun execute(context: BytecodeContext) {
XiaomiAccountManagerConstructorFingerprint.result?.mutableMethod?.addInstruction(
0,
"const/4 p2, 0x0",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure parameter 2 is never gonna change?

Copy link
Contributor Author

@pisek pisek Feb 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, no i am not sure as i am not the owner of the original app;)
Any proposal of how to do it in a better way?
It is a constructor fingerprint that takes boolean as second param. This param, if false, disables Android phone account login and enables login/password login

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this parameter is used somewhere in the code, you can obtain it from one of the instructions. If the compiled code updates the register count, the parameter 2 shifts accordingly, but since you'd obtain it from an existing instruction, you'd correctly reference the necessary register.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pisek The parameter seems still to be hardcoded

Copy link
Contributor Author

@pisek pisek Mar 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@oSumAtrIX , what do you mean?
I have changed XiaomiAccountManagerConstructorFingerprint to point directly to the param that i need.

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

internal object XiaomiAccountManagerConstructorFingerprint : MethodFingerprint(
    accessFlags = AccessFlags.PRIVATE or AccessFlags.CONSTRUCTOR,
    customFingerprint = { methodDef, _ ->
        methodDef.definingClass == "Lcom/xiaomi/passport/accountmanager/XiaomiAccountManager;"
    },
    parameters = listOf(
        "Landroid/content/Context;",
        "Z",
    ),
)

So in this case i will always use 2nd param - boolean.

The instruction that uses p2 is if-nez p2, :cond_0

What do you propose?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, the fingerprint could fail to resolve, which is about as fatal as the parameter changing because the patch would stop working in both cases. Instead, if you obtain the register from an existing instruction, the failure would be reduced down to the instruction shifting changing or moving. For now this is fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, i have updated the code to get the reg from instruction. Could you re-review?

) ?: throw XiaomiAccountManagerConstructorFingerprint.exception
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
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

internal object XiaomiAccountManagerConstructorFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PRIVATE or AccessFlags.CONSTRUCTOR,
customFingerprint = { methodDef, _ ->
methodDef.definingClass == "Lcom/xiaomi/passport/accountmanager/XiaomiAccountManager;"
},
parameters = listOf(
"Landroid/content/Context;",
"Z",
),
)
Loading