Skip to content

Commit

Permalink
perf: 优化规则执行逻辑
Browse files Browse the repository at this point in the history
  • Loading branch information
lisonge committed Nov 17, 2023
1 parent 80ac7a2 commit e927c8d
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 38 deletions.
10 changes: 4 additions & 6 deletions app/src/main/java/li/songe/gkd/service/AbState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -74,16 +74,14 @@ var activityChangeTime = 0L
// null: app 切换过
// true: 需要执行优化(此界面组需要存在开屏广告)
// false: 执行优化过了/已经过了优化时间
@Volatile
var openAdOptimized: Boolean? = null
const val openAdOptimizedTime = 5000L

fun isAvailableRule(rule: Rule): Boolean {
val t = System.currentTimeMillis()
if (!rule.isOpenAd && openAdOptimized == true) {
if (t - appChangeTime < openAdOptimizedTime) {
// app 切换一段时间内, 仅开屏广告可使用
return false
} else {
if (openAdOptimized == true) {
if (t - appChangeTime > openAdOptimizedTime) {
openAdOptimized = false
}
}
Expand Down Expand Up @@ -146,8 +144,8 @@ fun isAvailableRule(rule: Rule): Boolean {
}

fun insertClickLog(rule: Rule) {
toastClickTip()
rule.trigger()
toastClickTip()
appScope.launchTry(Dispatchers.IO) {
val clickLog = ClickLog(
appId = topActivityFlow.value?.appId,
Expand Down
97 changes: 65 additions & 32 deletions app/src/main/java/li/songe/gkd/service/GkdAbService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@ import com.blankj.utilcode.util.ServiceUtils
import io.ktor.client.request.get
import io.ktor.client.statement.bodyAsText
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import li.songe.gkd.composition.CompositionAbService
Expand All @@ -44,7 +48,7 @@ import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine


@OptIn(FlowPreview::class)
@OptIn(FlowPreview::class, ExperimentalCoroutinesApi::class)
class GkdAbService : CompositionAbService({
useLifeCycleLog()

Expand Down Expand Up @@ -93,12 +97,58 @@ class GkdAbService : CompositionAbService({
var lastTriggerShizukuTime = 0L
var lastContentEventTime = 0L
var job: Job? = null
val singleThread = Dispatchers.IO.limitedParallelism(1)
onDestroy {
singleThread.cancel()
}
val lastQueryTimeFlow = MutableStateFlow(0L)
val debounceTime = 500L
fun newQueryTask() {
job = scope.launchTry(singleThread) {
val activityRule = getCurrentRules()
for (rule in (activityRule.rules)) {
if (!isActive && !rule.isOpenAd) break
if (!isAvailableRule(rule)) continue
val nodeVal = safeActiveWindow ?: continue
val target = rule.query(nodeVal) ?: continue
if (activityRule !== getCurrentRules()) break

// 开始 action 延迟
if (rule.actionDelay > 0 && rule.actionDelayTriggerTime == 0L) {
rule.triggerDelay()
// 防止在 actionDelay 时间内没有事件发送导致无法触发
scope.launch(singleThread) {
delay(rule.actionDelay - debounceTime)
lastQueryTimeFlow.value = System.currentTimeMillis()
}
continue
}

// 如果节点在屏幕外部, click 的结果为 null
val actionResult = rule.performAction(context, target)
if (actionResult.result) {
LogUtils.d(
*rule.matches.toTypedArray(),
NodeInfo.abNodeToNode(nodeVal, target).attr,
actionResult
)
insertClickLog(rule)
}
}
}
}

scope.launch(singleThread) {
lastQueryTimeFlow.debounce(debounceTime).collect {
newQueryTask()
}
}
onAccessibilityEvent { event ->
if (event == null) return@onAccessibilityEvent
if (!(event.eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED || event.eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED)) return@onAccessibilityEvent

if (event.eventType == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
if (event.eventTime - appChangeTime > 10_000) {
if (event.eventTime - appChangeTime > 5_000) {
if (event.eventTime - lastContentEventTime < 100) {
return@onAccessibilityEvent
}
Expand Down Expand Up @@ -133,7 +183,7 @@ class GkdAbService : CompositionAbService({
}

if (rightAppId != topActivityFlow.value?.appId) {
// 从 锁屏,下拉通知栏 返回等情况
// 从 锁屏,下拉通知栏 返回等情况, 应用不会发送事件, 但是系统组件会发送事件
val shizukuTop = getShizukuTopActivity()
if (shizukuTop?.appId == rightAppId) {
topActivityFlow.value = shizukuTop
Expand All @@ -146,39 +196,22 @@ class GkdAbService : CompositionAbService({
return@onAccessibilityEvent
}

if (evAppId != rightAppId) return@onAccessibilityEvent
if (evAppId != rightAppId) {
return@onAccessibilityEvent
}
if (!storeFlow.value.enableService) return@onAccessibilityEvent
if (job?.isActive == true) return@onAccessibilityEvent

job = scope.launchTry(Dispatchers.Default) {
val activityRule = getCurrentRules()

for (rule in activityRule.rules) {
if (!isAvailableRule(rule)) continue
val nodeVal = safeActiveWindow ?: continue
val target = rule.query(nodeVal) ?: continue

if (activityRule !== getCurrentRules()) break

// 开始 action 延迟
if (rule.actionDelay > 0 && rule.actionDelayTriggerTime == 0L) {
rule.triggerDelay()
continue
}

// 如果节点在屏幕外部, click 的结果为 null
val actionResult = rule.performAction(context, target)
if (actionResult.result) {
LogUtils.d(
*rule.matches.toTypedArray(),
NodeInfo.abNodeToNode(nodeVal, target).attr,
actionResult
)
insertClickLog(rule)
}
val jobVal = job
if (jobVal?.isActive == true) {
if (openAdOptimized == true) {
jobVal.cancel()
} else {
return@onAccessibilityEvent
}
}

lastQueryTimeFlow.value = event.eventTime

newQueryTask()
}


Expand Down
4 changes: 4 additions & 0 deletions app/src/main/java/li/songe/gkd/util/SubsState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ val appIdToRulesFlow by lazy {
}
}
}
appIdToRules.values.forEach { rules ->
// 让开屏广告类规则全排在最前面
rules.sortBy { r -> if (r.isOpenAd) 0 else 1 }
}
appIdToRules.filter { it.value.isNotEmpty() }
}.stateIn<Map<String, List<Rule>>>(appScope, SharingStarted.Eagerly, emptyMap())
}
Expand Down

0 comments on commit e927c8d

Please sign in to comment.