Fix fucking issue #193 by removing recycle in finalize

This commit is contained in:
hyb1996
2017-05-06 15:29:44 +08:00
parent 68845c9a21
commit ed2ebe1599
24 changed files with 373 additions and 65 deletions

View File

@@ -1,4 +1,5 @@
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
apply plugin: 'com.getkeepsafe.dexcount'
def AAVersion = '4.2.0' def AAVersion = '4.2.0'
android { android {
@@ -49,6 +50,20 @@ android {
pickFirst 'org/mozilla/javascript/*.java.orig' pickFirst 'org/mozilla/javascript/*.java.orig'
pickFirst 'org/mozilla/javascript/tools/resources/*.properties' pickFirst 'org/mozilla/javascript/tools/resources/*.properties'
} }
dexcount {
format = "list"
includeClasses = false
includeFieldCount = true
includeTotalMethodCount = false
orderByMethodCount = false
verbose = false
maxTreeDepth = Integer.MAX_VALUE
teamCityIntegration = false
enableForInstantRun = false
teamCitySlug = null
runOnEachAssemble = true
maxMethodCount = 64000
}
configurations.all { configurations.all {
resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.1' resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.1'
} }

View File

@@ -7,7 +7,6 @@ import android.os.Bundle;
import android.support.annotation.Keep; import android.support.annotation.Keep;
import android.support.multidex.MultiDexApplication; import android.support.multidex.MultiDexApplication;
import com.flurry.android.FlurryAgent;
import com.squareup.leakcanary.LeakCanary; import com.squareup.leakcanary.LeakCanary;
import com.stardust.app.SimpleActivityLifecycleCallbacks; import com.stardust.app.SimpleActivityLifecycleCallbacks;
import com.stardust.app.VolumeChangeObserver; import com.stardust.app.VolumeChangeObserver;

View File

@@ -1,6 +1,5 @@
package com.stardust.scriptdroid.autojs; package com.stardust.scriptdroid.autojs;
import com.flurry.android.FlurryAgent;
import com.stardust.autojs.execution.ScriptExecution; import com.stardust.autojs.execution.ScriptExecution;
import com.stardust.autojs.execution.ScriptExecutionListener; import com.stardust.autojs.execution.ScriptExecutionListener;
import com.stardust.scriptdroid.App; import com.stardust.scriptdroid.App;

View File

@@ -6,7 +6,7 @@ import android.support.annotation.NonNull;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo;
import com.stardust.view.accessibility.AccessibilityNodeInfoAllocator; import com.stardust.automator.UiObject;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -74,19 +74,24 @@ public class NodeInfo {
this(new AccessibilityNodeInfoCompat(node)); this(new AccessibilityNodeInfoCompat(node));
} }
public static NodeInfo capture(@NonNull AccessibilityNodeInfo root) {
AccessibilityNodeInfoAllocator allocator = new AccessibilityNodeInfoAllocator(); public static NodeInfo capture(@NonNull UiObject root) {
NodeInfo nodeInfo = new NodeInfo(root); NodeInfo nodeInfo = new NodeInfo(root);
for (int i = 0; i < root.getChildCount(); i++) { int childCount = root.getChildCount();
AccessibilityNodeInfo child = allocator.getChild(root, i); for (int i = 0; i < childCount; i++) {
UiObject child = root.child(i);
if (child != null) { if (child != null) {
nodeInfo.children.add(capture(child)); nodeInfo.children.add(capture(child));
} }
} }
allocator.recycleAll();
return nodeInfo; return nodeInfo;
} }
public static NodeInfo capture(@NonNull AccessibilityNodeInfo root) {
UiObject r = UiObject.createRoot(root);
return capture(r);
}
public List<NodeInfo> getChildren() { public List<NodeInfo> getChildren() {
return children; return children;
} }

View File

