TAPL: verify input events

This will catch cases, for example, when the platform stops delivering
injected events to Launcher, or injects unexpected events, like Back
Button.

Also optimizing and fixing incorrect behavior of calculating the start
time for the event collection.

Change-Id: I2ba0108e6bfa112f2905a05bcb327b148ec08f77
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 8066d38..06f3453 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -76,6 +76,7 @@
 import android.view.KeyboardShortcutInfo;
 import android.view.LayoutInflater;
 import android.view.Menu;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
@@ -121,6 +122,7 @@
 import com.android.launcher3.popup.SystemShortcut;
 import com.android.launcher3.qsb.QsbContainerView;
 import com.android.launcher3.states.RotationHelper;
+import com.android.launcher3.testing.TestLogging;
 import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.touch.AllAppsSwipeController;
 import com.android.launcher3.touch.ItemClickHandler;
@@ -1778,10 +1780,21 @@
 
     @Override
     public boolean dispatchKeyEvent(KeyEvent event) {
+        if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+            TestLogging.recordEvent("Key event: " + event);
+        }
         return (event.getKeyCode() == KeyEvent.KEYCODE_HOME) || super.dispatchKeyEvent(event);
     }
 
     @Override
+    public boolean dispatchTouchEvent(MotionEvent ev) {
+        if (Utilities.IS_RUNNING_IN_TEST_HARNESS && ev.getAction() != MotionEvent.ACTION_MOVE) {
+            TestLogging.recordEvent("Touch event: " + ev);
+        }
+        return super.dispatchTouchEvent(ev);
+    }
+
+    @Override
     public void onBackPressed() {
         if (finishAutoCancelActionMode()) {
             return;
diff --git a/tests/tapl/com/android/launcher3/tapl/AllAppsFromOverview.java b/tests/tapl/com/android/launcher3/tapl/AllAppsFromOverview.java
index 8f9fec9..835790d 100644
--- a/tests/tapl/com/android/launcher3/tapl/AllAppsFromOverview.java
+++ b/tests/tapl/com/android/launcher3/tapl/AllAppsFromOverview.java
@@ -56,7 +56,8 @@
 
             final int endY = start.y + swipeHeight;
             LauncherInstrumentation.log("AllAppsFromOverview.switchBackToOverview before swipe");
-            mLauncher.swipeToState(start.x, start.y, start.x, endY, 60, OVERVIEW_STATE_ORDINAL);
+            mLauncher.swipeToState(start.x, start.y, start.x, endY, 60, OVERVIEW_STATE_ORDINAL,
+                    LauncherInstrumentation.GestureScope.INSIDE);
 
             try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer("swiped down")) {
                 return new Overview(mLauncher);
diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java
index 50bdf5c..c37e451 100644
--- a/tests/tapl/com/android/launcher3/tapl/Background.java
+++ b/tests/tapl/com/android/launcher3/tapl/Background.java
@@ -62,6 +62,10 @@
         }
     }
 
+    protected boolean zeroButtonToOverviewGestureStartsInLauncher() {
+        return false;
+    }
+
     protected void goToOverviewUnchecked() {
         switch (mLauncher.getNavigationModel()) {
             case ZERO_BUTTON: {
@@ -74,19 +78,26 @@
                         new Point(centerX, startY - swipeHeight - mLauncher.getTouchSlop());
 
                 final long downTime = SystemClock.uptimeMillis();
-                mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, start);
+                final LauncherInstrumentation.GestureScope gestureScope =
+                        zeroButtonToOverviewGestureStartsInLauncher()
+                                ? LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE
+                                : LauncherInstrumentation.GestureScope.OUTSIDE;
+                mLauncher.sendPointer(
+                        downTime, downTime, MotionEvent.ACTION_DOWN, start, gestureScope);
                 mLauncher.executeAndWaitForEvent(
                         () -> mLauncher.movePointer(
                                 downTime,
                                 downTime,
                                 ZERO_BUTTON_SWIPE_UP_GESTURE_DURATION,
                                 start,
-                                end),
+                                end,
+                                gestureScope),
                         event -> TestProtocol.PAUSE_DETECTED_MESSAGE.equals(event.getClassName()),
                         () -> "Pause wasn't detected");
                 mLauncher.runToState(
                         () -> mLauncher.sendPointer(
-                                downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, end),
+                                downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, end,
+                                gestureScope),
                         OVERVIEW_STATE_ORDINAL);
                 break;
             }
