Merge "Add unit tests for SplitSelectDataHolder" into udc-qpr-dev
diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
index 9b7a05f..eb4ecaf 100644
--- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -45,7 +45,6 @@
 import android.util.FloatProperty;
 import android.util.Log;
 import android.util.SparseArray;
-import android.util.TypedValue;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
@@ -284,9 +283,8 @@
                 0,
                 0 // Bottom left
         };
-        final TypedValue value = new TypedValue();
-        getContext().getTheme().resolveAttribute(android.R.attr.colorBackground, value, true);
-        mBottomSheetBackgroundColor = value.data;
+        mBottomSheetBackgroundColor =
+                Themes.getAttrColor(getContext(), R.attr.materialColorSurfaceDim);
         updateBackgroundVisibility(mActivityContext.getDeviceProfile());
         mSearchUiManager.initializeSearch(this);
     }
diff --git a/src/com/android/launcher3/celllayout/MulticellReorderAlgorithm.java b/src/com/android/launcher3/celllayout/MulticellReorderAlgorithm.java
index cb12161..a2e26b3 100644
--- a/src/com/android/launcher3/celllayout/MulticellReorderAlgorithm.java
+++ b/src/com/android/launcher3/celllayout/MulticellReorderAlgorithm.java
@@ -19,8 +19,10 @@
 
 import com.android.launcher3.CellLayout;
 import com.android.launcher3.MultipageCellLayout;
+import com.android.launcher3.ShortcutAndWidgetContainer;
 import com.android.launcher3.util.GridOccupancy;
 
+import java.util.Arrays;
 import java.util.function.Supplier;
 
 /**
@@ -79,7 +81,7 @@
         lp.canReorder = false;
         mcl.setCountX(mcl.getCountX() + 1);
         mcl.getShortcutsAndWidgets().addViewInLayout(mSeam, lp);
-        mcl.setOccupied(createGridOccupancyWithSeam(mcl.getOccupied()));
+        mcl.setOccupied(createGridOccupancyWithSeam());
         mcl.mTmpOccupied = new GridOccupancy(mcl.getCountX(), mcl.getCountY());
     }
 
@@ -93,7 +95,8 @@
 
     /**
      * The function supplied here will execute while the CellLayout has a simulated seam added.
-     * @param f function to run under simulation
+     *
+     * @param f   function to run under simulation
      * @param <T> return value of the supplied function
      * @return Value of supplied function
      */
@@ -110,18 +113,17 @@
         return res;
     }
 
-    GridOccupancy createGridOccupancyWithSeam(GridOccupancy gridOccupancy) {
+    GridOccupancy createGridOccupancyWithSeam() {
+        ShortcutAndWidgetContainer shortcutAndWidgets = mCellLayout.getShortcutsAndWidgets();
         GridOccupancy grid = new GridOccupancy(mCellLayout.getCountX(), mCellLayout.getCountY());
-        for (int x = 0; x < mCellLayout.getCountX(); x++) {
-            for (int y = 0; y < mCellLayout.getCountY(); y++) {
-                int offset = x >= mCellLayout.getCountX() / 2 ? 1 : 0;
-                if (x == mCellLayout.getCountX() / 2) {
-                    grid.cells[x][y] = true;
-                } else {
-                    grid.cells[x][y] = gridOccupancy.cells[x - offset][y];
-                }
-            }
+        for (int i = 0; i < shortcutAndWidgets.getChildCount(); i++) {
+            View view = shortcutAndWidgets.getChildAt(i);
+            CellLayoutLayoutParams lp = (CellLayoutLayoutParams) view.getLayoutParams();
+            int seamOffset = lp.getCellX() >= mCellLayout.getCountX() / 2 && lp.canReorder ? 1 : 0;
+            grid.markCells(lp.getCellX() + seamOffset, lp.getCellY(), lp.cellHSpan, lp.cellVSpan,
+                    true);
         }
+        Arrays.fill(grid.cells[mCellLayout.getCountX() / 2], true);
         return grid;
     }
 }
diff --git a/tests/Android.bp b/tests/Android.bp
index e7f4084..135a6e0 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -58,6 +58,7 @@
       "src/com/android/launcher3/util/rule/SimpleActivityRule.java",
       "src/com/android/launcher3/util/rule/TestStabilityRule.java",
       "src/com/android/launcher3/util/rule/TISBindRule.java",
+      "src/com/android/launcher3/util/viewcapture_analysis/*.java",
       "src/com/android/launcher3/testcomponent/BaseTestingActivity.java",
       "src/com/android/launcher3/testcomponent/OtherBaseTestingActivity.java",
       "src/com/android/launcher3/testcomponent/CustomShortcutConfigActivity.java",
diff --git a/tests/src/com/android/launcher3/util/rule/ViewCaptureRule.kt b/tests/src/com/android/launcher3/util/rule/ViewCaptureRule.kt
index 8e2aea8..b2a2f7f 100644
--- a/tests/src/com/android/launcher3/util/rule/ViewCaptureRule.kt
+++ b/tests/src/com/android/launcher3/util/rule/ViewCaptureRule.kt
@@ -24,6 +24,7 @@
 import com.android.app.viewcapture.ViewCapture.MAIN_EXECUTOR
 import com.android.app.viewcapture.data.ExportedData
 import com.android.launcher3.util.ActivityLifecycleCallbacksAdapter
+import com.android.launcher3.util.viewcapture_analysis.ViewCaptureAnalyzer
 import java.util.function.Supplier
 import org.junit.rules.TestRule
 import org.junit.runner.Description
@@ -82,6 +83,8 @@
                     // is removed while onDraw is running, resulting in an IllegalStateException.
                     MAIN_EXECUTOR.execute { windowListenerCloseables.onEach(SafeCloseable::close) }
                 }
