Skip to content

Commit ad66615

Browse files
committed
feat: upgrade to xposed api 101
1 parent 67396a4 commit ad66615

22 files changed

Lines changed: 211 additions & 365 deletions

.github/workflows/ci_build.yml

Lines changed: 3 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -33,49 +33,23 @@ jobs:
3333
echo ${{ secrets.KEY_STORE }} | base64 --decode > key.jks
3434
fi
3535
36-
- name: Checkout libxposed/api
37-
uses: actions/checkout@v4
38-
with:
39-
repository: libxposed/api
40-
path: libxposed/api
41-
42-
- name: Checkout libxposed/service
43-
uses: actions/checkout@v4
44-
with:
45-
repository: libxposed/service
46-
path: libxposed/service
47-
4836
- name: Setup Java
4937
uses: actions/setup-java@v4
5038
with:
5139
distribution: "temurin"
52-
java-version: "21"
40+
java-version: "17"
5341

5442
- name: Setup Gradle
55-
uses: gradle/gradle-build-action@v2
43+
uses: gradle/actions/setup-gradle@v4
5644
with:
5745
gradle-home-cache-cleanup: true
5846

59-
- name: Build dependencies
60-
working-directory: libxposed
47+
- name: Build MiCTS Release
6148
run: |
6249
echo 'org.gradle.caching=true' >> ~/.gradle/gradle.properties
6350
echo 'org.gradle.parallel=true' >> ~/.gradle/gradle.properties
6451
echo 'org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 -XX:+UseParallelGC' >> ~/.gradle/gradle.properties
65-
echo 'android.native.buildOutput=verbose' >> ~/.gradle/gradle.properties
66-
cd api
67-
./gradlew publishToMavenLocal
68-
cd ../service
69-
./gradlew publishToMavenLocal
7052
71-
- name: Setup Java
72-
uses: actions/setup-java@v4
73-
with:
74-
distribution: "temurin"
75-
java-version: "17"
76-
77-
- name: Build MiCTS Release
78-
run: |
7953
./gradlew :app:assembleMiCTSRelease
8054
echo "MiCTS_APK_PATH=$(find app/build/outputs/apk/MiCTS/release -name '*.apk')" >> $GITHUB_ENV
8155

