Merge changes from topic "options-popup-dialog-type" into tm-mainline-prod

* changes:
  [automerge] Add separate AFV type for options popup dialog. 2p: 7ef4fe42cb
  Add separate AFV type for options popup dialog.
diff --git a/Android.bp b/Android.bp
index 5a153a7..b3027bc 100644
--- a/Android.bp
+++ b/Android.bp
@@ -31,6 +31,7 @@
         "androidx.test.uiautomator_uiautomator",
         "androidx.preference_preference",
         "SystemUISharedLib",
+        "SystemUIAnimationLib",
     ],
     srcs: [
         "tests/tapl/**/*.java",
@@ -196,6 +197,7 @@
         "lottie",
         "SystemUISharedLib",
         "SystemUI-statsd",
+        "SystemUIAnimationLib",
     ],
     manifest: "quickstep/AndroidManifest.xml",
     min_sdk_version: "current",
@@ -304,6 +306,7 @@
         "SystemUISharedLib",
         "Launcher3CommonDepsLib",
         "QuickstepResLib",
+        "SystemUIAnimationLib",
     ],
     manifest: "quickstep/AndroidManifest.xml",
     platform_apis: true,
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index ebe6a04..eed67b6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -29,13 +29,16 @@
 
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.BaseQuickstepLauncher;
+import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.LauncherState;
+import com.android.launcher3.Utilities;
 import com.android.launcher3.statemanager.StateManager;
 import com.android.launcher3.util.MultiValueAlpha;
 import com.android.quickstep.AnimatedFloat;
 import com.android.quickstep.RecentsAnimationCallbacks;
 import com.android.quickstep.RecentsAnimationController;
 import com.android.quickstep.views.RecentsView;
+import com.android.systemui.animation.ViewRootSync;
 import com.android.systemui.shared.recents.model.ThumbnailData;
 
 import java.util.HashMap;
@@ -76,6 +79,9 @@
 
     private boolean mShouldDelayLauncherStateAnim;
 
+    // We skip any view synchronizations during init/destroy.
+    private boolean mCanSyncViews;
+
     private final StateManager.StateListener<LauncherState> mStateListener =
             new StateManager.StateListener<LauncherState>() {
 
@@ -102,6 +108,8 @@
             };
 
     public void init(TaskbarControllers controllers, BaseQuickstepLauncher launcher) {
+        mCanSyncViews = false;
+
         mControllers = controllers;
         mLauncher = launcher;
 
@@ -121,9 +129,13 @@
         updateStateForFlag(FLAG_RESUMED, launcher.hasBeenResumed());
         mLauncherState = launcher.getStateManager().getState();
         applyState(0);
+
+        mCanSyncViews = true;
     }
 
     public void onDestroy() {
+        mCanSyncViews = false;
+
         mIconAlignmentForResumedState.finishAnimation();
         mIconAlignmentForGestureState.finishAnimation();
         mIconAlignmentForLauncherState.finishAnimation();
@@ -131,6 +143,8 @@
         mIconAlphaForHome.setConsumer(null);
         mLauncher.getHotseat().setIconsAlpha(1f);
         mLauncher.getStateManager().removeStateListener(mStateListener);
+
+        mCanSyncViews = true;
     }
 
     public Animator createAnimToLauncher(@NonNull LauncherState toState,
@@ -380,6 +394,27 @@
             return;
         }
         float alignment = alignmentSupplier.get();
