diff --git a/app/build.gradle b/app/build.gradle index eba19a76..170c2439 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,4 +1,5 @@ apply plugin: 'com.android.application' +apply plugin: 'com.getkeepsafe.dexcount' def AAVersion = '4.2.0' android { @@ -49,6 +50,20 @@ android { pickFirst 'org/mozilla/javascript/*.java.orig' 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 { resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.1' } diff --git a/app/src/main/java/com/stardust/scriptdroid/App.java b/app/src/main/java/com/stardust/scriptdroid/App.java index 0a9c4650..7d561ac6 100644 --- a/app/src/main/java/com/stardust/scriptdroid/App.java +++ b/app/src/main/java/com/stardust/scriptdroid/App.java @@ -7,7 +7,6 @@ import android.os.Bundle; import android.support.annotation.Keep; import android.support.multidex.MultiDexApplication; -import com.flurry.android.FlurryAgent; import com.squareup.leakcanary.LeakCanary; import com.stardust.app.SimpleActivityLifecycleCallbacks; import com.stardust.app.VolumeChangeObserver; diff --git a/app/src/main/java/com/stardust/scriptdroid/autojs/ScriptExecutionGlobalListener.java b/app/src/main/java/com/stardust/scriptdroid/autojs/ScriptExecutionGlobalListener.java index 842dce30..48780a48 100644 --- a/app/src/main/java/com/stardust/scriptdroid/autojs/ScriptExecutionGlobalListener.java +++ b/app/src/main/java/com/stardust/scriptdroid/autojs/ScriptExecutionGlobalListener.java @@ -1,6 +1,5 @@ package com.stardust.scriptdroid.autojs; -import com.flurry.android.FlurryAgent; import com.stardust.autojs.execution.ScriptExecution; import com.stardust.autojs.execution.ScriptExecutionListener; import com.stardust.scriptdroid.App; diff --git a/app/src/main/java/com/stardust/scriptdroid/layout_inspector/NodeInfo.java b/app/src/main/java/com/stardust/scriptdroid/layout_inspector/NodeInfo.java index 1a6e574f..7685e6a0 100644 --- a/app/src/main/java/com/stardust/scriptdroid/layout_inspector/NodeInfo.java +++ b/app/src/main/java/com/stardust/scriptdroid/layout_inspector/NodeInfo.java @@ -6,7 +6,7 @@ import android.support.annotation.NonNull; import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; import android.view.accessibility.AccessibilityNodeInfo; -import com.stardust.view.accessibility.AccessibilityNodeInfoAllocator; +import com.stardust.automator.UiObject; import java.util.ArrayList; import java.util.List; @@ -74,19 +74,24 @@ public class NodeInfo { 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); - for (int i = 0; i < root.getChildCount(); i++) { - AccessibilityNodeInfo child = allocator.getChild(root, i); + int childCount = root.getChildCount(); + for (int i = 0; i < childCount; i++) { + UiObject child = root.child(i); if (child != null) { nodeInfo.children.add(capture(child)); } } - allocator.recycleAll(); return nodeInfo; } + public static NodeInfo capture(@NonNull AccessibilityNodeInfo root) { + UiObject r = UiObject.createRoot(root); + return capture(r); + } + public List getChildren() { return children; } diff --git a/app/src/main/java/com/stardust/scriptdroid/record/accessibility/AccessibilityActionConverter.java b/app/src/main/java/com/stardust/scriptdroid/record/accessibility/AccessibilityActionConverter.java index 19351f17..9166fa1e 100644 --- a/app/src/main/java/com/stardust/scriptdroid/record/accessibility/AccessibilityActionConverter.java +++ b/app/src/main/java/com/stardust/scriptdroid/record/accessibility/AccessibilityActionConverter.java @@ -123,13 +123,11 @@ public class AccessibilityActionConverter { AccessibilityNodeInfo source = event.getSource(); if (source == null) return; - AccessibilityNodeInfoAllocator allocator = new AccessibilityNodeInfoAllocator(); - UiObject uiObject = new UiObject(service.getRootInActiveWindow(), allocator); + UiObject uiObject = UiObject.createRoot(service.getRootInActiveWindow()); List editableList = FilterAction.EditableFilter.findEditable(uiObject); int i = findInEditableList(editableList, source); sb.append("while(!input(").append(i).append(", \"").append(source.getText()).append("\"));"); source.recycle(); - allocator.recycleAll(); } private static int findInEditableList(List editableList, AccessibilityNodeInfo editable) { diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/BaseActivity.java b/app/src/main/java/com/stardust/scriptdroid/ui/BaseActivity.java index a416c5ce..25e61e96 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/BaseActivity.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/BaseActivity.java @@ -1,26 +1,15 @@ package com.stardust.scriptdroid.ui; -import android.app.Activity; -import android.content.DialogInterface; import android.os.Build; import android.os.Bundle; -import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.RequiresApi; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; 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.tool.UpdateChecker; import com.stardust.scriptdroid.tool.VersionInfo; -import com.stardust.scriptdroid.ui.update.UpdateCheckDialog; import com.stardust.theme.ThemeColorManager; import com.stardust.util.BackPressedHandler; diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/console/StardustConsole.java b/app/src/main/java/com/stardust/scriptdroid/ui/console/StardustConsole.java index 142fbaad..236bbdf5 100644 --- a/app/src/main/java/com/stardust/scriptdroid/ui/console/StardustConsole.java +++ b/app/src/main/java/com/stardust/scriptdroid/ui/console/StardustConsole.java @@ -2,11 +2,13 @@ package com.stardust.scriptdroid.ui.console; import android.content.Context; import android.content.Intent; +import android.view.WindowManager; import com.stardust.autojs.runtime.api.AbstractConsole; import com.stardust.autojs.runtime.api.Console; import com.stardust.enhancedfloaty.FloatyService; import com.stardust.enhancedfloaty.ResizableExpandableFloatyWindow; +import com.stardust.scriptdroid.R; import com.stardust.scriptdroid.autojs.AutoJs; import com.stardust.util.UiHandler; @@ -82,7 +84,12 @@ public class StardustConsole extends AbstractConsole { mUiHandler.post(new Runnable() { @Override 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); + } } }); } diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/ProcessShell.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/ProcessShell.java index fe33764a..1d32338b 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/api/ProcessShell.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/api/ProcessShell.java @@ -61,22 +61,22 @@ public class ProcessShell extends AbstractShell implements AutoCloseable { @Override public void exit() { - if(mProcess != null) { + if (mProcess != null) { mProcess.destroy(); mProcess = null; } - if(mSucceedReader != null){ - try{ + if (mSucceedReader != null) { + try { mSucceedReader.close(); - }catch (IOException ignored){ + } catch (IOException ignored) { } mSucceedReader = null; } - if(mErrorReader != null){ - try{ + if (mErrorReader != null) { + try { mErrorReader.close(); - }catch (IOException ignored){ + } catch (IOException ignored) { } mErrorReader = null; @@ -158,8 +158,8 @@ public class ProcessShell extends AbstractShell implements AutoCloseable { } public static Result exec(String[] commands, boolean isRoot) { - try(ProcessShell shell = new ProcessShell(isRoot)){ - for(String command : commands){ + try (ProcessShell shell = new ProcessShell(isRoot)) { + for (String command : commands) { shell.exec(command); } shell.exec(COMMAND_EXIT); @@ -173,4 +173,5 @@ public class ProcessShell extends AbstractShell implements AutoCloseable { } } + } \ No newline at end of file diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/UiSelector.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/UiSelector.java index 1d64e6db..6e6244bc 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/api/UiSelector.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/api/UiSelector.java @@ -65,7 +65,7 @@ public class UiSelector extends UiGlobalSelector { public void execute(AccessibilityService service, AccessibilityEvent event) { AccessibilityNodeInfo root = service.getRootInActiveWindow(); 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) { AccessibilityNodeInfo root = service.getRootInActiveWindow(); if (root != null) { - return findOf(new UiObject(root, mAllocator)); + return findOf(UiObject.createRoot(root, mAllocator)); } } return null; diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/simple_action/SimpleActionAutomator.java b/autojs/src/main/java/com/stardust/autojs/runtime/simple_action/SimpleActionAutomator.java index 632a54d5..e8757d68 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/simple_action/SimpleActionAutomator.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/simple_action/SimpleActionAutomator.java @@ -200,7 +200,7 @@ public class SimpleActionAutomator { if (root == null) return false; Log.v(TAG, "performAction: " + simpleAction + " root = " + root); - return simpleAction.perform(new UiObject(root)); + return simpleAction.perform(UiObject.createRoot(root)); } private boolean isRunningPackageSelf() { diff --git a/automator/src/androidTest/java/com/stardust/automator/simple_action/DepthFirstSearchTargetActionTest.java b/automator/src/androidTest/java/com/stardust/automator/simple_action/DepthFirstSearchTargetActionTest.java new file mode 100644 index 00000000..fb5ff52f --- /dev/null +++ b/automator/src/androidTest/java/com/stardust/automator/simple_action/DepthFirstSearchTargetActionTest.java @@ -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 filter(UiObject root) { + List 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); + } + +} \ No newline at end of file diff --git a/automator/src/androidTest/java/com/stardust/automator/simple_action/ScrollMaxActionTest.java b/automator/src/androidTest/java/com/stardust/automator/simple_action/ScrollMaxActionTest.java new file mode 100644 index 00000000..a13cdee3 --- /dev/null +++ b/automator/src/androidTest/java/com/stardust/automator/simple_action/ScrollMaxActionTest.java @@ -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); + } + +} \ No newline at end of file diff --git a/automator/src/main/java/com/stardust/automator/UiObject.java b/automator/src/main/java/com/stardust/automator/UiObject.java index bd7828a9..c979a0d7 100644 --- a/automator/src/main/java/com/stardust/automator/UiObject.java +++ b/automator/src/main/java/com/stardust/automator/UiObject.java @@ -2,6 +2,8 @@ package com.stardust.automator; import android.graphics.Rect; import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.util.Pools; import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; import android.util.Log; 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.AccessibilityNodeInfoHelper; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -30,27 +34,62 @@ public class UiObject extends AccessibilityNodeInfoCompat { private static final String TAG = "UiObject"; 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 String mStackTrace = ""; + private boolean mIsRootNode = false; public UiObject(Object info) { this(info, null); } - public UiObject(Object info, AccessibilityNodeInfoAllocator allocator) { + public UiObject(Object info, AccessibilityNodeInfoAllocator allocator, boolean isRootNode) { super(info); + mIsRootNode = isRootNode; mAllocator = allocator; if (DEBUG) mStackTrace = Arrays.toString(Thread.currentThread().getStackTrace()); } - public UiObject parent() { - return new UiObject(getParent().getInfo()); + public UiObject(Object info, AccessibilityNodeInfoAllocator allocator) { + 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) { - 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) { @@ -110,6 +149,31 @@ public class UiObject extends AccessibilityNodeInfoCompat { 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) { Bundle bundle = new Bundle(); for (ActionArgument arg : arguments) { @@ -263,7 +327,8 @@ public class UiObject extends AccessibilityNodeInfoCompat { public static List compatListToUiObjectList(List compats, AccessibilityNodeInfoAllocator allocator) { List uiObjects = new ArrayList<>(compats.size()); for (AccessibilityNodeInfoCompat compat : compats) { - uiObjects.add(new UiObject(compat.getInfo(), allocator)); + if (compat != null) + uiObjects.add(new UiObject(compat.getInfo(), allocator)); } 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(); - } + } diff --git a/automator/src/main/java/com/stardust/automator/simple_action/DepthFirstSearchTargetAction.java b/automator/src/main/java/com/stardust/automator/simple_action/DepthFirstSearchTargetAction.java index 5dc5b6d4..7268040f 100644 --- a/automator/src/main/java/com/stardust/automator/simple_action/DepthFirstSearchTargetAction.java +++ b/automator/src/main/java/com/stardust/automator/simple_action/DepthFirstSearchTargetAction.java @@ -30,8 +30,6 @@ public class DepthFirstSearchTargetAction extends SearchTargetAction { UiObject node = searchTarget(child); if (node != null) return node; - else - child.recycle(); } return null; } diff --git a/automator/src/main/java/com/stardust/automator/simple_action/FilterAction.java b/automator/src/main/java/com/stardust/automator/simple_action/FilterAction.java index 40801b7a..0d48da9c 100644 --- a/automator/src/main/java/com/stardust/automator/simple_action/FilterAction.java +++ b/automator/src/main/java/com/stardust/automator/simple_action/FilterAction.java @@ -77,8 +77,6 @@ public abstract class FilterAction extends SimpleAction { UiObject nodeInfo = findAccessibilityNodeInfosByBounds(child); if (nodeInfo != null) return nodeInfo; - else - child.recycle(); } return null; } diff --git a/automator/src/main/java/com/stardust/automator/simple_action/ScrollAction.java b/automator/src/main/java/com/stardust/automator/simple_action/ScrollAction.java index c21f848a..96157371 100644 --- a/automator/src/main/java/com/stardust/automator/simple_action/ScrollAction.java +++ b/automator/src/main/java/com/stardust/automator/simple_action/ScrollAction.java @@ -34,24 +34,29 @@ public class ScrollAction extends SimpleAction { private List findScrollableNodes(UiObject root) { List list = new ArrayList<>(); - findScrollableNodes(root, list); + if (root != null) { + findScrollableNodes(root, list); + if (root.isScrollable()) { + list.add(root); + } + } return list; } - private static boolean findScrollableNodes(UiObject node, List list) { + private static void findScrollableNodes(UiObject node, List list) { if (node == null) { - return false; - } - if (node.isScrollable()) { - list.add(node); + return; } for (int i = 0; i < node.getChildCount(); i++) { UiObject child = node.child(i); if (child == null) continue; - if (!findScrollableNodes(child, list)) + findScrollableNodes(child, list); + if (child.isScrollable()) { + list.add(child); + } else { child.recycle(); + } } - return node.isScrollable(); } } diff --git a/automator/src/main/java/com/stardust/automator/simple_action/ScrollMaxAction.java b/automator/src/main/java/com/stardust/automator/simple_action/ScrollMaxAction.java index bd6ba2af..6c2eb2f4 100644 --- a/automator/src/main/java/com/stardust/automator/simple_action/ScrollMaxAction.java +++ b/automator/src/main/java/com/stardust/automator/simple_action/ScrollMaxAction.java @@ -5,6 +5,9 @@ import android.util.Log; import com.stardust.automator.UiObject; +import java.util.HashSet; +import java.util.Set; + /** * Created by Stardust on 2017/1/27. */ @@ -15,6 +18,7 @@ public class ScrollMaxAction extends SimpleAction { private int mScrollAction; private UiObject mMaxScrollableNode; private UiObject mRootNode; + private Set mRecycledMaxUiObjects = new HashSet<>(); public ScrollMaxAction(int scrollAction) { mScrollAction = scrollAction; @@ -35,6 +39,7 @@ public class ScrollMaxAction extends SimpleAction { mMaxScrollableNode.recycle(); } mMaxScrollableNode = mRootNode = null; + mRecycledMaxUiObjects.clear(); } private void findMaxScrollableNodeInfo(UiObject nodeInfo) { @@ -44,8 +49,10 @@ public class ScrollMaxAction extends SimpleAction { if (mMaxScrollableNode == null) { mMaxScrollableNode = nodeInfo; } else if (getAreaInScreen(mMaxScrollableNode) < getAreaInScreen(nodeInfo)) { - if (mMaxScrollableNode != mRootNode) + if (mMaxScrollableNode != mRootNode) { + mRecycledMaxUiObjects.add(mMaxScrollableNode); mMaxScrollableNode.recycle(); + } mMaxScrollableNode = nodeInfo; } } @@ -53,7 +60,7 @@ public class ScrollMaxAction extends SimpleAction { UiObject child = nodeInfo.child(i); if (child != null) { findMaxScrollableNodeInfo(child); - if (mMaxScrollableNode != child) { + if (mMaxScrollableNode != child && !mRecycledMaxUiObjects.contains(child)) { child.recycle(); } } diff --git a/automator/src/main/java/com/stardust/automator/simple_action/SearchUpTargetAction.java b/automator/src/main/java/com/stardust/automator/simple_action/SearchUpTargetAction.java index c01f9743..c5e1ba89 100644 --- a/automator/src/main/java/com/stardust/automator/simple_action/SearchUpTargetAction.java +++ b/automator/src/main/java/com/stardust/automator/simple_action/SearchUpTargetAction.java @@ -25,7 +25,6 @@ public class SearchUpTargetAction extends SearchTargetAction { while (node != null && !mAble.isAble(node)) { i++; if (i > LOOP_MAX) { - node.recycle(); return null; } node = node.parent(); diff --git a/automator/src/main/java/com/stardust/automator/simple_action/SimpleActionPerformHost.java b/automator/src/main/java/com/stardust/automator/simple_action/SimpleActionPerformHost.java index 47e72d95..2b9a024e 100644 --- a/automator/src/main/java/com/stardust/automator/simple_action/SimpleActionPerformHost.java +++ b/automator/src/main/java/com/stardust/automator/simple_action/SimpleActionPerformHost.java @@ -79,7 +79,7 @@ public class SimpleActionPerformHost implements AccessibilityDelegate { return; } Log.i(TAG, "perform simpleAction: " + mSimpleAction); - if (mSimpleAction.perform(new UiObject(mRoot))) { + if (mSimpleAction.perform(UiObject.createRoot(mRoot))) { mSimpleAction.setResult(true); onActionPerformed(mSimpleAction); } diff --git a/automator/src/main/java/com/stardust/automator/test/TestUiObject.java b/automator/src/main/java/com/stardust/automator/test/TestUiObject.java new file mode 100644 index 00000000..9621d144 --- /dev/null +++ b/automator/src/main/java/com/stardust/automator/test/TestUiObject.java @@ -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; + } +} diff --git a/automator/src/main/java/com/stardust/view/accessibility/AccessibilityNodeInfoAllocator.java b/automator/src/main/java/com/stardust/view/accessibility/AccessibilityNodeInfoAllocator.java index d1e71e8a..ee4b54d0 100644 --- a/automator/src/main/java/com/stardust/view/accessibility/AccessibilityNodeInfoAllocator.java +++ b/automator/src/main/java/com/stardust/view/accessibility/AccessibilityNodeInfoAllocator.java @@ -106,7 +106,7 @@ public class AccessibilityNodeInfoAllocator { return notRecycledCount; } - private AccessibilityNodeInfo add(@Nullable AccessibilityNodeInfo nodeInfo) { + public AccessibilityNodeInfo add(@Nullable AccessibilityNodeInfo nodeInfo) { String stackTrace = DEBUG ? Arrays.toString(Thread.currentThread().getStackTrace()) : null; if (nodeInfo != null) mAccessibilityNodeInfoList.put(nodeInfo, stackTrace); diff --git a/automator/src/test/java/com/stardust/automator/filter/DfsFilterTest.java b/automator/src/test/java/com/stardust/automator/filter/DfsFilterTest.java new file mode 100644 index 00000000..93162f3e --- /dev/null +++ b/automator/src/test/java/com/stardust/automator/filter/DfsFilterTest.java @@ -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 list = filter.filter(root); + for (UiObject uiObject : list) { + if (root != uiObject) + uiObject.recycle(); + } + System.out.println(TestUiObject.max); + assertEquals(1, TestUiObject.count); + } + +} \ No newline at end of file diff --git a/automator/src/test/java/com/stardust/automator/simple_action/ScrollActionTest.java b/automator/src/test/java/com/stardust/automator/simple_action/ScrollActionTest.java new file mode 100644 index 00000000..24613e64 --- /dev/null +++ b/automator/src/test/java/com/stardust/automator/simple_action/ScrollActionTest.java @@ -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); + } + +} \ No newline at end of file diff --git a/build.gradle b/build.gradle index 3e02bd9c..0f6f698f 100644 --- a/build.gradle +++ b/build.gradle @@ -6,6 +6,7 @@ buildscript { } dependencies { 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 // in the individual module build.gradle files