Add a no recent tasks message to the keyboard quick switch view

Flag: ENABLE_KEYBOARD_QUICK_SWITCH
Fixes: 280652620
Test: launched the keyboard quick switch with 0, <=6 and >6 tasks launched
Change-Id: I560707645b83b79ba2203460e62e4c540f5da421
diff --git a/quickstep/res/layout/keyboard_quick_switch_overview.xml b/quickstep/res/layout/keyboard_quick_switch_overview.xml
index 062a9c9..e7b1f23 100644
--- a/quickstep/res/layout/keyboard_quick_switch_overview.xml
+++ b/quickstep/res/layout/keyboard_quick_switch_overview.xml
@@ -41,8 +41,8 @@
             android:layout_height="@dimen/keyboard_quick_switch_recents_icon_size"
             android:layout_marginBottom="8dp"
             android:src="@drawable/ic_empty_recents"
+            android:tint="?androidprv:attr/materialColorOnSurface"
 
-            app:tint="?androidprv:attr/materialColorOnSurface"
             app:layout_constraintVertical_chainStyle="packed"
             app:layout_constraintTop_toTopOf="parent"
             app:layout_constraintBottom_toTopOf="@id/text"
@@ -50,7 +50,7 @@
             app:layout_constraintEnd_toEndOf="parent"/>
 
         <TextView
-            style="@style/KeyboardQuickSwitchOverview"
+            style="@style/KeyboardQuickSwitchText"
             android:id="@+id/text"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
diff --git a/quickstep/res/layout/keyboard_quick_switch_view.xml b/quickstep/res/layout/keyboard_quick_switch_view.xml
index 58c0c40..16abdee 100644
--- a/quickstep/res/layout/keyboard_quick_switch_view.xml
+++ b/quickstep/res/layout/keyboard_quick_switch_view.xml
@@ -15,6 +15,7 @@
 -->
 <com.android.launcher3.taskbar.KeyboardQuickSwitchView
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
@@ -27,6 +28,43 @@
     android:focusableInTouchMode="true"
     app:layout_ignoreInsets="true">
 
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/no_recent_items_pane"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/keyboard_quick_switch_taskview_height"
+        android:paddingVertical="@dimen/keyboard_quick_switch_view_spacing"
+        android:alpha="0"
+        android:visibility="gone">
+
+        <ImageView
+            android:id="@+id/no_recent_items_icon"
+            android:layout_width="@dimen/keyboard_quick_switch_no_recent_items_icon_size"
+            android:layout_height="@dimen/keyboard_quick_switch_no_recent_items_icon_size"
+            android:layout_marginBottom="@dimen/keyboard_quick_switch_no_recent_items_icon_margin"
+            android:src="@drawable/ic_empty_recents"
+            android:tint="?androidprv:attr/materialColorOnSurfaceInverse"
+            android:importantForAccessibility="no"
+
+            app:layout_constraintVertical_chainStyle="packed"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintBottom_toTopOf="@id/no_recent_items_text"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+        <TextView
+            style="@style/KeyboardQuickSwitchText.OnBackground"
+            android:id="@+id/no_recent_items_text"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/recents_empty_message"
+
+            app:layout_constraintTop_toBottomOf="@id/no_recent_items_icon"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"/>
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
     <HorizontalScrollView
         android:id="@+id/scroll_view"
         android:layout_width="wrap_content"
@@ -34,7 +72,7 @@
         android:fillViewport="true"
         android:scrollbars="none"
         android:alpha="0"
-        android:visibility="invisible"
+        android:visibility="gone"
 
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintBottom_toBottomOf="parent"
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index d69b155..e7dac6c 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -379,4 +379,6 @@
     <dimen name="keyboard_quick_switch_split_view_spacing">2dp</dimen>
     <dimen name="keyboard_quick_switch_view_radius">28dp</dimen>
     <dimen name="keyboard_quick_switch_task_view_radius">16dp</dimen>