@@ -109,7 +120,8 @@
                     startY = endY = mLauncher.getDevice().getDisplayHeight() / 2;
                 }
 
-                mLauncher.swipeToState(startX, startY, endX, endY, 10, OVERVIEW_STATE_ORDINAL);
+                mLauncher.swipeToState(startX, startY, endX, endY, 10, OVERVIEW_STATE_ORDINAL,
+                        LauncherInstrumentation.GestureScope.OUTSIDE);
                 break;
             }
 
@@ -162,7 +174,12 @@
                     endX = startX;
                     endY = 0;
                 }
-                mLauncher.swipeToState(startX, startY, endX, endY, 20, expectedState);
+                mLauncher.swipeToState(startX, startY, endX, endY, 20, expectedState,
+                        mLauncher.getNavigationModel()
+                                == LauncherInstrumentation.NavigationModel.ZERO_BUTTON
+                                ? LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE
+                                : LauncherInstrumentation.GestureScope.OUTSIDE
+                );
                 break;
             }
 
diff --git a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
index e13ea52..e5c83e2 100644
--- a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
+++ b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
@@ -82,7 +82,8 @@
                 flingForwardImpl();
             }
 
-            mLauncher.waitForObjectInContainer(verifyActiveContainer(), clearAllSelector).click();
+            mLauncher.clickLauncherObject(
+                    mLauncher.waitForObjectInContainer(verifyActiveContainer(), clearAllSelector));
         }
     }
 
diff --git a/tests/tapl/com/android/launcher3/tapl/Home.java b/tests/tapl/com/android/launcher3/tapl/Home.java
index 1a0fe3d..c06e254 100644
--- a/tests/tapl/com/android/launcher3/tapl/Home.java
+++ b/tests/tapl/com/android/launcher3/tapl/Home.java
@@ -61,6 +61,11 @@
     }
 
     @Override
+    protected boolean zeroButtonToOverviewGestureStartsInLauncher() {
+        return true;
+    }
+
+    @Override
     protected int getExpectedStateForQuickSwitch() {
         return QUICK_SWITCH_STATE_ORDINAL;
     }
diff --git a/tests/tapl/com/android/launcher3/tapl/Launchable.java b/tests/tapl/com/android/launcher3/tapl/Launchable.java
index f88a616..1722d5b 100644
--- a/tests/tapl/com/android/launcher3/tapl/Launchable.java
+++ b/tests/tapl/com/android/launcher3/tapl/Launchable.java
@@ -56,7 +56,7 @@
                 mObject.getVisibleCenter() + " in " + mObject.getVisibleBounds());
 
         mLauncher.executeAndWaitForEvent(
-                () -> mObject.click(),
+                () -> mLauncher.clickLauncherObject(mObject),
                 event -> event.getEventType() == TYPE_WINDOW_STATE_CHANGED,
                 () -> "Launching an app didn't open a new window: " + mObject.getText());
 
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 6df8790..857badd 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -49,7 +49,6 @@
 import android.view.accessibility.AccessibilityEvent;
 
 import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 import androidx.test.InstrumentationRegistry;
 import androidx.test.uiautomator.By;
 import androidx.test.uiautomator.BySelector;
@@ -69,9 +68,11 @@
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.lang.ref.WeakReference;
+import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Date;
 import java.util.Deque;
 import java.util.LinkedList;
 import java.util.List;
@@ -94,13 +95,14 @@
     private static final int GESTURE_STEP_MS = 16;
     private static long START_TIME = System.currentTimeMillis();
 
-    static final Pattern LOG_TIME = Pattern.compile(
-            "[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]\\.[0-9][0-9][0-9]");
-
     static final Pattern EVENT_LOG_ENTRY = Pattern.compile(
-            "(?<time>[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]\\.[0-9][0-9][0-9])"
+            "[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]\\.[0-9][0-9][0-9]"
                     + ".*" + TestProtocol.TAPL_EVENTS_TAG + ": (?<event>.*)");
 
