Merge changes from topic 'ArcPagingBackport' into arc-apps

* changes:
  Make Sorting/paging honor ENABLE_OMC_FEATURES flag
  Test/Demo paging support in DocsUI.
  Don't sort pre-sorted results.
diff --git a/tests/common/com/android/documentsui/bots/Bots.java b/tests/common/com/android/documentsui/bots/Bots.java
index bfa7743..57f5cfa 100644
--- a/tests/common/com/android/documentsui/bots/Bots.java
+++ b/tests/common/com/android/documentsui/bots/Bots.java
@@ -53,7 +53,7 @@
         sortHeader = new SortHeaderBot(device, context, TIMEOUT);
         keyboard = new KeyboardBot(device, context, TIMEOUT);
         search = new SearchBot(device, context, TIMEOUT);
-        gesture = new GestureBot(device, context, TIMEOUT);
+        gesture = new GestureBot(device, automation, context, TIMEOUT);
         menu = new MenuBot(device, context, TIMEOUT);
     }
 
diff --git a/tests/common/com/android/documentsui/bots/GestureBot.java b/tests/common/com/android/documentsui/bots/GestureBot.java
index a6f3b77..e0ca8b6 100644
--- a/tests/common/com/android/documentsui/bots/GestureBot.java
+++ b/tests/common/com/android/documentsui/bots/GestureBot.java
@@ -16,15 +16,20 @@
 
 package com.android.documentsui.bots;
 
+import android.app.UiAutomation;
 import android.content.Context;
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.os.SystemClock;
 import android.support.test.uiautomator.Configurator;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObject;
 import android.support.test.uiautomator.UiObjectNotFoundException;
 import android.support.test.uiautomator.UiSelector;
+import android.view.InputDevice;
 import android.view.MotionEvent;
+import android.view.MotionEvent.PointerCoords;
+import android.view.MotionEvent.PointerProperties;
 
 /**
  * A test helper class that provides support for controlling directory list
@@ -37,9 +42,14 @@
     private static final int TRAVELING_STEPS = 20;
     private static final int BAND_SELECTION_DEFAULT_STEPS = 100;
     private static final int STEPS_INBETWEEN_POINTS = 2;
+    // Inserted after each motion event injection.
+    private static final int MOTION_EVENT_INJECTION_DELAY_MILLIS = 5;
+    private final UiAutomation mAutomation;
+    private long mDownTime = 0;
 
-    public GestureBot(UiDevice device, Context context, int timeout) {
+    public GestureBot(UiDevice device, UiAutomation automation, Context context, int timeout) {
         super(device, context, timeout);
+        mAutomation = automation;
     }
 
     public void gestureSelectFiles(String startLabel, String endLabel) throws Exception {
@@ -73,7 +83,7 @@
     public void bandSelection(Point start, Point end, int steps) throws Exception {
         int toolType = Configurator.getInstance().getToolType();
         Configurator.getInstance().setToolType(MotionEvent.TOOL_TYPE_MOUSE);
-        mDevice.swipe(start.x, start.y, end.x, end.y, steps);
+        swipe(start.x, start.y, end.x, end.y, steps, MotionEvent.BUTTON_PRIMARY);
         Configurator.getInstance().setToolType(toolType);
     }
 
@@ -87,4 +97,69 @@
 
         return mDevice.findObject(docList.childSelector(new UiSelector().text(label)));
     }
+
+    private void swipe(int downX, int downY, int upX, int upY, int steps, int button) {
+        int swipeSteps = steps;
+        double xStep = 0;
+        double yStep = 0;
+
+        // avoid a divide by zero
+        if(swipeSteps == 0)
+            swipeSteps = 1;
+
+        xStep = ((double)(upX - downX)) / swipeSteps;
+        yStep = ((double)(upY - downY)) / swipeSteps;
+
+        // first touch starts exactly at the point requested
+        touchDown(downX, downY, button);
+        for(int i = 1; i < swipeSteps; i++) {
+            touchMove(downX + (int)(xStep * i), downY + (int)(yStep * i), button);
+            // set some known constant delay between steps as without it this
+            // become completely dependent on the speed of the system and results
+            // may vary on different devices. This guarantees at minimum we have
+            // a preset delay.
+            SystemClock.sleep(MOTION_EVENT_INJECTION_DELAY_MILLIS);
+        }
+        touchUp(upX, upY);
+    }
+
+    private boolean touchDown(int x, int y, int button) {
+        long mDownTime = SystemClock.uptimeMillis();
+        MotionEvent event = getMotionEvent(mDownTime, mDownTime, MotionEvent.ACTION_DOWN, button, x,
+                y);
+        return mAutomation.injectInputEvent(event, true);
+    }
+
+    private boolean touchUp(int x, int y) {
+        final long eventTime = SystemClock.uptimeMillis();
+        MotionEvent event = getMotionEvent(mDownTime, eventTime, MotionEvent.ACTION_UP, 0, x, y);
+        mDownTime = 0;
+        return mAutomation.injectInputEvent(event, true);
+    }
+
+    private boolean touchMove(int x, int y, int button) {
+        final long eventTime = SystemClock.uptimeMillis();
+        MotionEvent event = getMotionEvent(mDownTime, eventTime, MotionEvent.ACTION_MOVE, button, x,
+                y);
+        return mAutomation.injectInputEvent(event, true);
+    }
+
+    /** Helper function to obtain a MotionEvent. */
+    private static MotionEvent getMotionEvent(long downTime, long eventTime, int action, int button,
+            float x, float y) {
+
+        PointerProperties properties = new PointerProperties();
+        properties.id = 0;
+        properties.toolType = Configurator.getInstance().getToolType();
+
+        PointerCoords coords = new PointerCoords();
+        coords.pressure = 1;
+        coords.size = 1;
+        coords.x = x;
+        coords.y = y;
+
+        return MotionEvent.obtain(downTime, eventTime, action, 1,
+                new PointerProperties[] { properties }, new PointerCoords[] { coords },
+                0, button, 1.0f, 1.0f, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0);
+    }
 }