+        float currentValue = mIconAlphaForHome.getValue();
+        boolean taskbarWillBeVisible = alignment < 1;
+        boolean firstFrameVisChanged = (taskbarWillBeVisible && Float.compare(currentValue, 1) != 0)
+                || (!taskbarWillBeVisible && Float.compare(currentValue, 0) != 0);
+
+        // Sync the first frame where we swap taskbar and hotseat.
+        if (firstFrameVisChanged && mCanSyncViews && !Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+            DeviceProfile dp = mLauncher.getDeviceProfile();
+
+            // Do all the heavy work before the sync.
+            mControllers.taskbarViewController.createIconAlignmentControllerIfNotExists(dp);
+
+            ViewRootSync.synchronizeNextDraw(mLauncher.getHotseat(),
+                    mControllers.taskbarActivityContext.getDragLayer(),
+                    () -> updateIconAlignment(alignment));
+        } else {
+            updateIconAlignment(alignment);
+        }
+    }
+
+    private void updateIconAlignment(float alignment) {
         mControllers.taskbarViewController.setLauncherIconAlignment(
                 alignment, mLauncher.getDeviceProfile());
 
@@ -409,7 +444,8 @@
 
         @Override
         public void onRecentsAnimationCanceled(HashMap<Integer, ThumbnailData> thumbnailDatas) {
-            endGestureStateOverride(true);
+            boolean isInOverview = mLauncher.isInState(LauncherState.OVERVIEW);
+            endGestureStateOverride(!isInOverview);
         }
 
         @Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index f5c382d..e1ce898 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -200,15 +200,23 @@
     }
 
     /**
+     * Creates the icon alignment controller if it does not already exist.
+     * @param launcherDp Launcher device profile.
+     */
+    public void createIconAlignmentControllerIfNotExists(DeviceProfile launcherDp) {
+        if (mIconAlignControllerLazy == null) {
+            mIconAlignControllerLazy = createIconAlignmentController(launcherDp);
+        }
+    }
+
+    /**
      * Sets the taskbar icon alignment relative to Launcher hotseat icons
      * @param alignmentRatio [0, 1]
      *                       0 => not aligned
      *                       1 => fully aligned
      */
     public void setLauncherIconAlignment(float alignmentRatio, DeviceProfile launcherDp) {
-        if (mIconAlignControllerLazy == null) {
-            mIconAlignControllerLazy = createIconAlignmentController(launcherDp);
-        }
+        createIconAlignmentControllerIfNotExists(launcherDp);
         mIconAlignControllerLazy.setPlayFraction(alignmentRatio);
         if (alignmentRatio <= 0 || alignmentRatio >= 1) {
             // Cleanup lazy controller so that it is created again in next animation
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 9f35507..6e80402 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -583,7 +583,7 @@
         } else {
             runningTasks = new ActivityManager.RunningTaskInfo[]{mGestureState.getRunningTask()};
         }
-        mRecentsView.onGestureAnimationStart(runningTasks);
+        mRecentsView.onGestureAnimationStart(runningTasks, mDeviceState.getRotationTouchHelper());
     }
 
     private void launcherFrameDrawn() {
diff --git a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
index ed81d7e..9828467 100644
--- a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
@@ -212,7 +212,8 @@
         if (mRunningOverHome) {
             if (DisplayController.getNavigationMode(mContext).hasGestures) {
                 mRecentsView.onGestureAnimationStartOnHome(
-                        new ActivityManager.RunningTaskInfo[]{mGestureState.getRunningTask()});
+                        new ActivityManager.RunningTaskInfo[]{mGestureState.getRunningTask()},
+                        mDeviceState.getRotationTouchHelper());
             }
         } else {
             super.notifyGestureAnimationStartToRecents();
@@ -262,15 +263,13 @@
             } else {
                 mHomeAlpha = new AnimatedFloat(this::updateHomeAlpha);
                 mHomeAlpha.value = 0;
-                runActionOnRemoteHandles(remoteTargetHandle ->
-                        remoteTargetHandle.getTransformParams().setHomeBuilderProxy(
-                                FallbackHomeAnimationFactory.this
-                                        ::updateHomeActivityTransformDuringHomeAnim));
+                mHomeAlphaParams.setHomeBuilderProxy(
+                        this::updateHomeActivityTransformDuringHomeAnim);
             }
 
             mRecentsAlpha.value = 1;
             runActionOnRemoteHandles(remoteTargetHandle ->
-                    remoteTargetHandle.getTransformParams().setHomeBuilderProxy(
+                    remoteTargetHandle.getTransformParams().setBaseBuilderProxy(
                             FallbackHomeAnimationFactory.this
                                     ::updateRecentsActivityTransformDuringHomeAnim));
         }
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
index e6f73dc..eda2c5a 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -42,6 +42,7 @@
 import com.android.quickstep.FallbackActivityInterface;
 import com.android.quickstep.GestureState;
 import com.android.quickstep.RecentsActivity;
+import com.android.quickstep.RotationTouchHelper;
 import com.android.quickstep.util.GroupTask;
 import com.android.quickstep.util.SplitSelectStateController;
 import com.android.quickstep.util.TaskViewSimulator;
@@ -86,11 +87,12 @@
      * to the home task. This allows us to handle quick-switch similarly to a quick-switching
      * from a foreground task.
      */
