mirror of
https://github.com/gkd-kit/gkd.git
synced 2024-11-16 19:57:15 +08:00
feat: 快照标识节点quickFind
This commit is contained in:
parent
7b72c08fe2
commit
8762d0e7ea
|
@ -10,55 +10,117 @@ import java.util.ArrayDeque
|
|||
|
||||
@Serializable
|
||||
data class NodeInfo(
|
||||
val id: Int, val pid: Int, val index: Int,
|
||||
val id: Int,
|
||||
val pid: Int,
|
||||
val index: Int,
|
||||
/**
|
||||
* - null: 不满足查找条件
|
||||
* - true: 可查找的
|
||||
* - false: 不可查找的
|
||||
*/
|
||||
val quickFind: Boolean?,
|
||||
/**
|
||||
* null: when getChild(i) return null
|
||||
*/
|
||||
val attr: AttrInfo?,
|
||||
) {
|
||||
companion object {
|
||||
|
||||
private fun getQuickFind(
|
||||
rootNodeInfo: AccessibilityNodeInfo,
|
||||
nodeInfo: AccessibilityNodeInfo?,
|
||||
quickFind: Boolean?,
|
||||
): Boolean? {
|
||||
// 如果父节点是无法查找的, 则所有子节点都是无法查找的
|
||||
// 如果一个节点是可查找的, 则所有兄弟节点都是可查找的(如果满足条件)
|
||||
return if (nodeInfo != null) {
|
||||
val viewId = nodeInfo.viewIdResourceName
|
||||
if (viewId != null && viewId.isNotEmpty()) { // id='' 不满足查找
|
||||
quickFind ?: rootNodeInfo.findAccessibilityNodeInfosByViewId(viewId)
|
||||
.any { n -> n == nodeInfo }
|
||||
} else {
|
||||
val viewText = nodeInfo.text
|
||||
if (viewText != null && viewText.isNotEmpty()) { // text='' 不满足查找
|
||||
quickFind
|
||||
?: rootNodeInfo.findAccessibilityNodeInfosByText(viewText.toString())
|
||||
.any { n -> n == nodeInfo }
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun abNodeToNode(
|
||||
rootNodeInfo: AccessibilityNodeInfo,
|
||||
nodeInfo: AccessibilityNodeInfo?,
|
||||
id: Int = 0,
|
||||
pid: Int = -1,
|
||||
index: Int = 0,
|
||||
depth: Int = 0,
|
||||
parent: NodeInfo? = null,
|
||||
brother: NodeInfo? = null,
|
||||
): NodeInfo {
|
||||
return NodeInfo(
|
||||
id,
|
||||
pid,
|
||||
index,
|
||||
nodeInfo?.let { AttrInfo.info2data(nodeInfo, index, depth) })
|
||||
// 如果父节点是不可查找的, 则下面所有子节点都是不可查找的
|
||||
// 兄弟节点的可查找性一致
|
||||
return NodeInfo(id = id, pid = pid, index = index, quickFind = getQuickFind(
|
||||
rootNodeInfo, nodeInfo, if (parent?.quickFind == false) {
|
||||
false
|
||||
} else {
|
||||
brother?.quickFind
|
||||
}
|
||||
), attr = nodeInfo?.let { AttrInfo.info2data(nodeInfo, index, depth) })
|
||||
}
|
||||
|
||||
private const val MAX_KEEP_SIZE = 5000
|
||||
|
||||
fun info2nodeList(nodeInfo: AccessibilityNodeInfo?): List<NodeInfo> {
|
||||
if (nodeInfo == null) {
|
||||
fun info2nodeList(rootNodeInfo: AccessibilityNodeInfo?): List<NodeInfo> {
|
||||
if (rootNodeInfo == null) {
|
||||
return emptyList()
|
||||
}
|
||||
val st = System.currentTimeMillis()
|
||||
|
||||
/**
|
||||
* [node, id, depth]
|
||||
*/
|
||||
val stack = ArrayDeque<Tuple3<AccessibilityNodeInfo?, Int, Int>>()
|
||||
stack.push(Tuple3(nodeInfo, 0, 0))
|
||||
stack.push(Tuple3(rootNodeInfo, 0, 0))
|
||||
val list = mutableListOf<NodeInfo>()
|
||||
list.add(abNodeToNode(nodeInfo, index = 0))
|
||||
list.add(abNodeToNode(rootNodeInfo, rootNodeInfo, index = 0))
|
||||
while (stack.isNotEmpty()) {
|
||||
val top = stack.pop()
|
||||
val pid = top.t1
|
||||
val childDepth = top.t2 + 1
|
||||
var brother: NodeInfo? = null
|
||||
top.t0?.forEachIndexed { index, childNode ->
|
||||
stack.push(Tuple3(childNode, list.size, top.t2 + 1))
|
||||
list.add(abNodeToNode(childNode, list.size, top.t1, index, top.t2 + 1))
|
||||
val id = list.size
|
||||
stack.push(Tuple3(childNode, id, childDepth))
|
||||
val simpleNode = abNodeToNode(
|
||||
rootNodeInfo, childNode, id, pid, index, childDepth, list[pid], brother
|
||||
)
|
||||
list.add(simpleNode)
|
||||
brother = if (simpleNode.quickFind != null) {
|
||||
simpleNode
|
||||
} else {
|
||||
brother
|
||||
}
|
||||
}
|
||||
brother = null
|
||||
if (list.size > MAX_KEEP_SIZE) {
|
||||
// https://github.com/gkd-kit/gkd/issues/28
|
||||
ToastUtils.showShort("节点数量至多保留$MAX_KEEP_SIZE,丢弃后续节点")
|
||||
LogUtils.w(
|
||||
nodeInfo.packageName, topActivityFlow.value?.activityId, "节点数量过多"
|
||||
rootNodeInfo.packageName, topActivityFlow.value?.activityId, "节点数量过多"
|
||||
)
|
||||
break
|
||||
}
|
||||
}
|
||||
LogUtils.d(
|
||||
topActivityFlow.value,
|
||||
"快照收集:${list.size}, 耗时:${System.currentTimeMillis() - st}ms"
|
||||
)
|
||||
return list
|
||||
}
|
||||
}
|
||||
|
|
|
@ -145,7 +145,8 @@ class GkdAbService : CompositionAbService({
|
|||
val currentRules = currentRulesFlow.value
|
||||
for (rule in currentRules) {
|
||||
if (!isAvailableRule(rule)) continue
|
||||
val target = rule.query(safeActiveWindow) ?: continue
|
||||
val nodeVal = safeActiveWindow ?: continue
|
||||
val target = rule.query(nodeVal) ?: continue
|
||||
|
||||
// 开始延迟
|
||||
if (rule.delay > 0 && rule.delayTriggerTime == 0L) {
|
||||
|
@ -162,7 +163,7 @@ class GkdAbService : CompositionAbService({
|
|||
scope.launchTry(Dispatchers.IO) {
|
||||
LogUtils.d(
|
||||
*rule.matches.toTypedArray(),
|
||||
NodeInfo.abNodeToNode(target).attr,
|
||||
NodeInfo.abNodeToNode(nodeVal, target).attr,
|
||||
actionResult
|
||||
)
|
||||
val clickLog = ClickLog(
|
||||
|
|
Loading…
Reference in New Issue
Block a user