@@ -123,13 +123,11 @@ public class AccessibilityActionConverter {
AccessibilityNodeInfo source = event.getSource(); AccessibilityNodeInfo source = event.getSource();
if (source == null) if (source == null)
return; return;
AccessibilityNodeInfoAllocator allocator = new AccessibilityNodeInfoAllocator(); UiObject uiObject = UiObject.createRoot(service.getRootInActiveWindow());
UiObject uiObject = new UiObject(service.getRootInActiveWindow(), allocator);
List<UiObject> editableList = FilterAction.EditableFilter.findEditable(uiObject); List<UiObject> editableList = FilterAction.EditableFilter.findEditable(uiObject);
int i = findInEditableList(editableList, source); int i = findInEditableList(editableList, source);
sb.append("while(!input(").append(i).append(", \"").append(source.getText()).append("\"));"); sb.append("while(!input(").append(i).append(", \"").append(source.getText()).append("\"));");
source.recycle(); source.recycle();
allocator.recycleAll();
} }
private static int findInEditableList(List<UiObject> editableList, AccessibilityNodeInfo editable) { private static int findInEditableList(List<UiObject> editableList, AccessibilityNodeInfo editable) {

View File

@@ -1,26 +1,15 @@
package com.stardust.scriptdroid.ui; package com.stardust.scriptdroid.ui;
import android.app.Activity;
import android.content.DialogInterface;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi; import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.view.View; import android.view.View;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.flurry.android.FlurryAgent;
import com.stardust.pio.PFile;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.tool.UpdateChecker;
import com.stardust.scriptdroid.tool.VersionInfo; import com.stardust.scriptdroid.tool.VersionInfo;
import com.stardust.scriptdroid.ui.update.UpdateCheckDialog;
import com.stardust.theme.ThemeColorManager; import com.stardust.theme.ThemeColorManager;
import com.stardust.util.BackPressedHandler; import com.stardust.util.BackPressedHandler;

View File

@@ -2,11 +2,13 @@ package com.stardust.scriptdroid.ui.console;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.view.WindowManager;
import com.stardust.autojs.runtime.api.AbstractConsole; import com.stardust.autojs.runtime.api.AbstractConsole;
import com.stardust.autojs.runtime.api.Console; import com.stardust.autojs.runtime.api.Console;
import com.stardust.enhancedfloaty.FloatyService; import com.stardust.enhancedfloaty.FloatyService;
import com.stardust.enhancedfloaty.ResizableExpandableFloatyWindow; import com.stardust.enhancedfloaty.ResizableExpandableFloatyWindow;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.autojs.AutoJs; import com.stardust.scriptdroid.autojs.AutoJs;
import com.stardust.util.UiHandler; import com.stardust.util.UiHandler;
@@ -82,7 +84,12 @@ public class StardustConsole extends AbstractConsole {
mUiHandler.post(new Runnable() { mUiHandler.post(new Runnable() {
@Override @Override
public void run() { public void run() {
FloatyService.addWindow(mFloatyWindow); try {
FloatyService.addWindow(mFloatyWindow);
} catch (WindowManager.BadTokenException e) {
e.printStackTrace();
mUiHandler.toast(R.string.text_no_floating_window_permission);
}
} }
}); });
} }

View File

@@ -61,22 +61,22 @@ public class ProcessShell extends AbstractShell implements AutoCloseable {
@Override @Override
public void exit() { public void exit() {
if(mProcess != null) { if (mProcess != null) {
mProcess.destroy(); mProcess.destroy();
mProcess = null; mProcess = null;
} }
if(mSucceedReader != null){ if (mSucceedReader != null) {
try{ try {
mSucceedReader.close(); mSucceedReader.close();
}catch (IOException ignored){ } catch (IOException ignored) {
} }
mSucceedReader = null; mSucceedReader = null;
} }
if(mErrorReader != null){ if (mErrorReader != null) {
try{ try {
mErrorReader.close(); mErrorReader.close();
}catch (IOException ignored){ } catch (IOException ignored) {
} }
mErrorReader = null; mErrorReader = null;
@@ -158,8 +158,8 @@ public class ProcessShell extends AbstractShell implements AutoCloseable {
} }
public static Result exec(String[] commands, boolean isRoot) { public static Result exec(String[] commands, boolean isRoot) {
try(ProcessShell shell = new ProcessShell(isRoot)){ try (ProcessShell shell = new ProcessShell(isRoot)) {
for(String command : commands){ for (String command : commands) {
shell.exec(command); shell.exec(command);
} }
shell.exec(COMMAND_EXIT); shell.exec(COMMAND_EXIT);
@@ -173,4 +173,5 @@ public class ProcessShell extends AbstractShell implements AutoCloseable {
} }
} }
} }

View File

@@ -65,7 +65,7 @@ public class UiSelector extends UiGlobalSelector {
public void execute(AccessibilityService service, AccessibilityEvent event) { public void execute(AccessibilityService service, AccessibilityEvent event) {
AccessibilityNodeInfo root = service.getRootInActiveWindow(); AccessibilityNodeInfo root = service.getRootInActiveWindow();
if (root != null) { if (root != null) {
result = findOf(new UiObject(root, mAllocator)); result = findOf(UiObject.createRoot(root, mAllocator));
} }
} }
@@ -96,7 +96,7 @@ public class UiSelector extends UiGlobalSelector {
if (service != null) { if (service != null) {
AccessibilityNodeInfo root = service.getRootInActiveWindow(); AccessibilityNodeInfo root = service.getRootInActiveWindow();
if (root != null) { if (root != null) {
return findOf(new UiObject(root, mAllocator)); return findOf(UiObject.createRoot(root, mAllocator));
} }
} }
return null; return null;

View File

@@ -200,7 +200,7 @@ public class SimpleActionAutomator {
if (root == null) if (root == null)
return false; return false;
Log.v(TAG, "performAction: " + simpleAction + " root = " + root); Log.v(TAG, "performAction: " + simpleAction + " root = " + root);
return simpleAction.perform(new UiObject(root)); return simpleAction.perform(UiObject.createRoot(root));
} }
private boolean isRunningPackageSelf() { private boolean isRunningPackageSelf() {

View File

@@ -0,0 +1,38 @@
package com.stardust.automator.simple_action;
import android.view.accessibility.AccessibilityNodeInfo;
import com.stardust.automator.UiObject;
import com.stardust.automator.test.TestUiObject;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.*;
/**
* Created by Stardust on 2017/5/5.
*/
public class DepthFirstSearchTargetActionTest {
@Test
public void perform() {
DepthFirstSearchTargetAction action = new DepthFirstSearchTargetAction(AccessibilityNodeInfo.ACTION_CLICK, new FilterAction.Filter() {
@Override
public List<UiObject> filter(UiObject root) {
List<UiObject> list = new ArrayList<>();
for (int i = 0; i < root.getChildCount(); i++) {
list.add(root.child(i));
}
return list;
}
});
TestUiObject root = new TestUiObject(5);
action.perform(root);
System.out.println(TestUiObject.max);
assertEquals(1, TestUiObject.count);
}
}

View File

@@ -0,0 +1,25 @@
package com.stardust.automator.simple_action;
import android.view.accessibility.AccessibilityNodeInfo;
import com.stardust.automator.UiObject;
import com.stardust.automator.test.TestUiObject;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Created by Stardust on 2017/5/5.
*/
public class ScrollMaxActionTest {
@Test
public void perform() throws Exception {
ScrollMaxAction action = new ScrollMaxAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
UiObject root = new TestUiObject(20);
action.perform(root);
System.out.println(TestUiObject.max);
assertEquals(1, TestUiObject.count);
}
}

View File

@@ -2,6 +2,8 @@ package com.stardust.automator;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.util.Pools;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import android.util.Log; import android.util.Log;
import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo;
@@ -9,6 +11,8 @@ import android.view.accessibility.AccessibilityNodeInfo;
import com.stardust.view.accessibility.AccessibilityNodeInfoAllocator; import com.stardust.view.accessibility.AccessibilityNodeInfoAllocator;
import com.stardust.view.accessibility.AccessibilityNodeInfoHelper; import com.stardust.view.accessibility.AccessibilityNodeInfoHelper;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@@ -30,27 +34,62 @@ public class UiObject extends AccessibilityNodeInfoCompat {
private static final String TAG = "UiObject"; private static final String TAG = "UiObject";
private static final boolean DEBUG = false; private static final boolean DEBUG = false;
private static int notRecycledCount = 0;
public static UiObject createRoot(AccessibilityNodeInfo root) {
return new UiObject(root, null, true);
}
public static UiObject createRoot(AccessibilityNodeInfo root, AccessibilityNodeInfoAllocator allocator) {
return new UiObject(root, allocator, true);
}
private AccessibilityNodeInfoAllocator mAllocator = null; private AccessibilityNodeInfoAllocator mAllocator = null;
private String mStackTrace = ""; private String mStackTrace = "";
private boolean mIsRootNode = false;
public UiObject(Object info) { public UiObject(Object info) {
this(info, null); this(info, null);
} }
public UiObject(Object info, AccessibilityNodeInfoAllocator allocator) { public UiObject(Object info, AccessibilityNodeInfoAllocator allocator, boolean isRootNode) {
super(info); super(info);
mIsRootNode = isRootNode;
mAllocator = allocator; mAllocator = allocator;
if (DEBUG) if (DEBUG)
mStackTrace = Arrays.toString(Thread.currentThread().getStackTrace()); mStackTrace = Arrays.toString(Thread.currentThread().getStackTrace());
} }
public UiObject parent() { public UiObject(Object info, AccessibilityNodeInfoAllocator allocator) {
return new UiObject(getParent().getInfo()); this(info, allocator, false);
} }
@Nullable
public UiObject parent() {
try {
AccessibilityNodeInfoCompat parent = super.getParent();
if (parent == null)
return null;
return new UiObject(parent.getInfo());
} catch (IllegalStateException e) {
// FIXME: 2017/5/5
return null;
}
}
@Nullable
public UiObject child(int i) { public UiObject child(int i) {
return new UiObject(getChild(i).getInfo()); try {
AccessibilityNodeInfoCompat child = super.getChild(i);
if (child == null)
return null;
return new UiObject(child.getInfo());
} catch (IllegalStateException e) {
// FIXME: 2017/5/5
return null;
}
} }
public UiObjectCollection find(UiGlobalSelector selector) { public UiObjectCollection find(UiGlobalSelector selector) {
@@ -110,6 +149,31 @@ public class UiObject extends AccessibilityNodeInfoCompat {
return performAction(action, bundle); return performAction(action, bundle);
} }
@Override
public boolean performAction(int action, Bundle bundle) {
try {
return super.performAction(action);
} catch (IllegalStateException e) {
// FIXME: 2017/5/5
return false;
}
}
@Override
public boolean performAction(int action) {
try {
return super.performAction(action);
} catch (IllegalStateException e) {
// FIXME: 2017/5/5
return false;
}
}
public AccessibilityNodeInfoAllocator getAllocator() {
return mAllocator;
}
private static Bundle argumentsToBundle(ActionArgument[] arguments) { private static Bundle argumentsToBundle(ActionArgument[] arguments) {
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
for (ActionArgument arg : arguments) { for (ActionArgument arg : arguments) {
@@ -263,7 +327,8 @@ public class UiObject extends AccessibilityNodeInfoCompat {
public static List<UiObject> compatListToUiObjectList(List<AccessibilityNodeInfoCompat> compats, AccessibilityNodeInfoAllocator allocator) { public static List<UiObject> compatListToUiObjectList(List<AccessibilityNodeInfoCompat> compats, AccessibilityNodeInfoAllocator allocator) {
List<UiObject> uiObjects = new ArrayList<>(compats.size()); List<UiObject> uiObjects = new ArrayList<>(compats.size());
for (AccessibilityNodeInfoCompat compat : compats) { for (AccessibilityNodeInfoCompat compat : compats) {
uiObjects.add(new UiObject(compat.getInfo(), allocator)); if (compat != null)
uiObjects.add(new UiObject(compat.getInfo(), allocator));
} }
return uiObjects; return uiObjects;
} }
@@ -281,12 +346,5 @@ public class UiObject extends AccessibilityNodeInfoCompat {
} }
} }
@Override
protected void finalize() throws Throwable {
try {
super.recycle();
} catch (Exception ignored) {
}
super.finalize();
}
} }

View File

@@ -30,8 +30,6 @@ public class DepthFirstSearchTargetAction extends SearchTargetAction {
UiObject node = searchTarget(child); UiObject node = searchTarget(child);
if (node != null) if (node != null)
return node; return node;
else
child.recycle();
} }
return null; return null;
} }

View File

@@ -77,8 +77,6 @@ public abstract class FilterAction extends SimpleAction {
UiObject nodeInfo = findAccessibilityNodeInfosByBounds(child); UiObject nodeInfo = findAccessibilityNodeInfosByBounds(child);
if (nodeInfo != null) if (nodeInfo != null)
return nodeInfo; return nodeInfo;
else
child.recycle();
} }
return null; return null;
} }

View File

@@ -34,24 +34,29 @@ public class ScrollAction extends SimpleAction {
private List<UiObject> findScrollableNodes(UiObject root) { private List<UiObject> findScrollableNodes(UiObject root) {
List<UiObject> list = new ArrayList<>(); List<UiObject> list = new ArrayList<>();
findScrollableNodes(root, list); if (root != null) {
findScrollableNodes(root, list);
if (root.isScrollable()) {
list.add(root);
}
}
return list; return list;
} }
private static boolean findScrollableNodes(UiObject node, List<UiObject> list) { private static void findScrollableNodes(UiObject node, List<UiObject> list) {
if (node == null) { if (node == null) {
return false; return;
}
if (node.isScrollable()) {
list.add(node);
} }
for (int i = 0; i < node.getChildCount(); i++) { for (int i = 0; i < node.getChildCount(); i++) {
UiObject child = node.child(i); UiObject child = node.child(i);
if (child == null) if (child == null)
continue; continue;
if (!findScrollableNodes(child, list)) findScrollableNodes(child, list);
if (child.isScrollable()) {
list.add(child);
} else {
child.recycle(); child.recycle();
}
} }
return node.isScrollable();
} }
} }

View File

@@ -5,6 +5,9 @@ import android.util.Log;
import com.stardust.automator.UiObject; import com.stardust.automator.UiObject;
import java.util.HashSet;
import java.util.Set;
/** /**
* Created by Stardust on 2017/1/27. * Created by Stardust on 2017/1/27.
*/ */
@@ -15,6 +18,7 @@ public class ScrollMaxAction extends SimpleAction {
private int mScrollAction; private int mScrollAction;
private UiObject mMaxScrollableNode; private UiObject mMaxScrollableNode;
private UiObject mRootNode; private UiObject mRootNode;
private Set<UiObject> mRecycledMaxUiObjects = new HashSet<>();
public ScrollMaxAction(int scrollAction) { public ScrollMaxAction(int scrollAction) {
mScrollAction = scrollAction; mScrollAction = scrollAction;
@@ -35,6 +39,7 @@ public class ScrollMaxAction extends SimpleAction {
mMaxScrollableNode.recycle(); mMaxScrollableNode.recycle();
} }
mMaxScrollableNode = mRootNode = null; mMaxScrollableNode = mRootNode = null;
mRecycledMaxUiObjects.clear();
} }
private void findMaxScrollableNodeInfo(UiObject nodeInfo) { private void findMaxScrollableNodeInfo(UiObject nodeInfo) {
@@ -44,8 +49,10 @@ public class ScrollMaxAction extends SimpleAction {
if (mMaxScrollableNode == null) { if (mMaxScrollableNode == null) {
mMaxScrollableNode = nodeInfo; mMaxScrollableNode = nodeInfo;
} else if (getAreaInScreen(mMaxScrollableNode) < getAreaInScreen(nodeInfo)) { } else if (getAreaInScreen(mMaxScrollableNode) < getAreaInScreen(nodeInfo)) {
if (mMaxScrollableNode != mRootNode) if (mMaxScrollableNode != mRootNode) {
mRecycledMaxUiObjects.add(mMaxScrollableNode);
mMaxScrollableNode.recycle(); mMaxScrollableNode.recycle();
}
mMaxScrollableNode = nodeInfo; mMaxScrollableNode = nodeInfo;
} }
} }
@@ -53,7 +60,7 @@ public class ScrollMaxAction extends SimpleAction {
UiObject child = nodeInfo.child(i); UiObject child = nodeInfo.child(i);
if (child != null) { if (child != null) {
findMaxScrollableNodeInfo(child); findMaxScrollableNodeInfo(child);
if (mMaxScrollableNode != child) { if (mMaxScrollableNode != child && !mRecycledMaxUiObjects.contains(child)) {
child.recycle(); child.recycle();
} }
} }

View File

@@ -25,7 +25,6 @@ public class SearchUpTargetAction extends SearchTargetAction {
while (node != null && !mAble.isAble(node)) { while (node != null && !mAble.isAble(node)) {
i++; i++;
if (i > LOOP_MAX) { if (i > LOOP_MAX) {
node.recycle();
return null; return null;
} }
node = node.parent(); node = node.parent();

View File

@@ -79,7 +79,7 @@ public class SimpleActionPerformHost implements AccessibilityDelegate {
return; return;
} }
Log.i(TAG, "perform simpleAction: " + mSimpleAction); Log.i(TAG, "perform simpleAction: " + mSimpleAction);
if (mSimpleAction.perform(new UiObject(mRoot))) { if (mSimpleAction.perform(UiObject.createRoot(mRoot))) {
mSimpleAction.setResult(true); mSimpleAction.setResult(true);
onActionPerformed(mSimpleAction); onActionPerformed(mSimpleAction);
} }

View File

@@ -0,0 +1,100 @@
package com.stardust.automator.test;
import android.graphics.Rect;
import android.os.Bundle;
import android.util.Log;
import com.stardust.automator.UiObject;
import java.util.Arrays;
import java.util.Random;
/**
* Created by Stardust on 2017/5/5.
*/
public class TestUiObject extends UiObject {
public static int count = 0;
public static int max = 0;
private static Random random = new Random();
private int mHashCode = random.nextInt();
private boolean mRecycled = false;
private int mChildCount;
public TestUiObject(int i) {
super(null);
count++;
max = Math.max(max, count);
mChildCount = i;
}
public TestUiObject() {
this(Math.max(0, random.nextInt(6) - 2));
}
@Override
public UiObject child(int i) {
return new TestUiObject();
}
@Override
public UiObject parent() {
return new TestUiObject();
}
@Override
public int getChildCount() {
return mChildCount;
}
@Override
public boolean isScrollable() {
return random.nextInt(4) == 0;
}
@Override
public boolean isClickable() {
return random.nextBoolean();
}
@Override
public void getBoundsInScreen(Rect outBounds) {
int left = random.nextInt(1080);
int top = random.nextInt(1920);
int right = random.nextInt(1080 - left) + left;
int bottom = random.nextInt(1920 - top) + top;
outBounds.set(left, top, right, bottom);
}
@Override
public boolean performAction(int action, Bundle bundle) {
return random.nextBoolean();
}
@Override
public boolean performAction(int action) {
return random.nextBoolean();
}
@Override
public void recycle() {
if (mRecycled) {
throw new IllegalStateException();
}
mRecycled = true;
count--;
}
@Override
public String toString() {
return "UiObject@" + Integer.toHexString(hashCode());
}
@Override
public int hashCode() {
return mHashCode;
}
}

View File

@@ -106,7 +106,7 @@ public class AccessibilityNodeInfoAllocator {
return notRecycledCount; return notRecycledCount;
} }
private AccessibilityNodeInfo add(@Nullable AccessibilityNodeInfo nodeInfo) { public AccessibilityNodeInfo add(@Nullable AccessibilityNodeInfo nodeInfo) {
String stackTrace = DEBUG ? Arrays.toString(Thread.currentThread().getStackTrace()) : null; String stackTrace = DEBUG ? Arrays.toString(Thread.currentThread().getStackTrace()) : null;
if (nodeInfo != null) if (nodeInfo != null)
mAccessibilityNodeInfoList.put(nodeInfo, stackTrace); mAccessibilityNodeInfoList.put(nodeInfo, stackTrace);

View File

@@ -0,0 +1,41 @@
package com.stardust.automator.filter;
import com.stardust.automator.test.TestUiObject;
import com.stardust.automator.UiObject;
import org.junit.Test;
import java.util.List;
import java.util.Random;
import static org.junit.Assert.*;
/**
* Created by Stardust on 2017/5/5.
*/
public class DfsFilterTest {
private static class RandomDfsFilter extends DfsFilter {
private Random mRandom = new Random();
@Override
protected boolean isIncluded(UiObject nodeInfo) {
return mRandom.nextBoolean();
}
}
@Test
public void filter() throws Exception {
DfsFilter filter = new RandomDfsFilter();
UiObject root = new TestUiObject(10);
List<UiObject> list = filter.filter(root);
for (UiObject uiObject : list) {
if (root != uiObject)
uiObject.recycle();
}
System.out.println(TestUiObject.max);
assertEquals(1, TestUiObject.count);
}
}

View File

@@ -0,0 +1,25 @@
package com.stardust.automator.simple_action;
import android.view.accessibility.AccessibilityNodeInfo;
import com.stardust.automator.test.TestUiObject;
import com.stardust.automator.UiObject;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Created by Stardust on 2017/5/5.
*/
public class ScrollActionTest {
@Test
public void perform() throws Exception {
ScrollAction action = new ScrollAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD, 0);
UiObject root = new TestUiObject(5);
action.perform(root);
System.out.println(TestUiObject.max);
assertEquals(1, TestUiObject.count);
}
}

View File

@@ -6,6 +6,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:2.3.1' classpath 'com.android.tools.build:gradle:2.3.1'
classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.6.4'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files