+    private static final Pattern EVENT_TOUCH_DOWN = getTouchEventPattern("ACTION_DOWN");
+    private static final Pattern EVENT_TOUCH_UP = getTouchEventPattern("ACTION_UP");
+    private static final Pattern EVENT_TOUCH_CANCEL = getTouchEventPattern("ACTION_CANCEL");
+
     // Types for launcher containers that the user is interacting with. "Background" is a
     // pseudo-container corresponding to inactive launcher covered by another app.
     public enum ContainerType {
@@ -109,6 +111,13 @@
 
     public enum NavigationModel {ZERO_BUTTON, TWO_BUTTON, THREE_BUTTON}
 
+    // Where the gesture happens: outside of Launcher, inside or from inside to outside.
+    enum GestureScope {
+        OUTSIDE, INSIDE, INSIDE_TO_OUTSIDE
+    }
+
+    ;
+
     // Base class for launcher containers.
     static abstract class VisibleContainer {
         protected final LauncherInstrumentation mLauncher;
@@ -160,6 +169,15 @@
 
     private String mTimeBeforeFirstLogEvent;
 
+    private static Pattern getTouchEventPattern(String action) {
+        // The pattern includes sanity checks that we don't get a multi-touch events or other
+        // surprises.
+        return Pattern.compile(
+                "Touch event: MotionEvent.*?action=" + action + ".*?id\\[0\\]=0"
+                        +
+                        ".*?toolType\\[0\\]=TOOL_TYPE_FINGER.*?buttonState=0.*?pointerCount=1");
+    }
+
     /**
      * Constructs the root of TAPL hierarchy. You get all other objects from it.
      */
@@ -577,7 +595,7 @@
                             displaySize.x / 2, displaySize.y - 1,
                             displaySize.x / 2, 0,
                             ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME,
-                            false);
+                            false, GestureScope.INSIDE_TO_OUTSIDE);
                     try (LauncherInstrumentation.Closable c = addContextLayer(
                             "Swiped up from context menu to home")) {
                         waitUntilGone(CONTEXT_MENU_RES_ID);
@@ -594,7 +612,10 @@
                         swipeToState(
                                 displaySize.x / 2, displaySize.y - 1,
                                 displaySize.x / 2, 0,
-                                ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME, NORMAL_STATE_ORDINAL);
+                                ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME, NORMAL_STATE_ORDINAL,
+                                hasLauncherObject(By.textStartsWith(""))
+                                        ? GestureScope.INSIDE_TO_OUTSIDE
+                                        : GestureScope.OUTSIDE);
                     }
                 }
             } else {
@@ -763,11 +784,18 @@
         return object;
     }
 
-    @Nullable
     private boolean hasLauncherObject(String resId) {
         return mDevice.hasObject(getLauncherObjectSelector(resId));
     }
 
+    private boolean hasLauncherObject(BySelector selector) {
+        return mDevice.hasObject(makeLauncherSelector(selector));
+    }
+
+    private BySelector makeLauncherSelector(BySelector selector) {
+        return By.copy(selector).pkg(getLauncherPackageName());
+    }
+
     @NonNull
     UiObject2 waitForLauncherObject(String resName) {
         return waitForObjectBySelector(getLauncherObjectSelector(resName));
@@ -775,12 +803,12 @@
 
     @NonNull
     UiObject2 waitForLauncherObject(BySelector selector) {
-        return waitForObjectBySelector(By.copy(selector).pkg(getLauncherPackageName()));
+        return waitForObjectBySelector(makeLauncherSelector(selector));
     }
 
     @NonNull
     UiObject2 tryWaitForLauncherObject(BySelector selector, long timeout) {
-        return tryWaitForObjectBySelector(By.copy(selector).pkg(getLauncherPackageName()), timeout);
+        return tryWaitForObjectBySelector(makeLauncherSelector(selector), timeout);
     }
 
     @NonNull
@@ -857,8 +885,11 @@
         return actualState == expectedState;
     }
 
