Attempt to fix selector memeory leak. Add update checker
This commit is contained in:
@@ -352,27 +352,26 @@ public class UiGlobalSelector {
|
||||
return this;
|
||||
}
|
||||
|
||||
public UiObjectCollection findOf(AccessibilityNodeInfo node) {
|
||||
List<AccessibilityNodeInfo> list = new ArrayList<>();
|
||||
list.add(node);
|
||||
for (ListFilter filter : mFilters) {
|
||||
list = filter.filter(list);
|
||||
}
|
||||
return UiObjectCollection.of(list);
|
||||
}
|
||||
|
||||
public UiObjectCollection findOf(AccessibilityNodeInfoAllocator allocator, AccessibilityNodeInfo node) {
|
||||
List<AccessibilityNodeInfo> list = new ArrayList<>();
|
||||
list.add(node);
|
||||
for (ListFilter filter : mFilters) {
|
||||
list = filter.filter(list);
|
||||
list = filter.filter(allocator, list);
|
||||
}
|
||||
return UiObjectCollection.of(list);
|
||||
}
|
||||
|
||||
public UiObject findOneOf(AccessibilityNodeInfo node) {
|
||||
public UiObjectCollection findOf(AccessibilityNodeInfo node) {
|
||||
return findOf(AccessibilityNodeInfoAllocator.NONE, node);
|
||||
}
|
||||
|
||||
public UiObject findOneOf(AccessibilityNodeInfoAllocator allocator, AccessibilityNodeInfo node) {
|
||||
// TODO: 2017/3/9 优化
|
||||
return new UiObject(findOf(node).get(0).getInfo());
|
||||
return new UiObject(findOf(allocator, node).get(0).getInfo());
|
||||
}
|
||||
|
||||
public UiObject findOneOf(AccessibilityNodeInfo node) {
|
||||
return findOneOf(AccessibilityNodeInfoAllocator.NONE, node);
|
||||
}
|
||||
|
||||
public UiGlobalSelector addFilter(ListFilter filter) {
|
||||
|
||||
@@ -14,36 +14,36 @@ import java.util.List;
|
||||
public abstract class DfsFilter implements ListFilter, Filter {
|
||||
|
||||
@Override
|
||||
public List<AccessibilityNodeInfo> filter(List<AccessibilityNodeInfo> nodes) {
|
||||
public List<AccessibilityNodeInfo> filter(AccessibilityNodeInfoAllocator allocator, List<AccessibilityNodeInfo> nodes) {
|
||||
ArrayList<AccessibilityNodeInfo> list = new ArrayList<>();
|
||||
for (AccessibilityNodeInfo node : nodes) {
|
||||
if (isIncluded(node)) {
|
||||
list.add(node);
|
||||
}
|
||||
filterChildren(node, list);
|
||||
filterChildren(allocator, node, list);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<AccessibilityNodeInfo> filter(AccessibilityNodeInfo node) {
|
||||
public List<AccessibilityNodeInfo> filter(AccessibilityNodeInfoAllocator allocator, AccessibilityNodeInfo node) {
|
||||
ArrayList<AccessibilityNodeInfo> list = new ArrayList<>();
|
||||
if (isIncluded(node)) {
|
||||
list.add(node);
|
||||
}
|
||||
filterChildren(node, list);
|
||||
filterChildren(allocator, node, list);
|
||||
return list;
|
||||
}
|
||||
|
||||
private void filterChildren(AccessibilityNodeInfo parent, List<AccessibilityNodeInfo> list) {
|
||||
private void filterChildren(AccessibilityNodeInfoAllocator allocator, AccessibilityNodeInfo parent, List<AccessibilityNodeInfo> list) {
|
||||
for (int i = 0; i < parent.getChildCount(); i++) {
|
||||
AccessibilityNodeInfo child = AccessibilityNodeInfoAllocator.getGlobal().getChild(parent, i);
|
||||
AccessibilityNodeInfo child = allocator.getChild(parent, i);
|
||||
if (child == null)
|
||||
continue;
|
||||
boolean included = isIncluded(child);
|
||||
if (included) {
|
||||
list.add(child);
|
||||
}
|
||||
filterChildren(child, list);
|
||||
filterChildren(allocator, child, list);
|
||||
if (!included) {
|
||||
child.recycle();
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.stardust.automator.filter;
|
||||
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import com.stardust.view.accessibility.AccessibilityNodeInfoAllocator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -10,6 +12,6 @@ import java.util.List;
|
||||
|
||||
public interface Filter {
|
||||
|
||||
List<AccessibilityNodeInfo> filter(AccessibilityNodeInfo node);
|
||||
List<AccessibilityNodeInfo> filter(AccessibilityNodeInfoAllocator allocator, AccessibilityNodeInfo node);
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.stardust.automator.filter;
|
||||
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import com.stardust.view.accessibility.AccessibilityNodeInfoAllocator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -45,8 +47,8 @@ public class IdFilter extends ListFilter.Default {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AccessibilityNodeInfo> filter(AccessibilityNodeInfo node) {
|
||||
return node.findAccessibilityNodeInfosByViewId(mId);
|
||||
public List<AccessibilityNodeInfo> filter(AccessibilityNodeInfoAllocator allocator, AccessibilityNodeInfo node) {
|
||||
return allocator.findAccessibilityNodeInfosByViewId(node, mId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.stardust.automator.filter;
|
||||
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import com.stardust.view.accessibility.AccessibilityNodeInfoAllocator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -11,15 +13,15 @@ import java.util.List;
|
||||
|
||||
public interface ListFilter {
|
||||
|
||||
List<AccessibilityNodeInfo> filter(List<AccessibilityNodeInfo> nodes);
|
||||
List<AccessibilityNodeInfo> filter(AccessibilityNodeInfoAllocator allocator, List<AccessibilityNodeInfo> nodes);
|
||||
|
||||
abstract class Default implements Filter, ListFilter {
|
||||
|
||||
@Override
|
||||
public List<AccessibilityNodeInfo> filter(List<AccessibilityNodeInfo> nodes) {
|
||||
public List<AccessibilityNodeInfo> filter(AccessibilityNodeInfoAllocator allocator, List<AccessibilityNodeInfo> nodes) {
|
||||
List<AccessibilityNodeInfo> list = new ArrayList<>();
|
||||
for (AccessibilityNodeInfo node : nodes) {
|
||||
list.addAll(filter(node));
|
||||
list.addAll(filter(allocator, node));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.stardust.automator.filter;
|
||||
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import com.stardust.view.accessibility.AccessibilityNodeInfoAllocator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -46,7 +48,7 @@ public class TextFilter extends ListFilter.Default {
|
||||
|
||||
|
||||
@Override
|
||||
public List<AccessibilityNodeInfo> filter(AccessibilityNodeInfo node) {
|
||||
return node.findAccessibilityNodeInfosByText(mText);
|
||||
public List<AccessibilityNodeInfo> filter(AccessibilityNodeInfoAllocator allocator, AccessibilityNodeInfo node) {
|
||||
return allocator.findAccessibilityNodeInfosByText(node, mText);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ public class DepthFirstSearchTargetAction extends SearchTargetAction {
|
||||
|
||||
|
||||
private Able mAble;
|
||||
private static final long TIME_LIMIT = 500;
|
||||
|
||||
public DepthFirstSearchTargetAction(int action, Filter filter) {
|
||||
super(action, filter);
|
||||
@@ -27,7 +26,7 @@ public class DepthFirstSearchTargetAction extends SearchTargetAction {
|
||||
if (mAble.isAble(n))
|
||||
return n;
|
||||
for (int i = 0; i < n.getChildCount(); i++) {
|
||||
AccessibilityNodeInfo child = AccessibilityNodeInfoAllocator.getGlobal().getChild(n, i);
|
||||
AccessibilityNodeInfo child = getAllocator().getChild(n, i);
|
||||
if (child == null)
|
||||
continue;
|
||||
AccessibilityNodeInfo node = searchTarget(child);
|
||||
|
||||
@@ -18,7 +18,7 @@ public abstract class FilterAction extends SimpleAction {
|
||||
|
||||
public interface Filter {
|
||||
|
||||
List<AccessibilityNodeInfo> filter(AccessibilityNodeInfo root);
|
||||
List<AccessibilityNodeInfo> filter(AccessibilityNodeInfoAllocator allocator, AccessibilityNodeInfo root);
|
||||
}
|
||||
|
||||
public static class TextFilter implements Filter {
|
||||
@@ -32,12 +32,12 @@ public abstract class FilterAction extends SimpleAction {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AccessibilityNodeInfo> filter(AccessibilityNodeInfo root) {
|
||||
List<AccessibilityNodeInfo> list = AccessibilityNodeInfoAllocator.getGlobal().findAccessibilityNodeInfosByText(root, mText);
|
||||
public List<AccessibilityNodeInfo> filter(AccessibilityNodeInfoAllocator allocator, AccessibilityNodeInfo root) {
|
||||
List<AccessibilityNodeInfo> list = allocator.findAccessibilityNodeInfosByText(root, mText);
|
||||
if (mIndex == -1)
|
||||
return list;
|
||||
if (mIndex >= list.size())
|
||||
return Collections.EMPTY_LIST;
|
||||
return Collections.emptyList();
|
||||
return Collections.singletonList(list.get(mIndex));
|
||||
}
|
||||
|
||||
@@ -59,11 +59,11 @@ public abstract class FilterAction extends SimpleAction {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AccessibilityNodeInfo> filter(AccessibilityNodeInfo root) {
|
||||
return Collections.singletonList(findAccessibilityNodeInfosByBounds(root));
|
||||
public List<AccessibilityNodeInfo> filter(AccessibilityNodeInfoAllocator allocator, AccessibilityNodeInfo root) {
|
||||
return Collections.singletonList(findAccessibilityNodeInfosByBounds(allocator, root));
|
||||
}
|
||||
|
||||
private AccessibilityNodeInfo findAccessibilityNodeInfosByBounds(AccessibilityNodeInfo root) {
|
||||
private AccessibilityNodeInfo findAccessibilityNodeInfosByBounds(AccessibilityNodeInfoAllocator allocator, AccessibilityNodeInfo root) {
|
||||
if (root == null)
|
||||
return null;
|
||||
Rect rect = new Rect();
|
||||
@@ -72,10 +72,10 @@ public abstract class FilterAction extends SimpleAction {
|
||||
return root;
|
||||
}
|
||||
for (int i = 0; i < root.getChildCount(); i++) {
|
||||
AccessibilityNodeInfo child = AccessibilityNodeInfoAllocator.getGlobal().getChild(root, i);
|
||||
AccessibilityNodeInfo child = allocator.getChild(root, i);
|
||||
if (child == null)
|
||||
continue;
|
||||
AccessibilityNodeInfo nodeInfo = findAccessibilityNodeInfosByBounds(child);
|
||||
AccessibilityNodeInfo nodeInfo = findAccessibilityNodeInfosByBounds(allocator, child);
|
||||
if (nodeInfo != null)
|
||||
return nodeInfo;
|
||||
else
|
||||
@@ -101,16 +101,16 @@ public abstract class FilterAction extends SimpleAction {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AccessibilityNodeInfo> filter(AccessibilityNodeInfo root) {
|
||||
List<AccessibilityNodeInfo> editableList = findEditable(root);
|
||||
public List<AccessibilityNodeInfo> filter(AccessibilityNodeInfoAllocator allocator, AccessibilityNodeInfo root) {
|
||||
List<AccessibilityNodeInfo> editableList = findEditable(allocator, root);
|
||||
if (mIndex == -1)
|
||||
return editableList;
|
||||
if (mIndex >= editableList.size())
|
||||
return Collections.EMPTY_LIST;
|
||||
return Collections.emptyList();
|
||||
return Collections.singletonList(editableList.get(mIndex));
|
||||
}
|
||||
|
||||
public static List<AccessibilityNodeInfo> findEditable(AccessibilityNodeInfo root) {
|
||||
public static List<AccessibilityNodeInfo> findEditable(AccessibilityNodeInfoAllocator allocator, AccessibilityNodeInfo root) {
|
||||
if (root == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
@@ -119,7 +119,7 @@ public abstract class FilterAction extends SimpleAction {
|
||||
}
|
||||
List<AccessibilityNodeInfo> list = new LinkedList<>();
|
||||
for (int i = 0; i < root.getChildCount(); i++) {
|
||||
list.addAll(findEditable(AccessibilityNodeInfoAllocator.getGlobal().getChild(root, i)));
|
||||
list.addAll(findEditable(allocator, allocator.getChild(root, i)));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
@@ -141,8 +141,8 @@ public abstract class FilterAction extends SimpleAction {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AccessibilityNodeInfo> filter(AccessibilityNodeInfo root) {
|
||||
return AccessibilityNodeInfoAllocator.getGlobal().findAccessibilityNodeInfosByViewId(root, mId);
|
||||
public List<AccessibilityNodeInfo> filter(AccessibilityNodeInfoAllocator allocator, AccessibilityNodeInfo root) {
|
||||
return allocator.findAccessibilityNodeInfosByViewId(root, mId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -163,7 +163,7 @@ public abstract class FilterAction extends SimpleAction {
|
||||
public boolean perform(AccessibilityNodeInfo root) {
|
||||
if (root == null)
|
||||
return false;
|
||||
List<AccessibilityNodeInfo> list = mFilter.filter(root);
|
||||
List<AccessibilityNodeInfo> list = mFilter.filter(getAllocator(), root);
|
||||
boolean succeed = perform(list);
|
||||
AccessibilityNodeInfoAllocator.recycleList(root, list);
|
||||
return succeed;
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
package com.stardust.automator.simple_action;
|
||||
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import com.stardust.view.accessibility.AccessibilityNodeInfoAllocator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/14.
|
||||
*/
|
||||
|
||||
public class GetTextAction extends SimpleAction {
|
||||
|
||||
|
||||
@Override
|
||||
public boolean perform(AccessibilityNodeInfo root) {
|
||||
List<String> texts = new ArrayList<>();
|
||||
getText(root, texts);
|
||||
super.setResult(texts);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void getText(AccessibilityNodeInfo nodeInfo, List<String> texts) {
|
||||
CharSequence text = nodeInfo.getText();
|
||||
if (text != null && text.length() != 0) {
|
||||
texts.add(text.toString());
|
||||
}
|
||||
for (int i = 0; i < nodeInfo.getChildCount(); i++) {
|
||||
AccessibilityNodeInfo child = AccessibilityNodeInfoAllocator.getGlobal().getChild(nodeInfo, i);
|
||||
if (child != null) {
|
||||
getText(child, texts);
|
||||
child.recycle();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResult(Object result) {
|
||||
if (result instanceof List)
|
||||
super.setResult(result);
|
||||
}
|
||||
}
|
||||
@@ -36,11 +36,11 @@ public class ScrollAction extends SimpleAction {
|
||||
|
||||
private List<AccessibilityNodeInfo> findScrollableNodes(AccessibilityNodeInfo root) {
|
||||
List<AccessibilityNodeInfo> list = new ArrayList<>();
|
||||
findScrollableNodes(root, list);
|
||||
findScrollableNodes(getAllocator(), root, list);
|
||||
return list;
|
||||
}
|
||||
|
||||
private static boolean findScrollableNodes(AccessibilityNodeInfo node, List<AccessibilityNodeInfo> list) {
|
||||
private static boolean findScrollableNodes(AccessibilityNodeInfoAllocator allocator, AccessibilityNodeInfo node, List<AccessibilityNodeInfo> list) {
|
||||
if (node == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -48,10 +48,10 @@ public class ScrollAction extends SimpleAction {
|
||||
list.add(node);
|
||||
}
|
||||
for (int i = 0; i < node.getChildCount(); i++) {
|
||||
AccessibilityNodeInfo child = AccessibilityNodeInfoAllocator.getGlobal().getChild(node, i);
|
||||
AccessibilityNodeInfo child = allocator.getChild(node, i);
|
||||
if (child == null)
|
||||
continue;
|
||||
if (!findScrollableNodes(child, list))
|
||||
if (!findScrollableNodes(allocator, child, list))
|
||||
child.recycle();
|
||||
}
|
||||
return node.isScrollable();
|
||||
|
||||
@@ -51,7 +51,7 @@ public class ScrollMaxAction extends SimpleAction {
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < nodeInfo.getChildCount(); i++) {
|
||||
AccessibilityNodeInfo child = AccessibilityNodeInfoAllocator.getGlobal().getChild(nodeInfo, i);
|
||||
AccessibilityNodeInfo child = getAllocator().getChild(nodeInfo, i);
|
||||
if (child != null) {
|
||||
findMaxScrollableNodeInfo(child);
|
||||
if (mMaxScrollableNode != child) {
|
||||
|
||||
@@ -33,7 +33,7 @@ public class SearchUpTargetAction extends SearchTargetAction {
|
||||
node.recycle();
|
||||
return null;
|
||||
}
|
||||
AccessibilityNodeInfo parent = AccessibilityNodeInfoAllocator.getGlobal().getParent(node);
|
||||
AccessibilityNodeInfo parent = getAllocator().getParent(node);
|
||||
list.add(node);
|
||||
node = parent;
|
||||
}
|
||||
|
||||
@@ -1,31 +1,48 @@
|
||||
package com.stardust.automator.simple_action;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import com.stardust.view.accessibility.AccessibilityNodeInfoAllocator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/27.
|
||||
*/
|
||||
|
||||
public abstract class SimpleAction {
|
||||
|
||||
private boolean mValid = true;
|
||||
private Object mResult = false;
|
||||
|
||||
private volatile AccessibilityNodeInfoAllocator mAllocator = AccessibilityNodeInfoAllocator.NONE;
|
||||
private volatile boolean mValid = true;
|
||||
private volatile boolean mResult = false;
|
||||
|
||||
public abstract boolean perform(AccessibilityNodeInfo root);
|
||||
|
||||
public synchronized Object getResult() {
|
||||
public boolean getResult() {
|
||||
return mResult;
|
||||
}
|
||||
|
||||
public synchronized void setResult(Object result) {
|
||||
public void setResult(boolean result) {
|
||||
mResult = result;
|
||||
}
|
||||
|
||||
public synchronized void setValid(boolean valid) {
|
||||
public void setValid(boolean valid) {
|
||||
mValid = valid;
|
||||
}
|
||||
|
||||
public synchronized boolean isValid() {
|
||||
public boolean isValid() {
|
||||
return mValid;
|
||||
}
|
||||
|
||||
public AccessibilityNodeInfoAllocator getAllocator() {
|
||||
return mAllocator;
|
||||
}
|
||||
|
||||
public void setAllocator(@NonNull AccessibilityNodeInfoAllocator allocator) {
|
||||
mAllocator = allocator;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -56,7 +56,6 @@ public class SimpleActionPerformHost implements AccessibilityDelegate {
|
||||
|
||||
|
||||
private synchronized void onActionPerformed(SimpleAction simpleAction) {
|
||||
AccessibilityNodeInfoAllocator.getGlobal().recycleAll();
|
||||
synchronized (simpleAction) {
|
||||
simpleAction.notify();
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@ import com.stardust.view.accessibility.AccessibilityDelegate;
|
||||
public class AccessibilityInfoProvider implements AccessibilityDelegate {
|
||||
|
||||
|
||||
private String mLatestPackage = "";
|
||||
private String mLatestActivity = "";
|
||||
private volatile String mLatestPackage = "";
|
||||
private volatile String mLatestActivity = "";
|
||||
private PackageManager mPackageManager;
|
||||
|
||||
public AccessibilityInfoProvider(PackageManager packageManager) {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.stardust.view.accessibility;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
|
||||
import android.util.Log;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
@@ -104,9 +106,10 @@ public class AccessibilityNodeInfoAllocator {
|
||||
return notRecycledCount;
|
||||
}
|
||||
|
||||
private AccessibilityNodeInfo add(AccessibilityNodeInfo nodeInfo) {
|
||||
private AccessibilityNodeInfo add(@Nullable AccessibilityNodeInfo nodeInfo) {
|
||||
String stackTrace = DEBUG ? Arrays.toString(Thread.currentThread().getStackTrace()) : null;
|
||||
mAccessibilityNodeInfoList.put(nodeInfo, stackTrace);
|
||||
if (nodeInfo != null)
|
||||
mAccessibilityNodeInfoList.put(nodeInfo, stackTrace);
|
||||
return nodeInfo;
|
||||
}
|
||||
|
||||
@@ -117,8 +120,6 @@ public class AccessibilityNodeInfoAllocator {
|
||||
mAccessibilityNodeInfoList.put((AccessibilityNodeInfo) nodeInfo, stackTrace);
|
||||
} else if (nodeInfo instanceof AccessibilityNodeInfoCompat) {
|
||||
mAccessibilityNodeInfoList.put((AccessibilityNodeInfo) ((AccessibilityNodeInfoCompat) nodeInfo).getInfo(), stackTrace);
|
||||
} else {
|
||||
throw new IllegalArgumentException("nodeInfo: " + nodeInfo + " nodeInfos:" + nodeInfos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user