+    <dimen name="keyboard_quick_switch_no_recent_items_icon_size">24dp</dimen>
+    <dimen name="keyboard_quick_switch_no_recent_items_icon_margin">8dp</dimen>
 </resources>
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index 2b6f749..2d8c45a 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -295,6 +295,7 @@
             =1{Show # more app.}
             other{Show # more apps.}
         }</string>
+
     <!-- Accessibility label for quick switch tiles showing split tasks [CHAR LIMIT=NONE] -->
     <string name="quick_switch_split_task"><xliff:g id="app_name_1" example="Chrome">%1$s</xliff:g> and <xliff:g id="app_name_2" example="Gmail">%2$s</xliff:g></string>
 </resources>
diff --git a/quickstep/res/values/styles.xml b/quickstep/res/values/styles.xml
index e1afb26..ead5343 100644
--- a/quickstep/res/values/styles.xml
+++ b/quickstep/res/values/styles.xml
@@ -215,13 +215,17 @@
         <item name="android:textSize">14sp</item>
     </style>
 
-    <style name="KeyboardQuickSwitchOverview">
+    <style name="KeyboardQuickSwitchText">
         <item name="fontFamily">google-sans-text</item>
         <item name="android:textSize">14sp</item>
         <item name="android:textColor">?androidprv:attr/materialColorOnSurface</item>
         <item name="lineHeight">20sp</item>
     </style>
 
+    <style name="KeyboardQuickSwitchText.OnBackground" parent="KeyboardQuickSwitchText">
+        <item name="android:textColor">?androidprv:attr/materialColorOnSurfaceInverse</item>
+    </style>
+
     <style name="GestureTutorialActivity"
         parent="@style/AppTheme">
         <item name="background">@android:color/transparent</item>
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
index c4962cd..480c9d3 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
@@ -129,8 +129,8 @@
      */
     int launchFocusedTask() {
         // Return -1 so that the RecentsView is not incorrectly opened when the user closes the
-        // quick switch view by tapping the screen.
-        return mQuickSwitchViewController == null
+        // quick switch view by tapping the screen or when there are no recent tasks.
+        return mQuickSwitchViewController == null || mTasks.isEmpty()
                 ? -1 : mQuickSwitchViewController.launchFocusedTask();
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java
index 745defc..aa2ef00 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java
@@ -85,6 +85,8 @@
     private final AnimatedFloat mOutlineAnimationProgress = new AnimatedFloat(
             this::invalidateOutline);
 
+    private boolean mDisplayingRecentTasks;
+    private View mNoRecentItemsPane;
     private HorizontalScrollView mScrollView;
     private ConstraintLayout mContent;
 
@@ -119,6 +121,7 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
+        mNoRecentItemsPane = findViewById(R.id.no_recent_items_pane);
         mScrollView = findViewById(R.id.scroll_view);
         mContent = findViewById(R.id.content);
 
@@ -204,10 +207,6 @@
             boolean updateTasks,
             int currentFocusIndexOverride,
             @NonNull KeyboardQuickSwitchViewController.ViewCallbacks viewCallbacks) {
-        if (groupTasks.isEmpty()) {
-            // Do not show the quick switch view.
-            return;
-        }
         mViewCallbacks = viewCallbacks;
         Resources resources = context.getResources();
         int width = resources.getDimensionPixelSize(R.dimen.keyboard_quick_switch_taskview_width);
@@ -237,6 +236,7 @@
                             resources.getString(R.string.quick_switch_overflow),
                             Locale.getDefault()).format(args));
         }
+        mDisplayingRecentTasks = !groupTasks.isEmpty();
 
         getViewTreeObserver().addOnGlobalLayoutListener(
                 new ViewTreeObserver.OnGlobalLayoutListener() {
@@ -262,13 +262,16 @@
         alphaAnimation.setDuration(ALPHA_ANIMATION_DURATION_MS);
         closeAnimation.play(alphaAnimation);
 
+        View displayedContent = mDisplayingRecentTasks ? mScrollView : mNoRecentItemsPane;
         Animator translationYAnimation = ObjectAnimator.ofFloat(
-                mScrollView, TRANSLATION_Y, 0, -Utilities.dpToPx(CONTENT_START_TRANSLATION_Y_DP));
+                displayedContent,
+                TRANSLATION_Y,
+                0, -Utilities.dpToPx(CONTENT_START_TRANSLATION_Y_DP));
         translationYAnimation.setDuration(CONTENT_TRANSLATION_Y_ANIMATION_DURATION_MS);
         translationYAnimation.setInterpolator(CLOSE_TRANSLATION_Y_INTERPOLATOR);
         closeAnimation.play(translationYAnimation);
 
-        Animator contentAlphaAnimation = ObjectAnimator.ofFloat(mScrollView, ALPHA, 1f, 0f);
+        Animator contentAlphaAnimation = ObjectAnimator.ofFloat(displayedContent, ALPHA, 1f, 0f);
         contentAlphaAnimation.setDuration(CONTENT_ALPHA_ANIMATION_DURATION_MS);
         closeAnimation.play(contentAlphaAnimation);
 
@@ -300,19 +303,24 @@
         alphaAnimation.setDuration(ALPHA_ANIMATION_DURATION_MS);
         mOpenAnimation.play(alphaAnimation);
 
+        View displayedContent = mDisplayingRecentTasks ? mScrollView : mNoRecentItemsPane;
         Animator translationXAnimation = ObjectAnimator.ofFloat(
-                mScrollView, TRANSLATION_X, -Utilities.dpToPx(CONTENT_START_TRANSLATION_X_DP), 0);
+                displayedContent,
+                TRANSLATION_X,
+                -Utilities.dpToPx(CONTENT_START_TRANSLATION_X_DP), 0);
         translationXAnimation.setDuration(CONTENT_TRANSLATION_X_ANIMATION_DURATION_MS);
         translationXAnimation.setInterpolator(OPEN_TRANSLATION_X_INTERPOLATOR);
         mOpenAnimation.play(translationXAnimation);
 
         Animator translationYAnimation = ObjectAnimator.ofFloat(
-                mScrollView, TRANSLATION_Y, -Utilities.dpToPx(CONTENT_START_TRANSLATION_Y_DP), 0);
+                displayedContent,
+                TRANSLATION_Y,
+                -Utilities.dpToPx(CONTENT_START_TRANSLATION_Y_DP), 0);
         translationYAnimation.setDuration(CONTENT_TRANSLATION_Y_ANIMATION_DURATION_MS);
         translationYAnimation.setInterpolator(OPEN_TRANSLATION_Y_INTERPOLATOR);
         mOpenAnimation.play(translationYAnimation);
 
