Merge "Increasing string size limit" into ub-launcher3-rvc-dev
diff --git a/Android.mk b/Android.mk
index 352885b..9cfcf17 100644
--- a/Android.mk
+++ b/Android.mk
@@ -32,8 +32,7 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     LauncherPluginLib \
-    launcher_log_protos_lite \
-    uieventloggerlib
+    launcher_log_protos_lite
 
 LOCAL_SRC_FILES := \
     $(call all-proto-files-under, protos) \
@@ -131,10 +130,8 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     SystemUISharedLib \
-    SystemUI-statsd \
     launcherprotosnano \
     launcher_log_protos_lite
-
 ifneq (,$(wildcard frameworks/base))
   LOCAL_PRIVATE_PLATFORM_APIS := true
 else
@@ -205,10 +202,8 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     SystemUISharedLib \
-    SystemUI-statsd \
     launcherprotosnano \
     launcher_log_protos_lite
-
 ifneq (,$(wildcard frameworks/base))
   LOCAL_PRIVATE_PLATFORM_APIS := true
 else
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
index 7aee308..a18f7ba 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
@@ -30,8 +30,8 @@
 import static com.android.launcher3.anim.Interpolators.LINEAR;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_DISMISS_SWIPE_UP;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_SWIPE_DOWN;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.TASK_DISMISS_SWIPE_UP;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.TASK_LAUNCH_SWIPE_DOWN;
 import static com.android.launcher3.statehandlers.DepthController.DEPTH;
 import static com.android.launcher3.uioverrides.touchcontrollers.TaskViewTouchController.SUCCESS_TRANSITION_PROGRESS;
 import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.TAP;
@@ -1280,8 +1280,7 @@
             ComponentKey compKey = TaskUtils.getLaunchComponentKeyForTask(taskView.getTask().key);
             mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(
                     endState.logAction, Direction.UP, index, compKey);
-            mActivity.getStatsLogManager().log(LAUNCHER_TASK_DISMISS_SWIPE_UP,
-                    taskView.buildProto());
+            mActivity.getStatsLogManager().log(TASK_DISMISS_SWIPE_UP, taskView.buildProto());
         }
     }
 
@@ -1831,8 +1830,7 @@
                     mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(
                             endState.logAction, Direction.DOWN, indexOfChild(tv),
                             TaskUtils.getLaunchComponentKeyForTask(task.key));
-                    mActivity.getStatsLogManager().log(LAUNCHER_TASK_LAUNCH_SWIPE_DOWN,
-                            tv.buildProto()
+                    mActivity.getStatsLogManager().log(TASK_LAUNCH_SWIPE_DOWN, tv.buildProto()
                     );
                 }
             } else {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
index 171c91d..470b720 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
@@ -29,7 +29,7 @@
 import static com.android.launcher3.anim.Interpolators.LINEAR;
 import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.TASK_LAUNCH_TAP;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -209,7 +209,7 @@
             mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(
                     Touch.TAP, Direction.NONE, getRecentsView().indexOfChild(this),
                     TaskUtils.getLaunchComponentKeyForTask(getTask().key));
-            mActivity.getStatsLogManager().log(LAUNCHER_TASK_LAUNCH_TAP, buildProto());
+            mActivity.getStatsLogManager().log(TASK_LAUNCH_TAP, buildProto());
         });
         mCornerRadius = TaskCornerRadius.get(context);
         mWindowCornerRadius = QuickStepContract.getWindowCornerRadius(context.getResources());
diff --git a/quickstep/res/drawable-v28/back_gesture_tutorial_action_button_background.xml b/quickstep/res/drawable-v28/gesture_tutorial_action_button_background.xml
similarity index 91%
rename from quickstep/res/drawable-v28/back_gesture_tutorial_action_button_background.xml
rename to quickstep/res/drawable-v28/gesture_tutorial_action_button_background.xml
index cd30ef7..57423c2 100644
--- a/quickstep/res/drawable-v28/back_gesture_tutorial_action_button_background.xml
+++ b/quickstep/res/drawable-v28/gesture_tutorial_action_button_background.xml
@@ -16,5 +16,5 @@
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle">
     <corners android:radius="?android:attr/dialogCornerRadius"/>
-    <solid android:color="@color/back_gesture_tutorial_primary_color"/>
+    <solid android:color="@color/gesture_tutorial_primary_color"/>
 </shape>
\ No newline at end of file
diff --git a/quickstep/res/drawable/back_gesture_tutorial_action_button_background.xml b/quickstep/res/drawable/gesture_tutorial_action_button_background.xml
similarity index 91%
rename from quickstep/res/drawable/back_gesture_tutorial_action_button_background.xml
rename to quickstep/res/drawable/gesture_tutorial_action_button_background.xml
index d7b9102..3f3b288 100644
--- a/quickstep/res/drawable/back_gesture_tutorial_action_button_background.xml
+++ b/quickstep/res/drawable/gesture_tutorial_action_button_background.xml
@@ -16,5 +16,5 @@
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle">
     <corners android:radius="@dimen/default_dialog_corner_radius"/>
-    <solid android:color="@color/back_gesture_tutorial_primary_color"/>
+    <solid android:color="@color/gesture_tutorial_primary_color"/>
 </shape>
\ No newline at end of file
diff --git a/quickstep/res/drawable/back_gesture_tutorial_close_button.xml b/quickstep/res/drawable/gesture_tutorial_close_button.xml
similarity index 100%
rename from quickstep/res/drawable/back_gesture_tutorial_close_button.xml
rename to quickstep/res/drawable/gesture_tutorial_close_button.xml
diff --git a/quickstep/res/layout/back_gesture_tutorial_activity.xml b/quickstep/res/layout/gesture_tutorial_activity.xml
similarity index 92%
rename from quickstep/res/layout/back_gesture_tutorial_activity.xml
rename to quickstep/res/layout/gesture_tutorial_activity.xml
index e894e89..4dc8913 100644
--- a/quickstep/res/layout/back_gesture_tutorial_activity.xml
+++ b/quickstep/res/layout/gesture_tutorial_activity.xml
@@ -14,6 +14,6 @@
     limitations under the License.
 -->
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/back_gesture_tutorial_fragment_container"
+    android:id="@+id/gesture_tutorial_fragment_container"
     android:layout_width="match_parent"
     android:layout_height="match_parent"/>
\ No newline at end of file
diff --git a/quickstep/res/layout/back_gesture_tutorial_fragment.xml b/quickstep/res/layout/gesture_tutorial_fragment.xml
similarity index 71%
rename from quickstep/res/layout/back_gesture_tutorial_fragment.xml
rename to quickstep/res/layout/gesture_tutorial_fragment.xml
index d8c25bd..0bc062a 100644
--- a/quickstep/res/layout/back_gesture_tutorial_fragment.xml
+++ b/quickstep/res/layout/gesture_tutorial_fragment.xml
@@ -16,27 +16,27 @@
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:background="@color/back_gesture_tutorial_background_color">
+    android:background="@color/gesture_tutorial_background_color">
 
     <ImageView
-        android:id="@+id/back_gesture_tutorial_fragment_hand_coaching"
+        android:id="@+id/gesture_tutorial_fragment_hand_coaching"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:scaleType="centerCrop"/>
 
     <ImageButton
-        android:id="@+id/back_gesture_tutorial_fragment_close_button"
+        android:id="@+id/gesture_tutorial_fragment_close_button"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:padding="18dp"
         android:layout_marginTop="30dp"
         android:layout_marginStart="4dp"
-        android:layout_alignParentLeft="true"
+        android:layout_alignParentStart="true"
         android:layout_alignParentTop="true"
         android:background="@android:color/transparent"
