Skip to content

Commit

Permalink
fix: shizuku
Browse files Browse the repository at this point in the history
  • Loading branch information
lisonge committed Sep 25, 2023
1 parent aa706b9 commit c93fa87
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 98 deletions.
9 changes: 5 additions & 4 deletions app/src/main/java/li/songe/gkd/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,17 @@ class App : Application() {
super.onCreate()
_app = this

ShizukuProvider.enableMultiProcessSupport(isMainProcess)

CrashReport.initCrashReport(applicationContext, "d0ce46b353", false)
MMKV.initialize(this)
LogUtils.getConfig().apply {
isLog2FileSwitch = true
setConsoleSwitch(BuildConfig.DEBUG)
saveDays = 3
}
CrashReport.initCrashReport(applicationContext, "d0ce46b353", false)

ShizukuProvider.enableMultiProcessSupport(isMainProcess)
if (!isMainProcess) {
ShizukuProvider.requestBinderForNonProviderProcess(this)
}
if (isMainProcess) {
appScope.launchTry(Dispatchers.IO) {
initChannel()
Expand Down
41 changes: 8 additions & 33 deletions app/src/main/java/li/songe/gkd/service/GkdAbService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,8 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import li.songe.gkd.composition.CompositionAbService
import li.songe.gkd.composition.CompositionExt.useLifeCycleLog
Expand All @@ -37,9 +33,7 @@ import li.songe.gkd.data.click
import li.songe.gkd.data.clickCenter
import li.songe.gkd.data.clickNode
import li.songe.gkd.db.DbSet
import li.songe.gkd.shizuku.newActivityTaskManager
import li.songe.gkd.shizuku.shizukuIsSafeOK
import li.songe.gkd.shizuku.useShizukuAliveState
import li.songe.gkd.shizuku.useSafeGetTasksFc
import li.songe.gkd.util.Singleton
import li.songe.gkd.util.increaseClickCount
import li.songe.gkd.util.launchTry
Expand All @@ -51,6 +45,7 @@ import li.songe.selector.Selector
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine


@OptIn(FlowPreview::class)
class GkdAbService : CompositionAbService({
useLifeCycleLog()
Expand All @@ -77,34 +72,14 @@ class GkdAbService : CompositionAbService({
delay(1000)
}

val shizukuAliveFlow = useShizukuAliveState()
val shizukuGrantFlow = MutableStateFlow(false)
scope.launchWhile(IO) {
shizukuGrantFlow.value = if (shizukuAliveFlow.value) shizukuIsSafeOK() else false
delay(3000)
}
val activityTaskManagerFlow =
combine(shizukuAliveFlow, shizukuGrantFlow) { shizukuAlive, shizukuGrant ->
if (shizukuAlive && shizukuGrant) newActivityTaskManager() else null
}.flowOn(IO).stateIn(scope, SharingStarted.Eagerly, null)
var serviceConnected = false
onServiceConnected { serviceConnected = true }

val safeGetTasksFc = useSafeGetTasksFc(scope)
fun getActivityIdByShizuku(): String? {
try {
val topActivity =
activityTaskManagerFlow.value?.getTasks(1, false, true)?.firstOrNull()?.topActivity
return topActivity?.className
} catch (_: NoSuchMethodError) {
// java.lang.NoSuchMethodError
// 貌似不同手机的方法签名不一样
} catch (_: Exception) {
}
return null
return safeGetTasksFc()?.lastOrNull()?.topActivity?.className
}

var serviceConnected = false
onServiceConnected { serviceConnected = true }
onInterrupt { serviceConnected = false }

fun isActivity(appId: String, activityId: String): Boolean {
return activityId.startsWith(appId) || (try {
packageManager.getActivityInfo(ComponentName(appId, activityId), 0)
Expand All @@ -114,7 +89,7 @@ class GkdAbService : CompositionAbService({
}

onAccessibilityEvent { event -> // 根据事件获取 activityId, 概率不准确
if (event == null || isScreenLock) return@onAccessibilityEvent
if (event == null) return@onAccessibilityEvent

when (event.eventType) {
AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED -> {
Expand Down Expand Up @@ -221,7 +196,7 @@ class GkdAbService : CompositionAbService({

var lastUpdateSubsTime = System.currentTimeMillis()
scope.launchWhile(IO) { // 自动从网络更新订阅文件
delay(30 * 60_000)
delay(10 * 60_000) // 每 10 分钟检查一次
if (isScreenLock // 锁屏
|| storeFlow.value.updateSubsInterval <= 0 // 暂停更新
|| System.currentTimeMillis() - lastUpdateSubsTime < storeFlow.value.updateSubsInterval.coerceAtLeast(
Expand Down
10 changes: 1 addition & 9 deletions app/src/main/java/li/songe/gkd/service/ManageService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package li.songe.gkd.service

import android.content.Context
import android.content.Intent
import android.os.Build
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch
import li.songe.gkd.app
Expand All @@ -15,25 +14,18 @@ import li.songe.gkd.notif.defaultChannel
import li.songe.gkd.util.appIdToRulesFlow
import li.songe.gkd.util.clickCountFlow
import li.songe.gkd.util.storeFlow
import rikka.shizuku.ShizukuProvider

class ManageService : CompositionService({
useLifeCycleLog()
val context = this
createNotif(context, defaultChannel.id, abNotif)
val scope = useScope()

if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.TIRAMISU) {
// https://github.com/RikkaApps/Shizuku-API/issues/54
ShizukuProvider.requestBinderForNonProviderProcess(this)
}

scope.launch {
combine(appIdToRulesFlow, clickCountFlow, storeFlow) { appIdToRules, clickCount, store ->
if (!store.enableService) return@combine "服务已暂停"
val appSize = appIdToRules.keys.size
val groupSize =
appIdToRules.values.flatten().map { r -> r.group.hashCode() }.toSet().size
val groupSize = appIdToRules.values.sumOf { r -> r.size }
(if (groupSize > 0) {
"${appSize}应用/${groupSize}规则组"
} else {
Expand Down
104 changes: 104 additions & 0 deletions app/src/main/java/li/songe/gkd/shizuku/ShizukuApi.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package li.songe.gkd.shizuku


import android.app.ActivityManager
import android.app.IActivityTaskManager
import android.os.Build
import com.blankj.utilcode.util.LogUtils
import com.blankj.utilcode.util.RomUtils
import com.blankj.utilcode.util.ToastUtils
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.stateIn
import li.songe.gkd.composition.CanOnDestroy
import li.songe.gkd.data.DeviceInfo
import li.songe.gkd.util.launchWhile
import rikka.shizuku.Shizuku
import rikka.shizuku.ShizukuBinderWrapper
import rikka.shizuku.SystemServiceHelper
import kotlin.reflect.full.declaredMemberFunctions
import kotlin.reflect.typeOf

/**
* https://github.com/gkd-kit/gkd/issues/44
*/

val skipShizuku by lazy {
Build.VERSION.SDK_INT == Build.VERSION_CODES.P && RomUtils.isVivo()
}

fun newActivityTaskManager(): IActivityTaskManager? {
return SystemServiceHelper.getSystemService("activity_task").let(::ShizukuBinderWrapper)
.let(IActivityTaskManager.Stub::asInterface)
}

/**
* -1: invalid fc
* 1: (int) -> List<Task>
* 3: (int, boolean, boolean) -> List<Task>
*/
private var getTasksFcType: Int? = null

fun IActivityTaskManager.safeGetTasks(): List<ActivityManager.RunningTaskInfo>? {
if (getTasksFcType == null) {
val fcs = this::class.declaredMemberFunctions
val parameters = fcs.find { d -> d.name == "getTasks" }?.parameters
if (parameters != null) {
if (parameters.size == 4 && parameters[1].type == typeOf<Int>() && parameters[2].type == typeOf<Boolean>() && parameters[3].type == typeOf<Boolean>()) {
getTasksFcType = 3
} else if (parameters.size == 2 && parameters[1].type == typeOf<Int>()) {
getTasksFcType = 1
} else {
getTasksFcType = -1
LogUtils.d(DeviceInfo.instance)
LogUtils.d(fcs)
ToastUtils.showShort("Shizuku获取方法签名错误,[设置-问题反馈]可反应此问题")
}
}
}
if (getTasksFcType == 1) {
return this.getTasks(1)
} else if (getTasksFcType == 3) {
return this.getTasks(1, false, true)
}
return null
}


fun CanOnDestroy.useShizukuAliveState(): StateFlow<Boolean> {
val shizukuAliveFlow = MutableStateFlow(Shizuku.pingBinder())
val receivedListener = Shizuku.OnBinderReceivedListener { shizukuAliveFlow.value = true }
val deadListener = Shizuku.OnBinderDeadListener { shizukuAliveFlow.value = false }
Shizuku.addBinderReceivedListener(receivedListener)
Shizuku.addBinderDeadListener(deadListener)
onDestroy {
Shizuku.removeBinderReceivedListener(receivedListener)
Shizuku.removeBinderDeadListener(deadListener)
}
return shizukuAliveFlow
}

fun CanOnDestroy.useSafeGetTasksFc(scope: CoroutineScope): () -> List<ActivityManager.RunningTaskInfo>? {
if (skipShizuku) {
return { null }
}
val shizukuAliveFlow = useShizukuAliveState()
val shizukuGrantFlow = MutableStateFlow(false)
scope.launchWhile(Dispatchers.IO) {
shizukuGrantFlow.value = if (shizukuAliveFlow.value) shizukuIsSafeOK() else false
delay(3000)
}
val activityTaskManagerFlow =
combine(shizukuAliveFlow, shizukuGrantFlow) { shizukuAlive, shizukuGrant ->
if (shizukuAlive && shizukuGrant) newActivityTaskManager() else null
}.flowOn(Dispatchers.IO).stateIn(scope, SharingStarted.Lazily, null)
return {
activityTaskManagerFlow.value?.safeGetTasks()
}
}
3 changes: 1 addition & 2 deletions app/src/main/java/li/songe/gkd/shizuku/ShizukuExt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ fun shizukuIsSafeOK(): Boolean {
return try {
Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED
} catch (e: Exception) {
e.printStackTrace()
false
}
}
}
46 changes: 0 additions & 46 deletions app/src/main/java/li/songe/gkd/shizuku/ShizukuSystemServiceApi.kt

This file was deleted.

7 changes: 5 additions & 2 deletions app/src/main/java/li/songe/gkd/ui/DebugPage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import com.blankj.utilcode.util.LogUtils
import com.blankj.utilcode.util.ToastUtils
import com.dylanc.activityresult.launcher.launchForResult
import com.ramcosta.composedestinations.annotation.Destination
Expand All @@ -47,6 +48,7 @@ import li.songe.gkd.debug.FloatingService
import li.songe.gkd.debug.HttpService
import li.songe.gkd.debug.ScreenshotService
import li.songe.gkd.shizuku.newActivityTaskManager
import li.songe.gkd.shizuku.safeGetTasks
import li.songe.gkd.shizuku.shizukuIsSafeOK
import li.songe.gkd.ui.component.AuthCard
import li.songe.gkd.ui.component.SettingItem
Expand Down Expand Up @@ -94,13 +96,14 @@ fun DebugPage() {
if (shizukuIsOk) {
// check method type
appScope.launchTry(Dispatchers.IO) {
newActivityTaskManager()
LogUtils.d(newActivityTaskManager()?.safeGetTasks()
?.map { t -> t.topActivity?.className })
}
}
})
if (!shizukuIsOk) {
AuthCard(title = "Shizuku授权",
desc = "高级运行模式,能更准确识别界面活动ID\nAndroid14暂无法使用",
desc = "高级运行模式,能更准确识别界面活动ID",
onAuthClick = {
try {
Shizuku.requestPermission(Activity.RESULT_OK)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@

@SuppressWarnings("unused")
public interface IActivityTaskManager extends IInterface {
// miui
List<ActivityManager.RunningTaskInfo> getTasks(int maxNum, boolean filterOnlyVisibleRecents, boolean keepIntentExtra);

// https://github.com/gkd-kit/gkd/issues/58#issuecomment-1732245703
List<ActivityManager.RunningTaskInfo> getTasks(int maxNum);

abstract class Stub extends Binder implements IActivityTaskManager {
public static IActivityTaskManager asInterface(IBinder obj) {
throw new RuntimeException("Stub!");
Expand Down
4 changes: 2 additions & 2 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ dependencyResolutionManagement {
library("rikka.runtime", "dev.rikka.tools.refine:runtime:4.3.0")

// https://github.com/RikkaApps/Shizuku-API
library("rikka.shizuku.api", "dev.rikka.shizuku:api:13.1.4")
library("rikka.shizuku.provider", "dev.rikka.shizuku:provider:13.1.4")
library("rikka.shizuku.api", "dev.rikka.shizuku:api:13.1.5")
library("rikka.shizuku.provider", "dev.rikka.shizuku:provider:13.1.5")

// https://github.com/LSPosed/AndroidHiddenApiBypass
library("lsposed.hiddenapibypass", "org.lsposed.hiddenapibypass:hiddenapibypass:4.3")
Expand Down

0 comments on commit c93fa87

Please sign in to comment.