-        Animator contentAlphaAnimation = ObjectAnimator.ofFloat(mScrollView, ALPHA, 0f, 1f);
+        Animator contentAlphaAnimation = ObjectAnimator.ofFloat(displayedContent, ALPHA, 0f, 1f);
         contentAlphaAnimation.setStartDelay(CONTENT_ALPHA_ANIMATION_START_DELAY_MS);
         contentAlphaAnimation.setDuration(CONTENT_ALPHA_ANIMATION_DURATION_MS);
         mOpenAnimation.play(contentAlphaAnimation);
@@ -353,7 +361,7 @@
                 } else {
                     animateFocusMove(-1, currentFocusIndexOverride);
                 }
-                mScrollView.setVisibility(VISIBLE);
+                displayedContent.setVisibility(VISIBLE);
                 setVisibility(VISIBLE);
                 requestFocus();
             }
@@ -372,6 +380,9 @@
     }
 
     protected void animateFocusMove(int fromIndex, int toIndex) {
+        if (!mDisplayingRecentTasks) {
+            return;
+        }
         KeyboardQuickSwitchTaskView focusedTask = getTaskAt(toIndex);
         if (focusedTask == null) {
             return;
@@ -425,11 +436,15 @@
 
     @Override
     public boolean onKeyUp(int keyCode, KeyEvent event) {
-        return (mViewCallbacks != null && mViewCallbacks.onKeyUp(keyCode, event, mIsRtl))
+        return (mViewCallbacks != null
+                && mViewCallbacks.onKeyUp(keyCode, event, mIsRtl, mDisplayingRecentTasks))
                 || super.onKeyUp(keyCode, event);
     }
 
     private void initializeScroll(int index, boolean shouldTruncateTarget) {
+        if (!mDisplayingRecentTasks) {
+            return;
+        }
         View task = getTaskAt(index);
         if (task == null) {
             return;
@@ -449,6 +464,9 @@
 
     private void scrollRightTo(
             @NonNull View targetTask, boolean shouldTruncateTarget, boolean smoothScroll) {
+        if (!mDisplayingRecentTasks) {
+            return;
+        }
         if (smoothScroll && !shouldScroll(targetTask, shouldTruncateTarget)) {
             return;
         }
@@ -468,6 +486,9 @@
 
     private void scrollLeftTo(
             @NonNull View targetTask, boolean shouldTruncateTarget, boolean smoothScroll) {
+        if (!mDisplayingRecentTasks) {
+            return;
+        }
         if (smoothScroll && !shouldScroll(targetTask, shouldTruncateTarget)) {
             return;
         }
@@ -491,7 +512,7 @@
 
     @Nullable
     protected KeyboardQuickSwitchTaskView getTaskAt(int index) {
-        return index < 0 || index >= mContent.getChildCount()
+        return !mDisplayingRecentTasks || index < 0 || index >= mContent.getChildCount()
                 ? null : (KeyboardQuickSwitchTaskView) mContent.getChildAt(index);
     }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java
index c1f764f..9f036ec 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java
@@ -169,7 +169,7 @@
 
     class ViewCallbacks {
 
-        boolean onKeyUp(int keyCode, KeyEvent event, boolean isRTL) {
+        boolean onKeyUp(int keyCode, KeyEvent event, boolean isRTL, boolean allowTraversal) {
             if (keyCode != KeyEvent.KEYCODE_TAB
                     && keyCode != KeyEvent.KEYCODE_DPAD_RIGHT
                     && keyCode != KeyEvent.KEYCODE_DPAD_LEFT
@@ -181,6 +181,9 @@
                 closeQuickSwitchView(true);
                 return true;
             }
+            if (!allowTraversal) {
+                return false;
+            }
             boolean traverseBackwards = (keyCode == KeyEvent.KEYCODE_TAB && event.isShiftPressed())
                     || (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT && !isRTL)
                     || (keyCode == KeyEvent.KEYCODE_DPAD_LEFT && isRTL);