-    public void onGestureAnimationStartOnHome(RunningTaskInfo[] homeTaskInfo) {
+    public void onGestureAnimationStartOnHome(RunningTaskInfo[] homeTaskInfo,
+            RotationTouchHelper rotationTouchHelper) {
         // TODO(b/195607777) General fallback love, but this might be correct
         //  Home task should be defined as the front-most task info I think?
         mHomeTaskInfo = homeTaskInfo[0];
-        onGestureAnimationStart(homeTaskInfo);
+        onGestureAnimationStart(homeTaskInfo, rotationTouchHelper);
     }
 
     /**
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 25f8f01..52aad27 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -154,6 +154,7 @@
 import com.android.quickstep.RemoteAnimationTargets;
 import com.android.quickstep.RemoteTargetGluer;
 import com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle;
+import com.android.quickstep.RotationTouchHelper;
 import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.TaskOverlayFactory;
 import com.android.quickstep.TaskThumbnailCache;
@@ -2084,11 +2085,13 @@
     /**
      * Called when a gesture from an app is starting.
      */
-    public void onGestureAnimationStart(RunningTaskInfo[] runningTaskInfo) {
+    public void onGestureAnimationStart(RunningTaskInfo[] runningTaskInfo,
+            RotationTouchHelper rotationTouchHelper) {
         mGestureActive = true;
         // This needs to be called before the other states are set since it can create the task view
         if (mOrientationState.setGestureActive(true)) {
-            updateOrientationHandler();
+            setLayoutRotation(rotationTouchHelper.getCurrentActiveRotation(),
+                    rotationTouchHelper.getDisplayRotation());
         }
 
         showCurrentTask(runningTaskInfo);
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 399cd10..4d38822 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -32,7 +32,6 @@
 
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
-import com.android.launcher3.tapl.HomeAllApps;
 import com.android.launcher3.tapl.LaunchedAppState;
 import com.android.launcher3.tapl.LauncherInstrumentation.NavigationModel;
 import com.android.launcher3.tapl.Overview;
@@ -45,7 +44,6 @@
 
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -295,26 +293,16 @@
         getAndAssertLaunchedApp();
     }
 
-    // TODO(b/204830798): test with all navigation modes(add @NavigationModeSwitch annotation)
-    //  after the bug resolved.
-    @Ignore("b/205027405")
     @Test
     @PortraitLandscape
-    @ScreenRecord
+    @NavigationModeSwitch
     public void testPressBack() throws Exception {
         mLauncher.getWorkspace().switchToAllApps();
         mLauncher.pressBack();
         mLauncher.getWorkspace();
         waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL);
 
-        HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps();
-        allApps.freeze();
-        try {
-            allApps.getAppIcon(APP_NAME).dragToWorkspace(false, false);
-        } finally {
-            allApps.unfreeze();
-        }
-        mLauncher.getWorkspace().getWorkspaceAppIcon(APP_NAME).launch(getAppPackageName());
+        startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
         mLauncher.pressBack();
         mLauncher.getWorkspace();
         waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL);
diff --git a/res/layout/all_apps_tabs.xml b/res/layout/all_apps_tabs.xml
index cf68f51..6dcae21 100644
--- a/res/layout/all_apps_tabs.xml
+++ b/res/layout/all_apps_tabs.xml
@@ -25,7 +25,7 @@
     android:clipChildren="true"
     android:clipToPadding="false"
     android:descendantFocusability="afterDescendants"
-    android:paddingTop="@dimen/all_apps_header_top_padding"
+    android:paddingTop="@dimen/all_apps_paged_view_top_padding"
     launcher:pageIndicator="@+id/tabs" >
 
     <include layout="@layout/all_apps_rv_layout" />
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 281f0e7..9a41070 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -115,7 +115,9 @@
     <dimen name="all_apps_tabs_indicator_height">2dp</dimen>
     <dimen name="all_apps_header_top_margin">33dp</dimen>
     <dimen name="all_apps_header_top_padding">36dp</dimen>
-    <dimen name="all_apps_header_bottom_padding">6dp</dimen>
+    <dimen name="all_apps_header_bottom_padding">14dp</dimen>
+    <dimen name="all_apps_header_top_adjustment">6dp</dimen>
+    <dimen name="all_apps_header_bottom_adjustment">4dp</dimen>
     <dimen name="all_apps_work_profile_tab_footer_top_padding">16dp</dimen>
     <dimen name="all_apps_work_profile_tab_footer_bottom_padding">20dp</dimen>
     <dimen name="all_apps_tabs_button_horizontal_padding">4dp</dimen>
@@ -126,6 +128,7 @@
     <dimen name="all_apps_tip_bottom_margin">8dp</dimen>
     <dimen name="all_apps_height_extra">6dp</dimen>
     <dimen name="all_apps_bottom_sheet_horizontal_padding">0dp</dimen>
+    <dimen name="all_apps_paged_view_top_padding">40dp</dimen>
 
     <!-- The size of corner radius of the arrow in the arrow toast. -->
     <dimen name="arrow_toast_corner_radius">2dp</dimen>
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 6e86c43..847a9bf 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1189,7 +1189,7 @@
             mOverlayManager.onActivityResumed(this);
         }
 