-        android:accessibilityTraversalAfter="@id/back_gesture_tutorial_fragment_titles_container"
-        android:contentDescription="@string/back_gesture_tutorial_close_button_content_description"
-        android:src="@drawable/back_gesture_tutorial_close_button"/>
+        android:accessibilityTraversalAfter="@id/gesture_tutorial_fragment_titles_container"
+        android:contentDescription="@string/gesture_tutorial_close_button_content_description"
+        android:src="@drawable/gesture_tutorial_close_button"/>
 
     <LinearLayout
         android:layout_width="match_parent"
@@ -45,29 +45,29 @@
         android:orientation="vertical">
 
         <LinearLayout
-            android:id="@+id/back_gesture_tutorial_fragment_titles_container"
+            android:id="@+id/gesture_tutorial_fragment_titles_container"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="vertical"
             android:focusable="true">
 
             <TextView
-                android:id="@+id/back_gesture_tutorial_fragment_title_view"
+                android:id="@+id/gesture_tutorial_fragment_title_view"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center_horizontal"
-                android:layout_marginStart="@dimen/back_gesture_tutorial_title_margin_start_end"
-                android:layout_marginEnd="@dimen/back_gesture_tutorial_title_margin_start_end"
+                android:layout_marginStart="@dimen/gesture_tutorial_title_margin_start_end"
+                android:layout_marginEnd="@dimen/gesture_tutorial_title_margin_start_end"
                 style="@style/TextAppearance.BackGestureTutorial.Title"/>
 
             <TextView
-                android:id="@+id/back_gesture_tutorial_fragment_subtitle_view"
+                android:id="@+id/gesture_tutorial_fragment_subtitle_view"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center_horizontal"
                 android:layout_marginTop="10dp"
-                android:layout_marginStart="@dimen/back_gesture_tutorial_subtitle_margin_start_end"
-                android:layout_marginEnd="@dimen/back_gesture_tutorial_subtitle_margin_start_end"
+                android:layout_marginStart="@dimen/gesture_tutorial_subtitle_margin_start_end"
+                android:layout_marginEnd="@dimen/gesture_tutorial_subtitle_margin_start_end"
                 style="@style/TextAppearance.BackGestureTutorial.Subtitle"/>
 
         </LinearLayout>
@@ -91,21 +91,21 @@
             android:layout_gravity="center_horizontal">
 
             <Button
-                android:id="@+id/back_gesture_tutorial_fragment_action_button"
+                android:id="@+id/gesture_tutorial_fragment_action_button"
                 android:layout_width="142dp"
                 android:layout_height="49dp"
-                android:layout_marginEnd="@dimen/back_gesture_tutorial_button_margin_start_end"
+                android:layout_marginEnd="@dimen/gesture_tutorial_button_margin_start_end"
                 android:layout_alignParentEnd="true"
                 android:stateListAnimator="@null"
-                android:background="@drawable/back_gesture_tutorial_action_button_background"
+                android:background="@drawable/gesture_tutorial_action_button_background"
                 android:foreground="?android:attr/selectableItemBackgroundBorderless"
                 style="@style/TextAppearance.BackGestureTutorial.ButtonLabel"/>
 
             <Button
-                android:id="@+id/back_gesture_tutorial_fragment_action_text_button"
+                android:id="@+id/gesture_tutorial_fragment_action_text_button"
                 android:layout_width="142dp"
                 android:layout_height="49dp"
-                android:layout_marginStart="@dimen/back_gesture_tutorial_button_margin_start_end"
+                android:layout_marginStart="@dimen/gesture_tutorial_button_margin_start_end"
                 android:layout_alignParentStart="true"
                 android:stateListAnimator="@null"
                 android:background="@null"
@@ -113,7 +113,5 @@
                 style="@style/TextAppearance.BackGestureTutorial.TextButtonLabel"/>
 
         </RelativeLayout>
-
     </LinearLayout>
-
 </RelativeLayout>
\ No newline at end of file
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 9a61165..18dc19c 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -81,7 +81,7 @@
     <dimen name="gestures_overscroll_fling_threshold">40dp</dimen>
 
     <!-- Tips Gesture Tutorial -->
-    <dimen name="back_gesture_tutorial_title_margin_start_end">40dp</dimen>
-    <dimen name="back_gesture_tutorial_subtitle_margin_start_end">16dp</dimen>
-    <dimen name="back_gesture_tutorial_button_margin_start_end">18dp</dimen>
+    <dimen name="gesture_tutorial_title_margin_start_end">40dp</dimen>
+    <dimen name="gesture_tutorial_subtitle_margin_start_end">16dp</dimen>
+    <dimen name="gesture_tutorial_button_margin_start_end">18dp</dimen>
 </resources>
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index c6b1477..d7c976d 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -61,7 +61,7 @@
     <string name="all_apps_prediction_tip">Your predicted apps</string>
 
     <!-- Content description for a close button. [CHAR LIMIT=NONE] -->
-    <string  name="back_gesture_tutorial_close_button_content_description" translatable="false">Close</string>
+    <string  name="gesture_tutorial_close_button_content_description" translatable="false">Close</string>
 
 
     <!-- Hotseat migration notification title -->
@@ -110,9 +110,9 @@
     <string name="back_gesture_tutorial_confirm_subtitle" translatable="false">To change the sensitivity of the back gesture, go to Settings</string>
 
     <!-- Button text shown on a button on the confirm screen. [CHAR LIMIT=14] -->
-    <string name="back_gesture_tutorial_action_button_label" translatable="false">Done</string>
+    <string name="gesture_tutorial_action_button_label" translatable="false">Done</string>
     <!-- Button text shown on a text button on the confirm screen. [CHAR LIMIT=14] -->
-    <string name="back_gesture_tutorial_action_text_button_label" translatable="false">Settings</string>
+    <string name="gesture_tutorial_action_text_button_label" translatable="false">Settings</string>
 
     <!-- ******* Overview ******* -->
     <!-- Label for a button that causes the current overview app to be shared. [CHAR_LIMIT=40] -->
diff --git a/quickstep/res/values/styles.xml b/quickstep/res/values/styles.xml
index bf107fb..14e054e 100644
--- a/quickstep/res/values/styles.xml
+++ b/quickstep/res/values/styles.xml
@@ -35,14 +35,14 @@
     <style name="TextAppearance.BackGestureTutorial.Title"
         parent="TextAppearance.BackGestureTutorial">
         <item name="android:gravity">center</item>
-        <item name="android:textColor">@color/back_gesture_tutorial_title_color</item>
+        <item name="android:textColor">@color/gesture_tutorial_title_color</item>
         <item name="android:textSize">28sp</item>
     </style>
 
     <style name="TextAppearance.BackGestureTutorial.Subtitle"
         parent="TextAppearance.BackGestureTutorial">
         <item name="android:gravity">center</item>
-        <item name="android:textColor">@color/back_gesture_tutorial_subtitle_color</item>
+        <item name="android:textColor">@color/gesture_tutorial_subtitle_color</item>
         <item name="android:letterSpacing">0.03</item>
         <item name="android:textSize">21sp</item>
     </style>
@@ -50,7 +50,7 @@
     <style name="TextAppearance.BackGestureTutorial.ButtonLabel"
         parent="TextAppearance.BackGestureTutorial.CallToAction">
         <item name="android:gravity">center</item>
-        <item name="android:textColor">@color/back_gesture_tutorial_action_button_label_color</item>
+        <item name="android:textColor">@color/gesture_tutorial_action_button_label_color</item>
         <item name="android:letterSpacing">0.02</item>
         <item name="android:textSize">16sp</item>
         <item name="android:textAllCaps">false</item>
@@ -58,7 +58,7 @@
 
     <style name="TextAppearance.BackGestureTutorial.TextButtonLabel"
         parent="TextAppearance.BackGestureTutorial.ButtonLabel">
-        <item name="android:textColor">@color/back_gesture_tutorial_primary_color</item>
+        <item name="android:textColor">@color/gesture_tutorial_primary_color</item>
     </style>
 
     <style name="OverviewActionButton"
diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialConfirmController.java b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialConfirmController.java
deleted file mode 100644
index 486d676..0000000
--- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialConfirmController.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.quickstep.interaction;
-
-import android.view.View;
-
-import com.android.launcher3.R;
-import com.android.quickstep.interaction.BackGestureTutorialFragment.TutorialStep;
-
-import java.util.Optional;
-
-/**
- * An implementation of {@link BackGestureTutorialController} that defines the behavior of the
- * {@link TutorialStep#CONFIRM}.
- */
-final class BackGestureTutorialConfirmController extends BackGestureTutorialController {
-
-    BackGestureTutorialConfirmController(BackGestureTutorialFragment fragment,
-            BackGestureTutorialTypeInfo tutorialTypeInfo) {
-        super(fragment, TutorialStep.CONFIRM, Optional.of(tutorialTypeInfo));
-    }
-
-    @Override
-    Optional<Integer> getTitleStringId() {
-        return Optional.of(mTutorialTypeInfo.get().getTutorialConfirmTitleId());
-    }
-
-    @Override
-    Optional<Integer> getSubtitleStringId() {
-        return Optional.of(mTutorialTypeInfo.get().getTutorialConfirmSubtitleId());
-    }
-
-    @Override
-    Optional<Integer> getActionButtonStringId() {
-        return Optional.of(R.string.back_gesture_tutorial_action_button_label);
-    }
-
-    @Override
-    Optional<Integer> getActionTextButtonStringId() {
-        return Optional.of(R.string.back_gesture_tutorial_action_text_button_label);
-    }
-
-    @Override
-    void onActionButtonClicked(View button) {
-        hideHandCoachingAnimation();
-        if (button == mActionTextButton) {
-            mFragment.startSystemNavigationSetting();
-        }
-        mFragment.closeTutorial();
-    }
-}
diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
index 5c2e992..640ae76 100644
--- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
@@ -15,164 +15,101 @@
  */
 package com.android.quickstep.interaction;
 
+import static com.android.quickstep.interaction.TutorialController.TutorialType.BACK_NAVIGATION_COMPLETE;
+import static com.android.quickstep.interaction.TutorialController.TutorialType.LEFT_EDGE_BACK_NAVIGATION;
+
 import android.view.View;
-import android.widget.Button;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
 
 import com.android.launcher3.R;
-import com.android.quickstep.interaction.BackGestureTutorialFragment.TutorialStep;
-import com.android.quickstep.interaction.BackGestureTutorialFragment.TutorialType;
 import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureResult;
 
