Skip to content

Commit b3ef0b6

Browse files
committed
fix: stabilize Google Photos GmsCore support
1 parent 9ae81ab commit b3ef0b6

2 files changed

Lines changed: 58 additions & 21 deletions

File tree

extensions/shared-youtube/library/src/main/java/app/morphe/extension/shared/patches/GmsCoreSupportPatch.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ private static String getOriginalPackageName() {
6060
* @return If the current package name is the same as the original unpatched app.
6161
* If `GmsCore support` was not included during patching, this returns true;
6262
*/
63-
public static boolean isPackageNameOriginal() {
63+
public static boolean isPackageNameOriginal(Context context) {
6464
String originalPackageName = getOriginalPackageName();
6565
return originalPackageName == null
66-
|| originalPackageName.equals(Utils.getContext().getPackageName());
66+
|| originalPackageName.equals(context.getPackageName());
6767
}
6868

6969
private static void open(String queryOrLink) {
@@ -126,7 +126,7 @@ public static void checkGmsCore(Activity context) {
126126
// Verify the user has not included GmsCore for a root installation.
127127
// GmsCore Support changes the package name, but with a mounted installation
128128
// all manifest changes are ignored and the original package name is used.
129-
if (isPackageNameOriginal()) {
129+
if (isPackageNameOriginal(context)) {
130130
Logger.printInfo(() -> "App is mounted with root, but GmsCore patch was included");
131131
// Cannot use localize text here, since the app will load resources
132132
// from the unpatched app and all patch strings are missing.

patches/src/main/kotlin/app/morphe/patches/googlephotos/misc/login/Fingerprints.kt

Lines changed: 55 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,49 @@ package app.morphe.patches.googlephotos.misc.login
77
import app.morphe.patcher.Fingerprint
88
import app.morphe.util.getReference
99
import com.android.tools.smali.dexlib2.AccessFlags
10+
import com.android.tools.smali.dexlib2.iface.ClassDef
11+
import com.android.tools.smali.dexlib2.iface.Method
12+
import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction
1013
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
1114
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
15+
import com.android.tools.smali.dexlib2.iface.reference.StringReference
16+
17+
private fun Method.referencesString(value: String) =
18+
implementation?.instructions?.any {
19+
it.getReference<StringReference>()?.string == value
20+
} == true
21+
22+
private fun Method.referencesStringContaining(value: String) =
23+
implementation?.instructions?.any {
24+
it.getReference<StringReference>()?.string?.contains(value) == true
25+
} == true
26+
27+
private fun Method.referencesMethod(returnType: String, parameters: List<String>? = null) =
28+
implementation?.instructions?.any {
29+
it.getReference<MethodReference>()?.let { ref ->
30+
ref.returnType == returnType && (parameters == null || ref.parameterTypes.toList() == parameters)
31+
} == true
32+
} == true
33+
34+
private fun Method.referencesVoidMethodWithSingleObjectParameter() =
35+
implementation?.instructions?.any {
36+
it.getReference<MethodReference>()?.let { ref ->
37+
ref.returnType == "V" &&
38+
ref.parameterTypes.size == 1 &&
39+
ref.parameterTypes.first().startsWith("L")
40+
} == true
41+
} == true
42+
43+
private fun Method.referencesIntLiteral(value: Int) =
44+
implementation?.instructions?.any {
45+
it is NarrowLiteralInstruction && it.narrowLiteral == value
46+
} == true
47+
48+
private fun ClassDef.hasMethodReferencingString(value: String) =
49+
methods.any { it.referencesString(value) }
50+
51+
private fun ClassDef.hasMethodReferencingStringContaining(value: String) =
52+
methods.any { it.referencesStringContaining(value) }
1253

1354
/**
1455
* Matches `aext.d()` — the AccountValidityMonitor method that enqueues `CheckAccountTask`
@@ -18,18 +59,16 @@ internal object AccountValidityMonitorCheckFingerprint : Fingerprint(
1859
accessFlags = listOf(AccessFlags.PUBLIC, AccessFlags.FINAL),
1960
returnType = "V",
2061
parameters = listOf(),
21-
custom = { method, _ ->
22-
method.implementation?.instructions?.let { insns ->
23-
insns.any {
62+
custom = { method, classDef ->
63+
classDef.hasMethodReferencingString("AccountValidityMonitor") &&
64+
classDef.hasMethodReferencingString("com.google.android.apps.photos.login.AccountValidityMonitor.CheckAccountTask") &&
65+
method.implementation?.instructions?.let { instructions ->
66+
instructions.any {
2467
it.getReference<FieldReference>()?.let { ref ->
25-
ref.definingClass == "Laexv;" && ref.name == "a" && ref.type == "I"
68+
ref.name == "a" && ref.type == "I"
2669
} == true
27-
} && insns.any {
28-
it.getReference<MethodReference>()?.toString()?.contains(
29-
"AccountValidityMonitor\$CheckAccountTask"
30-
) == true
31-
}
32-
} ?: false
70+
} && method.referencesVoidMethodWithSingleObjectParameter()
71+
} == true
3372
},
3473
)
3574

@@ -42,14 +81,12 @@ internal object FrictionlessEligibilityFingerprint : Fingerprint(
4281
accessFlags = listOf(AccessFlags.PUBLIC, AccessFlags.FINAL),
4382
returnType = "Z",
4483
parameters = listOf(),
45-
custom = { method, _ ->
46-
method.implementation?.instructions?.let { insns ->
47-
insns.any {
48-
it.getReference<MethodReference>()?.toString() == "Lasgb;->b()Z"
49-
} && insns.any {
50-
it.getReference<MethodReference>()?.toString() == "Laexs;->o(I)V"
51-
}
52-
} ?: false
84+
custom = { method, classDef ->
85+
classDef.hasMethodReferencingStringContaining("maybeStartFrictionless") &&
86+
classDef.hasMethodReferencingString("ProvideFrctAccountTask") &&
87+
method.referencesMethod("Z", emptyList()) &&
88+
method.referencesMethod("V", listOf("I")) &&
89+
method.referencesIntLiteral(-1)
5390
},
5491
)
5592

0 commit comments

Comments
 (0)