Attempt to fix selector memeory leak. Add update checker

This commit is contained in:
hyb1996
2017-04-09 14:02:57 +08:00
parent 6844eb9841
commit 0e980c2e6a
72 changed files with 1282 additions and 415 deletions

View File

@@ -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) {

View File

@@ -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();
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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();

View File

@@ -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) {

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -56,7 +56,6 @@ public class SimpleActionPerformHost implements AccessibilityDelegate {
private synchronized void onActionPerformed(SimpleAction simpleAction) {
AccessibilityNodeInfoAllocator.getGlobal().recycleAll();
synchronized (simpleAction) {
simpleAction.notify();
}

View File

@@ -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) {

View File

@@ -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);
}
}
}