-        AbstractFloatingView.closeOpenViews(this, false, TYPE_ALL & ~TYPE_REBIND_SAFE);
+        AbstractFloatingView.closeAllOpenViewsExcept(this, false, TYPE_REBIND_SAFE);
         TraceHelper.INSTANCE.endSection(traceToken);
     }
 
diff --git a/src/com/android/launcher3/allapps/FloatingHeaderView.java b/src/com/android/launcher3/allapps/FloatingHeaderView.java
index ed8761e..72f14a8 100644
--- a/src/com/android/launcher3/allapps/FloatingHeaderView.java
+++ b/src/com/android/launcher3/allapps/FloatingHeaderView.java
@@ -82,6 +82,9 @@
     protected final Map<AllAppsRow, PluginHeaderRow> mPluginRows = new ArrayMap<>();
 
     private final int mHeaderTopPadding;
+    // These two values are necessary to ensure that the header protection is drawn correctly.
+    private final int mHeaderTopAdjustment;
+    private final int mHeaderBottomAdjustment;
     private final boolean mHeaderProtectionSupported;
 
     protected ViewGroup mTabLayout;
@@ -118,6 +121,10 @@
         super(context, attrs);
         mHeaderTopPadding = context.getResources()
                 .getDimensionPixelSize(R.dimen.all_apps_header_top_padding);
+        mHeaderTopAdjustment = context.getResources()
+                .getDimensionPixelSize(R.dimen.all_apps_header_top_adjustment);
+        mHeaderBottomAdjustment = context.getResources()
+                .getDimensionPixelSize(R.dimen.all_apps_header_bottom_adjustment);
         mHeaderProtectionSupported = context.getResources().getBoolean(
                 R.bool.config_header_protection_supported)
                 // TODO(b/208599118) Support header protection for bottom sheet.
@@ -255,6 +262,9 @@
         for (FloatingHeaderRow row : mAllRows) {
             mMaxTranslation += row.getExpectedHeight();
         }
+        if (!mTabsHidden) {
+            mMaxTranslation += mHeaderBottomAdjustment;
+        }
     }
 
     public void setMainActive(boolean active) {
@@ -317,9 +327,9 @@
 
         mTabLayout.setTranslationY(mTranslationY);
 
-        int clipHeight = mHeaderTopPadding - getPaddingBottom();
-        mRVClip.top = mTabsHidden ? clipHeight : 0;
-        mHeaderClip.top = clipHeight;
+        int clipTop = mHeaderTopPadding - mHeaderTopAdjustment;
+        mRVClip.top = mTabsHidden ? clipTop : 0;
+        mHeaderClip.top = clipTop;
         // clipping on a draw might cause additional redraw
         setClipBounds(mHeaderClip);
         mMainRV.setClipBounds(mRVClip);
@@ -447,5 +457,3 @@
         return Math.max(getHeight() - getPaddingTop() + mTranslationY, 0);
     }
 }
-
-
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index 73e9823..f0bef24 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -24,6 +24,7 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import android.content.Intent;
 import android.graphics.Point;
 
 import androidx.test.filters.LargeTest;
@@ -50,7 +51,6 @@
 import com.android.launcher3.widget.picker.WidgetsRecyclerView;
 
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -391,7 +391,6 @@
         folder.close();
     }
 
-    @Ignore("b/205027405")
     @Test
     @PortraitLandscape
     public void testPressBack() throws Exception {
@@ -400,14 +399,7 @@
         mLauncher.getWorkspace();
         waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL);
 
