Merge "Migrate ENABLE_SPLIT_FROM_FULLSCREEN_WITH_KEYBOARD_SHORTCUTS to aconfig" into main
diff --git a/quickstep/res/layout/overview_actions_container.xml b/quickstep/res/layout/overview_actions_container.xml
index 0fda0bf..fe517fa 100644
--- a/quickstep/res/layout/overview_actions_container.xml
+++ b/quickstep/res/layout/overview_actions_container.xml
@@ -31,7 +31,7 @@
             android:layout_height="1dp"
             android:layout_weight="1" />
 
-        <Button
+        <com.android.quickstep.views.ScreenshotActionButton
             android:id="@+id/action_screenshot"
             style="@style/OverviewActionButton"
             android:layout_width="wrap_content"
@@ -40,17 +40,12 @@
             android:text="@string/action_screenshot"
             android:theme="@style/ThemeControlHighlightWorkspaceColor" />
 
-        <Space
-            android:id="@+id/action_split_space"
-            android:layout_width="@dimen/overview_actions_button_spacing"
-            android:layout_height="1dp"
-            android:visibility="gone" />
-
-        <Button
+        <com.android.quickstep.views.SplitActionButton
             android:id="@+id/action_split"
             style="@style/OverviewActionButton"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            android:layout_marginStart="@dimen/overview_actions_button_spacing"
             android:text="@string/action_split"
             android:theme="@style/ThemeControlHighlightWorkspaceColor"
             android:visibility="gone" />