app/build.gradle.kts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ dependencies {
9292
implementation(libs.androidx.ui)
9393
implementation(libs.androidx.ui.graphics)
9494
implementation(libs.accompanist.drawablepainter)
95-
compileOnly(project(":libxposed-compat"))
9695
compileOnly(libs.libxposed.api)
9796
implementation(libs.libxposed.service)
9897
implementation(libs.hiddenapibypass)

app/src/main/java/com/parallelc/micts/ModuleMain.kt

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.parallelc.micts
22

33
import android.content.Context
44
import android.os.Build
5+
import android.util.Log
56
import com.parallelc.micts.config.TriggerService
67
import com.parallelc.micts.config.XposedConfig.CONFIG_NAME
78
import com.parallelc.micts.config.XposedConfig.DEFAULT_CONFIG
@@ -18,37 +19,36 @@ import com.parallelc.micts.hooker.NavBarEventHelperHooker
1819
import com.parallelc.micts.hooker.NavStubGestureEventManagerHooker
1920
import com.parallelc.micts.hooker.NavStubViewHooker
2021
import com.parallelc.micts.hooker.VIMSHooker
21-
import io.github.libxposed.api.XposedInterface
2222
import io.github.libxposed.api.XposedModule
2323
import io.github.libxposed.api.XposedModuleInterface.ModuleLoadedParam
24-
import io.github.libxposed.api.XposedModuleInterface.PackageLoadedParam
25-
import io.github.libxposed.api.XposedModuleInterface.SystemServerLoadedParam
24+
import io.github.libxposed.api.XposedModuleInterface.PackageReadyParam
25+
import io.github.libxposed.api.XposedModuleInterface.SystemServerStartingParam
2626

2727
var module: ModuleMain? = null
2828

29-
class ModuleMain(base: XposedInterface, param: ModuleLoadedParam) : XposedModule(base, param) {
29+
class ModuleMain : XposedModule() {
3030

31-
init {
31+
override fun onModuleLoaded(param: ModuleLoadedParam) {
3232
module = this
3333
}
3434

35-
override fun onSystemServerLoaded(param: SystemServerLoadedParam) {
36-
super.onSystemServerLoaded(param)
35+
override fun onSystemServerStarting(param: SystemServerStartingParam) {
36+
super.onSystemServerStarting(param)
3737

3838
if (BuildConfig.APP_NAME == "MiCTS") {
3939
if (TriggerService.getSupportedServices().contains(TriggerService.CSHelper)) {
4040
runCatching {
4141
VIMSHooker.hook(param)
4242
}.onFailure { e ->
43-
log("hook VIMS fail", e)
43+
log(Log.ERROR, "MiCTS", "hook VIMS fail", e)
4444
}
4545
}
4646

4747
if (TriggerService.getSupportedServices().contains(TriggerService.CSService)) {
4848
runCatching {
4949
CSMSHooker.hook(param)
5050
}.onFailure { e ->
51-
log("hook CSMS fail", e)
51+
log(Log.ERROR, "MiCTS", "hook CSMS fail", e)
5252
}
5353
}
5454
}
@@ -57,13 +57,13 @@ class ModuleMain(base: XposedInterface, param: ModuleLoadedParam) : XposedModule
5757
runCatching {
5858
LongPressHomeHooker.hook(param)
5959
}.onFailure { e ->
60-
log("hook LongPressHome fail", e)
60+
log(Log.ERROR, "MiCTS", "hook LongPressHome fail", e)
6161
}
6262
}
6363
}
6464

65-
override fun onPackageLoaded(param: PackageLoadedParam) {
66-
super.onPackageLoaded(param)
65+
override fun onPackageReady(param: PackageReadyParam) {
66+
super.onPackageReady(param)
6767
if (!param.isFirstPackage) return
6868

6969
val prefs = getRemotePreferences(CONFIG_NAME)
@@ -73,22 +73,24 @@ class ModuleMain(base: XposedInterface, param: ModuleLoadedParam) : XposedModule
7373
val skipHookTouch = runCatching {
7474
NavStubGestureEventManagerHooker.hook(param)
7575
}.onFailure { e ->
76-
log("hook NavStubGestureEventManager fail", e)
76+
log(Log.ERROR, "MiCTS", "hook NavStubGestureEventManager fail", e)
7777
}.recoverCatching {
7878
val circleToSearchHelper = param.classLoader.loadClass("com.miui.home.recents.cts.CircleToSearchHelper")
79-
hook(circleToSearchHelper.getDeclaredMethod("invokeOmni", Context::class.java, Int::class.java, Int::class.java), InvokeOmniHooker::class.java)
79+
hook(
80+
circleToSearchHelper.getDeclaredMethod("invokeOmni", Context::class.java, Int::class.java, Int::class.java)
81+
).intercept(InvokeOmniHooker())
8082
}.onFailure { e ->
81-
log("hook CircleToSearchHelper fail", e)
83+
log(Log.ERROR, "MiCTS", "hook CircleToSearchHelper fail", e)
8284
}.recoverCatching {
8385
NavBarEventHelperHooker.hook(param)
8486
}.onFailure { e ->
85-
log("hook NavBarEventHelper fail", e)
87+
log(Log.ERROR, "MiCTS", "hook NavBarEventHelper fail", e)
8688
}.isSuccess
8789

8890
runCatching {
8991
NavStubViewHooker.hook(param, skipHookTouch)
9092
}.onFailure { e ->
91-
log("hook NavStubView fail", e)
93+
log(Log.ERROR, "MiCTS", "hook NavStubView fail", e)
9294
}
9395
}
9496
"com.google.android.googlequicksearchbox" -> {
@@ -112,7 +114,7 @@ class ModuleMain(base: XposedInterface, param: ModuleLoadedParam) : XposedModule
112114
runCatching {
113115
NavBarActionsConfigHooker.hook(param)
114116
}.onFailure { e ->
115-
log("hook NavBarActionsConfig fail", e)
117+
log(Log.ERROR, "MiCTS", "hook NavBarActionsConfig fail", e)
116118
}
117119
}
118120
}

app/src/main/java/com/parallelc/micts/hooker/CSMSHooker.kt

Lines changed: 21 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@ package com.parallelc.micts.hooker
33
import android.annotation.SuppressLint
44
import android.content.Context
55
import android.os.IBinder
6+
import android.util.Log
67
import com.parallelc.micts.module
7-
import io.github.libxposed.api.XposedInterface.BeforeHookCallback
8+
import io.github.libxposed.api.XposedInterface.Chain
89
import io.github.libxposed.api.XposedInterface.Hooker
9-
import io.github.libxposed.api.XposedInterface.MethodUnhooker
10-
import io.github.libxposed.api.XposedModuleInterface.SystemServerLoadedParam
11-
import io.github.libxposed.api.annotations.BeforeInvocation
12-
import io.github.libxposed.api.annotations.XposedHooker
10+
import io.github.libxposed.api.XposedInterface.HookHandle
11+
import io.github.libxposed.api.XposedModuleInterface.SystemServerStartingParam
1312
import java.lang.reflect.Method
1413

1514
class CSMSHooker {
@@ -19,11 +18,12 @@ class CSMSHooker {
1918
private var contextualSearchPackageName: Int = 0
2019

2120
@SuppressLint("PrivateApi")
22-
fun hook(param: SystemServerLoadedParam) {
21+
fun hook(param: SystemServerStartingParam) {
2322
val rString = param.classLoader.loadClass("com.android.internal.R\$string")
2423
contextualSearchPackageName = rString.getField("config_defaultContextualSearchPackageName").getInt(null)
2524
val systemServer = param.classLoader.loadClass("com.android.server.SystemServer")
26-
module!!.hook(systemServer.getDeclaredMethod("deviceHasConfigString", Context::class.java, Int::class.java), DeviceHasConfigStringHooker::class.java)
25+
module!!.hook(systemServer.getDeclaredMethod("deviceHasConfigString", Context::class.java, Int::class.java))
26+
.intercept(DeviceHasConfigStringHooker())
2727

2828
val csms = param.classLoader.loadClass("com.android.server.contextualsearch.ContextualSearchManagerService")
2929
enforcePermission = csms.getDeclaredMethod("enforcePermission", String::class.java)
@@ -32,54 +32,41 @@ class CSMSHooker {
3232

3333
@SuppressLint("PrivateApi")
3434
fun startContextualSearch(entryPoint: Int): Boolean {
35-
var unhookers = mutableListOf<MethodUnhooker<Method>>()
35+
var hooks = mutableListOf<HookHandle>()
3636
return runCatching {
37-
unhookers += module!!.hook(enforcePermission!!, EnforcePermissionHooker::class.java)
38-
unhookers += module!!.hook(getContextualSearchPackageName!!, GetCSPackageNameHooker::class.java)
37+
hooks += module!!.hook(enforcePermission!!).intercept(EnforcePermissionHooker())
38+
hooks += module!!.hook(getContextualSearchPackageName!!).intercept(GetCSPackageNameHooker())
3939

4040
val icsmClass = Class.forName("android.app.contextualsearch.IContextualSearchManager")
4141
val cs = Class.forName("android.os.ServiceManager").getMethod("getService", String::class.java).invoke(null, "contextual_search")
4242
val icsm = Class.forName("android.app.contextualsearch.IContextualSearchManager\$Stub").getMethod("asInterface", IBinder::class.java).invoke(null, cs)
4343
icsmClass.getDeclaredMethod("startContextualSearch", Int::class.java).invoke(icsm, entryPoint)
4444
}.onFailure { e ->
45-
module!!.log("invoke startContextualSearch fail", e)
45+
module!!.log(Log.ERROR, "MiCTS", "invoke startContextualSearch fail", e)
4646
}.also {
47-
unhookers.forEach { unhooker -> unhooker.unhook() }
47+
hooks.forEach { hook -> hook.unhook() }
4848
}.isSuccess
4949
}
5050

51-
@XposedHooker
5251
class DeviceHasConfigStringHooker : Hooker {
53-
companion object {
54-
@JvmStatic
55-
@BeforeInvocation
56-
fun before(callback: BeforeHookCallback) {
57-
if (callback.args[1] == contextualSearchPackageName) {
58-
callback.returnAndSkip(true)
59-
}
52+
override fun intercept(chain: Chain): Any? {
53+
return if (chain.args[1] == contextualSearchPackageName) {
54+
true
55+
} else {
56+
chain.proceed()
6057
}
6158
}
6259
}
6360

64-
@XposedHooker
6561
class EnforcePermissionHooker : Hooker {
66-
companion object {
67-
@JvmStatic
68-
@BeforeInvocation
69-
fun before(callback: BeforeHookCallback) {
70-
callback.returnAndSkip(null)
71-
}
62+
override fun intercept(chain: Chain): Any? {
63+
return null
7264
}
7365
}
7466

75-
@XposedHooker
7667
class GetCSPackageNameHooker : Hooker {
77-
companion object {
78-
@JvmStatic
79-
@BeforeInvocation
80-
fun before(callback: BeforeHookCallback) {
81-
callback.returnAndSkip("com.google.android.googlequicksearchbox")
82-
}
68+
override fun intercept(chain: Chain): Any? {
69+
return "com.google.android.googlequicksearchbox"
8370
}
8471
}
8572
}

app/src/main/java/com/parallelc/micts/hooker/InvokeOmniHooker.kt

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,20 @@ import com.parallelc.micts.config.XposedConfig.KEY_GESTURE_TRIGGER
77
import com.parallelc.micts.config.XposedConfig.KEY_VIBRATE
88
import com.parallelc.micts.module
99
import com.parallelc.micts.ui.activity.triggerCircleToSearch
10-
import io.github.libxposed.api.XposedInterface.BeforeHookCallback
1110
import io.github.libxposed.api.XposedInterface.Hooker
12-
import io.github.libxposed.api.annotations.BeforeInvocation
13-
import io.github.libxposed.api.annotations.XposedHooker
11+
import io.github.libxposed.api.XposedInterface.Chain
1412

15-
@XposedHooker
1613
class InvokeOmniHooker : Hooker {
17-
companion object {
18-
@JvmStatic
19-
@BeforeInvocation
20-
fun before(callback: BeforeHookCallback) {
21-
val prefs = module!!.getRemotePreferences(CONFIG_NAME)
22-
if (prefs.getBoolean(KEY_GESTURE_TRIGGER, DEFAULT_CONFIG[KEY_GESTURE_TRIGGER] as Boolean)) {
23-
callback.returnAndSkip(
24-
triggerCircleToSearch(
25-
callback.args[2] as Int,
26-
callback.args[0] as Context?,
27-
prefs.getBoolean(KEY_VIBRATE, DEFAULT_CONFIG[KEY_VIBRATE] as Boolean)
28-
)
29-
)
30-
}
14+
override fun intercept(chain: Chain): Any? {
15+
val prefs = module!!.getRemotePreferences(CONFIG_NAME)
16+
return if (prefs.getBoolean(KEY_GESTURE_TRIGGER, DEFAULT_CONFIG[KEY_GESTURE_TRIGGER] as Boolean)) {
17+
triggerCircleToSearch(
18+
chain.args[2] as Int,
19+
chain.args[0] as Context?,
20+
prefs.getBoolean(KEY_VIBRATE, DEFAULT_CONFIG[KEY_VIBRATE] as Boolean)
21+
)
22+
} else {
23+
chain.proceed()
3124
}
3225
}
3326
}

0 commit comments

Comments
 (0)