-    void swipeToState(int startX, int startY, int endX, int endY, int steps, int expectedState) {
-        runToState(() -> linearGesture(startX, startY, endX, endY, steps, false), expectedState);
+    void swipeToState(int startX, int startY, int endX, int endY, int steps, int expectedState,
+            GestureScope gestureScope) {
+        runToState(
+                () -> linearGesture(startX, startY, endX, endY, steps, false, gestureScope),
+                expectedState);
     }
 
     int getBottomGestureSize() {
@@ -871,6 +902,12 @@
         return container.getVisibleBounds().bottom - bottomGestureStartOnScreen;
     }
 
+    void clickLauncherObject(UiObject2 object) {
+        expectEvent(LauncherInstrumentation.EVENT_TOUCH_DOWN);
+        expectEvent(LauncherInstrumentation.EVENT_TOUCH_UP);
+        object.click();
+    }
+
     void scrollToLastVisibleRow(
             UiObject2 container,
             Collection<UiObject2> items,
@@ -942,7 +979,8 @@
         }
 
         executeAndWaitForEvent(
-                () -> linearGesture(startX, startY, endX, endY, steps, slowDown),
+                () -> linearGesture(
+                        startX, startY, endX, endY, steps, slowDown, GestureScope.INSIDE),
                 event -> TestProtocol.SCROLL_FINISHED_MESSAGE.equals(event.getClassName()),
                 () -> "Didn't receive a scroll end message: " + startX + ", " + startY
                         + ", " + endX + ", " + endY);
@@ -950,21 +988,24 @@
 
     // Inject a swipe gesture. Inject exactly 'steps' motion points, incrementing event time by a
     // fixed interval each time.
-    void linearGesture(int startX, int startY, int endX, int endY, int steps, boolean slowDown) {
+    void linearGesture(int startX, int startY, int endX, int endY, int steps, boolean slowDown,
+            GestureScope gestureScope) {
         log("linearGesture: " + startX + ", " + startY + " -> " + endX + ", " + endY);
         final long downTime = SystemClock.uptimeMillis();
         final Point start = new Point(startX, startY);
         final Point end = new Point(endX, endY);
-        sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, start);
-        final long endTime = movePointer(start, end, steps, downTime, slowDown);
-        sendPointer(downTime, endTime, MotionEvent.ACTION_UP, end);
+        sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, start, gestureScope);
+        final long endTime = movePointer(start, end, steps, downTime, slowDown, gestureScope);
+        sendPointer(downTime, endTime, MotionEvent.ACTION_UP, end, gestureScope);
     }
 
-    long movePointer(Point start, Point end, int steps, long downTime, boolean slowDown) {
-        long endTime = movePointer(downTime, downTime, steps * GESTURE_STEP_MS, start, end);
+    long movePointer(Point start, Point end, int steps, long downTime, boolean slowDown,
+            GestureScope gestureScope) {
+        long endTime = movePointer(
+                downTime, downTime, steps * GESTURE_STEP_MS, start, end, gestureScope);
         if (slowDown) {
             endTime = movePointer(downTime, endTime + GESTURE_STEP_MS, 5 * GESTURE_STEP_MS, end,
-                    end);
+                    end, gestureScope);
         }
         return endTime;
     }
@@ -999,13 +1040,27 @@
                 0, 0, 1.0f, 1.0f, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0);
     }
 
