1
+ package com.parallelc.micts
2
+
3
+ import android.annotation.SuppressLint
4
+ import android.content.Context
5
+ import android.content.Intent
6
+ import android.content.res.Resources
7
+ import android.os.Build
8
+ import android.os.Bundle
9
+ import android.os.IBinder
10
+ import android.os.SystemClock
11
+ import android.view.MotionEvent
12
+ import android.view.View
13
+ import android.view.ViewConfiguration
14
+ import io.github.libxposed.api.XposedInterface
15
+ import io.github.libxposed.api.XposedInterface.AfterHookCallback
16
+ import io.github.libxposed.api.XposedInterface.BeforeHookCallback
17
+ import io.github.libxposed.api.XposedInterface.Hooker
18
+ import io.github.libxposed.api.XposedModule
19
+ import io.github.libxposed.api.XposedModuleInterface.ModuleLoadedParam
20
+ import io.github.libxposed.api.XposedModuleInterface.PackageLoadedParam
21
+ import io.github.libxposed.api.XposedModuleInterface.SystemServerLoadedParam
22
+ import io.github.libxposed.api.annotations.AfterInvocation
23
+ import io.github.libxposed.api.annotations.BeforeInvocation
24
+ import io.github.libxposed.api.annotations.XposedHooker
25
+
26
+ private lateinit var module: ModuleMain
27
+
28
+ class ModuleMain (base : XposedInterface , param : ModuleLoadedParam ) : XposedModule(base, param) {
29
+
30
+ init {
31
+ module = this
32
+ }
33
+
34
+ @XposedHooker
35
+ class ContextualSearchIntentHooker : Hooker {
36
+ companion object {
37
+ @JvmStatic
38
+ @AfterInvocation
39
+ fun after (callback : AfterHookCallback ) {
40
+ (callback.result as Intent ).putExtra(" com.android.contextualsearch.flag_secure_found" , false )
41
+ }
42
+ }
43
+ }
44
+
45
+ class ResourcesHooker {
46
+ companion object {
47
+ private var R : Class <* >? = null
48
+
49
+ @SuppressLint(" PrivateApi" )
50
+ fun hook (param : SystemServerLoadedParam ) {
51
+ R = param.classLoader.loadClass(" com.android.internal.R\$ string" )
52
+ module.hook(Resources ::class .java.getDeclaredMethod(" getString" , Int ::class .java), GetStringHooker ::class .java)
53
+ }
54
+
55
+ @XposedHooker
56
+ class GetStringHooker : Hooker {
57
+ companion object {
58
+ @JvmStatic
59
+ @BeforeInvocation
60
+ fun before (callback : BeforeHookCallback ) {
61
+ when (callback.args[0 ]) {
62
+ R !! .getField(" config_defaultContextualSearchKey" ).getInt(null ) -> {
63
+ callback.returnAndSkip(" omni.entry_point" )
64
+ }
65
+
66
+ R !! .getField(" config_defaultContextualSearchPackageName" ).getInt(null ) -> {
67
+ callback.returnAndSkip(" com.google.android.googlequicksearchbox" )
68
+ }
69
+ }
70
+ }
71
+ }
72
+ }
73
+ }
74
+ }
75
+
76
+ @SuppressLint(" PrivateApi" )
77
+ override fun onSystemServerLoaded (param : SystemServerLoadedParam ) {
78
+ super .onSystemServerLoaded(param)
79
+
80
+ runCatching {
81
+ ResourcesHooker .hook(param)
82
+ val vims = param.classLoader.loadClass(" com.android.server.voiceinteraction.VoiceInteractionManagerService\$ VoiceInteractionManagerServiceStub" )
83
+ hook(vims.getDeclaredMethod(" getContextualSearchIntent" , Bundle ::class .java), ContextualSearchIntentHooker ::class .java)
84
+ }.onFailure { e ->
85
+ log(" hook system fail" , e)
86
+ }
87
+ }
88
+
89
+ @XposedHooker
90
+ class ReturnTrueHooker : Hooker {
91
+ companion object {
92
+ @JvmStatic
93
+ @BeforeInvocation
94
+ fun before (callback : BeforeHookCallback ) {
95
+ callback.returnAndSkip(true )
96
+ }
97
+ }
98
+ }
99
+
100
+ @XposedHooker
101
+ class ReturnFalseHooker : Hooker {
102
+ companion object {
103
+ @JvmStatic
104
+ @BeforeInvocation
105
+ fun before (callback : BeforeHookCallback ) {
106
+ callback.returnAndSkip(false )
107
+ }
108
+ }
109
+ }
110
+
111
+ @XposedHooker
112
+ class NavStubViewHooker : Hooker {
113
+ companion object {
114
+ @SuppressLint(" PrivateApi" )
115
+ private val mCheckLongPress = Runnable {
116
+ runCatching {
117
+ val bundle = Bundle ()
118
+ bundle.putLong(" invocation_time_ms" , SystemClock .elapsedRealtime())
119
+ bundle.putInt(" omni.entry_point" , 1 )
120
+ val iVims = Class .forName(" com.android.internal.app.IVoiceInteractionManagerService\$ Stub" )
121
+ val asInterfaceMethod = iVims.getMethod(" asInterface" , IBinder ::class .java)
122
+ val getServiceMethod = Class .forName(" android.os.ServiceManager" ).getMethod(" getService" , String ::class .java)
123
+ val vimsInstance = asInterfaceMethod.invoke(null , getServiceMethod.invoke(null , " voiceinteraction" )) ? : return @Runnable
124
+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .UPSIDE_DOWN_CAKE ) {
125
+ val showSessionFromSession = vimsInstance.javaClass.getDeclaredMethod(" showSessionFromSession" , IBinder ::class .java, Bundle ::class .java, Integer .TYPE , String ::class .java)
126
+ showSessionFromSession.invoke(vimsInstance, null , bundle, 7 , " hyperOS_home" )
127
+ } else {
128
+ val showSessionFromSession = vimsInstance.javaClass.getDeclaredMethod(" showSessionFromSession" , IBinder ::class .java, Bundle ::class .java, Integer .TYPE )
129
+ showSessionFromSession.invoke(vimsInstance, null , bundle, 7 )
130
+ }
131
+ }.onFailure { e ->
132
+ module.log(" NavStubViewHooker mCheckLongPress fail" , e)
133
+ }
134
+ }
135
+
136
+ @JvmStatic
137
+ @AfterInvocation
138
+ fun after (callback : AfterHookCallback ) {
139
+ val view = callback.thisObject as View
140
+ view.removeCallbacks(this .mCheckLongPress)
141
+ runCatching {
142
+ val mCurrAction = callback.thisObject!! .javaClass.getDeclaredField(" mCurrAction" )
143
+ mCurrAction.isAccessible = true
144
+ if (mCurrAction.getInt(callback.thisObject) == 0 ) {
145
+ view.postDelayed(this .mCheckLongPress, ViewConfiguration .getLongPressTimeout().toLong())
146
+ }
147
+ }.onFailure { e ->
148
+ module.log(" NavStubViewHooker onTouchEvent fail" , e)
149
+ }
150
+ }
151
+ }
152
+ }
153
+
154
+ override fun onPackageLoaded (param : PackageLoadedParam ) {
155
+ super .onPackageLoaded(param)
156
+ if (param.packageName != " com.miui.home" || ! param.isFirstPackage) return
157
+
158
+ runCatching {
159
+ val circleToSearchHelper = param.classLoader.loadClass(" com.miui.home.recents.cts.CircleToSearchHelper" )
160
+ hook(circleToSearchHelper.getDeclaredMethod(" isSceneForbid" , Context ::class .java, Int ::class .java), ReturnFalseHooker ::class .java)
161
+ hook(circleToSearchHelper.getDeclaredMethod(" hasCtsFeature" , Context ::class .java), ReturnTrueHooker ::class .java)
162
+ hook(circleToSearchHelper.getDeclaredMethod(" isSettingsLongPressHomeAssistantEnabled" , Context ::class .java), ReturnTrueHooker ::class .java)
163
+ hook(circleToSearchHelper.getDeclaredMethod(" isThirdHome" , Context ::class .java), ReturnFalseHooker ::class .java)
164
+ return
165
+ }.onFailure { e ->
166
+ log(" hook CircleToSearchHelper fail" , e)
167
+ }
168
+
169
+ runCatching {
170
+ val navStubView = param.classLoader.loadClass(" com.miui.home.recents.NavStubView" )
171
+ runCatching { navStubView.getDeclaredField(" mCheckLongPress" ) }
172
+ .onSuccess { throw Exception (" mCheckLongPress exists" ) }
173
+ .onFailure {
174
+ hook(navStubView.getDeclaredMethod(" onTouchEvent" , MotionEvent ::class .java), NavStubViewHooker ::class .java)
175
+ }
176
+ }.onFailure { e ->
177
+ log(" hook NavStubView fail" , e)
178
+ }
179
+ }
180
+ }
0 commit comments