From 9ac2d634897d961eba1b704f2722ea757bb83e0a Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Mon, 18 Mar 2024 04:21:16 +0400 Subject: [PATCH] fix(TikTok): Hook application context earlier to prevent crash (#588) --- .../revanced/integrations/shared/Logger.java | 31 +++++++++------ .../revanced/integrations/shared/Utils.java | 20 +++++++--- .../tiktok/spoof/sim/SpoofSimPatch.java | 39 +++++++++++-------- 3 files changed, 57 insertions(+), 33 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/shared/Logger.java b/app/src/main/java/app/revanced/integrations/shared/Logger.java index f8c5c87e..25885050 100644 --- a/app/src/main/java/app/revanced/integrations/shared/Logger.java +++ b/app/src/main/java/app/revanced/integrations/shared/Logger.java @@ -5,14 +5,15 @@ import static app.revanced.integrations.shared.settings.BaseSettings.DEBUG_STACK import static app.revanced.integrations.shared.settings.BaseSettings.DEBUG_TOAST_ON_ERROR; import android.util.Log; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import app.revanced.integrations.shared.settings.BaseSettings; - import java.io.PrintWriter; import java.io.StringWriter; +import app.revanced.integrations.shared.settings.BaseSettings; + public class Logger { /** @@ -24,7 +25,7 @@ public class Logger { /** * @return For outer classes, this returns {@link Class#getSimpleName()}. - * For inner, static, or anonymous classes, this returns the simple name of the enclosing class.
+ * For static, inner, or anonymous classes, this returns the simple name of the enclosing class. *
* For example, each of these classes return 'SomethingView': * @@ -38,13 +39,13 @@ public class Logger { String fullClassName = selfClass.getName(); final int dollarSignIndex = fullClassName.indexOf('$'); - if (dollarSignIndex == -1) { - return selfClass.getSimpleName(); // already an outer class + if (dollarSignIndex < 0) { + return selfClass.getSimpleName(); // Already an outer class. } - // class is inner, static, or anonymous - // parse the simple name full name - // a class with no package returns index of -1, but incrementing gives index zero which is correct + // Class is inner, static, or anonymous. + // Parse the simple name full name. + // A class with no package returns index of -1, but incrementing gives index zero which is correct. final int simpleClassNameStartIndex = fullClassName.lastIndexOf('.') + 1; return fullClassName.substring(simpleClassNameStartIndex, dollarSignIndex); } @@ -137,11 +138,19 @@ public class Logger { } /** - * Logging to use if {@link BaseSettings#DEBUG} or {@link Utils#context} may not be initialized. - * Always logs even if Debugging is not enabled. + * Logging to use if {@link BaseSettings#DEBUG} or {@link Utils#getContext()} may not be initialized. * Normally this method should not be used. */ - public static void initializationError(@NonNull Class callingClass, @NonNull String message, @Nullable Exception ex) { + public static void initializationInfo(@NonNull Class callingClass, @NonNull String message) { + Log.i(REVANCED_LOG_PREFIX + callingClass.getSimpleName(), message); + } + + /** + * Logging to use if {@link BaseSettings#DEBUG} or {@link Utils#getContext()} may not be initialized. + * Normally this method should not be used. + */ + public static void initializationException(@NonNull Class callingClass, @NonNull String message, + @Nullable Exception ex) { Log.e(REVANCED_LOG_PREFIX + callingClass.getSimpleName(), message, ex); } diff --git a/app/src/main/java/app/revanced/integrations/shared/Utils.java b/app/src/main/java/app/revanced/integrations/shared/Utils.java index f92c9cfd..a7fbfcbc 100644 --- a/app/src/main/java/app/revanced/integrations/shared/Utils.java +++ b/app/src/main/java/app/revanced/integrations/shared/Utils.java @@ -54,13 +54,14 @@ public class Utils { try { final var packageName = Objects.requireNonNull(getContext()).getPackageName(); + PackageManager packageManager = context.getPackageManager(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) - packageInfo = context.getPackageManager().getPackageInfo( + packageInfo = packageManager.getPackageInfo( packageName, PackageManager.PackageInfoFlags.of(0) ); else - packageInfo = context.getPackageManager().getPackageInfo( + packageInfo = packageManager.getPackageInfo( packageName, 0 ); @@ -228,14 +229,23 @@ public class Utils { public static Context getContext() { if (context == null) { - Logger.initializationError(Utils.class, "Context is null, returning null!", null); + Logger.initializationException(Utils.class, "Context is null, returning null!", null); } return context; } public static void setContext(Context appContext) { context = appContext; - Logger.printDebug(() -> "Set context: " + appContext); // Cannot log before context is set. + // In some apps like TikTok, the Setting classes can load in weird orders due to cyclic class dependencies. + // Calling the regular printDebug method here can cause a Settings context null pointer exception, + // even though the context is already set before the call. + // + // The initialization logger methods do not directly or indirectly + // reference the Context or any Settings and are unaffected by this problem. + // + // Info level also helps debug if a patch hook is called before + // the context is set since debug logging is off by default. + Logger.initializationInfo(Utils.class, "Set context: " + appContext); } public static void setClipboard(@NonNull String text) { @@ -280,7 +290,7 @@ public class Utils { Objects.requireNonNull(messageToToast); runOnMainThreadNowOrLater(() -> { if (context == null) { - Logger.initializationError(Utils.class, "Cannot show toast (context is null): " + messageToToast, null); + Logger.initializationException(Utils.class, "Cannot show toast (context is null): " + messageToToast, null); } else { Logger.printDebug(() -> "Showing toast: " + messageToToast); Toast.makeText(context, messageToToast, toastDuration).show(); diff --git a/app/src/main/java/app/revanced/integrations/tiktok/spoof/sim/SpoofSimPatch.java b/app/src/main/java/app/revanced/integrations/tiktok/spoof/sim/SpoofSimPatch.java index 31145347..264bd893 100644 --- a/app/src/main/java/app/revanced/integrations/tiktok/spoof/sim/SpoofSimPatch.java +++ b/app/src/main/java/app/revanced/integrations/tiktok/spoof/sim/SpoofSimPatch.java @@ -1,32 +1,37 @@ package app.revanced.integrations.tiktok.spoof.sim; +import app.revanced.integrations.shared.Logger; import app.revanced.integrations.tiktok.settings.Settings; @SuppressWarnings("unused") public class SpoofSimPatch { - public static boolean isEnable() { - return Settings.SIM_SPOOF.get(); - } - public static String getCountryIso(String value) { - if (isEnable()) { - return Settings.SIM_SPOOF_ISO.get(); - } else { - return value; - } + private static final Boolean ENABLED = Settings.SIM_SPOOF.get(); + + public static String getCountryIso(String value) { + if (ENABLED) { + String iso = Settings.SIM_SPOOF_ISO.get(); + Logger.printDebug(() -> "Spoofing sim ISO from: " + value + " to: " + iso); + return iso; + } + return value; } + public static String getOperator(String value) { - if (isEnable()) { - return Settings.SIMSPOOF_MCCMNC.get(); - } else { - return value; + if (ENABLED) { + String mcc_mnc = Settings.SIMSPOOF_MCCMNC.get(); + Logger.printDebug(() -> "Spoofing sim MCC-MNC from: " + value + " to: " + mcc_mnc); + return mcc_mnc; } + return value; } + public static String getOperatorName(String value) { - if (isEnable()) { - return Settings.SIMSPOOF_OP_NAME.get(); - } else { - return value; + if (ENABLED) { + String operator = Settings.SIMSPOOF_OP_NAME.get(); + Logger.printDebug(() -> "Spoofing sim operator from: " + value + " to: " + operator); + return operator; } + return value; } }