-    void sendPointer(long downTime, long currentTime, int action, Point point) {
+    void sendPointer(long downTime, long currentTime, int action, Point point,
+            GestureScope gestureScope) {
+        if (gestureScope != GestureScope.OUTSIDE) {
+            switch (action) {
+                case MotionEvent.ACTION_DOWN:
+                    expectEvent(EVENT_TOUCH_DOWN);
+                    break;
+                case MotionEvent.ACTION_UP:
+                    expectEvent(gestureScope == GestureScope.INSIDE
+                            ? EVENT_TOUCH_UP : EVENT_TOUCH_CANCEL);
+                    break;
+            }
+        }
+
         final MotionEvent event = getMotionEvent(downTime, currentTime, action, point.x, point.y);
         mInstrumentation.getUiAutomation().injectInputEvent(event, true);
         event.recycle();
     }
 
-    long movePointer(long downTime, long startTime, long duration, Point from, Point to) {
+    long movePointer(long downTime, long startTime, long duration, Point from, Point to,
+            GestureScope gestureScope) {
         log("movePointer: " + from + " to " + to);
         final Point point = new Point();
         long steps = duration / GESTURE_STEP_MS;
@@ -1019,7 +1074,7 @@
             point.x = from.x + (int) (progress * (to.x - from.x));
             point.y = from.y + (int) (progress * (to.y - from.y));
 
-            sendPointer(downTime, currentTime, MotionEvent.ACTION_MOVE, point);
+            sendPointer(downTime, currentTime, MotionEvent.ACTION_MOVE, point, gestureScope);
         }
         return currentTime;
     }
@@ -1032,9 +1087,10 @@
     UiObject2 clickAndGet(@NonNull final UiObject2 target, @NonNull String resName) {
         final Point targetCenter = target.getVisibleCenter();
         final long downTime = SystemClock.uptimeMillis();
-        sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, targetCenter);
+        sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, targetCenter, GestureScope.INSIDE);
         final UiObject2 result = waitForLauncherObject(resName);
-        sendPointer(downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, targetCenter);
+        sendPointer(downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, targetCenter,
+                GestureScope.INSIDE);
         return result;
     }
 
@@ -1133,9 +1189,6 @@
                             + " -s " + TestProtocol.TAPL_EVENTS_TAG);
             final Matcher matcher = EVENT_LOG_ENTRY.matcher(logcatEvents);
             while (matcher.find()) {
-                final String eventTime = matcher.group("time");
-                if (eventTime.equals(mTimeBeforeFirstLogEvent)) continue;
-
                 events.add(matcher.group("event"));
             }
             return events;
@@ -1147,15 +1200,9 @@
     private void startRecordingEvents() {
         Assert.assertTrue("Already recording events", mExpectedEvents == null);
         mExpectedEvents = new ArrayList<>();
-
-        try {
-            final String lastLogLine =
-                    mDevice.executeShellCommand("logcat -d --pid=" + getPid() + " -t 1");
-            final Matcher matcher = LOG_TIME.matcher(lastLogLine);
-            mTimeBeforeFirstLogEvent = matcher.find() ? matcher.group().replaceAll(" ", "") : null;
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
+        mTimeBeforeFirstLogEvent = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")
+                .format(new Date())
+                .replaceAll(" ", "");
     }
 
     private void stopRecordingEvents() {
diff --git a/tests/tapl/com/android/launcher3/tapl/OptionsPopupMenuItem.java b/tests/tapl/com/android/launcher3/tapl/OptionsPopupMenuItem.java
index 461610d..c2f701b 100644
--- a/tests/tapl/com/android/launcher3/tapl/OptionsPopupMenuItem.java
+++ b/tests/tapl/com/android/launcher3/tapl/OptionsPopupMenuItem.java
@@ -38,7 +38,7 @@
         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
             LauncherInstrumentation.log("OptionsPopupMenuItem before click "
                     + mObject.getVisibleCenter() + " in " + mObject.getVisibleBounds());
-            mObject.click();
+            mLauncher.clickLauncherObject(mObject);
             mLauncher.assertTrue(
                     "App didn't start: " + By.pkg(expectedPackageName),
                     mLauncher.getDevice().wait(Until.hasObject(By.pkg(expectedPackageName)),
diff --git a/tests/tapl/com/android/launcher3/tapl/Overview.java b/tests/tapl/com/android/launcher3/tapl/Overview.java
index 6622c6e..4d673a8c 100644
--- a/tests/tapl/com/android/launcher3/tapl/Overview.java
+++ b/tests/tapl/com/android/launcher3/tapl/Overview.java
@@ -60,7 +60,8 @@
                     mLauncher.getDevice().getDisplayWidth() / 2,
                     0,
                     12,
-                    ALL_APPS_STATE_ORDINAL);
+                    ALL_APPS_STATE_ORDINAL,
+                    LauncherInstrumentation.GestureScope.INSIDE);
 
             try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
                     "swiped all way up from overview")) {
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
index 0d93cbc..b21b242 100644
--- a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
@@ -53,7 +53,8 @@
             final Rect taskBounds = mTask.getVisibleBounds();
             final int centerX = taskBounds.centerX();
             final int centerY = taskBounds.centerY();
-            mLauncher.linearGesture(centerX, centerY, centerX, 0, 10, false);
+            mLauncher.linearGesture(centerX, centerY, centerX, 0, 10, false,
+                    LauncherInstrumentation.GestureScope.INSIDE);
             mLauncher.waitForIdle();
         }
     }