-import java.util.Optional;
+/** A {@link TutorialController} for the Back tutorial. */
+final class BackGestureTutorialController extends TutorialController {
 
-/**
- * Defines the behavior of the particular {@link TutorialStep} and implements the transition to it.
- */
-abstract class BackGestureTutorialController {
-
-    final BackGestureTutorialFragment mFragment;
-    final TutorialStep mTutorialStep;
-    final Optional<BackGestureTutorialTypeInfo> mTutorialTypeInfo;
-    final Button mActionTextButton;
-    final Button mActionButton;
-    final TextView mSubtitleTextView;
-    final ImageButton mCloseButton;
-    final BackGestureTutorialHandAnimation mHandCoachingAnimation;
-    final LinearLayout mTitlesContainer;
-
-    private final TextView mTitleTextView;
-    private final ImageView mHandCoachingView;
-
-    BackGestureTutorialController(
-            BackGestureTutorialFragment fragment,
-            TutorialStep tutorialStep,
-            Optional<BackGestureTutorialTypeInfo> tutorialTypeInfo) {
-        mFragment = fragment;
-        mTutorialStep = tutorialStep;
-        mTutorialTypeInfo = tutorialTypeInfo;
-
-        View rootView = fragment.getRootView();
-        mActionTextButton = rootView.findViewById(
-                R.id.back_gesture_tutorial_fragment_action_text_button);
-        mActionButton = rootView.findViewById(R.id.back_gesture_tutorial_fragment_action_button);
-        mSubtitleTextView = rootView.findViewById(
-                R.id.back_gesture_tutorial_fragment_subtitle_view);
-        mTitleTextView = rootView.findViewById(R.id.back_gesture_tutorial_fragment_title_view);
-        mHandCoachingView = rootView.findViewById(
-                R.id.back_gesture_tutorial_fragment_hand_coaching);
-        mHandCoachingAnimation = mFragment.getHandAnimation();
-        mHandCoachingView.bringToFront();
-        mCloseButton = rootView.findViewById(R.id.back_gesture_tutorial_fragment_close_button);
-        mTitlesContainer = rootView.findViewById(
-                R.id.back_gesture_tutorial_fragment_titles_container);
+    BackGestureTutorialController(BackGestureTutorialFragment fragment, TutorialType tutorialType) {
+        super(fragment, tutorialType);
     }
 
+    @Override
     void transitToController() {
-        updateTitles();
-        updateActionButtons();
+        super.transitToController();
+        if (mTutorialType != BACK_NAVIGATION_COMPLETE) {
+            mHandCoachingAnimation.startLoopedAnimation(mTutorialType);
+        }
     }
 
-    void hideHandCoachingAnimation() {
-        mHandCoachingAnimation.stop();
+    @Override
+    Integer getTitleStringId() {
+        switch (mTutorialType) {
+            case RIGHT_EDGE_BACK_NAVIGATION:
+                return R.string.back_gesture_tutorial_playground_title_swipe_inward_right_edge;
+            case LEFT_EDGE_BACK_NAVIGATION:
+                return R.string.back_gesture_tutorial_playground_title_swipe_inward_left_edge;
+            case BACK_NAVIGATION_COMPLETE:
+                return R.string.back_gesture_tutorial_confirm_title;
+        }
+        return null;
     }
 
-    void onGestureAttempted(BackGestureResult result) {
-        if (mTutorialStep == TutorialStep.CONFIRM
-                && (result == BackGestureResult.BACK_COMPLETED_FROM_LEFT
-                    || result == BackGestureResult.BACK_COMPLETED_FROM_RIGHT)) {
-            mFragment.closeTutorial();
-            return;
+    @Override
+    Integer getSubtitleStringId() {
+        switch (mTutorialType) {
+            case RIGHT_EDGE_BACK_NAVIGATION:
+                return R.string.back_gesture_tutorial_engaged_subtitle_swipe_inward_right_edge;
+            case LEFT_EDGE_BACK_NAVIGATION:
+                return R.string.back_gesture_tutorial_engaged_subtitle_swipe_inward_left_edge;
+            case BACK_NAVIGATION_COMPLETE:
+                return R.string.back_gesture_tutorial_confirm_subtitle;
         }
+        return null;
+    }
 
-        if (!mTutorialTypeInfo.isPresent()) {
-            return;
+    @Override
+    Integer getActionButtonStringId() {
+        if (mTutorialType == BACK_NAVIGATION_COMPLETE) {
+            return R.string.gesture_tutorial_action_button_label;
         }
+        return null;
+    }
 
-        switch (mTutorialTypeInfo.get().getTutorialType()) {
+    @Override
+    Integer getActionTextButtonStringId() {
+        if (mTutorialType == BACK_NAVIGATION_COMPLETE) {
+            return R.string.gesture_tutorial_action_text_button_label;
+        }
+        return null;
+    }
+
+    @Override
+    void onActionButtonClicked(View button) {
+        hideHandCoachingAnimation();
+        if (button == mActionTextButton) {
+            mTutorialFragment.startSystemNavigationSetting();
+        }
+        mTutorialFragment.closeTutorial();
+    }
+
+    @Override
+    public void onBackGestureAttempted(BackGestureResult result) {
+        switch (mTutorialType) {
             case RIGHT_EDGE_BACK_NAVIGATION:
                 if (result == BackGestureResult.BACK_COMPLETED_FROM_RIGHT) {
                     hideHandCoachingAnimation();
-                    mFragment.changeController(
-                            TutorialStep.ENGAGED, TutorialType.LEFT_EDGE_BACK_NAVIGATION);
+                    mTutorialFragment.changeController(LEFT_EDGE_BACK_NAVIGATION);
                 }
                 break;
             case LEFT_EDGE_BACK_NAVIGATION:
                 if (result == BackGestureResult.BACK_COMPLETED_FROM_LEFT) {
                     hideHandCoachingAnimation();
-                    mFragment.changeController(TutorialStep.CONFIRM);
+                    mTutorialFragment.changeController(BACK_NAVIGATION_COMPLETE);
                 }
                 break;
-        }
-    }
-
-    abstract Optional<Integer> getTitleStringId();
-
-    abstract Optional<Integer> getSubtitleStringId();
-
-    abstract Optional<Integer> getActionButtonStringId();
-
-    abstract Optional<Integer> getActionTextButtonStringId();
-
-    abstract void onActionButtonClicked(View button);
-
-    private void updateActionButtons() {
-        updateButton(mActionButton, getActionButtonStringId(), this::onActionButtonClicked);
-        updateButton(mActionTextButton, getActionTextButtonStringId(), this::onActionButtonClicked);
-    }
-
-    private static void updateButton(Button button, Optional<Integer> stringId,
-            View.OnClickListener listener) {
-        if (!stringId.isPresent()) {
-            button.setVisibility(View.INVISIBLE);
-            return;
-        }
-
-        button.setVisibility(View.VISIBLE);
-        button.setText(stringId.get());
-        button.setOnClickListener(listener);
-    }
-
-    private void updateTitles() {
-        updateTitleView(mTitleTextView, getTitleStringId(),
-                R.style.TextAppearance_BackGestureTutorial_Title);
-        updateTitleView(mSubtitleTextView, getSubtitleStringId(),
-                R.style.TextAppearance_BackGestureTutorial_Subtitle);
-    }
-
-    private static void updateTitleView(TextView textView, Optional<Integer> stringId,
-            int styleId) {
-        if (!stringId.isPresent()) {
-            textView.setVisibility(View.GONE);
-            return;
-        }
-
-        textView.setVisibility(View.VISIBLE);
-        textView.setText(stringId.get());
-        textView.setTextAppearance(styleId);
-    }
-
-    /**
-     * Constructs {@link BackGestureTutorialController} for providing {@link TutorialType} and
-     * {@link TutorialStep}.
-     */
-    static Optional<BackGestureTutorialController> getTutorialController(
-            BackGestureTutorialFragment fragment, TutorialStep tutorialStep,
-            TutorialType tutorialType) {
-        BackGestureTutorialTypeInfo tutorialTypeInfo =
-                BackGestureTutorialTypeInfoProvider.getTutorialTypeInfo(tutorialType);
-        switch (tutorialStep) {
-            case ENGAGED:
-                return Optional.of(
-                        new BackGestureTutorialEngagedController(fragment, tutorialTypeInfo));
-            case CONFIRM:
-                return Optional.of(
-                        new BackGestureTutorialConfirmController(fragment, tutorialTypeInfo));
-            default:
-                throw new AssertionError("Unexpected tutorial step: " + tutorialStep);
+            case BACK_NAVIGATION_COMPLETE:
+                if (result == BackGestureResult.BACK_COMPLETED_FROM_LEFT
+                        || result == BackGestureResult.BACK_COMPLETED_FROM_RIGHT) {
+                    mTutorialFragment.closeTutorial();
+                }
+                break;
         }
     }
 }
diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialEngagedController.java b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialEngagedController.java
deleted file mode 100644
index 297c287..0000000
--- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialEngagedController.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.quickstep.interaction;
-
-import android.view.View;
-
-import com.android.quickstep.interaction.BackGestureTutorialFragment.TutorialStep;
-
-import java.util.Optional;
-
-/**
- * An implementation of {@link BackGestureTutorialController} that defines the behavior of the
- * {@link TutorialStep#ENGAGED}.
- */
-final class BackGestureTutorialEngagedController extends BackGestureTutorialController {
-
-    BackGestureTutorialEngagedController(
-            BackGestureTutorialFragment fragment, BackGestureTutorialTypeInfo tutorialTypeInfo) {
-        super(fragment, TutorialStep.ENGAGED, Optional.of(tutorialTypeInfo));
-    }
-
-    @Override
-    void transitToController() {
-        super.transitToController();
-        mHandCoachingAnimation.startLoopedAnimation(mTutorialTypeInfo.get().getTutorialType());
-    }
-
-    @Override
-    Optional<Integer> getTitleStringId() {
-        return Optional.of(mTutorialTypeInfo.get().getTutorialPlaygroundTitleId());
-    }
-
-    @Override
-    Optional<Integer> getSubtitleStringId() {
-        return Optional.of(mTutorialTypeInfo.get().getTutorialEngagedSubtitleId());
-    }
-
-    @Override
-    Optional<Integer> getActionButtonStringId() {
-        return Optional.empty();
-    }
-
-    @Override
-    Optional<Integer> getActionTextButtonStringId() {
-        return Optional.empty();
-    }
-
-    @Override
-    void onActionButtonClicked(View button) {
-    }
-}
diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialFragment.java
index aeb718d..ddf1cda 100644
--- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialFragment.java
@@ -15,172 +15,43 @@
  */
 package com.android.quickstep.interaction;
 
-import android.content.ActivityNotFoundException;
-import android.content.Intent;
-import android.graphics.Insets;
 import android.os.Bundle;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowInsets;
-
-import androidx.annotation.NonNull;
-import androidx.fragment.app.Fragment;
 
 import com.android.launcher3.R;
 import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureAttemptCallback;
 import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureResult;
-
-import java.net.URISyntaxException;
-import java.util.Optional;
+import com.android.quickstep.interaction.TutorialController.TutorialType;
 
 /** Shows the Back gesture interactive tutorial. */
-public class BackGestureTutorialFragment extends Fragment implements BackGestureAttemptCallback {
-
-    private static final String LOG_TAG = "TutorialFragment";
-    private static final String KEY_TUTORIAL_STEP = "tutorialStep";
-    private static final String KEY_TUTORIAL_TYPE = "tutorialType";
-    private static final String SYSTEM_NAVIGATION_SETTING_INTENT =
-            "#Intent;action=com.android.settings.SEARCH_RESULT_TRAMPOLINE;S"
-                    + ".:settings:fragment_args_key=gesture_system_navigation_input_summary;S"
-                    + ".:settings:show_fragment=com.android.settings.gestures"
-                    + ".SystemNavigationGestureSettings;end";
-
-    private TutorialStep mTutorialStep;
-    private TutorialType mTutorialType;
-    private Optional<BackGestureTutorialController> mTutorialController = Optional.empty();
-    private View mRootView;
-    private BackGestureTutorialHandAnimation mHandCoachingAnimation;
-    private EdgeBackGestureHandler mEdgeBackGestureHandler;
-
-    public static BackGestureTutorialFragment newInstance(
-            TutorialStep tutorialStep, TutorialType tutorialType) {
-        BackGestureTutorialFragment fragment = new BackGestureTutorialFragment();
-        Bundle args = new Bundle();
-        args.putSerializable(KEY_TUTORIAL_STEP, tutorialStep);
-        args.putSerializable(KEY_TUTORIAL_TYPE, tutorialType);
-        fragment.setArguments(args);
-        return fragment;
-    }
+public class BackGestureTutorialFragment extends TutorialFragment
+        implements BackGestureAttemptCallback {
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        Bundle args = savedInstanceState != null ? savedInstanceState : getArguments();
-        mTutorialStep = (TutorialStep) args.getSerializable(KEY_TUTORIAL_STEP);
-        mTutorialType = (TutorialType) args.getSerializable(KEY_TUTORIAL_TYPE);
-        mEdgeBackGestureHandler = new EdgeBackGestureHandler(getContext());
         mEdgeBackGestureHandler.registerBackGestureAttemptCallback(this);
     }
 
     @Override
-    public View onCreateView(
-            @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
-        super.onCreateView(inflater, container, savedInstanceState);
-
-        mRootView = inflater.inflate(R.layout.back_gesture_tutorial_fragment,
-                container, /* attachToRoot= */ false);
-        mRootView.findViewById(R.id.back_gesture_tutorial_fragment_close_button)
-                .setOnClickListener(this::onCloseButtonClicked);
-        mRootView.setOnApplyWindowInsetsListener((view, insets) -> {
-            Insets systemInsets = insets.getInsets(WindowInsets.Type.systemBars());
-            mEdgeBackGestureHandler.setInsets(systemInsets.left, systemInsets.right);
-            return insets;
-        });
-        mRootView.setOnTouchListener(mEdgeBackGestureHandler);
-        mHandCoachingAnimation = new BackGestureTutorialHandAnimation(getContext(), mRootView);
-
-        return mRootView;
+    public void onDestroy() {
+        super.onDestroy();
+        mEdgeBackGestureHandler.unregisterBackGestureAttemptCallback();
     }
 
     @Override
-    public void onResume() {
-        super.onResume();
-        changeController(mTutorialStep, mTutorialType);
+    int getHandAnimationResId() {
+        return R.drawable.back_gesture;
     }
 
     @Override
-    public void onPause() {
-        super.onPause();
-        mHandCoachingAnimation.stop();
-    }
-
-    void onAttachedToWindow() {
-        mEdgeBackGestureHandler.setViewGroupParent((ViewGroup) getRootView());
-    }
-
-    void onDetachedFromWindow() {
-        mEdgeBackGestureHandler.setViewGroupParent(null);
-    }
-
-    @Override
-    public void onSaveInstanceState(Bundle savedInstanceState) {
-        savedInstanceState.putSerializable(KEY_TUTORIAL_STEP, mTutorialStep);
-        savedInstanceState.putSerializable(KEY_TUTORIAL_TYPE, mTutorialType);
-        super.onSaveInstanceState(savedInstanceState);
-    }
-
-    View getRootView() {
-        return mRootView;
-    }
-
-    BackGestureTutorialHandAnimation getHandAnimation() {
-        return mHandCoachingAnimation;
-    }
-
-    void changeController(TutorialStep tutorialStep) {
-        changeController(tutorialStep, mTutorialType);
-    }
-
-    void changeController(TutorialStep tutorialStep, TutorialType tutorialType) {
-        Optional<BackGestureTutorialController> tutorialController =
-                BackGestureTutorialController.getTutorialController(/* fragment= */ this,
-                        tutorialStep, tutorialType);
-        if (!tutorialController.isPresent()) {
-            return;
-        }
-
-        mTutorialController = tutorialController;
-        mTutorialController.get().transitToController();
-        this.mTutorialStep = mTutorialController.get().mTutorialStep;
-        this.mTutorialType = tutorialType;
+    TutorialController createController(TutorialType type) {
+        return new BackGestureTutorialController(this, type);
     }
 
     @Override
     public void onBackGestureAttempted(BackGestureResult result) {
-        mTutorialController.ifPresent(controller -> controller.onGestureAttempted(result));
-    }
-
-    void closeTutorial() {
-        getActivity().finish();
-    }
-
-    void startSystemNavigationSetting() {
-        try {
-            startActivityForResult(
-                    Intent.parseUri(SYSTEM_NAVIGATION_SETTING_INTENT, /* flags= */ 0),
-                    /* requestCode= */ 0);
-        } catch (URISyntaxException e) {
-            Log.e(LOG_TAG, "The launch Intent Uri is wrong syntax: " + e);
-        } catch (ActivityNotFoundException e) {
-            Log.e(LOG_TAG, "The launch Activity not found: " + e);
+        if (mTutorialController != null) {
+            mTutorialController.onBackGestureAttempted(result);
         }
     }
-
-    private void onCloseButtonClicked(View button) {
-        closeTutorial();
-    }
-
-    /** Denotes the step of the tutorial. */
-    enum TutorialStep {
-        ENGAGED,
-        CONFIRM,
-    }
-
-    /** Denotes the type of the tutorial. */
-    enum TutorialType {
-        RIGHT_EDGE_BACK_NAVIGATION,
-        LEFT_EDGE_BACK_NAVIGATION,
-    }
 }
diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialTypeInfo.java b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialTypeInfo.java
deleted file mode 100644
index ac8443d..0000000
--- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialTypeInfo.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.quickstep.interaction;
-
-import com.android.quickstep.interaction.BackGestureTutorialFragment.TutorialType;
-
-/** Defines the UI element identifiers for the particular {@link TutorialType}. */
-final class BackGestureTutorialTypeInfo {
-
-    private final TutorialType mTutorialType;
-    private final int mTutorialPlaygroundTitleId;
-    private final int mTutorialEngagedSubtitleId;
-    private final int mTutorialConfirmTitleId;
-    private final int mTutorialConfirmSubtitleId;
-
-    TutorialType getTutorialType() {
-        return mTutorialType;
-    }
-
-    int getTutorialPlaygroundTitleId() {
-        return mTutorialPlaygroundTitleId;
-    }
-
-    int getTutorialEngagedSubtitleId() {
-        return mTutorialEngagedSubtitleId;
-    }
-
-    int getTutorialConfirmTitleId() {
-        return mTutorialConfirmTitleId;
-    }
-
-    int getTutorialConfirmSubtitleId() {
-        return mTutorialConfirmSubtitleId;
-    }
-
-    static Builder builder() {
-        return new Builder();
-    }
-
-    private BackGestureTutorialTypeInfo(
-            TutorialType tutorialType,
-            int tutorialPlaygroundTitleId,
-            int tutorialEngagedSubtitleId,
-            int tutorialConfirmTitleId,
-            int tutorialConfirmSubtitleId) {
-        mTutorialType = tutorialType;
-        mTutorialPlaygroundTitleId = tutorialPlaygroundTitleId;
-        mTutorialEngagedSubtitleId = tutorialEngagedSubtitleId;
-        mTutorialConfirmTitleId = tutorialConfirmTitleId;
-        mTutorialConfirmSubtitleId = tutorialConfirmSubtitleId;
-    }
-
-    /** Builder for producing {@link BackGestureTutorialTypeInfo} objects. */
-    static class Builder {
-
-        private TutorialType mTutorialType;
-        private Integer mTutorialPlaygroundTitleId;
-        private Integer mTutorialEngagedSubtitleId;
-        private Integer mTutorialConfirmTitleId;
-        private Integer mTutorialConfirmSubtitleId;
-
-        Builder setTutorialType(TutorialType tutorialType) {
-            mTutorialType = tutorialType;
-            return this;
-        }
-
-        Builder setTutorialPlaygroundTitleId(int stringId) {
-            mTutorialPlaygroundTitleId = stringId;
-            return this;
-        }
-
-        Builder setTutorialEngagedSubtitleId(int stringId) {
-            mTutorialEngagedSubtitleId = stringId;
-            return this;
-        }
-
-        Builder setTutorialConfirmTitleId(int stringId) {
-            mTutorialConfirmTitleId = stringId;
-            return this;
-        }
-
-        Builder setTutorialConfirmSubtitleId(int stringId) {
-            mTutorialConfirmSubtitleId = stringId;
-            return this;
-        }
-
-        BackGestureTutorialTypeInfo build() {
-            return new BackGestureTutorialTypeInfo(
-                    mTutorialType,
-                    mTutorialPlaygroundTitleId,
-                    mTutorialEngagedSubtitleId,
-                    mTutorialConfirmTitleId,
-                    mTutorialConfirmSubtitleId);
-        }
-    }
-}
diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialTypeInfoProvider.java b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialTypeInfoProvider.java
deleted file mode 100644
index 9575d83..0000000
--- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialTypeInfoProvider.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.quickstep.interaction;
-
-import com.android.launcher3.R;
-import com.android.quickstep.interaction.BackGestureTutorialFragment.TutorialType;
-
-/** Provides instances of {@link BackGestureTutorialTypeInfo} for each {@link TutorialType}. */
-final class BackGestureTutorialTypeInfoProvider {
-
-    private static final BackGestureTutorialTypeInfo RIGHT_EDGE_BACK_NAV_TUTORIAL_INFO =
-            BackGestureTutorialTypeInfo.builder()
-                    .setTutorialType(TutorialType.RIGHT_EDGE_BACK_NAVIGATION)
-                    .setTutorialPlaygroundTitleId(
-                            R.string.back_gesture_tutorial_playground_title_swipe_inward_right_edge)
-                    .setTutorialEngagedSubtitleId(
-                            R.string.back_gesture_tutorial_engaged_subtitle_swipe_inward_right_edge)
-                    .setTutorialConfirmTitleId(R.string.back_gesture_tutorial_confirm_title)
-                    .setTutorialConfirmSubtitleId(R.string.back_gesture_tutorial_confirm_subtitle)
-                    .build();
-
-    private static final BackGestureTutorialTypeInfo LEFT_EDGE_BACK_NAV_TUTORIAL_INFO =
-            BackGestureTutorialTypeInfo.builder()
-                    .setTutorialType(TutorialType.LEFT_EDGE_BACK_NAVIGATION)
-                    .setTutorialPlaygroundTitleId(
-                            R.string.back_gesture_tutorial_playground_title_swipe_inward_left_edge)
-                    .setTutorialEngagedSubtitleId(
-                            R.string.back_gesture_tutorial_engaged_subtitle_swipe_inward_left_edge)
-                    .setTutorialConfirmTitleId(R.string.back_gesture_tutorial_confirm_title)
-                    .setTutorialConfirmSubtitleId(R.string.back_gesture_tutorial_confirm_subtitle)
-                    .build();
-
-    static BackGestureTutorialTypeInfo getTutorialTypeInfo(TutorialType tutorialType) {
-        switch (tutorialType) {
-            case RIGHT_EDGE_BACK_NAVIGATION:
-                return RIGHT_EDGE_BACK_NAV_TUTORIAL_INFO;
-            case LEFT_EDGE_BACK_NAVIGATION:
-                return LEFT_EDGE_BACK_NAV_TUTORIAL_INFO;
-            default:
-                throw new AssertionError("Unexpected tutorial type: " + tutorialType);
-        }
-    }
-
-    private BackGestureTutorialTypeInfoProvider() {
-    }
-}
diff --git a/quickstep/src/com/android/quickstep/interaction/EdgeBackGestureHandler.java b/quickstep/src/com/android/quickstep/interaction/EdgeBackGestureHandler.java
index f34530e..89c57a0 100644
--- a/quickstep/src/com/android/quickstep/interaction/EdgeBackGestureHandler.java
+++ b/quickstep/src/com/android/quickstep/interaction/EdgeBackGestureHandler.java
@@ -20,7 +20,6 @@
 import android.graphics.Point;
 import android.graphics.PointF;
 import android.os.SystemProperties;
-import android.view.Display;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.View.OnTouchListener;
@@ -46,7 +45,6 @@
     private final Context mContext;
 
     private final Point mDisplaySize = new Point();
-    private final int mDisplayId;
 
     // The edge width where touch down is allowed
     private int mEdgeWidth;
@@ -91,8 +89,6 @@
     EdgeBackGestureHandler(Context context) {
         final Resources res = context.getResources();
         mContext = context;
-        mDisplayId = context.getDisplay() == null
-                ? Display.DEFAULT_DISPLAY : context.getDisplay().getDisplayId();
 
         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
         mLongPressTimeout = Math.min(MAX_LONG_PRESS_TIMEOUT,
@@ -126,6 +122,10 @@
         mGestureCallback = callback;
     }
 
+    void unregisterBackGestureAttemptCallback() {
+        mGestureCallback = null;
+    }
+
     private LayoutParams createLayoutParams() {
         Resources resources = mContext.getResources();
         return new LayoutParams(
diff --git a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
index 4815366..414ddfa 100644
--- a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
@@ -19,6 +19,7 @@
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.util.DisplayMetrics;
+import android.util.Log;
 import android.view.Display;
 import android.view.View;
 import android.view.Window;
@@ -26,26 +27,32 @@
 import androidx.fragment.app.FragmentActivity;
 
 import com.android.launcher3.R;
-import com.android.quickstep.interaction.BackGestureTutorialFragment.TutorialStep;
-import com.android.quickstep.interaction.BackGestureTutorialFragment.TutorialType;
+import com.android.quickstep.interaction.TutorialController.TutorialType;
 
 import java.util.List;
 
 /** Shows the gesture interactive sandbox in full screen mode. */
 public class GestureSandboxActivity extends FragmentActivity {
 
-    private BackGestureTutorialFragment mFragment;
+    private static final String LOG_TAG = "GestureSandboxActivity";
+
+    private TutorialFragment mFragment;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         requestWindowFeature(Window.FEATURE_NO_TITLE);
-        setContentView(R.layout.back_gesture_tutorial_activity);
+        setContentView(R.layout.gesture_tutorial_activity);
 
-        mFragment = BackGestureTutorialFragment.newInstance(
-            TutorialStep.ENGAGED, TutorialType.RIGHT_EDGE_BACK_NAVIGATION);
+        try {
+            mFragment = TutorialFragment.newInstance(BackGestureTutorialFragment.class,
+                    TutorialType.RIGHT_EDGE_BACK_NAVIGATION);
+        } catch (InstantiationException | IllegalAccessException e) {
+            Log.wtf(LOG_TAG, "Failed to create tutorial fragment!", e);
+            mFragment = new BackGestureTutorialFragment();
+        }
         getSupportFragmentManager().beginTransaction()
-                .add(R.id.back_gesture_tutorial_fragment_container, mFragment)
+                .add(R.id.gesture_tutorial_fragment_container, mFragment)
                 .commit();
     }
 
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
new file mode 100644
index 0000000..cd4d0d8
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.interaction;
+
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.annotation.CallSuper;
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.R;
+import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureResult;
+
+abstract class TutorialController {
+
+    final TutorialFragment mTutorialFragment;
+    final TutorialType mTutorialType;
+
+    final ImageButton mCloseButton;
+    final TextView mTitleTextView;
+    final TextView mSubtitleTextView;
+    final TutorialHandAnimation mHandCoachingAnimation;
+    final ImageView mHandCoachingView;
+    final Button mActionTextButton;
+    final Button mActionButton;
+
+    TutorialController(TutorialFragment tutorialFragment, TutorialType tutorialType) {
+        mTutorialFragment = tutorialFragment;
+        mTutorialType = tutorialType;
+
+        View rootView = tutorialFragment.getRootView();
+        mCloseButton = rootView.findViewById(R.id.gesture_tutorial_fragment_close_button);
+        mCloseButton.setOnClickListener(button -> mTutorialFragment.closeTutorial());
+        mTitleTextView = rootView.findViewById(R.id.gesture_tutorial_fragment_title_view);
+        mSubtitleTextView = rootView.findViewById(R.id.gesture_tutorial_fragment_subtitle_view);
+        mHandCoachingAnimation = tutorialFragment.getHandAnimation();
+        mHandCoachingView = rootView.findViewById(R.id.gesture_tutorial_fragment_hand_coaching);
+        mHandCoachingView.bringToFront();
+        mActionTextButton =
+                rootView.findViewById(R.id.gesture_tutorial_fragment_action_text_button);
+        mActionButton = rootView.findViewById(R.id.gesture_tutorial_fragment_action_button);
+    }
+
+    abstract void onBackGestureAttempted(BackGestureResult result);
+
+    @Nullable
+    Integer getTitleStringId() {
+        return null;
+    }
+
+    @Nullable
+    Integer getSubtitleStringId() {
+        return null;
+    }
+
+    @Nullable
+    Integer getActionButtonStringId() {
+        return null;
+    }
+
+    @Nullable
+    Integer getActionTextButtonStringId() {
+        return null;
+    }
+
+    void onActionButtonClicked(View button) {}
+
+    void hideHandCoachingAnimation() {
+        mHandCoachingAnimation.stop();
+    }
+
+    @CallSuper
+    void transitToController() {
+        updateTitles();
+        updateActionButtons();
+    }
+
+    private void updateTitles() {
+        updateTitleView(mTitleTextView, getTitleStringId(),
+                R.style.TextAppearance_BackGestureTutorial_Title);
+        updateTitleView(mSubtitleTextView, getSubtitleStringId(),
+                R.style.TextAppearance_BackGestureTutorial_Subtitle);
+    }
+
+    private void updateTitleView(TextView textView, @Nullable Integer stringId, int styleId) {
+        if (stringId == null) {
+            textView.setVisibility(View.GONE);
+            return;
+        }
+
+        textView.setVisibility(View.VISIBLE);
+        textView.setText(stringId);
+        textView.setTextAppearance(styleId);
+    }
+
+    private void updateActionButtons() {
+        updateButton(mActionButton, getActionButtonStringId(), this::onActionButtonClicked);
+        updateButton(mActionTextButton, getActionTextButtonStringId(), this::onActionButtonClicked);
+    }
+
+    private void updateButton(Button button, @Nullable Integer stringId, OnClickListener listener) {
+        if (stringId == null) {
+            button.setVisibility(View.INVISIBLE);
+            return;
+        }
+
+        button.setVisibility(View.VISIBLE);
+        button.setText(stringId);
+        button.setOnClickListener(listener);
+    }
+
+    /** Denotes the type of the tutorial. */
+    enum TutorialType {
+        RIGHT_EDGE_BACK_NAVIGATION,
+        LEFT_EDGE_BACK_NAVIGATION,
+        BACK_NAVIGATION_COMPLETE,
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
new file mode 100644
index 0000000..09ea8d6
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.interaction;
+
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.graphics.Insets;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowInsets;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentActivity;
+
+import com.android.launcher3.R;
+import com.android.quickstep.interaction.TutorialController.TutorialType;
+
+import java.net.URISyntaxException;
+
+abstract class TutorialFragment extends Fragment {
+
+    private static final String LOG_TAG = "TutorialFragment";
+    private static final String SYSTEM_NAVIGATION_SETTING_INTENT =
+            "#Intent;action=com.android.settings.SEARCH_RESULT_TRAMPOLINE;S"
+                    + ".:settings:fragment_args_key=gesture_system_navigation_input_summary;S"
+                    + ".:settings:show_fragment=com.android.settings.gestures"
+                    + ".SystemNavigationGestureSettings;end";
+    private static final String KEY_TUTORIAL_TYPE = "tutorialType";
+
+    TutorialType mTutorialType;
+    @Nullable TutorialController mTutorialController = null;
+    View mRootView;
+    TutorialHandAnimation mHandCoachingAnimation;
+    EdgeBackGestureHandler mEdgeBackGestureHandler;
+
+    public static TutorialFragment newInstance(
+            Class<? extends TutorialFragment> fragmentClass, TutorialType tutorialType)
+            throws java.lang.InstantiationException, IllegalAccessException {
+        TutorialFragment fragment = fragmentClass.newInstance();
+        Bundle args = new Bundle();
+        args.putSerializable(KEY_TUTORIAL_TYPE, tutorialType);
+        fragment.setArguments(args);
+        return fragment;
+    }
+
+    abstract int getHandAnimationResId();
+
+    abstract TutorialController createController(TutorialType type);
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Bundle args = savedInstanceState != null ? savedInstanceState : getArguments();
+        mTutorialType = (TutorialType) args.getSerializable(KEY_TUTORIAL_TYPE);
+        mEdgeBackGestureHandler = new EdgeBackGestureHandler(getContext());
+    }
+
+    @Override
+    public View onCreateView(
+            @NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+        super.onCreateView(inflater, container, savedInstanceState);
+
+        mRootView = inflater.inflate(R.layout.gesture_tutorial_fragment,
+                container, /* attachToRoot= */ false);
+        mRootView.setOnApplyWindowInsetsListener((view, insets) -> {
+            Insets systemInsets = insets.getInsets(WindowInsets.Type.systemBars());
+            mEdgeBackGestureHandler.setInsets(systemInsets.left, systemInsets.right);
+            return insets;
+        });
+        mRootView.setOnTouchListener(mEdgeBackGestureHandler);
+        mHandCoachingAnimation = new TutorialHandAnimation(getContext(), mRootView,
+                getHandAnimationResId());
+        return mRootView;
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        changeController(mTutorialType);
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+        mHandCoachingAnimation.stop();
+    }
+
+    void onAttachedToWindow() {
+        mEdgeBackGestureHandler.setViewGroupParent((ViewGroup) getRootView());
+    }
+
+    void onDetachedFromWindow() {
+        mEdgeBackGestureHandler.setViewGroupParent(null);
+    }
+
+    void changeController(TutorialType tutorialType) {
+        mTutorialController = createController(tutorialType);
+        mTutorialController.transitToController();
+        mTutorialType = tutorialType;
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle savedInstanceState) {
+        savedInstanceState.putSerializable(KEY_TUTORIAL_TYPE, mTutorialType);
+        super.onSaveInstanceState(savedInstanceState);
+    }
+
+    View getRootView() {
+        return mRootView;
+    }
+
+    TutorialHandAnimation getHandAnimation() {
+        return mHandCoachingAnimation;
+    }
+
+    void closeTutorial() {
+        FragmentActivity activity = getActivity();
+        if (activity != null) {
+            activity.finish();
+        }
+    }
+
+    void startSystemNavigationSetting() {
+        try {
+            startActivityForResult(
+                    Intent.parseUri(SYSTEM_NAVIGATION_SETTING_INTENT, /* flags= */ 0),
+                    /* requestCode= */ 0);
+        } catch (URISyntaxException e) {
+            Log.e(LOG_TAG, "The launch Intent Uri is wrong syntax: " + e);
+        } catch (ActivityNotFoundException e) {
+            Log.e(LOG_TAG, "The launch Activity not found: " + e);
+        }
+    }
+
+}
diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialHandAnimation.java b/quickstep/src/com/android/quickstep/interaction/TutorialHandAnimation.java
similarity index 85%
rename from quickstep/src/com/android/quickstep/interaction/BackGestureTutorialHandAnimation.java
rename to quickstep/src/com/android/quickstep/interaction/TutorialHandAnimation.java
index d7c10b0..5362aaf 100644
--- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialHandAnimation.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialHandAnimation.java
@@ -25,12 +25,12 @@
 import androidx.core.content.ContextCompat;
 
 import com.android.launcher3.R;
-import com.android.quickstep.interaction.BackGestureTutorialFragment.TutorialType;
+import com.android.quickstep.interaction.TutorialController.TutorialType;
 
 import java.time.Duration;
 
 /** Hand coaching animation. */
-final class BackGestureTutorialHandAnimation {
+final class TutorialHandAnimation {
 
     // A delay for waiting the Activity fully launches.
     private static final Duration ANIMATION_START_DELAY = Duration.ofMillis(300L);
@@ -38,16 +38,12 @@
     private final ImageView mHandCoachingView;
     private final AnimatedVectorDrawable mGestureAnimation;
 
-    BackGestureTutorialHandAnimation(Context context, View rootView) {
-        mHandCoachingView = rootView.findViewById(
-                R.id.back_gesture_tutorial_fragment_hand_coaching);
-        mGestureAnimation = (AnimatedVectorDrawable) ContextCompat.getDrawable(context,
-                R.drawable.back_gesture);
+    TutorialHandAnimation(Context context, View rootView, int resId) {
+        mHandCoachingView = rootView.findViewById(R.id.gesture_tutorial_fragment_hand_coaching);
+        mGestureAnimation = (AnimatedVectorDrawable) ContextCompat.getDrawable(context, resId);
     }
 
-    /**
-     * [Re]starts animation for the given tutorial.
-     */
+    /** [Re]starts animation for the given tutorial. */
     void startLoopedAnimation(TutorialType tutorialType) {
         if (mGestureAnimation.isRunning()) {
             stop();
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 194ef2c..adcff9a 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -38,11 +38,11 @@
     <color name="all_apps_bg_hand_fill">#E5E5E5</color>
     <color name="all_apps_bg_hand_fill_dark">#9AA0A6</color>
 
-    <color name="back_gesture_tutorial_background_color">#FFFFFFFF</color>
-    <color name="back_gesture_tutorial_subtitle_color">#99000000</color> <!-- 60% black -->
-    <color name="back_gesture_tutorial_title_color">#FF000000</color>
-    <color name="back_gesture_tutorial_action_button_label_color">#FFFFFFFF</color>
-    <color name="back_gesture_tutorial_primary_color">#1A73E8</color> <!-- Blue -->
+    <color name="gesture_tutorial_background_color">#FFFFFFFF</color>
+    <color name="gesture_tutorial_subtitle_color">#99000000</color> <!-- 60% black -->
+    <color name="gesture_tutorial_title_color">#FF000000</color>
+    <color name="gesture_tutorial_action_button_label_color">#FFFFFFFF</color>
+    <color name="gesture_tutorial_primary_color">#1A73E8</color> <!-- Blue -->
 
 
 </resources>
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index ec93eda..2dc7836 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -16,7 +16,7 @@
 
 package com.android.launcher3;
 
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.APP_LAUNCH_TAP;
 import static com.android.launcher3.util.DefaultDisplay.CHANGE_ROTATION;
 
 import android.app.ActivityOptions;
@@ -184,7 +184,7 @@
                         sourceContainer);
             }
             getUserEventDispatcher().logAppLaunch(v, intent, user);
-            getStatsLogManager().log(LAUNCHER_APP_LAUNCH_TAP, item.buildProto(null, null));
+            getStatsLogManager().log(APP_LAUNCH_TAP, item.buildProto(null, null));
             return true;
         } catch (NullPointerException|ActivityNotFoundException|SecurityException e) {
             Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
diff --git a/src/com/android/launcher3/BaseRecyclerView.java b/src/com/android/launcher3/BaseRecyclerView.java
index 9e8441a..41eeb78 100644
--- a/src/com/android/launcher3/BaseRecyclerView.java
+++ b/src/com/android/launcher3/BaseRecyclerView.java
@@ -16,17 +16,21 @@
 
 package com.android.launcher3;
 
+import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
+
 import android.content.Context;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityNodeInfo;
 
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.android.launcher3.compat.AccessibilityManagerCompat;
 import com.android.launcher3.testing.TestProtocol;
+import com.android.launcher3.views.ActivityContext;
 import com.android.launcher3.views.RecyclerViewFastScroller;
 
 
@@ -187,4 +191,28 @@
             AccessibilityManagerCompat.sendScrollFinishedEventToTest(getContext());
         }
     }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        if (isLayoutSuppressed()) info.setScrollable(false);
+        if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+            Log.d(TestProtocol.NO_SCROLL_END_WIDGETS,
+                    "onInitializeAccessibilityNodeInfo, scrollable: " + info.isScrollable());
+        }
+    }
+
+    @Override
+    public void setLayoutFrozen(boolean frozen) {
+        final boolean changing = frozen != isLayoutSuppressed();
+        super.setLayoutFrozen(frozen);
+        if (changing) {
+            if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+                Log.d(TestProtocol.NO_SCROLL_END_WIDGETS, "setLayoutFrozen " + frozen
+                        + " @ " + Log.getStackTraceString(new Throwable()));
+                ActivityContext.lookupContext(getContext()).getDragLayer()
+                        .sendAccessibilityEvent(TYPE_WINDOW_CONTENT_CHANGED);
+            }
+        }
+    }
 }
\ No newline at end of file
diff --git a/src/com/android/launcher3/logging/LauncherUiEvent.java b/src/com/android/launcher3/logging/LauncherUiEvent.java
new file mode 100644
index 0000000..4507ff7
--- /dev/null
+++ b/src/com/android/launcher3/logging/LauncherUiEvent.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.logging;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Retention(SOURCE)
+@Target(FIELD)
+public @interface LauncherUiEvent {
+    /** An explanation, suitable for Android analysts, of the UI event that this log represents. */
+    String doc();
+}
+
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index 60d790f..2829951 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -17,8 +17,6 @@
 
 import android.content.Context;
 
-import com.android.internal.logging.UiEvent;
-import com.android.internal.logging.UiEventLogger;
 import com.android.launcher3.R;
 import com.android.launcher3.logger.LauncherAtom;
 import com.android.launcher3.logger.LauncherAtom.ItemInfo;
@@ -30,15 +28,19 @@
  */
 public class StatsLogManager implements ResourceBasedOverride {
 
-    public enum LauncherEvent implements UiEventLogger.UiEventEnum {
-        @UiEvent(doc = "App launched from workspace, hotseat or folder in launcher")
-        LAUNCHER_APP_LAUNCH_TAP(338),
-        @UiEvent(doc = "Task launched from overview using TAP")
-        LAUNCHER_TASK_LAUNCH_TAP(339),
-        @UiEvent(doc = "Task launched from overview using SWIPE DOWN")
-        LAUNCHER_TASK_LAUNCH_SWIPE_DOWN(340),
-        @UiEvent(doc = "TASK dismissed from overview using SWIPE UP")
-        LAUNCHER_TASK_DISMISS_SWIPE_UP(341);
+    interface EventEnum {
+        int getId();
+    }
+
+    public enum LauncherEvent implements EventEnum {
+        @LauncherUiEvent(doc = "App launched from workspace, hotseat or folder in launcher")
+        APP_LAUNCH_TAP(1),
+        @LauncherUiEvent(doc = "Task launched from overview using TAP")
+        TASK_LAUNCH_TAP(2),
+        @LauncherUiEvent(doc = "Task launched from overview using SWIPE DOWN")
+        TASK_LAUNCH_SWIPE_DOWN(2),
+        @LauncherUiEvent(doc = "TASK dismissed from overview using SWIPE UP")
+        TASK_DISMISS_SWIPE_UP(3);
         // ADD MORE
 
         private final int mId;
diff --git a/src/com/android/launcher3/widget/WidgetsRecyclerView.java b/src/com/android/launcher3/widget/WidgetsRecyclerView.java
index 63e063f..17baa27 100644
--- a/src/com/android/launcher3/widget/WidgetsRecyclerView.java
+++ b/src/com/android/launcher3/widget/WidgetsRecyclerView.java
@@ -22,7 +22,6 @@
 import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.accessibility.AccessibilityNodeInfo;
 
 import com.android.launcher3.BaseRecyclerView;
 import com.android.launcher3.R;
@@ -210,24 +209,4 @@
         }
         super.stopNestedScroll();
     }
-
-    @Override
-    public void setLayoutFrozen(boolean frozen) {
-        if (frozen != isLayoutSuppressed()) {
-            if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
-                Log.d(TestProtocol.NO_SCROLL_END_WIDGETS, "setLayoutFrozen " + frozen
-                        + " @ " + android.util.Log.getStackTraceString(new Throwable()));
-            }
-        }
-        super.setLayoutFrozen(frozen);
-    }
-
-    @Override
-    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfo(info);
-        if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
-            Log.d(TestProtocol.NO_SCROLL_END_WIDGETS,
-                    "onInitializeAccessibilityNodeInfo, scrollable: " + info.isScrollable());
-        }
-    }
 }
\ No newline at end of file