+
+                ViewCaptureAnalyzer.assertNoAnomalies(viewCaptureData)
             }
 
             private fun startCapture(
diff --git a/tests/src/com/android/launcher3/util/viewcapture_analysis/AlphaJumpDetector.java b/tests/src/com/android/launcher3/util/viewcapture_analysis/AlphaJumpDetector.java
index e40fb79..2501801 100644
--- a/tests/src/com/android/launcher3/util/viewcapture_analysis/AlphaJumpDetector.java
+++ b/tests/src/com/android/launcher3/util/viewcapture_analysis/AlphaJumpDetector.java
@@ -28,33 +28,101 @@
  * Invisible views are treated as if they had zero alpha.
  */
 final class AlphaJumpDetector extends AnomalyDetector {
+    // Commonly used parts of the paths to ignore.
+    private static final String CONTENT = "DecorView|LinearLayout|FrameLayout:id/content|";
+    private static final String DRAG_LAYER =
+            CONTENT + "LauncherRootView:id/launcher|DragLayer:id/drag_layer|";
+
     // Paths of nodes that are excluded from analysis.
     private static final Collection<String> PATHS_TO_IGNORE = Set.of(
-            "DecorView|LinearLayout|FrameLayout:id/content|LauncherRootView:id/launcher|DragLayer"
-                    + ":id/drag_layer|SearchContainerView:id/apps_view|SearchRecyclerView:id"
-                    + "/search_results_list_view|SearchResultSmallIconRow",
-            "DecorView|LinearLayout|FrameLayout:id/content|LauncherRootView:id/launcher|DragLayer"
-                    + ":id/drag_layer|SearchContainerView:id/apps_view|SearchRecyclerView:id"
-                    + "/search_results_list_view|SearchResultIcon",
-            "DecorView|LinearLayout|FrameLayout:id/content|LauncherRootView:id/launcher|DragLayer"
-                    + ":id/drag_layer|LauncherRecentsView:id/overview_panel|TaskView",
-            "DecorView|LinearLayout|FrameLayout:id/content|LauncherRootView:id/launcher|DragLayer"
-                    + ":id/drag_layer|WidgetsFullSheet|SpringRelativeLayout:id/container"
-                    + "|WidgetsRecyclerView:id/primary_widgets_list_view|WidgetsListHeader:id"
-                    + "/widgets_list_header",
-            "DecorView|LinearLayout|FrameLayout:id/content|LauncherRootView:id/launcher|DragLayer"
-                    + ":id/drag_layer|WidgetsFullSheet|SpringRelativeLayout:id/container"
-                    + "|WidgetsRecyclerView:id/primary_widgets_list_view"
-                    + "|StickyHeaderLayout$EmptySpaceView",
-            "DecorView|LinearLayout|FrameLayout:id/content|LauncherRootView:id/launcher|DragLayer"
-                    + ":id/drag_layer|SearchContainerView:id/apps_view|AllAppsRecyclerView:id"
-                    + "/apps_list_view|BubbleTextView:id/icon",
-            "DecorView|LinearLayout|FrameLayout:id/content|LauncherRootView:id/launcher|DragLayer"
-                    + ":id/drag_layer|LauncherRecentsView:id/overview_panel|ClearAllButton:id"
-                    + "/clear_all",
-            "DecorView|LinearLayout|FrameLayout:id/content|LauncherRootView:id/launcher|DragLayer"
-                    + ":id/drag_layer|NexusOverviewActionsView:id/overview_actions_view"
-                    + "|LinearLayout:id/action_buttons"
+            CONTENT
+                    + "AddItemDragLayer:id/add_item_drag_layer|AddItemWidgetsBottomSheet:id"
+                    + "/add_item_bottom_sheet|LinearLayout:id/add_item_bottom_sheet_content"
+                    + "|ScrollView:id/widget_preview_scroll_view|WidgetCell:id/widget_cell"
+                    + "|WidgetCellPreview:id/widget_preview_container|ImageView:id/widget_badge",
+            CONTENT
+                    + "AddItemDragLayer:id/add_item_drag_layer|AddItemWidgetsBottomSheet:id"
+                    + "/add_item_bottom_sheet|LinearLayout:id/add_item_bottom_sheet_content"
+                    + "|ScrollView:id/widget_preview_scroll_view|WidgetCell:id/widget_cell"
+                    + "|WidgetCellPreview:id/widget_preview_container|WidgetCell$1|FrameLayout"
+                    + "|ImageView:id/icon",
+            CONTENT + "AddItemDragLayer:id/add_item_drag_layer|View",
+            DRAG_LAYER
+                    + "AppWidgetResizeFrame|FrameLayout|ImageButton:id/widget_reconfigure_button",
+            DRAG_LAYER
+                    + "AppWidgetResizeFrame|FrameLayout|ImageView:id/widget_resize_bottom_handle",
+            DRAG_LAYER + "AppWidgetResizeFrame|FrameLayout|ImageView:id/widget_resize_frame",
+            DRAG_LAYER + "AppWidgetResizeFrame|FrameLayout|ImageView:id/widget_resize_left_handle",
+            DRAG_LAYER + "AppWidgetResizeFrame|FrameLayout|ImageView:id/widget_resize_right_handle",
+            DRAG_LAYER + "AppWidgetResizeFrame|FrameLayout|ImageView:id/widget_resize_top_handle",
+            DRAG_LAYER + "FloatingTaskView|FloatingTaskThumbnailView:id/thumbnail",
+            DRAG_LAYER + "FloatingTaskView|SplitPlaceholderView:id/split_placeholder",
+            DRAG_LAYER + "Folder|FolderPagedView:id/folder_content",
+            DRAG_LAYER + "LauncherAllAppsContainerView:id/apps_view",
+            DRAG_LAYER + "LauncherDragView",
+            DRAG_LAYER + "LauncherRecentsView:id/overview_panel",
+            DRAG_LAYER
+                    + "NexusOverviewActionsView:id/overview_actions_view|FrameLayout:id"
+                    + "/select_mode_buttons|ImageButton:id/close",
+            DRAG_LAYER
+                    + "NexusOverviewActionsView:id/overview_actions_view|LinearLayout:id"
+                    + "/action_buttons|Button:id/action_screenshot",
+            DRAG_LAYER
+                    + "NexusOverviewActionsView:id/overview_actions_view|LinearLayout:id"
+                    + "/action_buttons|Button:id/action_select",
+            DRAG_LAYER
+                    + "NexusOverviewActionsView:id/overview_actions_view|LinearLayout:id"
+                    + "/action_buttons|Button:id/action_split",
+            DRAG_LAYER
+                    + "NexusOverviewActionsView:id/overview_actions_view|LinearLayout:id"
+                    + "/action_buttons|Space:id/action_split_space",
+            DRAG_LAYER
+                    + "PopupContainerWithArrow:id/popup_container|LinearLayout:id"
+                    + "/deep_shortcuts_container|DeepShortcutView:id/deep_shortcut_material"
+                    + "|DeepShortcutTextView:id/bubble_text",
+            DRAG_LAYER
+                    + "PopupContainerWithArrow:id/popup_container|LinearLayout:id"
+                    + "/deep_shortcuts_container|DeepShortcutView:id/deep_shortcut_material|View"
+                    + ":id/icon",
+            DRAG_LAYER
+                    + "PopupContainerWithArrow:id/popup_container|LinearLayout:id"
+                    + "/system_shortcuts_container|DeepShortcutView:id/system_shortcut"
+                    + "|BubbleTextView:id/bubble_text",
+            DRAG_LAYER
+                    + "PopupContainerWithArrow:id/popup_container|LinearLayout:id"
+                    + "/system_shortcuts_container|DeepShortcutView:id/system_shortcut|View:id"
+                    + "/icon",
+            DRAG_LAYER
+                    + "PopupContainerWithArrow:id/popup_container|LinearLayout:id"
+                    + "/system_shortcuts_container|ImageView",
+            DRAG_LAYER
+                    + "PopupContainerWithArrow:id/popup_container|LinearLayout:id"
+                    + "/widget_shortcut_container|DeepShortcutView:id/system_shortcut"
+                    + "|BubbleTextView:id/bubble_text",
+            DRAG_LAYER
+                    + "PopupContainerWithArrow:id/popup_container|LinearLayout:id"
+                    + "/widget_shortcut_container|DeepShortcutView:id/system_shortcut|View:id/icon",
+            DRAG_LAYER + "SearchContainerView:id/apps_view",
+            DRAG_LAYER + "Snackbar|TextView:id/action",
+            DRAG_LAYER + "Snackbar|TextView:id/label",
+            DRAG_LAYER + "SplitInstructionsView|AppCompatTextView:id/split_instructions_text",
+            DRAG_LAYER + "TaskMenuView|LinearLayout:id/menu_option_layout",
+            DRAG_LAYER + "TaskMenuView|TextView:id/task_name",
+            DRAG_LAYER + "View",
+            DRAG_LAYER + "WidgetsFullSheet|SpringRelativeLayout:id/container",
+            DRAG_LAYER + "WidgetsTwoPaneSheet|SpringRelativeLayout:id/container",
+            CONTENT + "LauncherRootView:id/launcher|FloatingIconView",
+            CONTENT
+                    + "LauncherRootView|RecentsDragLayer:id/drag_layer|FallbackRecentsView:id"
+                    + "/overview_panel",
+            CONTENT
+                    + "LauncherRootView|RecentsDragLayer:id/drag_layer|NexusOverviewActionsView"
+                    + ":id/overview_actions_view|LinearLayout:id/action_buttons|Button:id"
+                    + "/action_screenshot",
+            CONTENT
+                    + "LauncherRootView|RecentsDragLayer:id/drag_layer|NexusOverviewActionsView"
+                    + ":id/overview_actions_view|LinearLayout:id/action_buttons|Button:id"
+                    + "/action_select"
     );
     // Minimal increase or decrease of view's alpha between frames that triggers the error.
     private static final float ALPHA_JUMP_THRESHOLD = 1f;
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 5b67d73..89f141f 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -223,6 +223,10 @@
         return getTouchEventPattern("Touch event", action);
     }
 
+    private static Pattern getTouchEventPattern(String action, int pointerCount) {
+        return getTouchEventPattern("Touch event", action, pointerCount);
+    }
+
     private static Pattern getTouchEventPatternTIS(String action) {
         return getTouchEventPattern("TouchInteractionService.onInputEvent", action);
     }
@@ -1803,11 +1807,25 @@
                 break;
             case MotionEvent.ACTION_POINTER_DOWN:
                 mPointerCount++;
+                if (gestureScope != GestureScope.OUTSIDE_WITH_PILFER
+                        && gestureScope != GestureScope.OUTSIDE_WITHOUT_PILFER
+                        && gestureScope != GestureScope.OUTSIDE_WITH_KEYCODE
+                        && (!isTrackpadGesture || isTwoFingerTrackpadGesture)) {
+                    expectEvent(TestProtocol.SEQUENCE_MAIN,
+                            getTouchEventPattern("ACTION_POINTER_DOWN", mPointerCount));
+                }
                 expectEvent(TestProtocol.SEQUENCE_TIS, getTouchEventPatternTIS(
                         "ACTION_POINTER_DOWN", mPointerCount));
                 pointerCount = mPointerCount;
                 break;
             case MotionEvent.ACTION_POINTER_UP:
+                if (gestureScope != GestureScope.OUTSIDE_WITH_PILFER
+                        && gestureScope != GestureScope.OUTSIDE_WITHOUT_PILFER
+                        && gestureScope != GestureScope.OUTSIDE_WITH_KEYCODE
+                        && (!isTrackpadGesture || isTwoFingerTrackpadGesture)) {
+                    expectEvent(TestProtocol.SEQUENCE_MAIN,
+                            getTouchEventPattern("ACTION_POINTER_UP", mPointerCount));
+                }
                 // When the gesture is handled outside, it's cancelled within launcher.
                 if (gestureScope != GestureScope.INSIDE_TO_OUTSIDE_WITH_KEYCODE
                         && gestureScope != GestureScope.OUTSIDE_WITH_KEYCODE) {