diff --git a/quickstep/src/com/android/quickstep/views/ActionButton.kt b/quickstep/src/com/android/quickstep/views/ActionButton.kt
new file mode 100644
index 0000000..5c004cc
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/views/ActionButton.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2023 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.views
+
+import android.content.Context
+import android.util.AttributeSet
+import android.widget.Button
+
+/**
+ * A button on the Overview Actions Bar. Custom logic for hiding/showing each button type is handled
+ * in the respective subclass.
+ */
+open class ActionButton : Button {
+    private var mHiddenFlags = 0
+
+    constructor(context: Context) : super(context)
+    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
+    constructor(
+        context: Context,
+        attrs: AttributeSet?,
+        defStyleAttr: Int
+    ) : super(context, attrs, defStyleAttr)
+
+    /**
+     * Updates the proper flags to indicate whether the button should be hidden.
+     *
+     * @param flag The flag to update.
+     * @param enable Whether to enable the hidden flag: True will cause view to be hidden.
+     */
+    protected fun updateHiddenFlags(flag: Int, enable: Boolean) {
+        if (enable) {
+            mHiddenFlags = mHiddenFlags or flag
+        } else {
+            mHiddenFlags = mHiddenFlags and flag.inv()
+        }
+        val shouldBeVisible = mHiddenFlags == 0
+        this.visibility = if (shouldBeVisible) VISIBLE else GONE
+    }
+
+    /** Show/hide the button when the focused task is a single/pair. */
+    open fun updateForMultipleTasks(hasMultipleTasks: Boolean) {
+        // overridden in subclass, or else don't do anything
+    }
+
+    /** Show/hide the button depending on if the device is a tablet. */
+    open fun updateForTablet(isTablet: Boolean) {
+        // overridden in subclass, or else don't do anything
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
index 7f1d619..8692e4e 100644
--- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
+++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
@@ -22,7 +22,6 @@
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.View.OnClickListener;
-import android.widget.Button;
 import android.widget.FrameLayout;
 
 import androidx.annotation.IntDef;
@@ -41,6 +40,8 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * View for showing action buttons in Overview
@@ -89,14 +90,11 @@
     private static final int INDEX_SCROLL_ALPHA = 5;
     private static final int NUM_ALPHAS = 6;
 
-    public @interface SplitButtonHiddenFlags { }
-    public static final int FLAG_IS_NOT_TABLET = 1 << 0;
-
-    public @interface SplitButtonDisabledFlags { }
-    public static final int FLAG_SINGLE_TASK = 1 << 0;
-
     private MultiValueAlpha mMultiValueAlpha;
-    private Button mSplitButton;
+
+    private List<ActionButton> mActionButtons = new ArrayList<>();
+    private ScreenshotActionButton mScreenshotButton;
+    private SplitActionButton mSplitButton;
 
     @ActionsHiddenFlags
     private int mHiddenFlags;
@@ -104,12 +102,6 @@
     @ActionsDisabledFlags
     protected int mDisabledFlags;
 
-    @SplitButtonHiddenFlags
-    private int mSplitButtonHiddenFlags;
-
-    @SplitButtonDisabledFlags
-    private int mSplitButtonDisabledFlags;
-
     @Nullable
     protected T mCallbacks;
 
@@ -135,9 +127,12 @@
         mMultiValueAlpha = new MultiValueAlpha(findViewById(R.id.action_buttons), NUM_ALPHAS);
         mMultiValueAlpha.setUpdateVisibility(true);
 
-        findViewById(R.id.action_screenshot).setOnClickListener(this);
+        mScreenshotButton = findViewById(R.id.action_screenshot);
+        mScreenshotButton.setOnClickListener(this);
+        mActionButtons.add(mScreenshotButton);
         mSplitButton = findViewById(R.id.action_split);
         mSplitButton.setOnClickListener(this);
+        mActionButtons.add(mSplitButton);
     }
 
     /**
@@ -201,40 +196,28 @@
         }
         boolean isEnabled = (mDisabledFlags & ~DISABLED_ROTATED) == 0;
         LayoutUtils.setViewEnabled(this, isEnabled);
-        updateSplitButtonEnabledState();
     }
 
     /**
-     * Updates the proper flags to indicate whether the "Split screen" button should be hidden.
-     *
-     * @param flag   The flag to update.
-     * @param enable Whether to enable the hidden flag: True will cause view to be hidden.
+     * Updates flags to hide and show actions buttons when a grouped task (split screen) is focused.
+     * @param isGroupedTask True if the focused task is a grouped task.
      */
-    public void updateSplitButtonHiddenFlags(@SplitButtonHiddenFlags int flag, boolean enable) {
-        if (enable) {
-            mSplitButtonHiddenFlags |= flag;
-        } else {
-            mSplitButtonHiddenFlags &= ~flag;
+    public void updateForGroupedTask(boolean isGroupedTask) {
+        for (ActionButton button : mActionButtons) {
+            // Update flags to show/hide buttons.
+            button.updateForMultipleTasks(isGroupedTask);
         }
-        if (mSplitButton == null) return;
-        boolean shouldBeVisible = mSplitButtonHiddenFlags == 0;
-        mSplitButton.setVisibility(shouldBeVisible ? VISIBLE : GONE);
-        findViewById(R.id.action_split_space).setVisibility(shouldBeVisible ? VISIBLE : GONE);
     }
 
     /**
-     * Updates the proper flags to indicate whether the "Split screen" button should be disabled.
-     *
-     * @param flag   The flag to update.
-     * @param enable Whether to enable the disable flag: True will cause view to be disabled.
+     * Updates flags to hide and show actions buttons depending on if the device is a tablet.
+     * @param isTablet True if the current device is a tablet.
      */
-    public void updateSplitButtonDisabledFlags(@SplitButtonDisabledFlags int flag, boolean enable) {
-        if (enable) {
-            mSplitButtonDisabledFlags |= flag;
-        } else {
-            mSplitButtonDisabledFlags &= ~flag;
+    public void updateForTablet(boolean isTablet) {
+        for (ActionButton button : mActionButtons) {
+            // Update flags to show/hide buttons.
+            button.updateForTablet(isTablet);
         }
-        updateSplitButtonEnabledState();
     }
 
     public MultiProperty getContentAlpha() {
@@ -312,18 +295,4 @@
                 (dp.isLandscape ? R.drawable.ic_split_horizontal : R.drawable.ic_split_vertical),
                 0, 0, 0);
     }
-
-    /**
-     * Enables/disables the "Split" button based on the status of mSplitButtonDisabledFlags and
-     * mDisabledFlags.
-     */
-    private void updateSplitButtonEnabledState() {
-        if (mSplitButton == null) {
-            return;
-        }
-        boolean isParentEnabled = (mDisabledFlags & ~DISABLED_ROTATED) == 0;
-        boolean shouldBeEnabled = mSplitButtonDisabledFlags == 0 && isParentEnabled;
-        mSplitButton.setEnabled(shouldBeEnabled);
-    }
-
 }
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 7972999..6a275e6 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -20,7 +20,6 @@
 import static android.view.Surface.ROTATION_0;
 import static android.view.View.MeasureSpec.EXACTLY;
 import static android.view.View.MeasureSpec.makeMeasureSpec;
-
 import static com.android.app.animation.Interpolators.ACCELERATE;
 import static com.android.app.animation.Interpolators.ACCELERATE_0_75;
 import static com.android.app.animation.Interpolators.ACCELERATE_DECELERATE;
@@ -34,6 +33,7 @@
 import static com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU;
 import static com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType;
 import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
+import static com.android.launcher3.Flags.enableGridOnlyOverview;
 import static com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
 import static com.android.launcher3.LauncherState.BACKGROUND_APP;
@@ -42,7 +42,6 @@
 import static com.android.launcher3.Utilities.mapToRange;
 import static com.android.launcher3.Utilities.squaredHypot;
 import static com.android.launcher3.Utilities.squaredTouchSlop;
-import static com.android.launcher3.Flags.enableGridOnlyOverview;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_OVERVIEW_ACTIONS_SPLIT;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_CLEAR_ALL;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_DISMISS_SWIPE_UP;
@@ -57,8 +56,6 @@
 import static com.android.quickstep.util.LogUtils.splitFailureMessage;
 import static com.android.quickstep.views.ClearAllButton.DISMISS_ALPHA;
 import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
-import static com.android.quickstep.views.OverviewActionsView.FLAG_IS_NOT_TABLET;
-import static com.android.quickstep.views.OverviewActionsView.FLAG_SINGLE_TASK;
 import static com.android.quickstep.views.OverviewActionsView.HIDDEN_ACTIONS_IN_MENU;
 import static com.android.quickstep.views.OverviewActionsView.HIDDEN_DESKTOP;
 import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NON_ZERO_ROTATION;
@@ -3927,18 +3924,23 @@
     }
 
     /**
-     * Hides all overview actions if current page is for split apps, shows otherwise
-     * If actions are showing, we only show split option if
+     * Hides all overview actions if user is halfway through split selection, shows otherwise.
+     * We only show split option if:
+     * * Focused view is a single app
      * * Device is large screen
-     * * There are at least 2 tasks to invoke split
      */
     private void updateCurrentTaskActionsVisibility() {
-        boolean isCurrentSplit = getCurrentPageTaskView() instanceof GroupedTaskView;
-        mActionsView.updateHiddenFlags(HIDDEN_SPLIT_SCREEN, isCurrentSplit);
+        boolean isGroupedTask = getCurrentPageTaskView() != null
+                && getCurrentPageTaskView().containsMultipleTasks();
+        // Update flags to see if entire actions bar should be hidden.
+        mActionsView.updateHiddenFlags(HIDDEN_SPLIT_SCREEN, isGroupedTask);
         mActionsView.updateHiddenFlags(HIDDEN_SPLIT_SELECT_ACTIVE, isSplitSelectionActive());
-        mActionsView.updateSplitButtonHiddenFlags(FLAG_IS_NOT_TABLET,
-                !mActivity.getDeviceProfile().isTablet);
-        mActionsView.updateSplitButtonDisabledFlags(FLAG_SINGLE_TASK, /*enable=*/ false);
+        // Update flags to see if actions bar should show buttons for a single task or a pair of
+        // tasks.
+        mActionsView.updateForGroupedTask(isGroupedTask);
+        // Update flags to see if split button should be hidden.
+        mActionsView.updateForTablet(mActivity.getDeviceProfile().isTablet);
+
         if (isDesktopModeSupported()) {
             boolean isCurrentDesktop = getCurrentPageTaskView() instanceof DesktopTaskView;
             mActionsView.updateHiddenFlags(HIDDEN_DESKTOP, isCurrentDesktop);
diff --git a/quickstep/src/com/android/quickstep/views/ScreenshotActionButton.kt b/quickstep/src/com/android/quickstep/views/ScreenshotActionButton.kt
new file mode 100644
index 0000000..9cb48b8
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/views/ScreenshotActionButton.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2023 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.views
+
+import android.content.Context
+import android.util.AttributeSet
+
+/** A button on the Overview Actions Bar for screenshotting the focused app. */
+class ScreenshotActionButton : ActionButton {
+    companion object {
+        const val FLAG_MULTIPLE_TASKS_HIDE_SCREENSHOT = 1 shl 0
+    }
+
+    constructor(context: Context) : super(context)
+    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
+    constructor(
+        context: Context,
+        attrs: AttributeSet?,
+        defStyleAttr: Int
+    ) : super(context, attrs, defStyleAttr)
+
+    /** Show/hide the button when the focused task is a single/pair. */
+    override fun updateForMultipleTasks(hasMultipleTasks: Boolean) {
+        // Hidden for multiple tasks
+        updateHiddenFlags(FLAG_MULTIPLE_TASKS_HIDE_SCREENSHOT, hasMultipleTasks)
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/views/SplitActionButton.kt b/quickstep/src/com/android/quickstep/views/SplitActionButton.kt
new file mode 100644
index 0000000..88d1a77
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/views/SplitActionButton.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2023 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.views
+
+import android.content.Context
+import android.util.AttributeSet
+
+/** A button on the Overview Actions Bar for initiating split screen. */
+class SplitActionButton : ActionButton {
+    companion object {
+        const val FLAG_IS_NOT_TABLET_HIDE_SPLIT = 1 shl 0
+        const val FLAG_MULTIPLE_TASKS_HIDE_SPLIT = 1 shl 1
+    }
+
+    constructor(context: Context) : super(context)
+    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
+    constructor(
+        context: Context,
+        attrs: AttributeSet?,
+        defStyleAttr: Int
+    ) : super(context, attrs, defStyleAttr)
+
+    /** Show/hide the button when the focused task is a single/pair. */
+    override fun updateForMultipleTasks(hasMultipleTasks: Boolean) {
+        // Hidden for multiple tasks
+        updateHiddenFlags(FLAG_MULTIPLE_TASKS_HIDE_SPLIT, hasMultipleTasks)
+    }
+
+    /** Show/hide the button depending on if the device is a tablet. */
+    override fun updateForTablet(isTablet: Boolean) {
+        // Hidden for non-tablets
+        updateHiddenFlags(FLAG_IS_NOT_TABLET_HIDE_SPLIT, !isTablet)
+    }
+}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index ff8537b..0966350 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -103,6 +103,7 @@
     @Test
     @NavigationModeSwitch
     @PortraitLandscape
+    @PlatinumTest(focusArea = "launcher")
     public void testWorkspaceSwitchToAllApps() {
         assertNotNull("switchToAllApps() returned null",
                 mLauncher.getWorkspace().switchToAllApps());
@@ -179,6 +180,7 @@
     @Test
     @NavigationModeSwitch
     @PortraitLandscape
+    @PlatinumTest(focusArea = "launcher")
     public void testOverviewActions() throws Exception {
         assumeFalse("Skipping Overview Actions tests for grid only overview",
                 mLauncher.isTablet() && mLauncher.isGridOnlyOverviewEnabled());
@@ -215,6 +217,7 @@
     @NavigationModeSwitch
     @PortraitLandscape
     @ScreenRecord // b/238461765
+    @PlatinumTest(focusArea = "launcher")
     public void testSwitchToOverview() throws Exception {
         startTestAppsWithCheck();
         assertNotNull("Workspace.switchToOverview() returned null",
@@ -240,6 +243,7 @@
     @Test
     @NavigationModeSwitch
     @PortraitLandscape
+    @PlatinumTest(focusArea = "launcher")
     public void testBackground() throws Exception {
         startAppFast(CALCULATOR_APP_PACKAGE);
         final LaunchedAppState launchedAppState = getAndAssertLaunchedApp();
@@ -266,6 +270,7 @@
     @Test
     @NavigationModeSwitch
     @PortraitLandscape
+    @PlatinumTest(focusArea = "launcher")
     public void testQuickSwitchFromApp() throws Exception {
         startTestActivity(2);
         startTestActivity(3);
@@ -295,6 +300,7 @@
 
     @Test
     @ScreenRecord // b/242163205
+    @PlatinumTest(focusArea = "launcher")
     @TaskbarModeSwitch(mode = PERSISTENT)
     public void testQuickSwitchToPreviousAppForTablet() throws Exception {
         assumeTrue(mLauncher.isTablet());
@@ -321,6 +327,7 @@
     @Test
     @NavigationModeSwitch
     @PortraitLandscape
+    @PlatinumTest(focusArea = "launcher")
     public void testQuickSwitchFromHome() throws Exception {
         startTestActivity(2);
         mLauncher.goHome().quickSwitchToPreviousApp();