aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKevin Jin <kjin@google.com>2013-11-14 14:11:46 -0800
committerKevin Jin <kjin@google.com>2013-11-14 14:11:46 -0800
commitef176eeb3b29df478522c46cc100f421365b008e (patch)
tree0c9f1ca18e8a1545a2415481031881debb811fca /src
parent8d19bb634c670a49f7a58636a2a535c86b57d538 (diff)
downloaddroiddriver-ef176eeb3b29df478522c46cc100f421365b008e.tar.gz
warn the brittle SwipeAction.toFling and remove its use in StepBasedScroller
optimize AccessibilityEventScrollStepStrategy to match UiAutomator Change-Id: Iacac499659ca6d94daf82f5889700234b231e4d9
Diffstat (limited to 'src')
-rw-r--r--src/com/google/android/droiddriver/actions/SwipeAction.java24
-rw-r--r--src/com/google/android/droiddriver/scroll/AccessibilityEventScrollStepStrategy.java39
-rw-r--r--src/com/google/android/droiddriver/scroll/StepBasedScroller.java10
3 files changed, 64 insertions, 9 deletions
diff --git a/src/com/google/android/droiddriver/actions/SwipeAction.java b/src/com/google/android/droiddriver/actions/SwipeAction.java
index ca165f1..186b5dc 100644
--- a/src/com/google/android/droiddriver/actions/SwipeAction.java
+++ b/src/com/google/android/droiddriver/actions/SwipeAction.java
@@ -22,6 +22,7 @@ import static com.google.android.droiddriver.scroll.Direction.PhysicalDirection.
import static com.google.android.droiddriver.scroll.Direction.PhysicalDirection.UP;
import android.graphics.Rect;
+import android.os.Build;
import android.os.SystemClock;
import android.view.ViewConfiguration;
@@ -31,6 +32,7 @@ import com.google.android.droiddriver.scroll.Direction.PhysicalDirection;
import com.google.android.droiddriver.util.Events;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.primitives.Ints;
/**
* A {@link ScrollAction} that swipes the touch screen. Note the scroll
@@ -42,13 +44,18 @@ public class SwipeAction extends ScrollAction {
// The action is a fling if the ACTION_MOVE velocity is greater than
// ViewConfiguration#getScaledMinimumFlingVelocity. The velocity is calculated
// as <distance between ACTION_MOVE points> / ACTION_MOVE_INTERVAL
+ // Note: ACTION_MOVE_INTERVAL is the minimum interval between injected events;
+ // the actual interval typically is longer.
private static final int ACTION_MOVE_INTERVAL = 5;
// ViewConfiguration.MINIMUM_FLING_VELOCITY = 50, so if there is no scale, in
// theory a swipe of 20 steps is a scroll instead of fling on devices that
// have 20 * 50 * 5 = 5000 pixels in one direction. Make it 40 for safety.
private static final int SCROLL_STEPS = 40;
- // FLING_STEPS = 2 does not work on GingerBread
- private static final int FLING_STEPS = 3;
+ // TODO: Find the exact version-dependent fling steps. It is observed that 2
+ // does not work on GINGERBREAD; we haven't tested all versions so <JELLY_BEAN
+ // is used as a guess.
+ private static final int FLING_STEPS = Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN ? 3
+ : 2;
/**
* Common instances for convenience. The direction in names reflects the
@@ -88,6 +95,13 @@ public class SwipeAction extends ScrollAction {
/**
* Gets canned common instances for flinging. Note the scroll direction
* specifies where the content will move, instead of the finger.
+ * <p>
+ * Note: This may not actually fling, depending on the size of the target
+ * UiElement and the SDK version of the device. If it does not behave as
+ * expected, you can use SwipeAction instances with custom steps.
+ * </p>
+ *
+ * @see ViewConfiguration#getScaledMinimumFlingVelocity
*/
// TODO: We may use "smart" steps that depend on the size of the UiElement and
// ViewConfiguration#getScaledMinimumFlingVelocity.
@@ -127,15 +141,15 @@ public class SwipeAction extends ScrollAction {
/**
* @param direction the scroll direction specifying where the content will
* move, instead of the finger.
- * @param steps (steps-1) is the number of {@code ACTION_MOVE} that will be
- * injected between {@code ACTION_DOWN} and {@code ACTION_UP}
+ * @param steps minimum 2; (steps-1) is the number of {@code ACTION_MOVE} that
+ * will be injected between {@code ACTION_DOWN} and {@code ACTION_UP}.
* @param drag whether this is a drag
* @param timeoutMillis
*/
public SwipeAction(PhysicalDirection direction, int steps, boolean drag, long timeoutMillis) {
super(timeoutMillis);
this.direction = direction;
- this.steps = steps;
+ this.steps = Ints.max(2, steps);
this.drag = drag;
}
diff --git a/src/com/google/android/droiddriver/scroll/AccessibilityEventScrollStepStrategy.java b/src/com/google/android/droiddriver/scroll/AccessibilityEventScrollStepStrategy.java
index 0333d77..9a4fe05 100644
--- a/src/com/google/android/droiddriver/scroll/AccessibilityEventScrollStepStrategy.java
+++ b/src/com/google/android/droiddriver/scroll/AccessibilityEventScrollStepStrategy.java
@@ -17,14 +17,17 @@ package com.google.android.droiddriver.scroll;
import android.app.UiAutomation;
import android.app.UiAutomation.AccessibilityEventFilter;
+import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import com.google.android.droiddriver.DroidDriver;
import com.google.android.droiddriver.UiElement;
import com.google.android.droiddriver.actions.SwipeAction;
import com.google.android.droiddriver.finders.Finder;
+import com.google.android.droiddriver.scroll.Direction.Axis;
import com.google.android.droiddriver.scroll.Direction.DirectionConverter;
import com.google.android.droiddriver.scroll.Direction.PhysicalDirection;
+import com.google.android.droiddriver.util.Logs;
import java.util.concurrent.TimeoutException;
@@ -53,6 +56,9 @@ public class AccessibilityEventScrollStepStrategy implements ScrollStepStrategy
private final long scrollEventTimeoutMillis;
private final DirectionConverter directionConverter;
+ private Finder containerFinderAtEnd;
+ private PhysicalDirection directionAtEnd;
+
public AccessibilityEventScrollStepStrategy(UiAutomation uiAutomation,
long scrollEventTimeoutMillis, DirectionConverter converter) {
this.uiAutomation = uiAutomation;
@@ -63,14 +69,28 @@ public class AccessibilityEventScrollStepStrategy implements ScrollStepStrategy
@Override
public boolean scroll(DroidDriver driver, Finder containerFinder,
final PhysicalDirection direction) {
+ // Check if we've reached end after last scroll.
+ if (containerFinderAtEnd == containerFinder && directionAtEnd == direction) {
+ return false;
+ }
+
final UiElement container = driver.on(containerFinder);
try {
- uiAutomation.executeAndWaitForEvent(new Runnable() {
+ AccessibilityEvent event = uiAutomation.executeAndWaitForEvent(new Runnable() {
@Override
public void run() {
SwipeAction.toScroll(direction).perform(container.getInjector(), container);
}
}, SCROLL_EVENT_FILTER, scrollEventTimeoutMillis);
+
+ if (detectEnd(direction.axis(), event)) {
+ containerFinderAtEnd = containerFinder;
+ directionAtEnd = direction;
+ Logs.log(Log.DEBUG, "reached scroll end");
+ } else {
+ containerFinderAtEnd = null;
+ directionAtEnd = null;
+ }
} catch (TimeoutException e) {
// If no TYPE_VIEW_SCROLLED event, no more scrolling is possible
return false;
@@ -78,6 +98,23 @@ public class AccessibilityEventScrollStepStrategy implements ScrollStepStrategy
return true;
}
+ // Copied from UiAutomator.
+ // AdapterViews have indices we can use to check for the beginning.
+ private static boolean detectEnd(Axis axis, AccessibilityEvent event) {
+ boolean foundEnd = false;
+ if (event.getFromIndex() != -1 && event.getToIndex() != -1 && event.getItemCount() != -1) {
+ foundEnd = event.getFromIndex() == 0 || (event.getItemCount() - 1) == event.getToIndex();
+ } else if (event.getScrollX() != -1 && event.getScrollY() != -1) {
+ if (axis == Axis.VERTICAL) {
+ foundEnd = event.getScrollY() == 0 || event.getScrollY() == event.getMaxScrollY();
+ } else if (axis == Axis.HORIZONTAL) {
+ foundEnd = event.getScrollX() == 0 || event.getScrollX() == event.getMaxScrollX();
+ }
+ }
+ event.recycle();
+ return foundEnd;
+ }
+
@Override
public final DirectionConverter getDirectionConverter() {
return directionConverter;
diff --git a/src/com/google/android/droiddriver/scroll/StepBasedScroller.java b/src/com/google/android/droiddriver/scroll/StepBasedScroller.java
index 2ba8ceb..d7fd368 100644
--- a/src/com/google/android/droiddriver/scroll/StepBasedScroller.java
+++ b/src/com/google/android/droiddriver/scroll/StepBasedScroller.java
@@ -24,7 +24,6 @@ import com.google.android.droiddriver.DroidDriver;
import com.google.android.droiddriver.Poller;
import com.google.android.droiddriver.UiElement;
import com.google.android.droiddriver.actions.SingleKeyAction;
-import com.google.android.droiddriver.actions.SwipeAction;
import com.google.android.droiddriver.exceptions.ElementNotFoundException;
import com.google.android.droiddriver.exceptions.TimeoutException;
import com.google.android.droiddriver.finders.By;
@@ -149,8 +148,13 @@ public class StepBasedScroller implements Scroller {
container.perform(MOVE_HOME);
Logs.log(Log.DEBUG, "MOVE_HOME used");
} else {
- // Fling to beginning
- container.perform(SwipeAction.toFling(backwardDirection));
+ // Fling to beginning is not reliable; scroll to beginning
+ // container.perform(SwipeAction.toFling(backwardDirection));
+ for (int i = 0; i < maxScrolls; i++) {
+ if (!scrollStepStrategy.scroll(driver, containerFinder, backwardDirection)) {
+ break;
+ }
+ }
}
} else {
// search backward