Skip to content

Commit

Permalink
perf: shizuku state
Browse files Browse the repository at this point in the history
  • Loading branch information
lisonge committed Sep 24, 2024
1 parent 0da83e3 commit 3fda835
Show file tree
Hide file tree
Showing 9 changed files with 159 additions and 232 deletions.
16 changes: 4 additions & 12 deletions app/src/main/kotlin/li/songe/gkd/data/GkdAction.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import android.view.ViewConfiguration
import android.view.accessibility.AccessibilityNodeInfo
import com.blankj.utilcode.util.ScreenUtils
import kotlinx.serialization.Serializable
import li.songe.selector.FastQuery
import li.songe.gkd.shizuku.safeTap

@Serializable
data class GkdAction(
Expand All @@ -31,15 +31,13 @@ sealed class ActionPerformer(val action: String) {
context: AccessibilityService,
node: AccessibilityNodeInfo,
position: RawSubscription.Position?,
shizukuClickFc: ((x: Float, y: Float) -> Boolean?)? = null,
): ActionResult

data object ClickNode : ActionPerformer("clickNode") {
override fun perform(
context: AccessibilityService,
node: AccessibilityNodeInfo,
position: RawSubscription.Position?,
shizukuClickFc: ((x: Float, y: Float) -> Boolean?)?
): ActionResult {
return ActionResult(
action = action,
Expand All @@ -53,7 +51,6 @@ sealed class ActionPerformer(val action: String) {
context: AccessibilityService,
node: AccessibilityNodeInfo,
position: RawSubscription.Position?,
shizukuClickFc: ((x: Float, y: Float) -> Boolean?)?,
): ActionResult {
val rect = Rect()
node.getBoundsInScreen(rect)
Expand All @@ -64,7 +61,7 @@ sealed class ActionPerformer(val action: String) {
action = action,
// TODO 在分屏/小窗模式下会点击到应用界面外部导致误触其它应用
result = if (0 <= x && 0 <= y && x <= ScreenUtils.getScreenWidth() && y <= ScreenUtils.getScreenHeight()) {
val result = shizukuClickFc?.invoke(x, y)
val result = safeTap(x, y)
if (result != null) {
return ActionResult(action, result, true)
}
Expand All @@ -90,15 +87,14 @@ sealed class ActionPerformer(val action: String) {
context: AccessibilityService,
node: AccessibilityNodeInfo,
position: RawSubscription.Position?,
shizukuClickFc: ((x: Float, y: Float) -> Boolean?)?
): ActionResult {
if (node.isClickable) {
val result = ClickNode.perform(context, node, position)
if (result.result) {
return result
}
}
return ClickCenter.perform(context, node, position, shizukuClickFc)
return ClickCenter.perform(context, node, position)
}
}

Expand All @@ -107,7 +103,6 @@ sealed class ActionPerformer(val action: String) {
context: AccessibilityService,
node: AccessibilityNodeInfo,
position: RawSubscription.Position?,
shizukuClickFc: ((x: Float, y: Float) -> Boolean?)?
): ActionResult {
return ActionResult(
action = action,
Expand All @@ -121,7 +116,6 @@ sealed class ActionPerformer(val action: String) {
context: AccessibilityService,
node: AccessibilityNodeInfo,
position: RawSubscription.Position?,
shizukuClickFc: ((x: Float, y: Float) -> Boolean?)?
): ActionResult {
val rect = Rect()
node.getBoundsInScreen(rect)
Expand Down Expand Up @@ -156,15 +150,14 @@ sealed class ActionPerformer(val action: String) {
context: AccessibilityService,
node: AccessibilityNodeInfo,
position: RawSubscription.Position?,
shizukuClickFc: ((x: Float, y: Float) -> Boolean?)?
): ActionResult {
if (node.isLongClickable) {
val result = LongClickNode.perform(context, node, position)
if (result.result) {
return result
}
}
return LongClickCenter.perform(context, node, position, shizukuClickFc)
return LongClickCenter.perform(context, node, position)
}
}

Expand All @@ -173,7 +166,6 @@ sealed class ActionPerformer(val action: String) {
context: AccessibilityService,
node: AccessibilityNodeInfo,
position: RawSubscription.Position?,
shizukuClickFc: ((x: Float, y: Float) -> Boolean?)?
): ActionResult {
return ActionResult(
action = action,
Expand Down
5 changes: 2 additions & 3 deletions app/src/main/kotlin/li/songe/gkd/data/ResolvedRule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -190,10 +190,9 @@ sealed class ResolvedRule(

fun performAction(
context: AccessibilityService,
node: AccessibilityNodeInfo,
shizukuClickFc: ((x: Float, y: Float) -> Boolean?)? = null
node: AccessibilityNodeInfo
): ActionResult {
return performer.perform(context, node, rule.position, shizukuClickFc)
return performer.perform(context, node, rule.position)
}

var matchDelayJob: Job? = null
Expand Down
8 changes: 3 additions & 5 deletions app/src/main/kotlin/li/songe/gkd/debug/SnapshotTileService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import li.songe.gkd.service.TopActivity
import li.songe.gkd.service.getAndUpdateCurrentRules
import li.songe.gkd.service.safeActiveWindow
import li.songe.gkd.service.updateTopActivity
import li.songe.gkd.shizuku.safeGetTopActivity
import li.songe.gkd.util.launchTry
import li.songe.gkd.util.toast

Expand Down Expand Up @@ -46,11 +47,8 @@ class SnapshotTileService : TileService() {
} else if (latestAppId != oldAppId) {
LogUtils.d("SnapshotTileService::eventExecutor.execute")
A11yService.eventExecutor.execute {
updateTopActivity(
A11yService.instance?.getShizukuTopActivity?.invoke() ?: TopActivity(
appId = latestAppId
)
)
val topActivity = safeGetTopActivity() ?: TopActivity(appId = latestAppId)
updateTopActivity(topActivity)
getAndUpdateCurrentRules()
appScope.launchTry(Dispatchers.IO) {
captureSnapshot()
Expand Down
13 changes: 2 additions & 11 deletions app/src/main/kotlin/li/songe/gkd/permission/PermissionState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.updateAndGet
import li.songe.gkd.app
import li.songe.gkd.appScope
import li.songe.gkd.shizuku.newActivityTaskManager
import li.songe.gkd.shizuku.safeGetTasks
import li.songe.gkd.shizuku.shizukuIsSafeOK
import li.songe.gkd.shizuku.shizukuCheckGranted
import li.songe.gkd.util.initOrResetAppInfoCache
import li.songe.gkd.util.launchTry
import kotlin.coroutines.resume
Expand Down Expand Up @@ -161,14 +159,7 @@ val writeSecureSettingsState by lazy {

val shizukuOkState by lazy {
PermissionState(
check = {
shizukuIsSafeOK() && (try {
// 打开 shizuku 点击右上角停止, 此时 shizukuIsSafeOK() == true, 因此需要二次检查状态
newActivityTaskManager()?.safeGetTasks(log = false)?.isNotEmpty() == true
} catch (e: Exception) {
false
})
},
check = { shizukuCheckGranted() },
)
}

Expand Down
40 changes: 8 additions & 32 deletions app/src/main/kotlin/li/songe/gkd/service/A11yService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,8 @@ import li.songe.gkd.data.RuleStatus
import li.songe.gkd.data.clearNodeCache
import li.songe.gkd.debug.SnapshotExt
import li.songe.gkd.permission.shizukuOkState
import li.songe.gkd.shizuku.getShizukuCanUsedFlow
import li.songe.gkd.shizuku.useSafeGetTasksFc
import li.songe.gkd.shizuku.useSafeInputTapFc
import li.songe.gkd.shizuku.safeGetTopActivity
import li.songe.gkd.shizuku.serviceWrapperFlow
import li.songe.gkd.util.OnA11yConnected
import li.songe.gkd.util.OnA11yEvent
import li.songe.gkd.util.OnCreate
Expand Down Expand Up @@ -90,8 +89,6 @@ class A11yService : AccessibilityService(), OnCreate, OnA11yConnected, OnA11yEve
}

val scope = CoroutineScope(Dispatchers.Default)
val getShizukuTopActivity by lazy { useGetShizukuActivity() }
val getShizukuClick by lazy { useGetShizukuClick() }

init {
useRunningState()
Expand All @@ -101,8 +98,7 @@ class A11yService : AccessibilityService(), OnCreate, OnA11yConnected, OnA11yEve
useAutoUpdateSubs()
useRuleChangedLog()
useAutoCheckShizuku()
getShizukuTopActivity
getShizukuClick
serviceWrapperFlow
useMatchRule()
}

Expand Down Expand Up @@ -140,7 +136,7 @@ class A11yService : AccessibilityService(), OnCreate, OnA11yConnected, OnA11yEve

return ActionPerformer
.getAction(gkdAction.action)
.perform(serviceVal, targetNode, gkdAction.position, instance?.getShizukuClick)
.perform(serviceVal, targetNode, gkdAction.position)
}


Expand Down Expand Up @@ -241,7 +237,7 @@ private fun A11yService.useMatchRule() {
if (topActivityFlow.value.appId != rightAppId || (!matchApp && rule is AppRule)) {
A11yService.eventExecutor.execute {
if (topActivityFlow.value.appId != rightAppId) {
val shizukuTop = getShizukuTopActivity()
val shizukuTop = safeGetTopActivity()
if (shizukuTop?.appId == rightAppId) {
updateTopActivity(shizukuTop)
} else {
Expand Down Expand Up @@ -270,7 +266,7 @@ private fun A11yService.useMatchRule() {
continue
}
if (rule.status != RuleStatus.StatusOk) break
val actionResult = rule.performAction(context, target, getShizukuClick)
val actionResult = rule.performAction(context, target)
if (actionResult.result) {
rule.trigger()
scope.launch(A11yService.actionThread) {
Expand Down Expand Up @@ -356,7 +352,7 @@ private fun A11yService.useMatchRule() {
}
} else {
if (storeFlow.value.enableShizukuActivity && fixedEvent.time - lastTriggerShizukuTime > 300) {
val shizukuTop = getShizukuTopActivity()
val shizukuTop = safeGetTopActivity()
if (shizukuTop != null && shizukuTop.appId == rightAppId) {
if (shizukuTop.activityId == evActivityId) {
updateTopActivity(
Expand All @@ -373,7 +369,7 @@ private fun A11yService.useMatchRule() {
}
if (rightAppId != topActivityFlow.value.appId) {
// 从 锁屏,下拉通知栏 返回等情况, 应用不会发送事件, 但是系统组件会发送事件
val shizukuTop = getShizukuTopActivity()
val shizukuTop = safeGetTopActivity()
if (shizukuTop?.appId == rightAppId) {
updateTopActivity(shizukuTop)
} else {
Expand Down Expand Up @@ -429,26 +425,6 @@ private fun A11yService.useRunningState() {
}
}

private fun A11yService.useGetShizukuActivity(): () -> TopActivity? {
val enableShizukuActivityFlow = storeFlow.map(scope) { s -> s.enableShizukuActivity }
val shizukuActivityUsedFlow = getShizukuCanUsedFlow(scope, enableShizukuActivityFlow)
val safeGetTasksFc by lazy { useSafeGetTasksFc(scope, shizukuActivityUsedFlow) }
// 当锁屏/下拉通知栏时, safeActiveWindow 没有 activityId, 但是此时 shizuku 获取到是前台 app 的 appId 和 activityId
return fun(): TopActivity? {
if (!storeFlow.value.enableShizukuActivity) return null
// 平均耗时 5 ms
val top = safeGetTasksFc()?.lastOrNull()?.topActivity ?: return null
return TopActivity(appId = top.packageName, activityId = top.className)
}
}

private fun A11yService.useGetShizukuClick(): (Float, Float) -> Boolean? {
val shizukuClickUsedFlow =
getShizukuCanUsedFlow(scope, storeFlow.map(scope) { s -> s.enableShizukuClick })
val safeInjectClickEventFc = useSafeInputTapFc(scope, shizukuClickUsedFlow)
return safeInjectClickEventFc
}

private fun A11yService.useAutoCheckShizuku() {
var lastCheckShizukuTime = 0L
onA11yEvent {
Expand Down
Loading

0 comments on commit 3fda835

Please sign in to comment.