@@ -67,7 +68,7 @@
             try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
                     "clicking an overview task")) {
                 mLauncher.executeAndWaitForEvent(
-                        () -> mTask.click(),
+                        () -> mLauncher.clickLauncherObject(mTask),
                         event -> event.getEventType() == TYPE_WINDOW_STATE_CHANGED,
                         () -> "Launching task didn't open a new window: "
                                 + mTask.getParent().getContentDescription());
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index 1d2c821..a0d5443 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -38,11 +38,21 @@
 import com.android.launcher3.ResourceUtils;
 import com.android.launcher3.testing.TestProtocol;
 
+import java.util.regex.Pattern;
+
 /**
  * Operations on the workspace screen.
  */
 public final class Workspace extends Home {
     private static final int FLING_STEPS = 10;
+
+    static final Pattern EVENT_CTRL_W_DOWN = Pattern.compile(
+            "Key event: KeyEvent.*?action=ACTION_DOWN.*?keyCode=KEYCODE_W"
+                    + ".*?metaState=META_CTRL_ON");
+    static final Pattern EVENT_CTRL_W_UP = Pattern.compile(
+            "Key event: KeyEvent.*?action=ACTION_UP.*?keyCode=KEYCODE_W"
+                    + ".*?metaState=META_CTRL_ON");
+
     private final UiObject2 mHotseat;
 
     Workspace(LauncherInstrumentation launcher) {
@@ -108,7 +118,7 @@
                     0,
                     startY - swipeHeight - mLauncher.getTouchSlop(),
                     12,
-                    ALL_APPS_STATE_ORDINAL);
+                    ALL_APPS_STATE_ORDINAL, LauncherInstrumentation.GestureScope.INSIDE);
 
             try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
                     "swiped to all apps")) {
@@ -195,17 +205,19 @@
         launcher.runToState(
                 () -> {
                     launcher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN,
-                            launchableCenter);
+                            launchableCenter, LauncherInstrumentation.GestureScope.INSIDE);
                     LauncherInstrumentation.log("dragIconToWorkspace: sent down");
                     launcher.waitForLauncherObject(longPressIndicator);
                     LauncherInstrumentation.log("dragIconToWorkspace: indicator");
-                    launcher.movePointer(launchableCenter, dest, 10, downTime, true);
+                    launcher.movePointer(launchableCenter, dest, 10, downTime, true,
+                            LauncherInstrumentation.GestureScope.INSIDE);
                 },
                 SPRING_LOADED_STATE_ORDINAL);
         LauncherInstrumentation.log("dragIconToWorkspace: moved pointer");
         launcher.runToState(
                 () -> launcher.sendPointer(
-                        downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, dest),
+                        downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, dest,
+                        LauncherInstrumentation.GestureScope.INSIDE),
                 NORMAL_STATE_ORDINAL);
         LauncherInstrumentation.log("dragIconToWorkspace: end");
         launcher.waitUntilGone("drop_target_bar");
@@ -248,6 +260,8 @@
     public Widgets openAllWidgets() {
         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
             verifyActiveContainer();
+            mLauncher.expectEvent(EVENT_CTRL_W_DOWN);
+            mLauncher.expectEvent(EVENT_CTRL_W_UP);
             mLauncher.getDevice().pressKeyCode(KeyEvent.KEYCODE_W, KeyEvent.META_CTRL_ON);
             try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer("pressed Ctrl+W")) {
                 return new Widgets(mLauncher);