-        HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps();
-        allApps.freeze();
-        try {
-            allApps.getAppIcon(APP_NAME).dragToWorkspace(false, false);
-        } finally {
-            allApps.unfreeze();
-        }
-        mLauncher.getWorkspace().getWorkspaceAppIcon(APP_NAME).launch(getAppPackageName());
+        startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
         mLauncher.pressBack();
         mLauncher.getWorkspace();
         waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL);
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 84ef149..950e72c 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -113,6 +113,7 @@
 
     static final Pattern EVENT_TOUCH_DOWN_TIS = getTouchEventPatternTIS("ACTION_DOWN");
     static final Pattern EVENT_TOUCH_UP_TIS = getTouchEventPatternTIS("ACTION_UP");
+    static final Pattern EVENT_TOUCH_CANCEL_TIS = getTouchEventPatternTIS("ACTION_CANCEL");
 
     static final Pattern EVENT_KEY_BACK_DOWN = getKeyEventPattern("ACTION_DOWN", "KEYCODE_BACK");
     static final Pattern EVENT_KEY_BACK_UP = getKeyEventPattern("ACTION_UP", "KEYCODE_BACK");
@@ -135,6 +136,8 @@
     public enum GestureScope {
         OUTSIDE_WITHOUT_PILFER, OUTSIDE_WITH_PILFER, INSIDE, INSIDE_TO_OUTSIDE,
         INSIDE_TO_OUTSIDE_WITHOUT_PILFER,
+        INSIDE_TO_OUTSIDE_WITH_KEYCODE, // For gestures that will trigger a keycode from TIS.
+        OUTSIDE_WITH_KEYCODE,
     }
 
     // Base class for launcher containers.
@@ -967,9 +970,11 @@
             if (getNavigationModel() == NavigationModel.ZERO_BUTTON) {
                 final Point displaySize = getRealDisplaySize();
                 final GestureScope gestureScope =
-                        launcherVisible ? GestureScope.INSIDE_TO_OUTSIDE_WITHOUT_PILFER
-                                : GestureScope.OUTSIDE_WITHOUT_PILFER;
-                linearGesture(0, displaySize.y / 2, displaySize.x / 2, displaySize.y / 2,
+                        launcherVisible ? GestureScope.INSIDE_TO_OUTSIDE_WITH_KEYCODE
+                                : GestureScope.OUTSIDE_WITH_KEYCODE;
+                // TODO(b/225505986): change startY and endY back to displaySize.y / 2 once the
+                //  issue is solved.
+                linearGesture(0, displaySize.y / 4, displaySize.x / 2, displaySize.y / 4,
                         10, false, gestureScope);
             } else {
                 waitForNavigationUiObject("back").click();
@@ -1505,7 +1510,8 @@
         switch (action) {
             case MotionEvent.ACTION_DOWN:
                 if (gestureScope != GestureScope.OUTSIDE_WITH_PILFER
-                        && gestureScope != GestureScope.OUTSIDE_WITHOUT_PILFER) {
+                        && gestureScope != GestureScope.OUTSIDE_WITHOUT_PILFER
+                        && gestureScope != GestureScope.OUTSIDE_WITH_KEYCODE) {
                     expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_TOUCH_DOWN);
                 }
                 if (notLauncher3 && getNavigationModel() != NavigationModel.THREE_BUTTON) {
@@ -1520,14 +1526,18 @@
                     expectEvent(TestProtocol.SEQUENCE_PILFER, EVENT_PILFER_POINTERS);
                 }
                 if (gestureScope != GestureScope.OUTSIDE_WITH_PILFER
-                        && gestureScope != GestureScope.OUTSIDE_WITHOUT_PILFER) {
+                        && gestureScope != GestureScope.OUTSIDE_WITHOUT_PILFER
+                        && gestureScope != GestureScope.OUTSIDE_WITH_KEYCODE) {
                     expectEvent(TestProtocol.SEQUENCE_MAIN,
                             gestureScope == GestureScope.INSIDE
                                     || gestureScope == GestureScope.OUTSIDE_WITHOUT_PILFER
                                     ? EVENT_TOUCH_UP : EVENT_TOUCH_CANCEL);
                 }
                 if (notLauncher3 && getNavigationModel() != NavigationModel.THREE_BUTTON) {
-                    expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_UP_TIS);
+                    expectEvent(TestProtocol.SEQUENCE_TIS,
+                            gestureScope == GestureScope.INSIDE_TO_OUTSIDE_WITH_KEYCODE
+                                    || gestureScope == GestureScope.OUTSIDE_WITH_KEYCODE
+                                    ? EVENT_TOUCH_CANCEL_TIS : EVENT_TOUCH_UP_TIS);
                 }
                 break;
         }