commit ffd42de7f1f1370425ea051f4602588065ae83fb
parent d7d3834f215bc28dd82bb58f2b8a19e40cef8de8
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date:   Fri, 29 Dec 2023 01:01:28 +0100
fix(core): SuspendLocationUpdates
Diffstat:
1 file changed, 35 insertions(+), 4 deletions(-)
diff --git a/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/global/SuspendLocationUpdates.kt b/core/src/main/kotlin/me/rhunk/snapenhance/core/features/impl/global/SuspendLocationUpdates.kt
@@ -10,6 +10,7 @@ import me.rhunk.snapenhance.core.ui.ViewAppearanceHelper
 import me.rhunk.snapenhance.core.util.hook.HookStage
 import me.rhunk.snapenhance.core.util.hook.hook
 import me.rhunk.snapenhance.core.util.ktx.getId
+import java.util.WeakHashMap
 
 //TODO: bridge shared preferences
 class SuspendLocationUpdates : BridgeFileFeature(
@@ -17,15 +18,39 @@ class SuspendLocationUpdates : BridgeFileFeature(
     loadParams = FeatureLoadParams.INIT_SYNC or FeatureLoadParams.ACTIVITY_CREATE_SYNC,
     bridgeFileType = BridgeFileType.SUSPEND_LOCATION_STATE
 ) {
+    private val streamSendHandlerInstanceMap = WeakHashMap<Any, () -> Unit>()
     private val isEnabled get() = context.config.global.suspendLocationUpdates.get()
+
     override fun init() {
         if (!isEnabled) return
         reload()
 
-        context.classCache.unifiedGrpcService.hook("bidiStreamingCall", HookStage.BEFORE) { param ->
-            val uri = param.arg<String>(0)
-            if (uri == "/snapchat.valis.Valis/Communicate" && exists("true")) {
-                param.setResult(null)
+        findClass("com.snapchat.client.grpc.ClientStreamSendHandler\$CppProxy").hook("send", HookStage.BEFORE) { param ->
+            if (param.nullableThisObject<Any>() !in streamSendHandlerInstanceMap) return@hook
+            if (!exists("true")) return@hook
+            param.setResult(null)
+        }
+
+        context.classCache.unifiedGrpcService.apply {
+            hook("unaryCall", HookStage.BEFORE) { param ->
+                val uri = param.arg<String>(0)
+                if (exists("true") && uri == "/snapchat.valis.Valis/SendClientUpdate") {
+                    param.setResult(null)
+                }
+            }
+
+            hook("bidiStreamingCall", HookStage.AFTER) { param ->
+                val uri = param.arg<String>(0)
+                if (uri != "/snapchat.valis.Valis/Communicate") return@hook
+                param.getResult()?.let { instance ->
+                    streamSendHandlerInstanceMap[instance] = {
+                        runCatching {
+                            instance::class.java.methods.first { it.name == "closeStream" }.invoke(instance)
+                        }.onFailure {
+                            context.log.error("Failed to close stream send handler instance", it)
+                        }
+                    }
+                }
             }
         }
     }
@@ -47,6 +72,12 @@ class SuspendLocationUpdates : BridgeFileFeature(
                         ViewGroup.LayoutParams.WRAP_CONTENT
                     )
                     setOnCheckedChangeListener { _, isChecked ->
+                        if (isChecked) {
+                            streamSendHandlerInstanceMap.entries.removeIf { (_, closeStream) ->
+                                closeStream()
+                                true
+                            }
+                        }
                         setState("true", isChecked)
                     }
                 })